Failed Conditions
Branch release-2.1 (4e22cf)
by Rick
06:39
created

DbPackages-mysql.php ➔ smf_db_create_table()   F

Complexity

Conditions 21
Paths 7844

Size

Total Lines 91
Code Lines 53

Duplication

Lines 15
Ratio 16.48 %

Importance

Changes 0
Metric Value
cc 21
eloc 53
nc 7844
nop 6
dl 15
loc 91
rs 2
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * This file contains database functionality specifically designed for packages (mods) to utilize.
5
 *
6
 * Simple Machines Forum (SMF)
7
 *
8
 * @package SMF
9
 * @author Simple Machines http://www.simplemachines.org
10
 * @copyright 2017 Simple Machines and individual contributors
11
 * @license http://www.simplemachines.org/about/smf/license.php BSD
12
 *
13
 * @version 2.1 Beta 4
14
 */
15
16
if (!defined('SMF'))
17
	die('No direct access...');
18
19
/**
20
 * Add the file functions to the $smcFunc array.
21
 */
22 View Code Duplication
function db_packages_init()
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
23
{
24
	global $smcFunc, $reservedTables, $db_package_log, $db_prefix;
25
26
	if (!isset($smcFunc['db_create_table']) || $smcFunc['db_create_table'] != 'smf_db_create_table')
27
	{
28
		$smcFunc += array(
29
			'db_add_column' => 'smf_db_add_column',
30
			'db_add_index' => 'smf_db_add_index',
31
			'db_calculate_type' => 'smf_db_calculate_type',
32
			'db_change_column' => 'smf_db_change_column',
33
			'db_create_table' => 'smf_db_create_table',
34
			'db_drop_table' => 'smf_db_drop_table',
35
			'db_table_structure' => 'smf_db_table_structure',
36
			'db_list_columns' => 'smf_db_list_columns',
37
			'db_list_indexes' => 'smf_db_list_indexes',
38
			'db_remove_column' => 'smf_db_remove_column',
39
			'db_remove_index' => 'smf_db_remove_index',
40
		);
41
		$db_package_log = array();
42
	}
43
44
	// We setup an array of SMF tables we can't do auto-remove on - in case a mod writer cocks it up!
45
	$reservedTables = array('admin_info_files', 'approval_queue', 'attachments', 'ban_groups', 'ban_items',
46
		'board_permissions', 'boards', 'calendar', 'calendar_holidays', 'categories',
47
		'custom_fields', 'group_moderators', 'log_actions', 'log_activity', 'log_banned', 'log_boards',
48
		'log_digest', 'log_errors', 'log_floodcontrol', 'log_group_requests', 'log_mark_read',
49
		'log_notify', 'log_online', 'log_packages', 'log_polls', 'log_reported', 'log_reported_comments',
50
		'log_scheduled_tasks', 'log_search_messages', 'log_search_results', 'log_search_subjects',
51
		'log_search_topics', 'log_topics', 'mail_queue', 'membergroups', 'members', 'message_icons',
52
		'messages', 'moderators', 'package_servers', 'permission_profiles', 'permissions', 'personal_messages',
53
		'pm_recipients', 'poll_choices', 'polls', 'scheduled_tasks', 'sessions', 'settings', 'smileys',
54
		'themes', 'topics');
55
	foreach ($reservedTables as $k => $table_name)
56
		$reservedTables[$k] = strtolower($db_prefix . $table_name);
57
58
	// We in turn may need the extra stuff.
59
	db_extend('extra');
60
}
61
62
/**
63
 * This function can be used to create a table without worrying about schema
64
 *  compatibilities across supported database systems.
65
 *  - If the table exists will, by default, do nothing.
66
 *  - Builds table with columns as passed to it - at least one column must be sent.
67
 *  The columns array should have one sub-array for each column - these sub arrays contain:
68
 *  	'name' = Column name
69
 *  	'type' = Type of column - values from (smallint, mediumint, int, text, varchar, char, tinytext, mediumtext, largetext)
70
 *  	'size' => Size of column (If applicable) - for example 255 for a large varchar, 10 for an int etc.
71
 *  		If not set SMF will pick a size.
72
 *  	- 'default' = Default value - do not set if no default required.
73
 *  	- 'null' => Can it be null (true or false) - if not set default will be false.
74
 *  	- 'auto' => Set to true to make it an auto incrementing column. Set to a numerical value to set from what
75
 *  		 it should begin counting.
76
 *  - Adds indexes as specified within indexes parameter. Each index should be a member of $indexes. Values are:
77
 *  	- 'name' => Index name (If left empty SMF will generate).
78
 *  	- 'type' => Type of index. Choose from 'primary', 'unique' or 'index'. If not set will default to 'index'.
79
 *  	- 'columns' => Array containing columns that form part of key - in the order the index is to be created.
80
 *  - parameters: (None yet)
81
 *  - if_exists values:
82
 *  	- 'ignore' will do nothing if the table exists. (And will return true)
83
 *  	- 'overwrite' will drop any existing table of the same name.
84
 *  	- 'error' will return false if the table already exists.
85
 *
86
 * @param string $table_name The name of the table to create
87
 * @param array $columns An array of column info in the specified format
88
 * @param array $indexes An array of index info in the specified format
89
 * @param array $parameters Extra parameters. Currently only 'engine', the desired MySQL storage engine, is used.
90
 * @param string $if_exists What to do if the table exists.
91
 * @param string $error
92
 * @return boolean Whether or not the operation was successful
93
 */
