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

Sources/DbExtra-postgresql.php (9 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 rarely used extended database functionality.
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 functions implemented in this file to the $smcFunc array.
21
 */
22
function db_extra_init()
0 ignored issues
show
The function db_extra_init() has been defined more than once; this definition is ignored, only the first definition in Sources/DbExtra-mysql.php (L22-35) 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...
23
{
24
	global $smcFunc;
25
26 View Code Duplication
	if (!isset($smcFunc['db_backup_table']) || $smcFunc['db_backup_table'] != 'smf_db_backup_table')
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...
27
		$smcFunc += array(
28
			'db_backup_table' => 'smf_db_backup_table',
29
			'db_optimize_table' => 'smf_db_optimize_table',
30
			'db_table_sql' => 'smf_db_table_sql',
31
			'db_list_tables' => 'smf_db_list_tables',
32
			'db_get_version' => 'smf_db_get_version',
33
			'db_get_engine' => 'smf_db_get_engine',
34
		);
35
}
36
37
/**
38
 * Backup $table to $backup_table.
39
 * @param string $table The name of the table to backup
40
 * @param string $backup_table The name of the backup table for this table
41
 * @return resource -the request handle to the table creation query
42
 */
43
function smf_db_backup_table($table, $backup_table)
0 ignored issues
show
The function smf_db_backup_table() has been defined more than once; this definition is ignored, only the first definition in Sources/DbExtra-mysql.php (L43-168) 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...
44
{
45
	global $smcFunc, $db_prefix;
46
47
	$table = str_replace('{db_prefix}', $db_prefix, $table);
48
49
	// Do we need to drop it first?
50
	$tables = smf_db_list_tables(false, $backup_table);
51
	if (!empty($tables))
52
		$smcFunc['db_query']('', '
53
			DROP TABLE {raw:backup_table}',
54
			array(
55
				'backup_table' => $backup_table,
56
			)
57
		);
58
59
	/**
60
	 * @todo Should we create backups of sequences as well?
61
	 */
62
	$smcFunc['db_query']('', '
63
		CREATE TABLE {raw:backup_table}
64
		(
65
			LIKE {raw:table}
66
			INCLUDING DEFAULTS
67
		)',
68
		array(
69
			'backup_table' => $backup_table,
70
			'table' => $table,
71
		)
72
	);
73
	$smcFunc['db_query']('', '
74
		INSERT INTO {raw:backup_table}
75
		SELECT * FROM {raw:table}',
76
		array(
77
			'backup_table' => $backup_table,
78
			'table' => $table,
79
		)
80
	);
81
}
82
83
/**
84
 * This function optimizes a table.
85
 * @param string $table The table to be optimized
86
 * @return int How much space was gained
87
 */
88
function smf_db_optimize_table($table)
0 ignored issues
show
The function smf_db_optimize_table() has been defined more than once; this definition is ignored, only the first definition in Sources/DbExtra-mysql.php (L175-214) 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...
89
{
90
	global $smcFunc, $db_prefix;
91
92
	$table = str_replace('{db_prefix}', $db_prefix, $table);
93
94
	$pg_tables = array('pg_catalog','information_schema');
95
96
	$request = $smcFunc['db_query']('', '
97
		SELECT pg_relation_size(C.oid) AS "size"
98
		FROM pg_class C
99
		LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
100
		WHERE nspname NOT IN ({array_string:pg_tables})
101
		and relname = {string:table}',
102
		array(
103
			'table' => $table,
104
			'pg_tables' => $pg_tables,
105
		)
106
	);
107
108
	$row = $smcFunc['db_fetch_assoc']($request);
109
	$smcFunc['db_free_result']($request);
110
111
	$old_size = $row['size'];
112
113
	$request = $smcFunc['db_query']('', '
114
			VACUUM FULL ANALYZE {raw:table}',
115
			array(
116
				'table' => $table,
117
			)
118
		);
119
120
	if (!$request)
121
		return -1;
122
123
	$request = $smcFunc['db_query']('', '
124
		SELECT pg_relation_size(C.oid) AS "size"
125
		FROM pg_class C
126
		LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
127
		WHERE nspname NOT IN ({array_string:pg_tables})
128
		and relname = {string:table}',
129
		array(
130
			'table' => $table,
131
			'pg_tables' => $pg_tables,
132
		)
133
	);
134
135
136
	$row = $smcFunc['db_fetch_assoc']($request);
137
	$smcFunc['db_free_result']($request);
138
139
	if (isset($row['size']))
140
			return ($old_size - $row['size']) / 1024;
141
	else
142
		return 0;
143
}
144
145
/**
146
 * This function lists all tables in the database.
147
 * The listing could be filtered according to $filter.
148
 *
149
 * @param string|boolean $db string The database name or false to use the current DB
150
 * @param string|boolean $filter String to filter by or false to list all tables
151
 * @return array An array of table names
152
 */
153
function smf_db_list_tables($db = false, $filter = false)
0 ignored issues
show
The function smf_db_list_tables() has been defined more than once; this definition is ignored, only the first definition in Sources/DbExtra-mysql.php (L224-247) 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 $db 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...
154
{
155
	global $smcFunc;
156
157
	$request = $smcFunc['db_query']('', '
158
		SELECT tablename
159
		FROM pg_tables
160
		WHERE schemaname = {string:schema_public}' . ($filter == false ? '' : '
161
			AND tablename LIKE {string:filter}') . '
162
		ORDER BY tablename',
163
		array(
164
			'schema_public' => 'public',
165
			'filter' => $filter,
166
		)
167
	);
168
169
	$tables = array();
170
	while ($row = $smcFunc['db_fetch_row']($request))
171
		$tables[] = $row[0];
172
	$smcFunc['db_free_result']($request);
173
174
	return $tables;
175
}
176
177
/**
178
 * Dumps the schema (CREATE) for a table.
179
 * @todo why is this needed for?
180
 * @param string $tableName The name of the table
181
 * @return string The "CREATE TABLE" SQL string for this table
182
 */
183
function smf_db_table_sql($tableName)
0 ignored issues
show
The function smf_db_table_sql() has been defined more than once; this definition is ignored, only the first definition in Sources/DbExtra-mysql.php (L255-358) 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...
184
{
185
	global $smcFunc, $db_prefix;
186
187
	$tableName = str_replace('{db_prefix}', $db_prefix, $tableName);
188
189
	// This will be needed...
190
	$crlf = "\r\n";
191
192
	// Drop it if it exists.
193
	$schema_create = 'DROP TABLE IF EXISTS ' . $tableName . ';' . $crlf . $crlf;
194
195
	// Start the create table...
196
	$schema_create .= 'CREATE TABLE ' . $tableName . ' (' . $crlf;
197
	$index_create = '';
198
	$seq_create = '';
199
200
	// Find all the fields.
201
	$result = $smcFunc['db_query']('', '
202
		SELECT column_name, column_default, is_nullable, data_type, character_maximum_length
203
		FROM information_schema.columns
204
		WHERE table_name = {string:table}
205
		ORDER BY ordinal_position',
206
		array(
207
			'table' => $tableName,
208
		)
209
	);
210
	while ($row = $smcFunc['db_fetch_assoc']($result))
211
	{
212
		if ($row['data_type'] == 'character varying')
213
			$row['data_type'] = 'varchar';
214
		elseif ($row['data_type'] == 'character')
215
			$row['data_type'] = 'char';
216
		if ($row['character_maximum_length'])
217
			$row['data_type'] .= '(' . $row['character_maximum_length'] . ')';
218
219
		// Make the CREATE for this column.
220
		$schema_create .= ' "' . $row['column_name'] . '" ' . $row['data_type'] . ($row['is_nullable'] != 'YES' ? ' NOT NULL' : '');
221
222
		// Add a default...?
223
		if (trim($row['column_default']) != '')
224
		{
225
			$schema_create .= ' default ' . $row['column_default'] . '';
226
227
			// Auto increment?
228
			if (preg_match('~nextval\(\'(.+?)\'(.+?)*\)~i', $row['column_default'], $matches) != 0)
229
			{
230
				// Get to find the next variable first!
231
				$count_req = $smcFunc['db_query']('', '
232
					SELECT MAX("{raw:column}")
233
					FROM {raw:table}',
234
					array(
235
						'column' => $row['column_name'],
236
						'table' => $tableName,
237
					)
238
				);
239
				list ($max_ind) = $smcFunc['db_fetch_row']($count_req);
240
				$smcFunc['db_free_result']($count_req);
241
				// Get the right bloody start!
242
				$seq_create .= 'CREATE SEQUENCE ' . $matches[1] . ' START WITH ' . ($max_ind + 1) . ';' . $crlf . $crlf;
243
			}
244
		}
245
246
		$schema_create .= ',' . $crlf;
247
	}
248
	$smcFunc['db_free_result']($result);
249
250
	// Take off the last comma.
251
	$schema_create = substr($schema_create, 0, -strlen($crlf) - 1);
252
253
	$result = $smcFunc['db_query']('', '
254
		SELECT CASE WHEN i.indisprimary THEN 1 ELSE 0 END AS is_primary, pg_get_indexdef(i.indexrelid) AS inddef
255
		FROM pg_class AS c
256
			INNER JOIN pg_index AS i ON (i.indrelid = c.oid)
257
			INNER JOIN pg_class AS c2 ON (c2.oid = i.indexrelid)
258
		WHERE c.relname = {string:table}',
259
		array(
260
			'table' => $tableName,
261
		)
262
	);
263
264
	while ($row = $smcFunc['db_fetch_assoc']($result))
265
	{
266
		if ($row['is_primary'])
267
		{
268
			if (preg_match('~\(([^\)]+?)\)~i', $row['inddef'], $matches) == 0)
269
				continue;
270
271
			$index_create .= $crlf . 'ALTER TABLE ' . $tableName . ' ADD PRIMARY KEY ("' . $matches[1] . '");';
272
		}
273
		else
274
			$index_create .= $crlf . $row['inddef'] . ';';
275
	}
276
	$smcFunc['db_free_result']($result);
277
278
	// Finish it off!
279
	$schema_create .= $crlf . ');';
280
281
	return $seq_create . $schema_create . $index_create;
282
}
283
284
/**
285
 *  Get the version number.
286
 *  @return string The version
287
 */
288
function smf_db_get_version()
0 ignored issues
show
The function smf_db_get_version() has been defined more than once; this definition is ignored, only the first definition in Sources/DbExtra-mysql.php (L364-382) 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...
289
{
290
	static $ver;
291
292
	if(!empty($ver))
293
		return $ver;
294
295
	global $smcFunc;
296
297
	$request = $smcFunc['db_query']('', '
298
		SHOW server_version',
299
		array(
300
		)
301
	);
302
	list ($ver) = $smcFunc['db_fetch_row']($request);
303
	$smcFunc['db_free_result']($request);
304
305
	return $ver;
306
}
307
308
/**
309
 * Return PostgreSQL
310
 *
311
 * @return string The database engine we are using
312
*/
313
function smf_db_get_engine()
314
{
315
	return 'PostgreSQL';
316
}
317
318
?>
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...