Passed
Push — develop ( 869758...563aca )
by Felipe
04:57
created

ADOdbBase::hasNamedParams()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
eloc 1
nc 1
nop 0
1
<?php
2
3
/**
4
 * PHPPgAdmin v6.0.0-beta.40
5
 */
6
7
namespace PHPPgAdmin\Database;
8
9
/**
10
 * @file
11
 * Parent class of all ADODB objects.
12
 *
13
 * Id: ADOdbBase.php,v 1.24 2008/02/20 20:43:10 ioguix Exp $
14
 *
15
 * @package PHPPgAdmin
16
 */
17
class ADOdbBase
18
{
19
    use \PHPPgAdmin\HelperTrait;
1 ignored issue
show
introduced by
The trait PHPPgAdmin\HelperTrait requires some properties which are not provided by PHPPgAdmin\Database\ADOdbBase: $responseobj, $requestobj
Loading history...
20
21
    public $conn;
22
23
    // The backend platform.  Set to UNKNOWN by default.
24
    public $platform = 'UNKNOWN';
25
26
    public $major_version = 9.6;
27
    // Max object name length
28
    public $_maxNameLen = 63;
1 ignored issue
show
Coding Style introduced by
Public member variable "_maxNameLen" must not be prefixed with an underscore
Loading history...
29
    // Store the current schema
30
    public $_schema;
1 ignored issue
show
Coding Style introduced by
Public member variable "_schema" must not be prefixed with an underscore
Loading history...
31
    // Map of database encoding names to HTTP encoding names.  If a
32
    // database encoding does not appear in this list, then its HTTP
33
    // encoding name is the same as its database encoding name.
34
    public $codemap = [
35
        'BIG5'       => 'BIG5',
36
        'EUC_CN'     => 'GB2312',
37
        'EUC_JP'     => 'EUC-JP',
38
        'EUC_KR'     => 'EUC-KR',
39
        'EUC_TW'     => 'EUC-TW',
40
        'GB18030'    => 'GB18030',
41
        'GBK'        => 'GB2312',
42
        'ISO_8859_5' => 'ISO-8859-5',
43
        'ISO_8859_6' => 'ISO-8859-6',
44
        'ISO_8859_7' => 'ISO-8859-7',
45
        'ISO_8859_8' => 'ISO-8859-8',
46
        'JOHAB'      => 'CP1361',
47
        'KOI8'       => 'KOI8-R',
48
        'LATIN1'     => 'ISO-8859-1',
49
        'LATIN2'     => 'ISO-8859-2',
50
        'LATIN3'     => 'ISO-8859-3',
51
        'LATIN4'     => 'ISO-8859-4',
52
        'LATIN5'     => 'ISO-8859-9',
53
        'LATIN6'     => 'ISO-8859-10',
54
        'LATIN7'     => 'ISO-8859-13',
55
        'LATIN8'     => 'ISO-8859-14',
56
        'LATIN9'     => 'ISO-8859-15',
57
        'LATIN10'    => 'ISO-8859-16',
58
        'SJIS'       => 'SHIFT_JIS',
59
        'SQL_ASCII'  => 'US-ASCII',
60
        'UHC'        => 'WIN949',
61
        'UTF8'       => 'UTF-8',
62
        'WIN866'     => 'CP866',
63
        'WIN874'     => 'CP874',
64
        'WIN1250'    => 'CP1250',
65
        'WIN1251'    => 'CP1251',
66
        'WIN1252'    => 'CP1252',
67
        'WIN1256'    => 'CP1256',
68
        'WIN1258'    => 'CP1258',
69
    ];
70
    public $defaultprops = ['', '', ''];
71
    // Extra "magic" types.  BIGSERIAL was added in PostgreSQL 7.2.
72
    public $extraTypes = ['SERIAL', 'BIGSERIAL'];
73
    // Foreign key stuff.  First element MUST be the default.
74
    public $fkactions    = ['NO ACTION', 'RESTRICT', 'CASCADE', 'SET NULL', 'SET DEFAULT'];
75
    public $fkdeferrable = ['NOT DEFERRABLE', 'DEFERRABLE'];
76
    public $fkinitial    = ['INITIALLY IMMEDIATE', 'INITIALLY DEFERRED'];
77
    public $fkmatches    = ['MATCH SIMPLE', 'MATCH FULL'];
78
    // Function properties
79
    public $funcprops = [
80
        ['', 'VOLATILE', 'IMMUTABLE', 'STABLE'],
81
        ['', 'CALLED ON NULL INPUT', 'RETURNS NULL ON NULL INPUT'],
82
        ['', 'SECURITY INVOKER', 'SECURITY DEFINER'],
83
    ];
84
85
    // Default help URL
86
    public $help_base;
87
    // Help sub pages
88
    public $help_page;
89
    // Name of id column
90
    public $id = 'oid';
91
92
    // Supported join operations for use with view wizard
93
    public $joinOps = ['INNER JOIN' => 'INNER JOIN', 'LEFT JOIN' => 'LEFT JOIN', 'RIGHT JOIN' => 'RIGHT JOIN', 'FULL JOIN' => 'FULL JOIN'];
94
    // Map of internal language name to syntax highlighting name
95
    public $langmap = [
96
        'sql'       => 'SQL',
97
        'plpgsql'   => 'SQL',
98
        'php'       => 'PHP',
99
        'phpu'      => 'PHP',
100
        'plphp'     => 'PHP',
101
        'plphpu'    => 'PHP',
102
        'perl'      => 'Perl',
103
        'perlu'     => 'Perl',
104
        'plperl'    => 'Perl',
105
        'plperlu'   => 'Perl',
106
        'java'      => 'Java',
107
        'javau'     => 'Java',
108
        'pljava'    => 'Java',
109
        'pljavau'   => 'Java',
110
        'plj'       => 'Java',
111
        'plju'      => 'Java',
112
        'python'    => 'Python',
113
        'pythonu'   => 'Python',
114
        'plpython'  => 'Python',
115
        'plpythonu' => 'Python',
116
        'ruby'      => 'Ruby',
117
        'rubyu'     => 'Ruby',
118
        'plruby'    => 'Ruby',
119
        'plrubyu'   => 'Ruby',
120
    ];
121
    // Predefined size types
122
    public $predefined_size_types = [
123
        'abstime',
124
        'aclitem',
125
        'bigserial',
126
        'boolean',
127
        'bytea',
128
        'cid',
129
        'cidr',
130
        'circle',
131
        'date',
132
        'float4',
133
        'float8',
134
        'gtsvector',
135
        'inet',
136
        'int2',
137
        'int4',
138
        'int8',
139
        'macaddr',
140
        'money',
141
        'oid',
142
        'path',
143
        'polygon',
144
        'refcursor',
145
        'regclass',
146
        'regoper',
147
        'regoperator',
148
        'regproc',
149
        'regprocedure',
150
        'regtype',
151
        'reltime',
152
        'serial',
153
        'smgr',
154
        'text',
155
        'tid',
156
        'tinterval',
157
        'tsquery',
158
        'tsvector',
159
        'varbit',
160
        'void',
161
        'xid',
162
    ];
163
    // List of all legal privileges that can be applied to different types
164
    // of objects.
165
    public $privlist = [
166
        'table'      => ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'REFERENCES', 'TRIGGER', 'ALL PRIVILEGES'],
167
        'view'       => ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'REFERENCES', 'TRIGGER', 'ALL PRIVILEGES'],