94
function smf_db_create_table($table_name, $columns, $indexes = array(), $parameters = array(), $if_exists = 'ignore', $error = 'fatal')
0 ignored issues
show
Unused Code introduced by
The parameter $parameters is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $error is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
95
{
96
	global $reservedTables, $smcFunc, $db_package_log, $db_prefix, $db_character_set;
97
98
	static $engines = array();
99
100
	// Strip out the table name, we might not need it in some cases
101
	$real_prefix = preg_match('~^(`?)(.+?)\\1\\.(.*?)$~', $db_prefix, $match) === 1 ? $match[3] : $db_prefix;
102
103
	// With or without the database name, the fullname looks like this.
104
	$full_table_name = str_replace('{db_prefix}', $real_prefix, $table_name);
105
	$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
106
107
	// First - no way do we touch SMF tables.
108
	if (in_array(strtolower($table_name), $reservedTables))
109
		return false;
110
111
	// Log that we'll want to remove this on uninstall.
112
	$db_package_log[] = array('remove_table', $table_name);
113
114
	// Slightly easier on MySQL than the others...
115
	$tables = $smcFunc['db_list_tables']();
116 View Code Duplication
	if (in_array($full_table_name, $tables))
117
	{
118
		// This is a sad day... drop the table? If not, return false (error) by default.
119
		if ($if_exists == 'overwrite')
120
			$smcFunc['db_drop_table']($table_name);
121
		else
122
			return $if_exists == 'ignore';
123
	}
124
125
	// Righty - let's do the damn thing!
126
	$table_query = 'CREATE TABLE ' . $table_name . "\n" . '(';
127
	foreach ($columns as $column)
128
		$table_query .= "\n\t" . smf_db_create_query_column($column) . ',';
129
130
	// Loop through the indexes next...
131
	foreach ($indexes as $index)
132
	{
133
		$columns = implode(',', $index['columns']);
134
135
		// Is it the primary?
136
		if (isset($index['type']) && $index['type'] == 'primary')
137
			$table_query .= "\n\t" . 'PRIMARY KEY (' . implode(',', $index['columns']) . '),';
138
		else
139
		{
140
			if (empty($index['name']))
141
				$index['name'] = implode('_', $index['columns']);
142
			$table_query .= "\n\t" . (isset($index['type']) && $index['type'] == 'unique' ? 'UNIQUE' : 'KEY') . ' ' . $index['name'] . ' (' . $columns . '),';
143
		}
144
	}
145
146
	// No trailing commas!
147 View Code Duplication
	if (substr($table_query, -1) == ',')
148
		$table_query = substr($table_query, 0, -1);
149
150
	// Which engine do we want here?
151
	if (empty($engines))
152
	{
153
		// Figure out which engines we have
154
		$get_engines = $smcFunc['db_query']('', 'SHOW ENGINES', array());
155
156 View Code Duplication
		while ($row = $smcFunc['db_fetch_assoc']($get_engines))
157
		{
158
			if ($row['Support'] == 'YES' || $row['Support'] == 'DEFAULT')
159
				$engines[] = $row['Engine'];
160
		}
161
162
		$smcFunc['db_free_result']($get_engines);
163
	}
164
165
	// If we don't have this engine, or didn't specify one, default to InnoDB or MyISAM
166
	// depending on which one is available
167
	if (!isset($parameters['engine']) || !in_array($parameters['engine'], $engines))
168
	{
169
		$parameters['engine'] = in_array('InnoDB', $engines) ? 'InnoDB' : 'MyISAM';
170
	}
171
172
	$table_query .= ') ENGINE=' . $parameters['engine'];
173
	if (!empty($db_character_set) && $db_character_set == 'utf8')
174
		$table_query .= ' DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci';
175
176
	// Create the table!
177
	$smcFunc['db_query']('', $table_query,
178
		array(
179
			'security_override' => true,
180
		)
181
	);
182
183
	return true;
184
}
185
186
/**
187
 * Drop a table.
188
 *
189
 * @param string $table_name The name of the table to drop
190
 * @param array $parameters Not used at the moment
191
 * @param string $error
192
 * @return boolean Whether or not the operation was successful
193
 */
