Completed
Branch master (024767)
by Henry Stivens
02:30
created

DbOracle   D

Complexity

Total Complexity 87

Size/Duplication

Total Lines 574
Duplicated Lines 32.23 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
dl 185
loc 574
rs 4.8717
c 0
b 0
f 0
wmc 87
lcom 1
cbo 3

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like DbOracle often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use DbOracle, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * KumbiaPHP web & app Framework
4
 *
5
 * LICENSE
6
 *
7
 * This source file is subject to the new BSD license that is bundled
8
 * with this package in the file LICENSE.txt.
9
 * It is also available through the world-wide-web at this URL:
10
 * http://wiki.kumbiaphp.com/Licencia
11
 * If you did not receive a copy of the license and are unable to
12
 * obtain it through the world-wide-web, please send an email
13
 * to [email protected] so we can send you a copy immediately.
14
 *
15
 * @category   Kumbia
16
 * @package    Db
17
 * @subpackage Adapters
18
 * @copyright  Copyright (c) 2005 - 2017 Kumbia Team (http://www.kumbiaphp.com)
19
 * @license    http://wiki.kumbiaphp.com/Licencia     New BSD License
20
 */
21
22
/**
23
 * Oracle Database Support
24
 *
25
 * @category   Kumbia
26
 * @package    Db
27
 * @subpackage Adapters
28
 */
29
class DbOracle extends DbBase implements DbBaseInterface
30
{
31
32
    /**
33
     * Resource de la Conexion a Oracle
34
     *
35
     * @var resource
36
     */
37
    public $id_connection;
38
    /**
39
     * Ultimo Resultado de una Query
40
     *
41
     * @var resource
42
     */
43
    public $last_result_query;
44
    /**
45
     * Ultima sentencia SQL enviada a Oracle
46
     *
47
     * @var string
48
     */
49
    protected $last_query;
50
    /**
51
     * Ultimo error generado por Oracle
52
     *
53
     * @var string
54
     */
55
    public $last_error;
56
    /**
57
     * Indica si los modelos usan autocommit
58
     *
59
     * @var boolean
60
     */
61
    private $autocommit = false;
62
    /**
63
     * NUmero de filas devueltas
64
     *
65
     * @var boolean
66
     */
67
    private $num_rows = false;
68
69
    /**
70
     * Resultado de Array Asociativo
71
     *
72
     */
73
    const DB_ASSOC = OCI_ASSOC;
74
75
76
    /**
77
     * Resultado de Array Asociativo y Numerico
78
     *
79
     */
80
    const DB_BOTH = OCI_BOTH;
81
82
    /**
83
     * Resultado de Array Numerico
84
     *
85
     */
86
    const DB_NUM = OCI_NUM;
87
88
    /**
89
     * Tipo de Dato Integer
90
     *
91
     */
92
    const TYPE_INTEGER = 'INTEGER';
93
94
    /**
95
     * Tipo de Dato Date
96
     *
97
     */
98
    const TYPE_DATE = 'DATE';
99
100
    /**
101
     * Tipo de Dato Varchar
102
     *
103
     */
104
    const TYPE_VARCHAR = 'VARCHAR2';
105
106
    /**
107
     * Tipo de Dato Decimal
108
     *
109
     */
110
    const TYPE_DECIMAL = 'DECIMAL';
111
112
    /**
113
     * Tipo de Dato Datetime
114
     *
115
     */
116
    const TYPE_DATETIME = 'DATETIME';
117
118
    /**
119
     * Tipo de Dato Char
120
     *
121
     */
122
    const TYPE_CHAR = 'CHAR';
123
124
    /**
125
     * Hace una conexion a la base de datos de Oracle
126
     *
127
     * @param array $config
128
     * @return bool
129
     */
130
    function connect($config)
131
    {
132
133
        if (!extension_loaded('oci8')) {
134
            throw new KumbiaException('Debe cargar la extensión de PHP llamada php_oci8');
135
        }
136
137
        if ($this->id_connection = @oci_pconnect($config['username'], $config['password'], "//{$config['host']}/{$config['name']}")) {
138
            /**
139
             * Cambio el formato de fecha al estandar YYYY-MM-DD
140
             */
141
            $this->query("alter session set nls_date_format = 'YYYY-MM-DD'");
142
            return true;
143
        } else {
144
            throw new KumbiaException($this->error($php_errormsg));
145
        }
146
    }
147
148
    /**
149
     * Efectua operaciones SQL sobre la base de datos
150
     *
151
     * @param string $sqlQuery
152
     * @return resource or false
153
     */
154
    function query($sqlQuery)
155
    {
156
        $this->debug($sqlQuery);
157
        if ($this->logger) {
158
            Logger::debug($sqlQuery);
159
        }
160
161
        $this->num_rows = false;
162
        $this->last_query = $sqlQuery;
163
        $resultQuery = @oci_parse($this->id_connection, $sqlQuery);
164
        if ($resultQuery) {
165
            $this->last_result_query = $resultQuery;
166
        } else {
167
            throw new KumbiaException($this->error($php_errormsg));
168
        }
169
        if ($this->autocommit) {
170
            $commit = OCI_COMMIT_ON_SUCCESS;
171
        } else {
172
            $commit = OCI_DEFAULT;
173
        }
174
175
        if (!@oci_execute($resultQuery, $commit)) {
176
            throw new KumbiaException($this->error($php_errormsg));
177
        }
178
        return $resultQuery;
179
    }
180
181
    /**
182
     * Cierra la Conexión al Motor de Base de datos
183
     */
184
    function close()
185
    {
186
        if ($this->id_connection) {
187
            return oci_close($this->id_connection);
188
        }
189
    }
190
191
    /**
192
     * Devuelve fila por fila el contenido de un select
193
     *
194
     * @param resource $resultQuery
195
     * @param int $opt
196
     * @return array
197
     */
198
    function fetch_array($resultQuery=NULL, $opt=OCI_BOTH)
199
    {
200
201
        if (!$resultQuery) {
202
            $resultQuery = $this->last_result_query;
203
            if (!$resultQuery) {
204
                return false;
205
            }
206
        }
207
        $result = oci_fetch_array($resultQuery, $opt);
208
        if (is_array($result)) {
209
            $result_to_lower = array();
210
            foreach ($result as $key => $value) {
211
                $result_to_lower[strtolower($key)] = $value;
212
            }
213
            return $result_to_lower;
214
        }
215
        return false;
216
    }
217
218
    /**
219
     * Constructor de la Clase
220
     *
221
     * @param array $config
222
     */
223
    function __construct($config)
224
    {
225
        $this->connect($config);
226
    }
227
228
    /**
229
     * Devuelve el numero de filas de un select
230
     */
231
    function num_rows($resultQuery=NULL)
232
    {
233
234
        if (!$resultQuery) {
235
            $resultQuery = $this->last_result_query;
236
            if (!$resultQuery) {
237
                throw new KumbiaException($this->error('Resource invalido para db::num_rows'));
238
            }
239
        }
240
241
        // El Adaptador cachea la ultima llamada a num_rows por razones de performance
242
243
        /* if($resultQuery==$this->last_result_query){
244
          if($this->num_rows!==false){
245
          return $this->num_rows;
246
          }
247
          } */
248
        if ($this->autocommit) {
249
            $commit = OCI_COMMIT_ON_SUCCESS;
250
        } else {
251
            $commit = OCI_DEFAULT;
252
        }
253
        if (!@oci_execute($resultQuery, $commit)) {
254
            throw new KumbiaException($this->error($php_errormsg . " al ejecutar <em>'{$this->lastQuery}'</em>"));
255
        }
256
        $tmp = array();
257
        $this->num_rows = oci_fetch_all($resultQuery, $tmp);
258
        unset($tmp);
259
        @oci_execute($resultQuery, $commit);
260
        return $this->num_rows;
261
    }
262
263
    /**
264
     * Devuelve el nombre de un campo en el resultado de un select
265
     *
266
     * @param int $number
267
     * @param resource $resultQuery
268
     * @return string
269
     */
270
    function field_name($number, $resultQuery=NULL)
271
    {
272
273
        if (!$resultQuery) {
274
            $resultQuery = $this->last_result_query;
275
            if (!$resultQuery) {
276
                throw new KumbiaException($this->error('Resource invalido para db::field_name'));
277
            }
278
        }
279
280
        if (($fieldName = oci_field_name($resultQuery, $number + 1)) !== false) {
281
            return strtolower($fieldName);
282
        } else {
283
            throw new KumbiaException($this->error());
284
        }
285
    }
286
287
    /**
288
     * Se Mueve al resultado indicado por $number en un select
289
     *
290
     * @param int $number
291
     * @param resource $resultQuery
292
     * @return boolean
293
     */
294
    function data_seek($number, $resultQuery=NULL)
295
    {
296
        if (!$resultQuery) {
297
            $resultQuery = $this->last_result_query;
298
            if (!$resultQuery) {
299
                throw new KumbiaException($this->error('Resource invalido para db::data_seek'));
300
            }
301
        }
302
        if ($this->autocommit) {
303
            $commit = OCI_COMMIT_ON_SUCCESS;
304
        } else {
305
            $commit = OCI_DEFAULT;
306
        }
307
        if (!@oci_execute($resultQuery, $commit)) {
308
            throw new KumbiaException($this->error($php_errormsg . " al ejecutar <em>'{$this->lastQuery}'</em>"));
309
        }
310
        if ($number) {
311
            for ($i = 0; $i <= $number - 1; $i++) {
312
                if (!oci_fetch_row($resultQuery)) {
313
                    return false;
314
                }
315
            }
316
        } else {
317
            return true;
318
        }
319
        return true;
320
    }
321
322
    /**
323
     * Número de Filas afectadas en un insert, update ó delete
324
     *
325
     * @param resource $resultQuery
326
     * @return int
327
     */
328
    function affected_rows($resultQuery=NULL)
329
    {
330
331
        if (!$resultQuery) {
332
            $resultQuery = $this->last_result_query;
333
            if (!$resultQuery) {
334
                return false;
335
            }
336
        }
337
        if (($numberRows = oci_num_rows($resultQuery)) !== false) {
338
            return $numberRows;
339
        } else {
340
            throw new KumbiaException($this->error('Resource invalido para db::affected_rows'));
341
        }
342
    }
343
344
    /**
345
     * Devuelve el error de Oracle
346
     *
347
     * @return string
348
     */
349
    function error($err='')
350
    {
351
        if (!$this->id_connection) {
352
            $error = oci_error() ? oci_error() : "[Error Desconocido en Oracle]";
353
            if (is_array($error)) {
354
                $error['message'].=" > $err ";
355
                return $error['message'];
356
            } else {
357
                //$error.=" $php_errormsg ";
358
                return $error;
359
            }
360
        }
361
        $error = oci_error($this->id_connection);
362
        if ($error) {
363
            $error['message'].=" > $err ";
364
        } else {
365
            $error['message'] = $err;
366
        }
367
        return $error['message'];
368
    }
369
370
    /**
371
     * Devuelve el no error de Oracle
372
     *
373
     * @return int
374
     */
375
    function no_error()
376
    {
377
        if (!$this->id_connection) {
378
            $error = oci_error() ? oci_error() : 0;
379
            if (is_array($error)) {
380
                return $error['code'];
381
            } else {
382
                return $error;
383
            }
384
        }
385
        $error = oci_error($this->id_connection);
386
        return $error['code'];
387
    }
388
389
    /**
390
     * Devuelve un LIMIT valido para un SELECT del RBDM
391
     *
392
     * @param int $number
393
     * @return string
394
     */
395
    public function limit($sql, $number)
396
    {
397
        if (!is_numeric($number) || $number < 0) {
398
            return $sql;
399
        }
400
        if (eregi("ORDER[\t\n\r ]+BY", $sql)) {
401
            if (stripos($sql, "WHERE")) {
402
                return eregi_replace("ORDER[\t\n\r ]+BY", "AND ROWNUM <= $number ORDER BY", $sql);
403
            } else {
404
                return eregi_replace("ORDER[\t\n\r ]+BY", "WHERE ROWNUM <= $number ORDER BY", $sql);
405
            }
406
        } else {
407
            if (stripos($sql, "WHERE")) {
408
                return "$sql AND ROWNUM <= $number";
409
            } else {
410
                return "$sql WHERE ROWNUM <= $number";
411
            }
412
        }
413
    }
414
415
    /**
416
     * Borra una tabla de la base de datos
417
     *
418
     * @param string $table
419
     * @return boolean
420
     */
421
    public function drop_table($table, $if_exists=true)
422
    {
423
        if ($if_exists) {
424
            if ($this->table_exists($table)) {
425
                return $this->query("DROP TABLE $table");
426
            } else {
427
                return true;
428
            }
429
        } else {
430
            return $this->query("DROP TABLE $table");
431
        }
432
    }
433
434
    /**
435
     * Crea una tabla utilizando SQL nativo del RDBM
436
     *
437
     * TODO:
438
     * - Falta que el parametro index funcione. Este debe listar indices compuestos multipes y unicos
439
     * - Agregar el tipo de tabla que debe usarse (Oracle)
440
     * - Soporte para campos autonumericos
441
     * - Soporte para llaves foraneas
442
     *
443
     * @param string $table
444
     * @param array $definition
445
     * @return resource
446
     */
447
    public function create_table($table, $definition, $index=array())
448
    {
449
        $create_sql = "CREATE TABLE $table (";
450
        if (!is_array($definition)) {
451
            throw new KumbiaException("Definición invalida para crear la tabla '$table'");
452
        }
453
        $create_lines = array();
454
        $index = array();
455
        $unique_index = array();
456
        $primary = array();
457
        //$not_null = "";
458
        //$size = "";
459
        foreach ($definition as $field => $field_def) {
460
            if (isset($field_def['not_null'])) {
461
                $not_null = $field_def['not_null'] ? 'NOT NULL' : '';
462
            } else {
463
                $not_null = "";
464
            }
465
            if (isset($field_def['size'])) {
466
                $size = $field_def['size'] ? '(' . $field_def['size'] . ')' : '';
467
            } else {
468
                $size = "";
469
            }
470
            if (isset($field_def['index'])) {
471
                if ($field_def['index']) {
472
                    $index[] = "INDEX($field)";
473
                }
474
            }
475
            if (isset($field_def['unique_index'])) {
476
                if ($field_def['unique_index']) {
477
                    $index[] = "UNIQUE($field)";
478
                }
479
            }
480
            if (isset($field_def['primary'])) {
481
                if ($field_def['primary']) {
482
                    $primary[] = "$field";
483
                }
484
            }
485
            if (isset($field_def['auto'])) {
486
                if ($field_def['auto']) {
487
                    $this->query("CREATE SEQUENCE {$table}_{$field}_seq START WITH 1");
488
                }
489
            }
490
            if (isset($field_def['extra'])) {
491
                $extra = $field_def['extra'];
492
            } else {
493
                $extra = "";
494
            }
495
            $create_lines[] = "$field " . $field_def['type'] . $size . ' ' . $not_null . ' ' . $extra;
496
        }
497
        $create_sql.= join(',', $create_lines);
498
        $last_lines = array();
499
        if (count($primary)) {
500
            $last_lines[] = 'PRIMARY KEY(' . join(",", $primary) . ')';
501
        }
502
        if (count($index)) {
503
            $last_lines[] = join(',', $index);
504
        }
505
        if (count($unique_index)) {
506
            $last_lines[] = join(',', $unique_index);
507
        }
508
        if (count($last_lines)) {
509
            $create_sql.= ',' . join(',', $last_lines) . ')';
510
        }
511
        return $this->query($create_sql);
512
    }
513
514
    /**
515
     * Listado de Tablas
516
     *
517
     * @return boolean
518
     */
519
    function list_tables()
520
    {
521
        return $this->fetch_all("SELECT table_name FROM all_tables");
522
    }
523
524
    /**
525
     * Devuelve el ultimo id autonumerico generado en la BD
526
     *
527
     * @return int
528
     */
529
    public function last_insert_id($table='', $primary_key='')
530
    {
531
        if (!$this->id_connection) {
532
            return false;
533
        }
534
        /**
535
         * Oracle No soporta columnas autonum&eacute;ricas
536
         */
537
        if ($table && $primary_key) {
538
            $sequence = $table . "_" . $primary_key . "_seq";
539
            $value = $this->fetch_one("SELECT $sequence.CURRVAL FROM dual");
540
            return $value[0];
541
        }
542
        return false;
543
    }
544
545
    /**
546
     * Verifica si una tabla existe o no
547
     *
548
     * @param string $table
549
     * @return boolean
550
     */
551
    function table_exists($table, $schema='')
552
    {
553
        $num = $this->fetch_one("SELECT COUNT(*) FROM ALL_TABLES WHERE TABLE_NAME = '" . strtoupper($table) . "'");
554
        return $num[0];
555
    }
556
557
    /**
558
     * Listar los campos de una tabla
559
     *
560
     * @param string $table
561
     * @return array
562
     */
563
    public function describe_table($table, $schema='')
564
    {
565
        /**
566
         * Soporta schemas?
567
         */
568
        $describe = $this->fetch_all("SELECT LOWER(ALL_TAB_COLUMNS.COLUMN_NAME) AS FIELD, LOWER(ALL_TAB_COLUMNS.DATA_TYPE) AS TYPE, ALL_TAB_COLUMNS.DATA_LENGTH AS LENGTH, (SELECT COUNT(*) FROM ALL_CONS_COLUMNS WHERE TABLE_NAME = '" . strtoupper($table) . "' AND ALL_CONS_COLUMNS.COLUMN_NAME = ALL_TAB_COLUMNS.COLUMN_NAME AND ALL_CONS_COLUMNS.POSITION IS NOT NULL) AS KEY, ALL_TAB_COLUMNS.NULLABLE AS ISNULL FROM ALL_TAB_COLUMNS WHERE ALL_TAB_COLUMNS.TABLE_NAME = '" . strtoupper($table) . "'");
569
        $final_describe = array();
570
        foreach ($describe as $key => $value) {
571
            $final_describe[] = array(
572
                "Field" => $value["field"],
573
                "Type" => $value["type"],
574
                "Null" => $value["isnull"] == "Y" ? "YES" : "NO",
575
                "Key" => $value["key"] == 1 ? "PRI" : ""
576
            );
577
        }
578
        return $final_describe;
579
    }
580
581
    /**
582
     * Inicia una transacci&oacute;n si es posible
583
     *
584
     */
585
    public function begin()
586
    {
587
        //Siempre hay una transaccion
588
        //return $this->query("BEGIN WORK");
589
        return true;
590
    }
591
592
    /**
593
     * Devuelve la ultima sentencia sql ejecutada por el Adaptador
594
     *
595
     * @return string
596
     */
597
    public function last_sql_query()
598
    {
599
        return $this->last_query;
600
    }
601
602
}
603