168
        'sequence'   => ['SELECT', 'UPDATE', 'ALL PRIVILEGES'],
169
        'database'   => ['CREATE', 'TEMPORARY', 'CONNECT', 'ALL PRIVILEGES'],
170
        'function'   => ['EXECUTE', 'ALL PRIVILEGES'],
171
        'language'   => ['USAGE', 'ALL PRIVILEGES'],
172
        'schema'     => ['CREATE', 'USAGE', 'ALL PRIVILEGES'],
173
        'tablespace' => ['CREATE', 'ALL PRIVILEGES'],
174
        'column'     => ['SELECT', 'INSERT', 'UPDATE', 'REFERENCES', 'ALL PRIVILEGES'],
175
    ];
176
    // List of characters in acl lists and the privileges they
177
    // refer to.
178
    public $privmap = [
179
        'r' => 'SELECT',
180
        'w' => 'UPDATE',
181
        'a' => 'INSERT',
182
        'd' => 'DELETE',
183
        'D' => 'TRUNCATE',
184
        'R' => 'RULE',
185
        'x' => 'REFERENCES',
186
        't' => 'TRIGGER',
187
        'X' => 'EXECUTE',
188
        'U' => 'USAGE',
189
        'C' => 'CREATE',
190
        'T' => 'TEMPORARY',
191
        'c' => 'CONNECT',
192
    ];
193
    // Rule action types
194
    public $rule_events = ['SELECT', 'INSERT', 'UPDATE', 'DELETE'];
195
    // Select operators
196
    public $selectOps = [
197
        '='                   => 'i',
198
        '!='                  => 'i',
199
        '<'                   => 'i',
200
        '>'                   => 'i',
201
        '<='                  => 'i',
202
        '>='                  => 'i',
203
        '<<'                  => 'i',
204
        '>>'                  => 'i',
205
        '<<='                 => 'i',
206
        '>>='                 => 'i',
207
        'LIKE'                => 'i',
208
        'NOT LIKE'            => 'i',
209
        'ILIKE'               => 'i',
210
        'NOT ILIKE'           => 'i',
211
        'SIMILAR TO'          => 'i',
212
        'NOT SIMILAR TO'      => 'i',
213
        '~'                   => 'i',
214
        '!~'                  => 'i',
215
        '~*'                  => 'i',
216
        '!~*'                 => 'i',
217
        'IS NULL'             => 'p',
218
        'IS NOT NULL'         => 'p',
219
        'IN'                  => 'x',
220
        'NOT IN'              => 'x',
221
        '@@'                  => 'i',
222
        '@@@'                 => 'i',
223
        '@>'                  => 'i',
224
        '<@'                  => 'i',
225
        '@@ to_tsquery'       => 't',
226
        '@@@ to_tsquery'      => 't',
227
        '@> to_tsquery'       => 't',
228
        '<@ to_tsquery'       => 't',
229
        '@@ plainto_tsquery'  => 't',
230
        '@@@ plainto_tsquery' => 't',
231
        '@> plainto_tsquery'  => 't',
232
        '<@ plainto_tsquery'  => 't',
233
    ];