194
function smf_db_drop_table($table_name, $parameters = array(), $error = 'fatal')
0 ignored issues
show
Unused Code introduced by
The parameter $parameters is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $error is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
195
{
196
	global $reservedTables, $smcFunc, $db_prefix;
197
198
	// After stripping away the database name, this is what's left.
199
	$real_prefix = preg_match('~^(`?)(.+?)\\1\\.(.*?)$~', $db_prefix, $match) === 1 ? $match[3] : $db_prefix;
200
201
	// Get some aliases.
202
	$full_table_name = str_replace('{db_prefix}', $real_prefix, $table_name);
203
	$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
204
205
	// God no - dropping one of these = bad.
206
	if (in_array(strtolower($table_name), $reservedTables))
207
		return false;
208
209
	// Does it exist?
210
	if (in_array($full_table_name, $smcFunc['db_list_tables']()))
211
	{
212
		$query = 'DROP TABLE ' . $table_name;
213
		$smcFunc['db_query']('',
214
			$query,
215
			array(
216
				'security_override' => true,
217
			)
218
		);
219
220
		return true;
221
	}
222
223
	// Otherwise do 'nout.
224
	return false;
225
}
226
227
/**
228
 * This function adds a column.
229
 *
230
 * @param string $table_name The name of the table to add the column to
231
 * @param array $column_info An array of column info ({@see smf_db_create_table})
232
 * @param array $parameters Not used?
233
 * @param string $if_exists What to do if the column exists. If 'update', column is updated.
234
 * @param string $error
235
 * @return boolean Whether or not the operation was successful
236
 */
237
function smf_db_add_column($table_name, $column_info, $parameters = array(), $if_exists = 'update', $error = 'fatal')
0 ignored issues
show
Unused Code introduced by
The parameter $parameters is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $error is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
238
{
239
	global $smcFunc, $db_package_log, $db_prefix;
240
241
	$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
242
243
	// Log that we will want to uninstall this!
244
	$db_package_log[] = array('remove_column', $table_name, $column_info['name']);
245
246
	// Does it exist - if so don't add it again!
247
	$columns = $smcFunc['db_list_columns']($table_name, false);
248 View Code Duplication
	foreach ($columns as $column)
249
		if ($column == $column_info['name'])
250
		{
251
			// If we're going to overwrite then use change column.
252
			if ($if_exists == 'update')
253
				return $smcFunc['db_change_column']($table_name, $column_info['name'], $column_info);
254
			else
255
				return false;
256
		}
257
258
	// Get the specifics...
259
	$column_info['size'] = isset($column_info['size']) && is_numeric($column_info['size']) ? $column_info['size'] : null;
260
261
	// Now add the thing!
262
	$query = '
263
		ALTER TABLE ' . $table_name . '
264
		ADD ' . smf_db_create_query_column($column_info) . (empty($column_info['auto']) ? '' : ' primary key');
265
	$smcFunc['db_query']('', $query,
266
		array(
267
			'security_override' => true,
268
		)
269
	);
270
271
	return true;
272
}
273
274
/**
275
 * Removes a column.
276
 *
277
 * @param string $table_name The name of the table to drop the column from
278
 * @param string $column_name The name of the column to drop
279
 * @param array $parameters Not used?
280
 * @param string $error
281
 * @return boolean Whether or not the operation was successful
282
 */
