Completed
Branch master (024767)
by Henry Stivens
01:46
created

DbInformix   D

Complexity

Total Complexity 88

Size/Duplication

Total Lines 640
Duplicated Lines 22.66 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
dl 145
loc 640
rs 4.7089
c 0
b 0
f 0
wmc 88
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 DbInformix 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 DbInformix, 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
 * Informix Database Support
24
 *
25
 * @category   Kumbia
26
 * @package    Db
27
 * @subpackage Adapters
28
 */
29
class DbInformix extends DbBase implements DbBaseInterface
30
{
31
32
    /**
33
     * Resource de la Conexion a Informix
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 Informix
46
     *
47
     * @var string
48
     */
49
    protected $last_query;
50
    /**
51
     * Ultimo error generado por Informix
52
     *
53
     * @var string
54
     */
55
    public $last_error;
56
    /**
57
     * Indica si query devuelve registros o no;
58
     *
59
     * @var boolean
60
     */
61
    private $return_rows = true;
62
    /**
63
     * Emula un limit a nivel de Adaptador para Informix
64
     *
65
     * @var int
66
     */
67
    private $limit = -1;
68
    /**
69
     * Numero de limit actual para fetch_array
70
     *
71
     * @var int
72
     */
73
    private $actual_limit = 0;
74
75
    /**
76
     * Resultado de Array Asociativo
77
     *
78
     */
79
    const DB_ASSOC = 1;
80
81
    /**
82
     * Resultado de Array Asociativo y Numerico
83
     *
84
     */
85
    const DB_BOTH = 2;
86
87
    /**
88
     * Resultado de Array Numerico
89
     *
90
     */
91
    const DB_NUM = 3;
92
93
    /**
94
     * Tipo de Dato Integer
95
     *
96
     */
97
    const TYPE_INTEGER = 'INTEGER';
98
99
    /**
100
     * Tipo de Dato Date
101
     *
102
     */
103
    const TYPE_DATE = 'DATE';
104
105
    /**
106
     * Tipo de Dato Varchar
107
     *
108
     */
109
    const TYPE_VARCHAR = 'VARCHAR';
110
111
    /**
112
     * Tipo de Dato Decimal
113
     *
114
     */
115
    const TYPE_DECIMAL = 'DECIMAL';
116
117
    /**
118
     * Tipo de Dato Datetime
119
     *
120
     */
121
    const TYPE_DATETIME = 'DATETIME';
122
123
    /**
124
     * Tipo de Dato Char
125
     *
126
     */
127
    const TYPE_CHAR = 'CHAR';
128
129
    /**
130
     * Hace una conexión a la base de datos de Informix
131
     *
132
     * @param array $config
133
     * @return bool
134
     */
135
    public function connect($config)
136
    {
137
        if (!extension_loaded('informix')) {
138
            throw new KumbiaException('Debe cargar la extensión de PHP llamada php_ifx');
139
        }
140
141
        if ($this->id_connection = ifx_connect("{$config['name']}@{$config['host']}", $config['username'], $config['password'])) {
142
            return true;
143
        } else {
144
            throw new KumbiaException($this->error());
145
        }
146
    }
147
148
    /**
149
     * Efectua operaciones SQL sobre la base de datos
150
     *
151
     * @param string $sql_query
152
     * @return resource or false
153
     */
154
    public function query($sql_query)
155
    {
156
        $this->debug($sql_query);
157
        if ($this->logger) {
158
            Logger::debug($sql_query);
159
        }
160
161
        $this->last_query = $sql_query;
162
163
        // Los resultados que devuelven filas usan cursores tipo SCROLL
164
        if ($this->return_rows) {
165
            $result_query = ifx_query($sql_query, $this->id_connection, IFX_HOLD);
166
        } else {
167
            $result_query = ifx_query($sql_query, $this->id_connection);
168
        }
169
        $this->set_return_rows(true);
170
        if ($result_query === false) {
171
            throw new KumbiaException($this->error(" al ejecutar <em>\"$sql_query\"</em>"));
172
        }
173
        $this->last_result_query = $result_query;
174
        return $result_query;
175
    }
176
177
    /**
178
     * Cierra la Conexión al Motor de Base de datos
179
     *
180
     */
181
    public function close()
182
    {
183
        if ($this->id_connection) {
184
            return ifx_close($this->id_connection);
185
        }
186
        return false;
187
    }
188
189
    /**
190
     * Devuelve fila por fila el contenido de un select
191
     *
192
     * @param resource $result_query
193
     * @param int $opt
194
     * @return array
195
     */
196
    public function fetch_array($result_query=NULL, $opt=2)
197
    {
198
199
        if (!$result_query) {
200
            $result_query = $this->last_result_query;
201
            if (!$result_query) {
202
                return false;
203
            }
204
        }
205
        $fetch = ifx_fetch_row($result_query, $opt);
206
207
        // Informix no soporta limit por eso hay que emularlo
208
        if ($this->limit != -1) {
209
            if ($this->actual_limit >= $this->limit) {
210
                $this->limit = -1;
211
                $this->actual_limit = 0;
212
                return false;
213
            } else {
214
                $this->actual_limit++;
215
                if ($this->actual_limit == $this->limit) {
216
                    $this->limit = -1;
217
                    $this->actual_limit = 0;
218
                }
219
            }
220
        }
221
222
        // Informix no soporta fetch numerico, solo asociativo
223
        if (!is_array($fetch) || ($opt == self::DB_ASSOC)) {
224
            return $fetch;
225
        }
226
        if ($opt == self::DB_BOTH) {
227
            $result = array();
228
            $i = 0;
229
            foreach ($fetch as $key => $value) {
230
                $result[$key] = $value;
231
                $result[$i++] = $value;
232
            }
233
            return $result;
234
        }
235
        if ($opt == self::DB_NUM) {
236
            return array_values($fetch);
237
        }
238
    }
239
240
    /**
241
     * Constructor de la Clase
242
     *
243
     * @param array $config
244
     */
245
    public function __construct($config)
246
    {
247
        $this->connect($config);
248
    }
249
250
    /**
251
     * Devuelve el numero de filas de un select
252
     *
253
     * @param resource $result_query
254
     * @return int
255
     */
256
    public function num_rows($result_query=NULL)
257
    {
258
259
        if (!$result_query) {
260
            $result_query = $this->last_result_query;
261
            if (!$result_query) {
262
                return false;
263
            }
264
        }
265
        if (($number_rows = ifx_num_rows($result_query)) !== false) {
266
267
            // Emula un limit a nivel de adaptador
268
            if ($this->limit == -1) {
269
                return $number_rows;
270
            } else {
271
                return $this->limit < $number_rows ? $this->limit : $number_rows;
272
            }
273
        } else {
274
            throw new KumbiaException($this->error());
275
        }
276
    }
277
278
    /**
279
     * Devuelve el nombre de un campo en el resultado de un select
280
     *
281
     * @param int $number
282
     * @param resource $result_query
283
     * @return string
284
     */
285
    public function field_name($number, $result_query=NULL)
286
    {
287
288
        if (!$result_query) {
289
            $result_query = $this->last_result_query;
290
            if (!$result_query) {
291
                return false;
292
            }
293
        }
294
        $fields = ifx_fieldproperties($result_query);
295
        if (!is_array($fields)) {
296
            return false;
297
        }
298
299
        $fields = array_keys($fields);
300
        return $fields[$number];
301
    }
302
303
    /**
304
     * Se Mueve al resultado indicado por $number en un select
305
     * Hay problemas con este metodo hay problemas con curesores IFX_SCROLL
306
     *
307
     * @param int $number
308
     * @param resource $result_query
309
     * @return boolean
310
     */
311
    public function data_seek($number, $result_query=NULL)
312
    {
313
        if (!$result_query) {
314
            $result_query = $this->last_result_query;
315
            if (!$result_query) {
316
                return false;
317
            }
318
        }
319
        if (($success = ifx_fetch_row($result_query, $number)) !== false) {
320
            return $success;
321
        } else {
322
            throw new KumbiaException($this->error());
323
        }
324
    }
325
326
    /**
327
     * Numero de Filas afectadas en un insert, update o delete
328
     *
329
     * @param resource $result_query
330
     * @return int
331
     */
332
    public function affected_rows($result_query=NULL)
333
    {
334
        if (!$result_query) {
335
            $result_query = $this->last_result_query;
336
            if (!$result_query) {
337
                return false;
338
            }
339
        }
340
        if (($numberRows = ifx_affected_rows($result_query)) !== false) {
341
            return $numberRows;
342
        } else {
343
            throw new KumbiaException($this->error());
344
        }
345
    }
346
347
    /**
348
     * Devuelve el error de Informix
349
     *
350
     * @return string
351
     */
352
    public function error($err='')
353
    {
354
        if (!$this->id_connection) {
355
            $this->last_error = ifx_errormsg() ? ifx_errormsg() : "[Error Desconocido en Informix: $err]";
356
            if ($this->logger) {
357
                Logger::error($this->last_error);
358
            }
359
            return $this->last_error;
360
        }
361
        $this->last_error = ifx_errormsg($this->id_connection) ? ifx_errormsg($this->id_connection) : "[Error Desconocido en Informix: $err]";
362
        $this->last_error.= $err;
363
        if ($this->logger) {
364
            Logger::error($this->last_error);
365
        }
366
        return $this->last_error;
367
    }
368
369
    /**
370
     * Devuelve el no error de Informix
371
     *
372
     * @return int
373
     */
374
    public function no_error()
375
    {
376
        return ifx_error();
377
    }
378
379
    /**
380
     * Devuelve el ultimo id autonumerico generado en la BD
381
     *
382
     * @return int
383
     */
384
    public function last_insert_id($table='', $primary_key='')
385
    {
386
        $sqlca = ifx_getsqlca($this->last_result_query);
387
        return $sqlca["sqlerrd1"];
388
    }
389
390
    /**
391
     * Verifica si una tabla existe o no
392
     *
393
     * @param string $table
394
     * @return integer
395
     */
396
    public function table_exists($table, $schema='')
397
    {
398
        // Informix no soporta schemas
399
        $table = addslashes("$table");
400
        $num = $this->fetch_one("SELECT COUNT(*) FROM systables WHERE tabname = '$table'");
401
        return (int) $num[0];
402
    }
403
404
    /**
405
     * Devuelve un LIMIT valido para un SELECT del RBDM
406
     *
407
     * @param string $sql
408
     * @return string
409
     */
410
    public function limit($sql){
411
           /**
412
                 * No esta soportado por Informix
413
                 */
414
                return "$sql \n";
415
    }
416
417
418
    /**
419
     * Borra una tabla de la base de datos
420
     *
421
     * @param string $table
422
     * @return boolean
423
     */
424
    public function drop_table($table, $if_exists=true)
425
    {
426
        if ($if_exists) {
427
            if ($this->table_exists($table)) {
428
                $this->set_return_rows(false);
429
                return $this->query("DROP TABLE $table");
430
            } else {
431
                return true;
432
            }
433
        } else {
434
            $this->set_return_rows(false);
435
            return $this->query("DROP TABLE $table");
436
        }
437
    }
438
439
    /**
440
     * Crea una tabla utilizando SQL nativo del RDBM
441
     *
442
     * TODO:
443
     * - Falta que el parametro index funcione. Este debe listar indices compuestos multipes y unicos
444
     * - Agregar el tipo de tabla que debe usarse (Informix)
445
     * - Soporte para campos autonumericos
446
     * - Soporte para llaves foraneas
447
     *
448
     * @param string $table
449
     * @param array $definition
450
     * @return resource
451
     */
452
    public function create_table($table, $definition, $index=array())
453
    {
454
        $create_sql = "CREATE TABLE $table (";
455
        if (!is_array($definition)) {
456
            throw new KumbiaException("Definición invalida para crear la tabla '$table'");
457
        }
458
        $create_lines = array();
459
        $index = array();
460
        $unique_index = array();
461
        $primary = array();
462
        //$not_null = "";
463
        //$size = "";
464
        foreach ($definition as $field => $field_def) {
465
            if (isset($field_def['not_null'])) {
466
                $not_null = $field_def['not_null'] ? 'NOT NULL' : '';
467
            } else {
468
                $not_null = "";
469
            }
470
            if (isset($field_def['size'])) {
471
                $size = $field_def['size'] ? '(' . $field_def['size'] . ')' : '';
472
            } else {
473
                $size = "";
474
            }
475
            if (isset($field_def['index'])) {
476
                if ($field_def['index']) {
477
                    $index[] = "INDEX($field)";
478
                }
479
            }
480
            if (isset($field_def['unique_index'])) {
481
                if ($field_def['unique_index']) {
482
                    $index[] = "UNIQUE($field)";
483
                }
484
            }
485
            if (isset($field_def['primary'])) {
486
                if ($field_def['primary']) {
487
                    $primary[] = "$field";
488
                }
489
            }
490
            if (isset($field_def['auto'])) {
491
                if ($field_def['auto']) {
492
                    $field_def['type'] = "SERIAL";
493
                }
494
            }
495
            if (isset($field_def['extra'])) {
496
                $extra = $field_def['extra'];
497
            } else {
498
                $extra = "";
499
            }
500
            $create_lines[] = "$field " . $field_def['type'] . $size . ' ' . $not_null . ' ' . $extra;
501
        }
502
        $create_sql.= join(',', $create_lines);
503
        $last_lines = array();
504
        if (count($primary)) {
505
            $last_lines[] = 'PRIMARY KEY(' . join(",", $primary) . ')';
506
        }
507
        if (count($index)) {
508
            $last_lines[] = join(',', $index);
509
        }
510
        if (count($unique_index)) {
511
            $last_lines[] = join(',', $unique_index);
512
        }
513
        if (count($last_lines)) {
514
            $create_sql.= ',' . join(',', $last_lines) . ')';
515
        }
516
        $this->set_return_rows(false);
517
        return $this->query($create_sql);
518
    }
519
520
    /**
521
     * Listar las tablas en la base de datos
522
     *
523
     * @return array
524
     */
525
    public function list_tables()
526
    {
527
        return $this->fetch_all("SELECT tabname FROM systables WHERE tabtype = 'T' AND version <> 65537");
528
    }
529
530
    /**
531
     * Listar los campos de una tabla
532
     *
533
     * @param string $table
534
     * @return array
535
     */
536
    public function describe_table($table, $schema='')
537
    {
538
539
        // Informix no soporta schemas
540
        // TODO: No hay un metodo identificable para obtener llaves primarias
541
        // no nulos y tamaños reales de campos
542
        // Primary Key, Null
543
        $describe = $this->fetch_all("SELECT c.colname AS Field, c.coltype AS Type,
544
                'YES' AS NULL FROM systables t, syscolumns c WHERE
545
                c.tabid = t.tabid AND t.tabname = '$table' ORDER BY c.colno");
546
        $final_describe = array();
547
        foreach ($describe as $field) {
548
            //Serial
549
            if ($field['field'] == 'id') {
550
                $field["key"] = 'PRI';
551
                $field["null"] = 'NO';
552
            } else {
553
                $field["key"] = '';
554
            }
555
            if (substr($field['field'], -3) == '_id') {
556
                $field["null"] = 'NO';
557
            }
558
            if ($field['type'] == 262) {
559
                $field['type'] = "serial";
560
            }
561
            if ($field['type'] == 13) {
562
                $field['type'] = "varchar";
563
            }
564
            if ($field['type'] == 7) {
565
                $field['type'] = "date";
566
            }
567
            $final_describe[] = array(
568
                "Field" => $field["field"],
569
                "Type" => $field["type"],
570
                "Null" => $field["null"],
571
                "Key" => $field["key"]
572
            );
573
        }
574
        return $final_describe;
575
    }
576
577
    /**
578
     * Realiza una inserci&oacute;n (Sobreescrito para indicar que no devuelve registros)
579
     *
580
     * @param string $table
581
     * @param array $values
582
     * @param array $fields
583
     * @return boolean
584
     */
585
    public function insert($table, $values, $fields=null)
586
    {
587
        $this->set_return_rows(false);
588
        return parent::insert($table, $values, $fields);
589
    }
590
591
    /**
592
     * Actualiza registros en una tabla
593
     *
594
     * @param string $table
595
     * @param array $fields
596
     * @param array $values
597
     * @param string $where_condition
598
     * @return boolean
599
     */
600
    public function update($table, $fields, $values, $where_condition=null)
601
    {
602
        $this->set_return_rows(false);
603
        return parent::update($table, $fields, $values, $where_condition);
604
    }
605
606
    /**
607
     * Borra registros de una tabla!
608
     *
609
     * @param string $table
610
     * @param string $where_condition
611
     */
612
    public function delete($table, $where_condition)
613
    {
614
        $this->set_return_rows(false);
615
        return parent::delete($table, $where_condition);
616
    }
617
618
    /**
619
     * Indica internamente si el resultado obtenido es devuelve registros o no
620
     *
621
     * @param boolean $value
622
     */
623
    public function set_return_rows($value=true)
624
    {
625
        $this->return_rows = $value;
626
    }
627
628
    /**
629
     * Inicia una transacci&oacute;n si es posible
630
     *
631
     */
632
    public function begin()
633
    {
634
        $this->set_return_rows(false);
635
        return $this->query("BEGIN WORK");
636
    }
637
638
    /**
639
     * Cancela una transacci&oacute;n si es posible
640
     *
641
     */
642
    public function rollback()
643
    {
644
        $this->set_return_rows(false);
645
        return $this->query("ROLLBACK");
646
    }
647
648
    /**
649
     * Hace commit sobre una transacci&oacute;n si es posible
650
     *
651
     */
652
    public function commit()
653
    {
654
        $this->set_return_rows(false);
655
        return $this->query("COMMIT");
656
    }
657
658
    /**
659
     * Devuelve la ultima sentencia sql ejecutada por el Adaptador
660
     *
661
     * @return string
662
     */
663
    public function last_sql_query()
664
    {
665
        return $this->last_query;
666
    }
667
668
}
669