234
    // Array of allowed trigger events
235
    public $triggerEvents = [
236
        'INSERT',
237
        'UPDATE',
238
        'DELETE',
239
        'INSERT OR UPDATE',
240
        'INSERT OR DELETE',
241
        'DELETE OR UPDATE',
242
        'INSERT OR DELETE OR UPDATE',
243
    ];
244
    // When to execute the trigger
245
    public $triggerExecTimes = ['BEFORE', 'AFTER'];
246
    // How often to execute the trigger
247
    public $triggerFrequency = ['ROW', 'STATEMENT'];
248
    // Array of allowed type alignments
249
    public $typAligns = ['char', 'int2', 'int4', 'double'];
250
    // The default type alignment
251
    public $typAlignDef = 'int4';
252
    // Default index type
253
    public $typIndexDef = 'BTREE';
254
    // Array of allowed index types
255
    public $typIndexes = ['BTREE', 'RTREE', 'GIST', 'GIN', 'HASH'];
256
    // Array of allowed type storage attributes
257
    public $typStorages = ['plain', 'external', 'extended', 'main'];
258
    // The default type storage
259
    public $typStorageDef = 'plain';
260
261
    public $lang;
262
    public $conf;
263
    protected $container;
264
    /**
265
     * Base constructor.
266
     *
267
     * @param \ADONewConnection &$conn The connection object
0 ignored issues
show
Bug introduced by
The type ADONewConnection was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
Coding Style introduced by
Doc comment for parameter &$conn does not match actual variable name $conn
Loading history...
268
     */
269
    public function __construct(&$conn, $container)
270
    {
271
        $this->container = $container;
272
273
        $this->lang = $container->get('lang');
274
        $this->conf = $container->get('conf');
275
276
        $this->prtrace('instanced connection class');
277
        $this->conn = $conn;
278
    }
279
280
    /**
281
     * Sets the comment for an object in the database.
0 ignored issues
show
Bug introduced by
The type PHPPgAdmin\Database\the was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
282
     *
283
     * @pre All parameters must already be cleaned
284
     *
285
     * @param      $obj_type One of 'TABLE' | 'COLUMN' | 'VIEW' | 'SCHEMA' | 'SEQUENCE' | 'TYPE' | 'FUNCTION' | 'AGGREGATE'
1 ignored issue
show
Bug introduced by
The type PHPPgAdmin\Database\One was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
Coding Style introduced by
Parameter tags must be defined first in a doc comment
Loading history...
286
     * @param      $obj_name the name of the object for which to attach a comment
287
     * @param      $table    Name of table that $obj_name belongs to.  Ignored unless $obj_type is 'TABLE' or 'COLUMN'.
0 ignored issues
show
Bug introduced by
The type PHPPgAdmin\Database\Name was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
Coding Style introduced by
Doc comment for parameter $obj_name does not match actual variable name $table
Loading history...
288
     * @param      $comment  the comment to add
289
     * @param null $basetype
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $basetype is correct as it would always require null to be passed?
Loading history...
290
     *
291
     * @return int 0 if operation was successful
292
     */
293
    public function setComment($obj_type, $obj_name, $table, $comment, $basetype = null)
294
    {
295
        $sql      = "COMMENT ON {$obj_type} ";
296
        $f_schema = $this->_schema;
297
        $this->fieldClean($f_schema);
298
        $this->clean($comment); // Passing in an already cleaned comment will lead to double escaped data
299
        // So, while counter-intuitive, it is important to not clean comments before
300
        // calling setComment. We will clean it here instead.
301
        /*
302
        $this->fieldClean($table);
303
        $this->fieldClean($obj_name);
304
         */
305
306
        switch ($obj_type) {
307
            case 'TABLE':
308
                $sql .= "\"{$f_schema}\".\"{$table}\" IS ";
309
310
                break;
311
            case 'COLUMN':
312
                $sql .= "\"{$f_schema}\".\"{$table}\".\"{$obj_name}\" IS ";
313
314
                break;
315
            case 'SEQUENCE':
316
            case 'VIEW':
317
            case 'TEXT SEARCH CONFIGURATION':
318
            case 'TEXT SEARCH DICTIONARY':
319
            case 'TEXT SEARCH TEMPLATE':
320
            case 'TEXT SEARCH PARSER':
321
            case 'TYPE':
322
                $sql .= "\"{$f_schema}\".";
323
            // no break
324
            case 'DATABASE':
325
            case 'ROLE':
326
            case 'SCHEMA':
327
            case 'TABLESPACE':
328
                $sql .= "\"{$obj_name}\" IS ";
329
330
                break;
331
            case 'FUNCTION':
332
                $sql .= "\"{$f_schema}\".{$obj_name} IS ";
333
334
                break;
335
            case 'AGGREGATE':
336
                $sql .= "\"{$f_schema}\".\"{$obj_name}\" (\"{$basetype}\") IS ";
337
338
                break;
339
            default:
340
                // Unknown object type
341
                return -1;
342
        }
343
344
        if ($comment != '') {
345
            $sql .= "'{$comment}';";
346
        } else {
347
            $sql .= 'NULL;';
348
        }
349
350
        return $this->execute($sql);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->execute($sql) returns the type ADORecordSet which is incompatible with the documented return type integer.
Loading history...
351
    }