283
function smf_db_remove_column($table_name, $column_name, $parameters = array(), $error = 'fatal')
0 ignored issues
show
Unused Code introduced by
The parameter $parameters is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $error is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
284
{
285
	global $smcFunc, $db_prefix;
286
287
	$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
288
289
	// Does it exist?
290
	$columns = $smcFunc['db_list_columns']($table_name, true);
291
	foreach ($columns as $column)
292
		if ($column['name'] == $column_name)
293
		{
294
			$smcFunc['db_query']('', '
295
				ALTER TABLE ' . $table_name . '
296
				DROP COLUMN ' . $column_name,
297
				array(
298
					'security_override' => true,
299
				)
300
			);
301
302
			return true;
303
		}
304
305
	// If here we didn't have to work - joy!
306
	return false;
307
}
308
309
/**
310
 * Change a column.
311
 *
312
 * @param string $table_name The name of the table this column is in
313
 * @param string $old_column The name of the column we want to change
314
 * @param array $column_info An array of info about the "new" column definition (see {@link smf_db_create_table()})
315
 * @return bool
316
 */
317
function smf_db_change_column($table_name, $old_column, $column_info)
318
{
319
	global $smcFunc, $db_prefix;
320
321
	$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
322
323
	// Check it does exist!
324
	$columns = $smcFunc['db_list_columns']($table_name, true);
325
	$old_info = null;
326
	foreach ($columns as $column)
327
		if ($column['name'] == $old_column)
328
			$old_info = $column;
329
330
	// Nothing?
331
	if ($old_info == null)
332
		return false;
333
334
	// Get the right bits.
335
	if (!isset($column_info['name']))
336
		$column_info['name'] = $old_column;
337
	if (!isset($column_info['default']))
338
		$column_info['default'] = $old_info['default'];
339
	if (!isset($column_info['null']))
340
		$column_info['null'] = $old_info['null'];
341
	if (!isset($column_info['auto']))
342
		$column_info['auto'] = $old_info['auto'];
343
	if (!isset($column_info['type']))
344
		$column_info['type'] = $old_info['type'];
345
	if (!isset($column_info['size']) || !is_numeric($column_info['size']))
346
		$column_info['size'] = $old_info['size'];
347
	if (!isset($column_info['unsigned']) || !in_array($column_info['type'], array('int', 'tinyint', 'smallint', 'mediumint', 'bigint')))
348
		$column_info['unsigned'] = '';
349
350
	list ($type, $size) = $smcFunc['db_calculate_type']($column_info['type'], $column_info['size']);
351
352
	// Allow for unsigned integers (mysql only)
353
	$unsigned = in_array($type, array('int', 'tinyint', 'smallint', 'mediumint', 'bigint')) && !empty($column_info['unsigned']) ? 'unsigned ' : '';
354
355
	if ($size !== null)
356
		$type = $type . '(' . $size . ')';
357
358
	$smcFunc['db_query']('', '
359
		ALTER TABLE ' . $table_name . '
360
		CHANGE COLUMN `' . $old_column . '` `' . $column_info['name'] . '` ' . $type . ' ' . (!empty($unsigned) ? $unsigned : '') . (empty($column_info['null']) ? 'NOT NULL' : '') . ' ' .
361
			(!isset($column_info['default']) ? '' : 'default \'' . $smcFunc['db_escape_string']($column_info['default']) . '\'') . ' ' .
362
			(empty($column_info['auto']) ? '' : 'auto_increment') . ' ',
363
		array(
364
			'security_override' => true,
365
		)
366
	);
367
}
368
369
/**
370
 * Add an index.
371
 *
372
 * @param string $table_name The name of the table to add the index to
373
 * @param array $index_info An array of index info (see {@link smf_db_create_table()})
374
 * @param array $parameters Not used?
375
 * @param string $if_exists What to do if the index exists. If 'update', the definition will be updated.
376
 * @param string $error
377
 * @return boolean Whether or not the operation was successful
0 ignored issues
show
Documentation introduced by
Should the return type not be false|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
378
 */
