Completed
Push — release-2.1 ( aa21c4...7040ad )
by Mathias
09:20
created

Sources/DbPackages-postgresql.php (35 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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
The function db_packages_init() has been defined more than once; this definition is ignored, only the first definition in Sources/DbPackages-mysql.php (L22-60) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
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 Currently not used
90
 * @param string $if_exists What to do if the table exists.
91
 * @param string $error
92
 */
93
function smf_db_create_table($table_name, $columns, $indexes = array(), $parameters = array(), $if_exists = 'ignore', $error = 'fatal')
0 ignored issues
show
The function smf_db_create_table() has been defined more than once; this definition is ignored, only the first definition in Sources/DbPackages-mysql.php (L94-184) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
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...
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...
94
{
95
	global $reservedTables, $smcFunc, $db_package_log, $db_prefix;
96
97
	// Strip out the table name, we might not need it in some cases
98
	$real_prefix = preg_match('~^("?)(.+?)\\1\\.(.*?)$~', $db_prefix, $match) === 1 ? $match[3] : $db_prefix;
99
100
	// With or without the database name, the fullname looks like this.
101
	$full_table_name = str_replace('{db_prefix}', $real_prefix, $table_name);
102
	$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
103
104
	// First - no way do we touch SMF tables.
105
	if (in_array(strtolower($table_name), $reservedTables))
106
		return false;
107
108
	// Log that we'll want to remove this on uninstall.
109
	$db_package_log[] = array('remove_table', $table_name);
110
111
	// This... my friends... is a function in a half - let's start by checking if the table exists!
112
	$tables = $smcFunc['db_list_tables']();
113 View Code Duplication
	if (in_array($full_table_name, $tables))
0 ignored issues
show
This code seems to be duplicated across 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...
114
	{
115
		// This is a sad day... drop the table? If not, return false (error) by default.
116
		if ($if_exists == 'overwrite')
117
			$smcFunc['db_drop_table']($table_name);
118
		else
119
			return $if_exists == 'ignore';
120
	}
121
122
	// If we've got this far - good news - no table exists. We can build our own!
123
	$smcFunc['db_transaction']('begin');
124
	$table_query = 'CREATE TABLE ' . $table_name . "\n" . '(';
125
	foreach ($columns as $column)
126
	{
127
		// If we have an auto increment do it!
128
		if (!empty($column['auto']))
129
		{
130
			$smcFunc['db_query']('', '
131
				CREATE SEQUENCE ' . $table_name . '_seq',
132
				array(
133
					'security_override' => true,
134
				)
135
			);
136
			$default = 'default nextval(\'' . $table_name . '_seq\')';
137
		}
138 View Code Duplication
		elseif (isset($column['default']) && $column['default'] !== null)
0 ignored issues
show
This code seems to be duplicated across 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...
139
			$default = 'default \'' . $smcFunc['db_escape_string']($column['default']) . '\'';
140
		else
141
			$default = '';
142
143
		// Sort out the size...
144
		$column['size'] = isset($column['size']) && is_numeric($column['size']) ? $column['size'] : null;
145
		list ($type, $size) = $smcFunc['db_calculate_type']($column['type'], $column['size']);
146
		if ($size !== null)
147
			$type = $type . '(' . $size . ')';
148
149
		// Now just put it together!
150
		$table_query .= "\n\t\"" . $column['name'] . '" ' . $type . ' ' . (!empty($column['null']) ? '' : 'NOT NULL') . ' ' . $default . ',';
151
	}
152
153
	// Loop through the indexes a sec...
154
	$index_queries = array();
155
	foreach ($indexes as $index)
156
	{
157
		$columns = implode(',', $index['columns']);
158
159
		// Primary goes in the table...
160
		if (isset($index['type']) && $index['type'] == 'primary')
161
			$table_query .= "\n\t" . 'PRIMARY KEY (' . implode(',', $index['columns']) . '),';
162
		else
163
		{
164
			if (empty($index['name']))
165
				$index['name'] = implode('_', $index['columns']);
166
			$index_queries[] = 'CREATE ' . (isset($index['type']) && $index['type'] == 'unique' ? 'UNIQUE' : '') . ' INDEX ' . $table_name . '_' . $index['name'] . ' ON ' . $table_name . ' (' . $columns . ')';
167
		}
168
	}
169
170
	// No trailing commas!
171 View Code Duplication
	if (substr($table_query, -1) == ',')
0 ignored issues
show
This code seems to be duplicated across 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...
172
		$table_query = substr($table_query, 0, -1);
173
174
	$table_query .= ')';
175
176
	// Create the table!
177
	$smcFunc['db_query']('', $table_query,
178
		array(
179
			'security_override' => true,
180
		)
181
	);
182
	// And the indexes...
183
	foreach ($index_queries as $query)
184
		$smcFunc['db_query']('', $query,
185
		array(
186
			'security_override' => true,
187
		)
188
	);
189
190
	// Go, go power rangers!
191
	$smcFunc['db_transaction']('commit');
192
193
	return true;
194
}
195
196
/**
197
 * Drop a table and its associated sequences.
198
 *
199
 * @param string $table_name The name of the table to drop
200
 * @param array $parameters Not used at the moment
201
 * @param string $error
202
 * @return boolean Whether or not the operation was successful
203
 */
204
function smf_db_drop_table($table_name, $parameters = array(), $error = 'fatal')
0 ignored issues
show
The function smf_db_drop_table() has been defined more than once; this definition is ignored, only the first definition in Sources/DbPackages-mysql.php (L194-225) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
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...
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...
205
{
206
	global $reservedTables, $smcFunc, $db_prefix;
207
208
	// After stripping away the database name, this is what's left.
209
	$real_prefix = preg_match('~^("?)(.+?)\\1\\.(.*?)$~', $db_prefix, $match) === 1 ? $match[3] : $db_prefix;
210
211
	// Get some aliases.
212
	$full_table_name = str_replace('{db_prefix}', $real_prefix, $table_name);
213
	$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
214
215
	// God no - dropping one of these = bad.
216
	if (in_array(strtolower($table_name), $reservedTables))
217
		return false;
218
219
	// Does it exist?
220
	if (in_array($full_table_name, $smcFunc['db_list_tables']()))
221
	{
222
		// We can then drop the table.
223
		$smcFunc['db_transaction']('begin');
224
225
		// the table
226
		$table_query = 'DROP TABLE ' . $table_name;
227
228
		// and the assosciated sequence, if any
229
		$sequence_query = 'DROP SEQUENCE IF EXISTS ' . $table_name . '_seq';
230
231
		// drop them
232
		$smcFunc['db_query']('',
233
			$table_query,
234
			array(
235
				'security_override' => true,
236
			)
237
		);
238
		$smcFunc['db_query']('',
239
			$sequence_query,
240
			array(
241
				'security_override' => true,
242
			)
243
		);
244
245
		$smcFunc['db_transaction']('commit');
246
247
		return true;
248
	}
249
250
	// Otherwise do 'nout.
251
	return false;
252
}
253
254
/**
255
 * This function adds a column.
256
 *
257
 * @param string $table_name The name of the table to add the column to
258
 * @param array $column_info An array of column info (see {@link smf_db_create_table()})
259
 * @param array $parameters Not used?
260
 * @param string $if_exists What to do if the column exists. If 'update', column is updated.
261
 * @param string $error
262
 * @return boolean Whether or not the operation was successful
263
 */
264
function smf_db_add_column($table_name, $column_info, $parameters = array(), $if_exists = 'update', $error = 'fatal')
0 ignored issues
show
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...
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...
The function smf_db_add_column() has been defined more than once; this definition is ignored, only the first definition in Sources/DbPackages-mysql.php (L237-272) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
265
{
266
	global $smcFunc, $db_package_log, $db_prefix;
267
268
	$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
269
270
	// Log that we will want to uninstall this!
271
	$db_package_log[] = array('remove_column', $table_name, $column_info['name']);
272
273
	// Does it exist - if so don't add it again!
274
	$columns = $smcFunc['db_list_columns']($table_name, false);
275 View Code Duplication
	foreach ($columns as $column)
0 ignored issues
show
This code seems to be duplicated across 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...
276
		if ($column == $column_info['name'])
277
		{
278
			// If we're going to overwrite then use change column.
279
			if ($if_exists == 'update')
280
				return $smcFunc['db_change_column']($table_name, $column_info['name'], $column_info);
281
			else
282
				return false;
283
		}
284
285
	// Get the specifics...
286
	$column_info['size'] = isset($column_info['size']) && is_numeric($column_info['size']) ? $column_info['size'] : null;
287
	list ($type, $size) = $smcFunc['db_calculate_type']($column_info['type'], $column_info['size']);
288
	if ($size !== null)
289
		$type = $type . '(' . $size . ')';
290
291
	// Now add the thing!
292
	$query = '
293
		ALTER TABLE ' . $table_name . '
294
		ADD COLUMN ' . $column_info['name'] . ' ' . $type;
295
	$smcFunc['db_query']('', $query,
296
		array(
297
			'security_override' => true,
298
		)
299
	);
300
301
	// If there's more attributes they need to be done via a change on PostgreSQL.
302
	unset($column_info['type'], $column_info['size']);
303
304
	if (count($column_info) != 1)
305
		return $smcFunc['db_change_column']($table_name, $column_info['name'], $column_info);
306
	else
307
		return true;
308
}
309
310
/**
311
 * Removes a column.
312
 *
313
 * @param string $table_name The name of the table to drop the column from
314
 * @param string $column_name The name of the column to drop
315
 * @param array $parameters Not used?
316
 * @param string $error
317
 * @return boolean Whether or not the operation was successful
318
 */
319
function smf_db_remove_column($table_name, $column_name, $parameters = array(), $error = 'fatal')
0 ignored issues
show
The function smf_db_remove_column() has been defined more than once; this definition is ignored, only the first definition in Sources/DbPackages-mysql.php (L283-307) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
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...
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...
320
{
321
	global $smcFunc, $db_prefix;
322
323
	$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
324
325
	// Does it exist?
326
	$columns = $smcFunc['db_list_columns']($table_name, true);
327
	foreach ($columns as $column)
328
		if ($column['name'] == $column_name)
329
		{
330
			// If there is an auto we need remove it!
331
			if ($column['auto'])
332
				$smcFunc['db_query']('',
333
					'DROP SEQUENCE ' . $table_name . '_seq',
334
					array(
335
						'security_override' => true,
336
					)
337
				);
338
339
			$smcFunc['db_query']('', '
340
				ALTER TABLE ' . $table_name . '
341
				DROP COLUMN ' . $column_name,
342
				array(
343
					'security_override' => true,
344
				)
345
			);
346
347
			return true;
348
		}
349
350
	// If here we didn't have to work - joy!
351
	return false;
352
}
353
354
/**
355
 * Change a column.
356
 *
357
 * @param string $table_name The name of the table this column is in
358
 * @param string $old_column The name of the column we want to change
359
 * @param array $column_info An array of info about the "new" column definition (see {@link smf_db_create_table()})
360
 * @return bool
361
 */
362
function smf_db_change_column($table_name, $old_column, $column_info)
0 ignored issues
show
The function smf_db_change_column() has been defined more than once; this definition is ignored, only the first definition in Sources/DbPackages-mysql.php (L317-367) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
363
{
364
	global $smcFunc, $db_prefix;
365
366
	$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
367
368
	// Check it does exist!
369
	$columns = $smcFunc['db_list_columns']($table_name, true);
370
	$old_info = null;
371
	foreach ($columns as $column)
372
		if ($column['name'] == $old_column)
373
			$old_info = $column;
374
375
	// Nothing?
376
	if ($old_info == null)
377
		return false;
378
379
	// Now we check each bit individually and ALTER as required.
380
	if (isset($column_info['name']) && $column_info['name'] != $old_column)
381
	{
382
		$smcFunc['db_query']('', '
383
			ALTER TABLE ' . $table_name . '
384
			RENAME COLUMN ' . $old_column . ' TO ' . $column_info['name'],
385
			array(
386
				'security_override' => true,
387
			)
388
		);
389
	}
390
	// Different default?
391 View Code Duplication
	if (isset($column_info['default']) && $column_info['default'] != $old_info['default'])
0 ignored issues
show
This code seems to be duplicated across 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...
392
	{
393
		$action = $column_info['default'] !== null ? 'SET DEFAULT \'' . $smcFunc['db_escape_string']($column_info['default']) . '\'' : 'DROP DEFAULT';
394
		$smcFunc['db_query']('', '
395
			ALTER TABLE ' . $table_name . '
396
			ALTER COLUMN ' . $column_info['name'] . ' ' . $action,
397
			array(
398
				'security_override' => true,
399
			)
400
		);
401
	}
402
	// Is it null - or otherwise?
403
	if (isset($column_info['null']) && $column_info['null'] != $old_info['null'])
404
	{
405
		$action = $column_info['null'] ? 'DROP' : 'SET';
406
		$smcFunc['db_transaction']('begin');
407 View Code Duplication
		if (!$column_info['null'])
0 ignored issues
show
This code seems to be duplicated across 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...
408
		{
409
			// We have to set it to something if we are making it NOT NULL. And we must comply with the current column format.
410
			$setTo = isset($column_info['default']) ? $column_info['default'] : (strpos($old_info['type'], 'int') !== false ? 0 : '');
411
			$smcFunc['db_query']('', '
412
				UPDATE ' . $table_name . '
413
				SET ' . $column_info['name'] . ' = \'' . $setTo . '\'
414
				WHERE ' . $column_info['name'] . ' IS NULL',
415
				array(
416
					'security_override' => true,
417
				)
418
			);
419
		}
420
		$smcFunc['db_query']('', '
421
			ALTER TABLE ' . $table_name . '
422
			ALTER COLUMN ' . $column_info['name'] . ' ' . $action . ' NOT NULL',
423
			array(
424
				'security_override' => true,
425
			)
426
		);
427
		$smcFunc['db_transaction']('commit');
428
	}
429
	// What about a change in type?
430
	if (isset($column_info['type']) && ($column_info['type'] != $old_info['type'] || (isset($column_info['size']) && $column_info['size'] != $old_info['size'])))
431
	{
432
		$column_info['size'] = isset($column_info['size']) && is_numeric($column_info['size']) ? $column_info['size'] : null;
433
		list ($type, $size) = $smcFunc['db_calculate_type']($column_info['type'], $column_info['size']);
434
		if ($size !== null)
435
			$type = $type . '(' . $size . ')';
436
437
		// The alter is a pain.
438
		$smcFunc['db_transaction']('begin');
439
		$smcFunc['db_query']('', '
440
			ALTER TABLE ' . $table_name . '
441
			ADD COLUMN ' . $column_info['name'] . '_tempxx ' . $type,
442
			array(
443
				'security_override' => true,
444
			)
445
		);
446
		$smcFunc['db_query']('', '
447
			UPDATE ' . $table_name . '
448
			SET ' . $column_info['name'] . '_tempxx = CAST(' . $column_info['name'] . ' AS ' . $type . ')',
449
			array(
450
				'security_override' => true,
451
			)
452
		);
453
		$smcFunc['db_query']('', '
454
			ALTER TABLE ' . $table_name . '
455
			DROP COLUMN ' . $column_info['name'],
456
			array(
457
				'security_override' => true,
458
			)
459
		);
460
		$smcFunc['db_query']('', '
461
			ALTER TABLE ' . $table_name . '
462
			RENAME COLUMN ' . $column_info['name'] . '_tempxx TO ' . $column_info['name'],
463
			array(
464
				'security_override' => true,
465
			)
466
		);
467
		$smcFunc['db_transaction']('commit');
468
	}
469
	// Finally - auto increment?!
470
	if (isset($column_info['auto']) && $column_info['auto'] != $old_info['auto'])
471
	{
472
		// Are we removing an old one?
473
		if ($old_info['auto'])
474
		{
475
			// Alter the table first - then drop the sequence.
476
			$smcFunc['db_query']('', '
477
				ALTER TABLE ' . $table_name . '
478
				ALTER COLUMN ' . $column_info['name'] . ' SET DEFAULT \'0\'',
479
				array(
480
					'security_override' => true,
481
				)
482
			);
483
			$smcFunc['db_query']('', '
484
				DROP SEQUENCE ' . $table_name . '_seq',
485
				array(
486
					'security_override' => true,
487
				)
488
			);
489
		}
490
		// Otherwise add it!
491
		else
492
		{
493
			$smcFunc['db_query']('', '
494
				CREATE SEQUENCE ' . $table_name . '_seq',
495
				array(
496
					'security_override' => true,
497
				)
498
			);
499
			$smcFunc['db_query']('', '
500
				ALTER TABLE ' . $table_name . '
501
				ALTER COLUMN ' . $column_info['name'] . ' SET DEFAULT nextval(\'' . $table_name . '_seq\')',
502
				array(
503
					'security_override' => true,
504
				)
505
			);
506
		}
507
	}
508
509
	return true;
510
}
511
512
/**
513
 * Add an index.
514
 *
515
 * @param string $table_name The name of the table to add the index to
516
 * @param array $index_info An array of index info (see {@link smf_db_create_table()})
517
 * @param array $parameters Not used?
518
 * @param string $if_exists What to do if the index exists. If 'update', the definition will be updated.
519
 * @param string $error
520
 * @return boolean Whether or not the operation was successful
521
 */
522
function smf_db_add_index($table_name, $index_info, $parameters = array(), $if_exists = 'update', $error = 'fatal')
0 ignored issues
show
The function smf_db_add_index() has been defined more than once; this definition is ignored, only the first definition in Sources/DbPackages-mysql.php (L379-439) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
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...
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...
523
{
524
	global $smcFunc, $db_package_log, $db_prefix;
525
526
	$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
527
528
	// No columns = no index.
529
	if (empty($index_info['columns']))
530
		return false;
531
	$columns = implode(',', $index_info['columns']);
532
533
	// No name - make it up!
534
	if (empty($index_info['name']))
535
	{
536
		// No need for primary.
537
		if (isset($index_info['type']) && $index_info['type'] == 'primary')
538
			$index_info['name'] = '';
539
		else
540
			$index_info['name'] = $table_name . implode('_', $index_info['columns']);
541
	}
542
	else
543
		$index_info['name'] = $table_name . $index_info['name'];
544
545
	// Log that we are going to want to remove this!
546
	$db_package_log[] = array('remove_index', $table_name, $index_info['name']);
547
548
	// Let's get all our indexes.
549
	$indexes = $smcFunc['db_list_indexes']($table_name, true);
550
	// Do we already have it?
551
	foreach ($indexes as $index)
552
	{
553
		if ($index['name'] == $index_info['name'] || ($index['type'] == 'primary' && isset($index_info['type']) && $index_info['type'] == 'primary'))
554
		{
555
			// If we want to overwrite simply remove the current one then continue.
556
			if ($if_exists != 'update' || $index['type'] == 'primary')
557
				return false;
558
			else
559
				$smcFunc['db_remove_index']($table_name, $index_info['name']);
560
		}
561
	}
562
563
	// If we're here we know we don't have the index - so just add it.
564
	if (!empty($index_info['type']) && $index_info['type'] == 'primary')
565
	{
566
		$smcFunc['db_query']('', '
567
			ALTER TABLE ' . $table_name . '
568
			ADD PRIMARY KEY (' . $columns . ')',
569
			array(
570
				'security_override' => true,
571
			)
572
		);
573
	}
574
	else
575
	{
576
		$smcFunc['db_query']('', '
577
			CREATE ' . (isset($index_info['type']) && $index_info['type'] == 'unique' ? 'UNIQUE' : '') . ' INDEX ' . $index_info['name'] . ' ON ' . $table_name . ' (' . $columns . ')',
578
			array(
579
				'security_override' => true,
580
			)
581
		);
582
	}
583
}
584
585
/**
586
 * Remove an index.
587
 *
588
 * @param string $table_name The name of the table to remove the index from
589
 * @param string $index_name The name of the index to remove
590
 * @param array $parameters Not used?
591
 * @param string $error
592
 * @return boolean Whether or not the operation was successful
593
 */
594
function smf_db_remove_index($table_name, $index_name, $parameters = array(), $error = 'fatal')
0 ignored issues
show
The function smf_db_remove_index() has been defined more than once; this definition is ignored, only the first definition in Sources/DbPackages-mysql.php (L450-492) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
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...
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...
595
{
596
	global $smcFunc, $db_prefix;
597
598
	$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
599
600
	// Better exist!
601
	$indexes = $smcFunc['db_list_indexes']($table_name, true);
602
	if ($index_name != 'primary')
603
		$index_name = $table_name . '_' . $index_name;
604
605 View Code Duplication
	foreach ($indexes as $index)
0 ignored issues
show
This code seems to be duplicated across 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...
606
	{
607
		// If the name is primary we want the primary key!
608
		if ($index['type'] == 'primary' && $index_name == 'primary')
609
		{
610
			// Dropping primary key is odd...
611
			$smcFunc['db_query']('', '
612
				ALTER TABLE ' . $table_name . '
613
				DROP CONSTRAINT ' . $index['name'],
614
				array(
615
					'security_override' => true,
616
				)
617
			);
618
619
			return true;
620
		}
621
		if ($index['name'] == $index_name)
622
		{
623
			// Drop the bugger...
624
			$smcFunc['db_query']('', '
625
				DROP INDEX ' . $index_name,
626
				array(
627
					'security_override' => true,
628
				)
629
			);
630
631
			return true;
632
		}
633
	}
634
635
	// Not to be found ;(
636
	return false;
637
}
638
639
/**
640
 * Get the schema formatted name for a type.
641
 *
642
 * @param string $type_name The data type (int, varchar, smallint, etc.)
643
 * @param int $type_size The size (8, 255, etc.)
644
 * @param boolean $reverse If true, returns specific types for a generic type
645
 * @return array An array containing the appropriate type and size for this DB type
646
 */
647
function smf_db_calculate_type($type_name, $type_size = null, $reverse = false)
0 ignored issues
show
The function smf_db_calculate_type() has been defined more than once; this definition is ignored, only the first definition in Sources/DbPackages-mysql.php (L502-541) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
648
{
649
	// Let's be sure it's lowercase MySQL likes both, others no.
650
	$type_name = strtolower($type_name);
651
	// Generic => Specific.
652
	if (!$reverse)
653
	{
654
		$types = array(
655
			'varchar' => 'character varying',
656
			'char' => 'character',
657
			'mediumint' => 'int',
658
			'tinyint' => 'smallint',
659
			'tinytext' => 'character varying',
660
			'mediumtext' => 'text',
661
			'largetext' => 'text',
662
			'inet' => 'inet',
663
			'time' => 'time without time zone',
664
			'datetime' => 'timestamp without time zone',
665
			'timestamp' => 'timestamp without time zone',
666
		);
667
	}
668
	else
669
	{
670
		$types = array(
671
			'character varying' => 'varchar',
672
			'character' => 'char',
673
			'integer' => 'int',
674
			'inet' => 'inet',
675
			'time without time zone' => 'time',
676
			'timestamp without time zone' => 'datetime',
677
			'numeric' => 'decimal',
678
		);
679
	}
680
681
	// Got it? Change it!
682
	if (isset($types[$type_name]))
683
	{
684
		if ($type_name == 'tinytext')
685
			$type_size = 255;
686
		$type_name = $types[$type_name];
687
	}
688
689
	// Only char fields got size
690
	if (strpos($type_name, 'char') === false)
691
			$type_size = null;
692
693
694
	return array($type_name, $type_size);
695
}
696
697
/**
698
 * Get table structure.
699
 *
700
 * @param string $table_name The name of the table
701
 * @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()}
702
 */
703
function smf_db_table_structure($table_name)
0 ignored issues
show
The function smf_db_table_structure() has been defined more than once; this definition is ignored, only the first definition in Sources/DbPackages-mysql.php (L549-575) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
704
{
705
	global $smcFunc, $db_prefix;
706
707
	$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
708
709
	return array(
710
		'name' => $table_name,
711
		'columns' => $smcFunc['db_list_columns']($table_name, true),
712
		'indexes' => $smcFunc['db_list_indexes']($table_name, true),
713
	);
714
}
715
716
/**
717
 * Return column information for a table.
718
 *
719
 * @param string $table_name The name of the table to get column info for
720
 * @param bool $detail Whether or not to return detailed info. If true, returns the column info. If false, just returns the column names.
721
 * @param array $parameters Not used?
722
 * @return array An array of column names or detailed column info, depending on $detail
723
 */
724
function smf_db_list_columns($table_name, $detail = false, $parameters = array())
0 ignored issues
show
The function smf_db_list_columns() has been defined more than once; this definition is ignored, only the first definition in Sources/DbPackages-mysql.php (L585-643) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
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...
725
{
726
	global $smcFunc, $db_prefix;
727
728
	$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
729
730
	$result = $smcFunc['db_query']('', '
731
		SELECT column_name, column_default, is_nullable, data_type, character_maximum_length
732
		FROM information_schema.columns
733
		WHERE table_name = \'' . $table_name . '\'
734
		ORDER BY ordinal_position',
735
		array(
736
			'security_override' => true,
737
		)
738
	);
739
	$columns = array();
740
	while ($row = $smcFunc['db_fetch_assoc']($result))
741
	{
742
		if (!$detail)
743
		{
744
			$columns[] = $row['column_name'];
745
		}
746
		else
747
		{
748
			$auto = false;
749
			// What is the default?
750
			if (preg_match('~nextval\(\'(.+?)\'(.+?)*\)~i', $row['column_default'], $matches) != 0)
751
			{
752
				$default = null;
753
				$auto = true;
754
			}
755
			elseif (trim($row['column_default']) != '')
756
				$default = strpos($row['column_default'], '::') === false ? $row['column_default'] : substr($row['column_default'], 0, strpos($row['column_default'], '::'));
757
			else
758
				$default = null;
759
760
			// Make the type generic.
761
			list ($type, $size) = $smcFunc['db_calculate_type']($row['data_type'], $row['character_maximum_length'], true);
762
763
			$columns[$row['column_name']] = array(
764
				'name' => $row['column_name'],
765
				'null' => $row['is_nullable'] ? true : false,
766
				'default' => $default,
767
				'type' => $type,
768
				'size' => $size,
769
				'auto' => $auto,
770
			);
771
		}
772
	}
773
	$smcFunc['db_free_result']($result);
774
775
	return $columns;
776
}
777
778
/**
779
 * Get index information.
780
 *
781
 * @param string $table_name The name of the table to get indexes for
782
 * @param bool $detail Whether or not to return detailed info.
783
 * @param array $parameters Not used?
784
 * @return array An array of index names or a detailed array of index info, depending on $detail
785
 */
786
function smf_db_list_indexes($table_name, $detail = false, $parameters = array())
0 ignored issues
show
The function smf_db_list_indexes() has been defined more than once; this definition is ignored, only the first definition in Sources/DbPackages-mysql.php (L653-703) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
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...
787
{
788
	global $smcFunc, $db_prefix;
789
790
	$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
791
792
	$result = $smcFunc['db_query']('', '
793
		SELECT CASE WHEN i.indisprimary THEN 1 ELSE 0 END AS is_primary,
794
			CASE WHEN i.indisunique THEN 1 ELSE 0 END AS is_unique,
795
			c2.relname AS name,
796
			pg_get_indexdef(i.indexrelid) AS inddef
797
		FROM pg_class AS c, pg_class AS c2, pg_index AS i
798
		WHERE c.relname = \'' . $table_name . '\'
799
			AND c.oid = i.indrelid
800
			AND i.indexrelid = c2.oid',
801
		array(
802
			'security_override' => true,
803
		)
804
	);
805
	$indexes = array();
806
	while ($row = $smcFunc['db_fetch_assoc']($result))
807
	{
808
		// Try get the columns that make it up.
809
		if (preg_match('~\(([^\)]+?)\)~i', $row['inddef'], $matches) == 0)
810
			continue;
811
812
		$columns = explode(',', $matches[1]);
813
814
		if (empty($columns))
815
			continue;
816
817
		foreach ($columns as $k => $v)
818
			$columns[$k] = trim($v);
819
820
		// Fix up the name to be consistent cross databases
821
		if (substr($row['name'], -5) == '_pkey' && $row['is_primary'] == 1)
822
			$row['name'] = 'PRIMARY';
823
		else
824
			$row['name'] = str_replace($table_name . '_', '', $row['name']);
825
826
		if (!$detail)
827
			$indexes[] = $row['name'];
828
		else
829
		{
830
			$indexes[$row['name']] = array(
831
				'name' => $row['name'],
832
				'type' => $row['is_primary'] ? 'primary' : ($row['is_unique'] ? 'unique' : 'index'),
833
				'columns' => $columns,
834
			);
835
		}
836
	}
837
	$smcFunc['db_free_result']($result);
838
839
	return $indexes;
840
}
841
842
?>
0 ignored issues
show
It is not recommended to use PHP's closing tag ?> in files other than templates.

Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.

A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.

Loading history...