352
353
    /**
354
     * Turns on or off query debugging.
355
     *
356
     * @param $debug True to turn on debugging, false otherwise
357
     */
358
    public function setDebug($debug)
359
    {
360
        $this->conn->debug = $debug;
361
    }
362
363
    /**
364
     * Cleans (escapes) an array.
365
     *
366
     * @param $arr The array to clean, by reference
0 ignored issues
show
Bug introduced by
The type PHPPgAdmin\Database\The was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
367
     *
368
     * @return The cleaned array
369
     */
370
    public function arrayClean(&$arr)
371
    {
372
        reset($arr);
373
        //while (list($k, $v) = each($arr)) {
374
        foreach ($arr as $k => $v) {
375
            $arr[$k] = addslashes($v);
376
        }
377
378
        return $arr;
379
    }
380
381
    /**
382
     * Executes a query on the underlying connection.
383
     *
384
     * @param $sql The SQL query to execute
385
     *
386
     * @return \ADORecordSet A recordset
387
     */
388
    public function execute($sql)
389
    {
390
        // Execute the statement
391
        $rs = $this->conn->Execute($sql);
1 ignored issue
show
Unused Code introduced by
The assignment to $rs is dead and can be removed.
Loading history...
392
393
        // If failure, return error value
394
        return $this->conn->ErrorNo();
395
    }
396
397
    /**
398
     * Closes the connection the database class
399
     * relies on.
400
     */
401
    public function close()
402
    {
403
        $this->conn->close();
404
    }
405
406
    /**
407
     * Retrieves a ResultSet from a query.
408
     *
409
     * @param $sql The SQL statement to be executed
410
     *
411
     * @return \ADORecordSet A recordset
412
     */
413
    public function selectSet($sql)
414
    {
415
        // Execute the statement
416
        $rs = $this->conn->Execute($sql);
417
418
        if (!$rs) {
419
            return $this->conn->ErrorNo();
420
        }
421
422
        return $rs;
423
    }
424
425
    /**
426
     * Retrieves a single value from a query.
427
     *
428
     * @@ assumes that the query will return only one row - returns field value in the first row
429
     *
430
     * @param $sql   The SQL statement to be executed
1 ignored issue
show
Coding Style introduced by
Parameter tags must be defined first in a doc comment
Loading history...
431
     * @param $field The field name to be returned
432
     *
433
     * @return A  single field value
434
     * @return -1 No rows were found
0 ignored issues
show
Coding Style introduced by
Only 1 @return tag is allowed in a function comment
Loading history...
435
     */
436
    public function selectField($sql, $field)
437
    {
438
        // Execute the statement
439
        $rs = $this->conn->Execute($sql);
440
441
        // If failure, or no rows returned, return error value
442
        if (!$rs) {
443
            return $this->conn->ErrorNo();
444
        }
445
446
        if ($rs->RecordCount() == 0) {
447
            return -1;
0 ignored issues
show
Bug Best Practice introduced by
The expression return -1 returns the type integer which is incompatible with the documented return type PHPPgAdmin\Database\A.
Loading history...
448
        }
449
450
        return $rs->fields[$field];
451
    }
452
453
    /**
454
     * Delete from the database.
455
     *
456
     * @param        $table      The name of the table
457
     * @param        $conditions (array) A map of field names to conditions
458
     * @param string $schema     (optional) The table's schema
459
     *
460
     * @return int 0 success
461
     */
462
    public function delete($table, $conditions, $schema = '')
463
    {
464
        $this->fieldClean($table);
465
466
        reset($conditions);
467
468
        if (!empty($schema)) {
469
            $this->fieldClean($schema);
470
            $schema = "\"{$schema}\".";
471
        }
472
473
        // Build clause
474
        $sql = '';
475
        //while (list($key, $value) = each($conditions)) {
476
        foreach ($conditions as $key => $value) {
477
            $this->clean($key);
478
            $this->clean($value);
479
            if ($sql) {
480
                $sql .= " AND \"{$key}\"='{$value}'";
481
            } else {
482
                $sql = "DELETE FROM {$schema}\"{$table}\" WHERE \"{$key}\"='{$value}'";
483
            }
484
        }
485
486
        // Check for failures
487
        if (!$this->conn->Execute($sql)) {
488
            // Check for referential integrity failure
489
            if (stristr($this->conn->ErrorMsg(), 'referential')) {
490
                return -1;
491
            }
492
        }
493
494
        // Check for no rows modified
495
        if ($this->conn->Affected_Rows() == 0) {
496
            return -2;
497
        }
498
499
        return $this->conn->ErrorNo();
500
    }