379
function smf_db_add_index($table_name, $index_info, $parameters = array(), $if_exists = 'update', $error = 'fatal')
0 ignored issues
show
Unused Code introduced by
The parameter $parameters is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $error is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
380
{
381
	global $smcFunc, $db_package_log, $db_prefix;
382
383
	$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
384
385
	// No columns = no index.
386
	if (empty($index_info['columns']))
387
		return false;
388
	$columns = implode(',', $index_info['columns']);
389
390
	// No name - make it up!
391 View Code Duplication
	if (empty($index_info['name']))
392
	{
393
		// No need for primary.
394
		if (isset($index_info['type']) && $index_info['type'] == 'primary')
395
			$index_info['name'] = '';
396
		else
397
			$index_info['name'] = implode('_', $index_info['columns']);
398
	}
399
400
	// Log that we are going to want to remove this!
401
	$db_package_log[] = array('remove_index', $table_name, $index_info['name']);
402
403
	// Let's get all our indexes.
404
	$indexes = $smcFunc['db_list_indexes']($table_name, true);
405
	// Do we already have it?
406
	foreach ($indexes as $index)
407
	{
408
		if ($index['name'] == $index_info['name'] || ($index['type'] == 'primary' && isset($index_info['type']) && $index_info['type'] == 'primary'))
409
		{
410
			// If we want to overwrite simply remove the current one then continue.
411
			if ($if_exists != 'update' || $index['type'] == 'primary')
412
				return false;
413
			else
414
				$smcFunc['db_remove_index']($table_name, $index_info['name']);
415
		}
416
	}
417
418
	// If we're here we know we don't have the index - so just add it.
419
	if (!empty($index_info['type']) && $index_info['type'] == 'primary')
420
	{
421
		$smcFunc['db_query']('', '
422
			ALTER TABLE ' . $table_name . '
423
			ADD PRIMARY KEY (' . $columns . ')',
424
			array(
425
				'security_override' => true,
426
			)
427
		);
428
	}
429
	else
430
	{
431
		$smcFunc['db_query']('', '
432
			ALTER TABLE ' . $table_name . '
433
			ADD ' . (isset($index_info['type']) && $index_info['type'] == 'unique' ? 'UNIQUE' : 'INDEX') . ' ' . $index_info['name'] . ' (' . $columns . ')',
434
			array(
435
				'security_override' => true,
436
			)
437
		);
438
	}
439
}
440
441
/**
442
 * Remove an index.
443
 *
444
 * @param string $table_name The name of the table to remove the index from
445
 * @param string $index_name The name of the index to remove
446
 * @param array $parameters Not used?
447
 * @param string $error
448
 * @return boolean Whether or not the operation was successful
449
 */
450
function smf_db_remove_index($table_name, $index_name, $parameters = array(), $error = 'fatal')
0 ignored issues
show
Unused Code introduced by
The parameter $parameters is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $error is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
451
{
452
	global $smcFunc, $db_prefix;
453
454
	$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
455
456
	// Better exist!
457
	$indexes = $smcFunc['db_list_indexes']($table_name, true);
458
459 View Code Duplication
	foreach ($indexes as $index)
460
	{
461
		// If the name is primary we want the primary key!
462
		if ($index['type'] == 'primary' && $index_name == 'primary')
463
		{
464
			// Dropping primary key?
465
			$smcFunc['db_query']('', '
466
				ALTER TABLE ' . $table_name . '
467
				DROP PRIMARY KEY',
468
				array(
469
					'security_override' => true,
470
				)
471
			);
472
473
			return true;
474
		}
475
		if ($index['name'] == $index_name)
476
		{
477
			// Drop the bugger...
478
			$smcFunc['db_query']('', '
479
				ALTER TABLE ' . $table_name . '
480
				DROP INDEX ' . $index_name,
481
				array(
482
					'security_override' => true,
483
				)
484
			);
485
486
			return true;
487
		}
488
	}
489
490
	// Not to be found ;(
491
	return false;
492
}
493
494
/**
495
 * Get the schema formatted name for a type.
496
 *
497
 * @param string $type_name The data type (int, varchar, smallint, etc.)
498
 * @param int $type_size The size (8, 255, etc.)
0 ignored issues
show
Documentation introduced by
Should the type for parameter $type_size not be integer|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
499
 * @param boolean $reverse
500
 * @return array An array containing the appropriate type and size for this DB type
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string|integer|null>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
501
 */