501
502
    /**
503
     * Cleans (escapes) an object name (eg. table, field).
504
     *
505
     * @param $str The string to clean, by reference
506
     *
507
     * @return The cleaned string
508
     */
509
    public function fieldClean(&$str)
510
    {
511
        $str = str_replace('"', '""', $str);
512
513
        return $str;
514
    }
515
516
    /**
517
     * Cleans (escapes) a string.
518
     *
519
     * @param string $str The string to clean, by reference
520
     *
521
     * @return string The cleaned string
522
     */
523
    public function clean(&$str)
524
    {
525
        $str = addslashes($str);
526
527
        return $str;
528
    }
529
530
    /**
531
     * Escapes bytea data for display on the screen.
532
     *
533
     * @param string $data The bytea data
534
     *
535
     * @return string Data formatted for on-screen display
536
     */
537
    public function escapeBytea($data)
538
    {
539
        return htmlentities($data, ENT_QUOTES, 'UTF-8');
540
    }
541
542
    /**
543
     * Insert a set of values into the database.
544
     *
545
     * @param $table The table to insert into
546
     * @param $vars  (array) A mapping of the field names to the values to be inserted
547
     *
548
     * @return int 0 success
549
     */
550
    public function insert($table, $vars)
551
    {
552
        $this->fieldClean($table);
553
554
        // Build clause
555
        if (sizeof($vars) > 0) {
556
            $fields = '';
557
            $values = '';
558
            foreach ($vars as $key => $value) {
559
                $this->clean($key);
560
                $this->clean($value);
561
562
                if ($fields) {
563
                    $fields .= ", \"{$key}\"";
564
                } else {
565
                    $fields = "INSERT INTO \"{$table}\" (\"{$key}\"";
566
                }
567
568
                if ($values) {
569
                    $values .= ", '{$value}'";
570
                } else {
571
                    $values = ") VALUES ('{$value}'";
572
                }
573
            }
574
            $sql = $fields . $values . ')';
575
        }
576
577
        // Check for failures
578
        if (!$this->conn->Execute($sql)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $sql does not seem to be defined for all execution paths leading up to this point.
Loading history...
579
            // Check for unique constraint failure
580
            if (stristr($this->conn->ErrorMsg(), 'unique')) {
581
                return -1;
582
            }
583
584
            if (stristr($this->conn->ErrorMsg(), 'referential')) {
585
                return -2;
586
            } // Check for referential integrity failure
587
        }
588
589
        return $this->conn->ErrorNo();
590
    }
591
592
    /**
593
     * Update a row in the database.
594
     *
595
     * @param       $table The table that is to be updated
596
     * @param       $vars  (array) A mapping of the field names to the values to be updated
597
     * @param       $where (array) A mapping of field names to values for the where clause
598
     * @param array $nulls (array, optional) An array of fields to be set null
599
     *
600
     * @return int 0 success
601
     */
602
    public function update($table, $vars, $where, $nulls = [])
603
    {
604
        $this->fieldClean($table);
605
606
        $setClause   = '';
607
        $whereClause = '';
608
609
        // Populate the syntax arrays
610
        reset($vars);
611
        //while (list($key, $value) = each($vars)) {
612
        foreach ($vars as $key => $value) {
613
            $this->fieldClean($key);
614
            $this->clean($value);
615
            if ($setClause) {
616
                $setClause .= ", \"{$key}\"='{$value}'";
617
            } else {
618
                $setClause = "UPDATE \"{$table}\" SET \"{$key}\"='{$value}'";
619
            }
620
        }
621
622
        reset($nulls);
623
        //while (list(, $value) = each($nulls)) {
624
        foreach ($nulls as $key => $value) {
625
            $this->fieldClean($value);
626
            if ($setClause) {
627
                $setClause .= ", \"{$value}\"=NULL";
628
            } else {
629
                $setClause = "UPDATE \"{$table}\" SET \"{$value}\"=NULL";
630
            }
631
        }
632
633
        reset($where);
634
        //while (list($key, $value) = each($where)) {
635
        foreach ($where as $key => $value) {
636
            $this->fieldClean($key);
637
            $this->clean($value);
638
            if ($whereClause) {
639
                $whereClause .= " AND \"{$key}\"='{$value}'";
640
            } else {
641
                $whereClause = " WHERE \"{$key}\"='{$value}'";
642
            }
643
        }
644
645
        // Check for failures
646
        if (!$this->conn->Execute($setClause . $whereClause)) {
647
            // Check for unique constraint failure
648
            if (stristr($this->conn->ErrorMsg(), 'unique')) {
649
                return -1;
650
            }
651
652
            if (stristr($this->conn->ErrorMsg(), 'referential')) {
653
                return -2;
654
            } // Check for referential integrity failure
655
        }
656
657
        // Check for no rows modified
658
        if ($this->conn->Affected_Rows() == 0) {
659
            return -3;
660
        }
661
662
        return $this->conn->ErrorNo();
663
    }
664
665
    /**
666
     * Begin a transaction.
667
     *
668
     * @return bool 0 success
669
     */
670
    public function beginTransaction()
671
    {
672
        return !$this->conn->BeginTrans();
673
    }
674
675
    /**
676
     * End a transaction.
677
     *
678
     * @return bool 0 success
679
     */
680
    public function endTransaction()
681
    {
682
        return !$this->conn->CommitTrans();
683
    }
684
685
    /**
686
     * Roll back a transaction.
687
     *
688
     * @return bool 0 success
689
     */
690
    public function rollbackTransaction()
691
    {
692
        return !$this->conn->RollbackTrans();
693
    }
694
695
    /**
696
     * Get the backend platform.
697
     *
698
     * @return The backend platform
699
     */
700
    public function getPlatform()
701
    {
702
        //return $this->conn->platform;
703
        return 'UNKNOWN';
0 ignored issues
show
Bug Best Practice introduced by
The expression return 'UNKNOWN' returns the type string which is incompatible with the documented return type PHPPgAdmin\Database\The.
Loading history...
704
    }
705
706
    // Type conversion routines
707
708
    /**
709
     * Change the value of a parameter to database representation depending on whether it evaluates to true or false.
710
     *
711
     * @param $parameter the parameter
712
     *
713
     * @return \PHPPgAdmin\Database\the
714
     */
715
    public function dbBool(&$parameter)
716
    {
717
        return $parameter;
718
    }
719
720
    /**
721
     * Change a parameter from database representation to a boolean, (others evaluate to false).
722
     *
723
     * @param $parameter the parameter
724
     *
725
     * @return \PHPPgAdmin\Database\the
726
     */
727
    public function phpBool($parameter)
728
    {
729
        return $parameter;
730
    }
731
732
    /**
733
     * Change a db array into a PHP array.
734
     *
735
     * @param $dbarr
736
     *
737
     * @return array A PHP array
738
     *
739
     * @internal param String $arr representing the DB array
740
     */
741
    public function phpArray($dbarr)
742
    {
743
        // Take off the first and last characters (the braces)
744
        $arr = substr($dbarr, 1, strlen($dbarr) - 2);
745
746
        // Pick out array entries by carefully parsing.  This is necessary in order
747
        // to cope with double quotes and commas, etc.
748
        $elements  = [];
749
        $i         = $j         = 0;
750
        $in_quotes = false;
751
        while ($i < strlen($arr)) {
752
            // If current char is a double quote and it's not escaped, then
753
            // enter quoted bit
754
            $char = substr($arr, $i, 1);
755
            if ($char == '"' && ($i == 0 || substr($arr, $i - 1, 1) != '\\')) {
756
                $in_quotes = !$in_quotes;
1 ignored issue
show
introduced by
$in_quotes is of type mixed, thus it always evaluated to false.
Loading history...
757
            } elseif ($char == ',' && !$in_quotes) {
758
                // Add text so far to the array
759
                $elements[] = substr($arr, $j, $i - $j);
760
                $j          = $i + 1;
761
            }
762
            ++$i;
763
        }
764
        // Add final text to the array
765
        $elements[] = substr($arr, $j);
766
767
        // Do one further loop over the elements array to remote double quoting
768
        // and escaping of double quotes and backslashes
769
        for ($i = 0; $i < sizeof($elements); ++$i) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function sizeof() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
770
            $v = $elements[$i];
771
            if (strpos($v, '"') === 0) {
772
                $v            = substr($v, 1, strlen($v) - 2);
773
                $v            = str_replace('\\"', '"', $v);
774
                $v            = str_replace('\\\\', '\\', $v);
775
                $elements[$i] = $v;
776
            }
777
        }
778
779
        return $elements;
780
    }
781
782
    /**
783
     * Determines if it has tablespaces.
784
     *
785
     * @return bool true if has tablespaces, False otherwise
786
     */
787
    public function hasTablespaces()
788
    {
789
        return true;
790
    }
791
792
    /**
793
     * Determines if it has shared comments.
794
     *
795
     * @return bool true if has shared comments, False otherwise
796
     */
797
    public function hasSharedComments()
798
    {
799
        return true;
800
    }
801
802
    /**
803
     * Determines if it has roles.
804
     *
805
     * @return bool true if has roles, False otherwise
806
     */
807
    public function hasRoles()
808
    {
809
        return true;
810
    }
811
812
    /**
813
     * Determines if it has grant option.
814
     *
815
     * @return bool true if has grant option, False otherwise
816
     */
817
    public function hasGrantOption()
818
    {
819
        return true;
820
    }