502
function smf_db_calculate_type($type_name, $type_size = null, $reverse = false)
503
{
504
	// MySQL is actually the generic baseline.
505
506
	$type_name = strtolower($type_name);
507
	// Generic => Specific.
508
	if (!$reverse)
509
	{
510
		$types = array(
511
			'inet' => 'varbinary',
512
		);
513
	}
514
	else
515
	{
516
		$types = array(
517
			'varbinary' => 'inet',
518
		);
519
	}
520
521
	// Got it? Change it!
522
	if (isset($types[$type_name]))
523
	{
524
		if ($type_name == 'inet' && !$reverse)
525
		{
526
			$type_size = 16;
527
			$type_name = 'varbinary';
528
		}
529
		elseif ($type_name == 'varbinary' && $reverse && $type_size == 16)
530
		{
531
			$type_name = 'inet';
532
			$type_size = null;
533
		}
534
		elseif ($type_name == 'varbinary')
535
			$type_name = 'varbinary';
536
		else
537
			$type_name = $types[$type_name];
538
	}
539
540
	return array($type_name, $type_size);
541
}
542
543
/**
544
 * Get table structure.
545
 *
546
 * @param string $table_name The name of the table
547
 * @return array An array of table structure - the name, the column info from {@link smf_db_list_columns()} and the index info from {@link smf_db_list_indexes()}
548
 */
549
function smf_db_table_structure($table_name)
550
{
551
	global $smcFunc, $db_prefix;
552
553
	$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
554
555
	// Find the table engine and add that to the info as well
556
	$table_status = $smcFunc['db_query']('', '
557
		SHOW TABLE STATUS
558
		LIKE {string:table}',
559
		array(
560
			'table' => strtr($table_name, array('_' => '\\_', '%' => '\\%'))
561
		)
562
	);
563
564
	// Only one row, so no need for a loop...
565
	$row = $smcFunc['db_fetch_assoc']($table_status);
566
567
	$smcFunc['db_free_result']($table_status);
568
569
	return array(
570
		'name' => $table_name,
571
		'columns' => $smcFunc['db_list_columns']($table_name, true),
572
		'indexes' => $smcFunc['db_list_indexes']($table_name, true),
573
		'engine' => $row['Engine'],
574
	);
575
}
576
577
/**
578
 * Return column information for a table.
579
 *
580
 * @param string $table_name The name of the table to get column info for
581
 * @param bool $detail Whether or not to return detailed info. If true, returns the column info. If false, just returns the column names.
582
 * @param array $parameters Not used?
583
 * @return array An array of column names or detailed column info, depending on $detail
584
 */
585
function smf_db_list_columns($table_name, $detail = false, $parameters = array())
0 ignored issues
show
Unused Code introduced by
The parameter $parameters is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
586
{
587
	global $smcFunc, $db_prefix;
588
589
	$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
590
591
	$result = $smcFunc['db_query']('', '
592
		SHOW FIELDS
593
		FROM {raw:table_name}',
594
		array(
595
			'table_name' => substr($table_name, 0, 1) == '`' ? $table_name : '`' . $table_name . '`',
596
		)
597
	);
598
	$columns = array();
599
	while ($row = $smcFunc['db_fetch_assoc']($result))
600
	{
601
		if (!$detail)
602
		{
603
			$columns[] = $row['Field'];
604
		}
605
		else
606
		{
607
			// Is there an auto_increment?
608
			$auto = strpos($row['Extra'], 'auto_increment') !== false ? true : false;
609
610
			// Can we split out the size?
611
			if (preg_match('~(.+?)\s*\((\d+)\)(?:(?:\s*)?(unsigned))?~i', $row['Type'], $matches) === 1)
612
			{
613
				$type = $matches[1];
614
				$size = $matches[2];
615
				if (!empty($matches[3]) && $matches[3] == 'unsigned')
616
					$unsigned = true;
617
			}
618
			else
619
			{
620
				$type = $row['Type'];
621
				$size = null;
622
			}
623
624
			$columns[$row['Field']] = array(
625
				'name' => $row['Field'],
626
				'null' => $row['Null'] != 'YES' ? false : true,
627
				'default' => isset($row['Default']) ? $row['Default'] : null,
628
				'type' => $type,
629
				'size' => $size,
630
				'auto' => $auto,
631
			);
632
633
			if (isset($unsigned))
634
			{
635
				$columns[$row['Field']]['unsigned'] = $unsigned;
636
				unset($unsigned);
637
			}
638
		}
639
	}
640
	$smcFunc['db_free_result']($result);
641
642
	return $columns;
643
}
644
645
/**
646
 * Get index information.
647
 *
648
 * @param string $table_name The name of the table to get indexes for
649
 * @param bool $detail Whether or not to return detailed info.
650
 * @param array $parameters Not used?
651
 * @return array An array of index names or a detailed array of index info, depending on $detail
652
 */
653
function smf_db_list_indexes($table_name, $detail = false, $parameters = array())
0 ignored issues
show
Unused Code introduced by
The parameter $parameters is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
654
{
655
	global $smcFunc, $db_prefix;
656
657
	$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
658
659
	$result = $smcFunc['db_query']('', '
660
		SHOW KEYS
661
		FROM {raw:table_name}',
662
		array(
663
			'table_name' => substr($table_name, 0, 1) == '`' ? $table_name : '`' . $table_name . '`',
664
		)
665
	);
666
	$indexes = array();
667
	while ($row = $smcFunc['db_fetch_assoc']($result))
668
	{
669
		if (!$detail)
670
			$indexes[] = $row['Key_name'];
671
		else
672
		{
673
			// What is the type?
674
			if ($row['Key_name'] == 'PRIMARY')
675
				$type = 'primary';
676
			elseif (empty($row['Non_unique']))
677
				$type = 'unique';
678
			elseif (isset($row['Index_type']) && $row['Index_type'] == 'FULLTEXT')
679
				$type = 'fulltext';
680
			else
681
				$type = 'index';
682
683
			// This is the first column we've seen?
684
			if (empty($indexes[$row['Key_name']]))
685
			{
686
				$indexes[$row['Key_name']] = array(
687
					'name' => $row['Key_name'],
688
					'type' => $type,
689
					'columns' => array(),
690
				);
691
			}
692
693
			// Is it a partial index?
694
			if (!empty($row['Sub_part']))
695
				$indexes[$row['Key_name']]['columns'][] = $row['Column_name'] . '(' . $row['Sub_part'] . ')';
696
			else
697
				$indexes[$row['Key_name']]['columns'][] = $row['Column_name'];
698
		}
699
	}
700
	$smcFunc['db_free_result']($result);
701
702
	return $indexes;
703
}
704
705
/**
706
 * Creates a query for a column
707
 *
708
 * @param array $column An array of column info
709
 * @return string The column definition
710
 */
711
function smf_db_create_query_column($column)
712
{
713
	global $smcFunc;
714
715
	// Auto increment is easy here!
716
	if (!empty($column['auto']))
717
	{
718
		$default = 'auto_increment';
719
	}
720 View Code Duplication
	elseif (isset($column['default']) && $column['default'] !== null)
721
		$default = 'default \'' . $smcFunc['db_escape_string']($column['default']) . '\'';
722
	else
723
		$default = '';
724
725
	// Sort out the size... and stuff...
726
	$column['size'] = isset($column['size']) && is_numeric($column['size']) ? $column['size'] : null;
727
	list ($type, $size) = $smcFunc['db_calculate_type']($column['type'], $column['size']);
728
729
	// Allow unsigned integers (mysql only)
730
	$unsigned = in_array($type, array('int', 'tinyint', 'smallint', 'mediumint', 'bigint')) && !empty($column['unsigned']) ? 'unsigned ' : '';
731
732
	if ($size !== null)
733
		$type = $type . '(' . $size . ')';
734
735
	// Now just put it together!
736
	return '`' . $column['name'] . '` ' . $type . ' ' . (!empty($unsigned) ? $unsigned : '') . (!empty($column['null']) ? '' : 'NOT NULL') . ' ' . $default;
737
}
738
739
?>