821
822
    /**
823
     * Determines if it has create table like with constraints.
824
     *
825
     * @return bool true if has create table like with constraints, False otherwise
826
     */
827
    public function hasCreateTableLikeWithConstraints()
828
    {
829
        return true;
830
    }
831
832
    /**
833
     * Determines if it has create table like with indexes.
834
     *
835
     * @return bool true if has create table like with indexes, False otherwise
836
     */
837
    public function hasCreateTableLikeWithIndexes()
838
    {
839
        return true;
840
    }
841
842
    /**
843
     * Determines if it has create field with constraints.
844
     *
845
     * @return bool true if has create field with constraints, False otherwise
846
     */
847
    public function hasCreateFieldWithConstraints()
848
    {
849
        return true;
850
    }
851
852
    /**
853
     * Determines if it has domain constraints.
854
     *
855
     * @return bool true if has domain constraints, False otherwise
856
     */
857
    public function hasDomainConstraints()
858
    {
859
        return true;
860
    }
861
862
    /**
863
     * Determines if it has function alter owner.
864
     *
865
     * @return bool true if has function alter owner, False otherwise
866
     */
867
    public function hasFunctionAlterOwner()
868
    {
869
        return true;
870
    }
871
872
    /**
873
     * Determines if it has function alter schema.
874
     *
875
     * @return bool true if has function alter schema, False otherwise
876
     */
877
    public function hasFunctionAlterSchema()
878
    {
879
        return true;
880
    }
881
882
    /**
883
     * Determines if it has read only queries.
884
     *
885
     * @return bool true if has read only queries, False otherwise
886
     */
887
    public function hasReadOnlyQueries()
888
    {
889
        return true;
890
    }
891
892
    /**
893
     * Determines if it has aggregate sort operation.
894
     *
895
     * @return bool true if has aggregate sort operation, False otherwise
896
     */
897
    public function hasAggregateSortOp()
898
    {
899
        return true;
900
    }
901
902
    /**
903
     * Determines if it has alter aggregate.
904
     *
905
     * @return bool true if has alter aggregate, False otherwise
906
     */
907
    public function hasAlterAggregate()
908
    {
909
        return true;
910
    }
911
912
    /**
913
     * Determines if it has alter column type.
914
     *
915
     * @return bool true if has alter column type, False otherwise
916
     */
917
    public function hasAlterColumnType()
918
    {
919
        return true;
920
    }
921
922
    /**
923
     * Determines if it has alter database owner.
924
     *
925
     * @return bool true if has alter database owner, False otherwise
926
     */
927
    public function hasAlterDatabaseOwner()
928
    {
929
        return true;
930
    }
931
932
    /**
933
     * Determines if it has alter schema.
934
     *
935
     * @return bool true if has alter schema, False otherwise
936
     */
937
    public function hasAlterSchema()
938
    {
939
        return true;
940
    }
941
942
    /**
943
     * Determines if it has alter schema owner.
944
     *
945
     * @return bool true if has alter schema owner, False otherwise
946
     */
947
    public function hasAlterSchemaOwner()
948
    {
949
        return true;
950
    }
951
952
    /**
953
     * Determines if it has alter sequence schema.
954
     *
955
     * @return bool true if has alter sequence schema, False otherwise
956
     */
957
    public function hasAlterSequenceSchema()
958
    {
959
        return true;
960
    }
961
962
    /**
963
     * Determines if it has alter sequence start.
964
     *
965
     * @return bool true if has alter sequence start, False otherwise
966
     */
967
    public function hasAlterSequenceStart()
968
    {
969
        return true;
970
    }
971
972
    /**
973
     * Determines if it has alter table schema.
974
     *
975
     * @return bool true if has alter table schema, False otherwise
976
     */
977
    public function hasAlterTableSchema()
978
    {
979
        return true;
980
    }
981
982
    /**
983
     * Determines if it has autovacuum.
984
     *
985
     * @return bool true if has autovacuum, False otherwise
986
     */
987
    public function hasAutovacuum()
988
    {
989
        return true;
990
    }
991
992
    /**
993
     * Determines if it has create table like.
994
     *
995
     * @return bool true if has create table like, False otherwise
996
     */
997
    public function hasCreateTableLike()
998
    {
999
        return true;
1000
    }
1001
1002
    /**
1003
     * Determines if it has disable triggers.
1004
     *
1005
     * @return bool true if has disable triggers, False otherwise
1006
     */
1007
    public function hasDisableTriggers()
1008
    {
1009
        return true;
1010
    }
1011
1012
    /**
1013
     * Determines if it has alter domains.
1014
     *
1015
     * @return bool true if has alter domains, False otherwise
1016
     */
1017
    public function hasAlterDomains()
1018
    {
1019
        return true;
1020
    }
1021
1022
    /**
1023
     * Determines if it has enum types.
1024
     *
1025
     * @return bool true if has enum types, False otherwise
1026
     */
1027
    public function hasEnumTypes()
1028
    {
1029
        return true;
1030
    }
1031
1032
    /**
1033
     * Determines if it has fts.
1034
     *
1035
     * @return bool true if has fts, False otherwise
1036
     */
1037
    public function hasFTS()
1038
    {
1039
        return true;
1040
    }
1041
1042
    /**
1043
     * Determines if it has function costing.
1044
     *
1045
     * @return bool true if has function costing, False otherwise
1046
     */
1047
    public function hasFunctionCosting()
1048
    {
1049
        return true;
1050
    }
1051
1052
    /**
1053
     * Determines if it has function guc.
1054
     *
1055
     * @return bool true if has function guc, False otherwise
1056
     */
1057
    public function hasFunctionGUC()
1058
    {
1059
        return true;
1060
    }
1061
1062
    /**
1063
     * Determines if it has named parameters.
1064
     *
1065
     * @return bool true if has named parameters, False otherwise
1066
     */
1067
    public function hasNamedParams()
1068
    {
1069
        return true;
1070
    }
1071
1072
    /**
1073
     * Determines if it has prepare.
1074
     *
1075
     * @return bool true if has prepare, False otherwise
1076
     */
1077
    public function hasPrepare()
1078
    {
1079
        return true;
1080
    }
1081
1082
    /**
1083
     * Determines if it has prepared xacts.
1084
     *
1085
     * @return bool true if has prepared xacts, False otherwise
1086
     */
1087
    public function hasPreparedXacts()
1088
    {
1089
        return true;
1090
    }
1091
1092
    /**
1093
     * Determines if it has recluster.
1094
     *
1095
     * @return bool true if has recluster, False otherwise
1096
     */
1097
    public function hasRecluster()
1098
    {
1099
        return true;
1100
    }
1101
1102
    /**
1103
     * Determines if it has server admin funcs.
1104
     *
1105
     * @return bool true if has server admin funcs, False otherwise
1106
     */
1107
    public function hasServerAdminFuncs()
1108
    {
1109
        return true;
1110
    }
1111
1112
    /**
1113
     * Determines if it has query cancel.
1114
     *
1115
     * @return bool true if has query cancel, False otherwise
1116
     */
1117
    public function hasQueryCancel()
1118
    {
1119
        return true;
1120
    }
1121
1122
    /**
1123
     * Determines if it has user rename.
1124
     *
1125
     * @return bool true if has user rename, False otherwise
1126
     */
1127
    public function hasUserRename()
1128
    {
1129
        return true;
1130
    }
1131
1132
    /**
1133
     * Determines if it has user signals.
1134
     *
1135
     * @return bool true if has user signals, False otherwise
1136
     */
1137
    public function hasUserSignals()
1138
    {
1139
        return true;
1140
    }
1141
1142
    /**
1143
     * Determines if it has virtual transaction identifier.
1144
     *
1145
     * @return bool true if has virtual transaction identifier, False otherwise
1146
     */
1147
    public function hasVirtualTransactionId()
1148
    {
1149
        return true;
1150
    }
1151
1152
    /**
1153
     * Determines if it has alter database.
1154
     *
1155
     * @return bool true if has alter database, False otherwise
1156
     */
1157
    public function hasAlterDatabase()
1158
    {
1159
        return $this->hasAlterDatabaseRename();
1160
    }
1161
1162
    /**
1163
     * Determines if it has alter database rename.
1164
     *
1165
     * @return bool true if has alter database rename, False otherwise
1166
     */
1167
    public function hasAlterDatabaseRename()
1168
    {
1169
        return true;
1170
    }
1171
1172
    /**
1173
     * Determines if it has database collation.
1174
     *
1175
     * @return bool true if has database collation, False otherwise
1176
     */
1177
    public function hasDatabaseCollation()
1178
    {
1179
        return true;
1180
    }
1181
1182
    /**
1183
     * Determines if it has magic types.
1184
     *
1185
     * @return bool true if has magic types, False otherwise
1186
     */
1187
    public function hasMagicTypes()
1188
    {
1189
        return true;
1190
    }
1191
1192
    /**
1193
     * Determines if it has query kill.
1194
     *
1195
     * @return bool true if has query kill, False otherwise
1196
     */
1197
    public function hasQueryKill()
1198
    {
1199
        return true;
1200
    }
1201
1202
    /**
1203
     * Determines if it has concurrent index build.
1204
     *
1205
     * @return bool true if has concurrent index build, False otherwise
1206
     */
1207
    public function hasConcurrentIndexBuild()
1208
    {
1209
        return true;
1210
    }
1211
1212
    /**
1213
     * Determines if it has force reindex.
1214
     *
1215
     * @return bool true if has force reindex, False otherwise
1216
     */
1217
    public function hasForceReindex()
1218
    {
1219
        return false;
1220
    }
1221
1222
    /**
1223
     * Determines if it has bytea hexadecimal default.
1224
     *
1225
     * @return bool true if has bytea hexadecimal default, False otherwise
1226
     */
1227
    public function hasByteaHexDefault()
1228
    {
1229
        return true;
1230
    }
1231
}
1232