Test Failed
Pull Request — develop (#380)
by Felipe
03:38
created

FtsTrait::getFtsConfigurationByName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 24
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 20
nc 1
nop 1
dl 0
loc 24
rs 9.6
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * PHPPgAdmin 6.1.3
5
 */
6
7
namespace PHPPgAdmin\Database\Traits;
8
9
use ADORecordSet;
10
11
/**
12
 * Common trait for full text search manipulation.
13
 */
14
trait FtsTrait
15
{
16
    /**
17
     * Creates a new FTS configuration.
18
     *
19
     * @param string       $cfgname  The name of the FTS configuration to create
20
     * @param array|string $parser   The parser to be used in new FTS configuration
21
     * @param array|string $template The existing FTS configuration to be used as template for the new one
22
     * @param string       $comment  If omitted, defaults to nothing
23
     *
24
     * @return bool|int 0 success
25
     *
26
     * @internal param string $locale Locale of the FTS configuration
27
     * @internal param string $withmap Should we copy whole map of existing FTS configuration to the new one
28
     * @internal param string $makeDefault Should this configuration be the default for locale given
29
     */
30
    public function createFtsConfiguration($cfgname, $parser = '', $template = '', $comment = '')
31
    {
32
        $f_schema = $this->_schema;
33
        $this->fieldClean($f_schema);
34
        $this->fieldClean($cfgname);
35
36
        $sql = \sprintf(
37
            'CREATE TEXT SEARCH CONFIGURATION "%s"."%s" (',
38
            $f_schema,
39
            $cfgname
40
        );
41
42
        if ('' !== $parser) {
43
            $this->fieldClean($parser['schema']);
44
            $this->fieldClean($parser['parser']);
45
            $parser = \sprintf(
46
                '"%s"."%s"',
47
                $parser['schema'],
48
                $parser['parser']
49
            );
50
            $sql .= \sprintf(
51
                ' PARSER = %s',
52
                $parser
53
            );
54
        }
55
56
        if ('' !== $template) {
57
            $this->fieldClean($template['schema']);
58
            $this->fieldClean($template['name']);
59
            $sql .= \sprintf(
60
                ' COPY = "%s"."%s"',
61
                $template['schema'],
62
                $template['name']
63
            );
64
        }
65
        $sql .= ')';
66
67
        if ('' !== $comment) {
68
            $status = $this->beginTransaction();
69
70
            if (0 !== $status) {
71
                return -1;
72
            }
73
        }
74
75
        // Create the FTS configuration
76
        $status = $this->execute($sql);
77
78
        if (0 !== $status) {
79
            $this->rollbackTransaction();
80
81
            return -1;
82
        }
83
84
        // Set the comment
85
        if ('' !== $comment) {
86
            $status = $this->setComment('TEXT SEARCH CONFIGURATION', $cfgname, '', $comment);
87
88
            if (0 !== $status) {
89
                $this->rollbackTransaction();
90
91
                return -1;
92
            }
93
94
            return $this->endTransaction();
95
        }
96
97
        return 0;
98
    }
99
100
    // Language functions
101
102
    /**
103
     * Returns available FTS configurations.
104
     *
105
     * @param bool $all if false, returns schema qualified FTS confs
106
     *
107
     * @return ADORecordSet|int
108
     */
109
    public function getFtsConfigurations($all = true)
110
    {
111
        $c_schema = $this->_schema;
112
        $this->clean($c_schema);
113
        $sql = "
114
            SELECT
115
                n.nspname as schema,
116
                c.cfgname as name,
117
                pg_catalog.obj_description(c.oid, 'pg_ts_config') as comment
118
            FROM
119
                pg_catalog.pg_ts_config c
120
                JOIN pg_catalog.pg_namespace n ON n.oid = c.cfgnamespace
121
            WHERE
122
                pg_catalog.pg_ts_config_is_visible(c.oid)";
123
124
        if (!$all) {
125
            $sql .= \sprintf(
126
                ' AND  n.nspname=\'%s\'
127
',
128
                $c_schema
129
            );
130
        }
131
132
        $sql .= 'ORDER BY name';
133
134
        return $this->selectSet($sql);
135
    }
136
137
    // Aggregate functions
138
139
    /**
140
     * Returns the map of FTS configuration given
141
     * (list of mappings (tokens) and their processing dictionaries).
142
     *
143
     * @param string $ftscfg Name of the FTS configuration
144
     *
145
     * @return ADORecordSet|int
146
     */
147
    public function getFtsConfigurationMap($ftscfg)
148
    {
149
        $c_schema = $this->_schema;
150
        $this->clean($c_schema);
151
        $this->fieldClean($ftscfg);
152
153
        $oidSet = $this->selectSet(\sprintf(
154
            'SELECT c.oid
155
            FROM pg_catalog.pg_ts_config AS c
156
                LEFT JOIN pg_catalog.pg_namespace n ON (n.oid = c.cfgnamespace)
157
            WHERE c.cfgname = \'%s\'
158
                AND n.nspname=\'%s\'',
159
            $ftscfg,
160
            $c_schema
161
        ));
162
163
        $oid = $oidSet->fields['oid'];
164
165
        $sql = \sprintf(
166
            '
167
            SELECT
168
                (SELECT t.alias FROM pg_catalog.ts_token_type(c.cfgparser) AS t WHERE t.tokid = m.maptokentype) AS name,
169
                (SELECT t.description FROM pg_catalog.ts_token_type(c.cfgparser) AS t WHERE t.tokid = m.maptokentype) AS description,
170
                c.cfgname AS cfgname, n.nspname ||\'.\'|| d.dictname as dictionaries
171
            FROM
172
                pg_catalog.pg_ts_config AS c, pg_catalog.pg_ts_config_map AS m, pg_catalog.pg_ts_dict d,
173
                pg_catalog.pg_namespace n
174
            WHERE
175
                c.oid = %s
176
                AND m.mapcfg = c.oid
177
                AND m.mapdict = d.oid
178
                AND d.dictnamespace = n.oid
179
            ORDER BY name
180
            ',
181
            $oid
182
        );
183
184
        return $this->selectSet($sql);
185
    }
186
187
    /**
188
     * Returns FTS parsers available.
189
     *
190
     * @param bool $all if false, return only Parsers from the current schema
191
     *
192
     * @return ADORecordSet|int
193
     */
194
    public function getFtsParsers($all = true)
195
    {
196
        $c_schema = $this->_schema;
197
        $this->clean($c_schema);
198
        $sql = "
199
            SELECT
200
               n.nspname as schema,
201
               p.prsname as name,
202
               pg_catalog.obj_description(p.oid, 'pg_ts_parser') as comment
203
            FROM pg_catalog.pg_ts_parser p
204
                LEFT JOIN pg_catalog.pg_namespace n ON (n.oid = p.prsnamespace)
205
            WHERE pg_catalog.pg_ts_parser_is_visible(p.oid)";
206
207
        if (!$all) {
208
            $sql .= \sprintf(
209
                ' AND n.nspname=\'%s\'
210
',
211
                $c_schema
212
            );
213
        }
214
215
        $sql .= 'ORDER BY name';
216
217
        return $this->selectSet($sql);
218
    }
219
220
    /**
221
     * Returns FTS dictionaries available.
222
     *
223
     * @param bool $all if false, return only Dics from the current schema
224
     *
225
     * @return ADORecordSet|int
226
     */
227
    public function getFtsDictionaries($all = true)
228
    {
229
        $c_schema = $this->_schema;
230
        $this->clean($c_schema);
231
        $sql = "
232
            SELECT
233
                n.nspname as schema, d.dictname as name,
234
                pg_catalog.obj_description(d.oid, 'pg_ts_dict') as comment
235
            FROM pg_catalog.pg_ts_dict d
236
                LEFT JOIN pg_catalog.pg_namespace n ON n.oid = d.dictnamespace
237
            WHERE pg_catalog.pg_ts_dict_is_visible(d.oid)";
238
239
        if (!$all) {
240
            $sql .= \sprintf(
241
                ' AND n.nspname=\'%s\'
242
',
243
                $c_schema
244
            );
245
        }
246
247
        $sql .= 'ORDER BY name;';
248
249
        return $this->selectSet($sql);
250
    }
251
252
    /**
253
     * Returns all FTS dictionary templates available.
254
     *
255
     * @return ADORecordSet|int
256
     */
257
    public function getFtsDictionaryTemplates()
258
    {
259
        $sql = "
260
            SELECT
261
                n.nspname as schema,
262
                t.tmplname as name,
263
                ( SELECT COALESCE(np.nspname, '(null)')::pg_catalog.text || '.' || p.proname
264
                    FROM pg_catalog.pg_proc p
265
                    LEFT JOIN pg_catalog.pg_namespace np ON np.oid = p.pronamespace
266
                    WHERE t.tmplinit = p.oid ) AS  init,
267
                ( SELECT COALESCE(np.nspname, '(null)')::pg_catalog.text || '.' || p.proname
268
                    FROM pg_catalog.pg_proc p
269
                    LEFT JOIN pg_catalog.pg_namespace np ON np.oid = p.pronamespace
270
                    WHERE t.tmpllexize = p.oid ) AS  lexize,
271
                pg_catalog.obj_description(t.oid, 'pg_ts_template') as comment
272
            FROM pg_catalog.pg_ts_template t
273
                LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.tmplnamespace
274
            WHERE pg_catalog.pg_ts_template_is_visible(t.oid)
275
            ORDER BY name;";
276
277
        return $this->selectSet($sql);
278
    }
279
280
    /**
281
     * Drops FTS coniguration.
282
     *
283
     * @param string $ftscfg  The configuration's name
284
     * @param bool   $cascade true to Cascade to dependenced objects
285
     *
286
     * @return ADORecordSet|int
287
     */
288
    public function dropFtsConfiguration($ftscfg, $cascade)
289
    {
290
        $f_schema = $this->_schema;
291
        $this->fieldClean($f_schema);
292
        $this->fieldClean($ftscfg);
293
294
        $sql = \sprintf(
295
            'DROP TEXT SEARCH CONFIGURATION "%s"."%s"',
296
            $f_schema,
297
            $ftscfg
298
        );
299
300
        if ($cascade) {
301
            $sql .= ' CASCADE';
302
        }
303
304
        return $this->execute($sql);
305
    }
306
307
    /**
308
     * Drops FTS dictionary.
309
     *
310
     * @param string $ftsdict The dico's name
311
     * @param bool   $cascade Cascade to dependenced objects
312
     *
313
     * @return ADORecordSet|int
314
     *
315
     * @todo Support of dictionary templates dropping
316
     */
317
    public function dropFtsDictionary($ftsdict, $cascade)
318
    {
319
        $f_schema = $this->_schema;
320
        $this->fieldClean($f_schema);
321
        $this->fieldClean($ftsdict);
322
323
        $sql = 'DROP TEXT SEARCH DICTIONARY';
324
        $sql .= \sprintf(
325
            ' "%s"."%s"',
326
            $f_schema,
327
            $ftsdict
328
        );
329
330
        if ($cascade) {
331
            $sql .= ' CASCADE';
332
        }
333
334
        return $this->execute($sql);
335
    }
336
337
    /**
338
     * Alters FTS configuration.
339
     *
340
     * @param string $cfgname The conf's name
341
     * @param string $comment A comment on for the conf
342
     * @param string $name    The new conf name
343
     *
344
     * @return bool|int 0 on success
345
     */
346
    public function updateFtsConfiguration($cfgname, $comment, $name)
347
    {
348
        $status = $this->beginTransaction();
349
350
        if (0 !== $status) {
351
            $this->rollbackTransaction();
352
353
            return -1;
354
        }
355
356
        $this->fieldClean($cfgname);
357
358
        $status = $this->setComment('TEXT SEARCH CONFIGURATION', $cfgname, '', $comment);
359
360
        if (0 !== $status) {
361
            $this->rollbackTransaction();
362
363
            return -1;
364
        }
365
366
        // Only if the name has changed
367
        if ($name !== $cfgname) {
368
            $f_schema = $this->_schema;
369
            $this->fieldClean($f_schema);
370
            $this->fieldClean($name);
371
372
            $sql = \sprintf(
373
                'ALTER TEXT SEARCH CONFIGURATION "%s"."%s" RENAME TO "%s"',
374
                $f_schema,
375
                $cfgname,
376
                $name
377
            );
378
            $status = $this->execute($sql);
379
380
            if (0 !== $status) {
381
                $this->rollbackTransaction();
382
383
                return -1;
384
            }
385
        }
386
387
        return $this->endTransaction();
388
    }
389
390
    /**
391
     * Creates a new FTS dictionary or FTS dictionary template.
392
     *
393
     * @param string $dictname   The name of the FTS dictionary to create
394
     * @param bool   $isTemplate Flag whether we create usual dictionary or dictionary template
395
     * @param string $template   The existing FTS dictionary to be used as template for the new one
396
     * @param string $lexize     The name of the function, which does transformation of input word
397
     * @param string $init       The name of the function, which initializes dictionary
398
     * @param string $option     Usually, it stores various options required for the dictionary
399
     * @param string $comment    If omitted, defaults to nothing
400
     *
401
     * @return bool|int 0 success
402
     */
403
    public function createFtsDictionary(
404
        $dictname,
405
        $isTemplate = false,
406
        $template = '',
407
        $lexize = '',
408
        $init = '',
409
        $option = '',
410
        $comment = ''
411
    ) {
412
        $f_schema = $this->_schema;
413
        $this->fieldClean($f_schema);
414
        $this->fieldClean($dictname);
415
        $this->fieldClean($template);
416
        $this->fieldClean($lexize);
417
        $this->fieldClean($init);
418
        $this->fieldClean($option);
419
420
        $sql = 'CREATE TEXT SEARCH';
421
422
        if ($isTemplate) {
423
            $sql .= \sprintf(
424
                ' TEMPLATE "%s"."%s" (',
425
                $f_schema,
426
                $dictname
427
            );
428
429
            if ('' !== $lexize) {
430
                $sql .= \sprintf(
431
                    ' LEXIZE = %s',
432
                    $lexize
433
                );
434
            }
435
436
            if ('' !== $init) {
437
                $sql .= \sprintf(
438
                    ', INIT = %s',
439
                    $init
440
                );
441
            }
442
443
            $sql .= ')';
444
            $whatToComment = 'TEXT SEARCH TEMPLATE';
445
        } else {
446
            $sql .= \sprintf(
447
                ' DICTIONARY "%s"."%s" (',
448
                $f_schema,
449
                $dictname
450
            );
451
452
            if ('' !== $template) {
453
                $this->fieldClean($template['schema']);
454
                $this->fieldClean($template['name']);
455
                $template = \sprintf(
456
                    '"%s"."%s"',
457
                    $template['schema'],
458
                    $template['name']
459
                );
460
461
                $sql .= \sprintf(
462
                    ' TEMPLATE = %s',
463
                    $template
464
                );
465
            }
466
467
            if ('' !== $option) {
468
                $sql .= \sprintf(
469
                    ', %s',
470
                    $option
471
                );
472
            }
473
474
            $sql .= ')';
475
            $whatToComment = 'TEXT SEARCH DICTIONARY';
476
        }
477
478
        /* if comment, begin a transaction to
479
         * run both commands */
480
        if ('' !== $comment) {
481
            $status = $this->beginTransaction();
482
483
            if (0 !== $status) {
484
                return -1;
485
            }
486
        }
487
488
        // Create the FTS dictionary
489
        $status = $this->execute($sql);
490
491
        if (0 !== $status) {
492
            $this->rollbackTransaction();
493
494
            return -1;
495
        }
496
497
        // Set the comment
498
        if ('' !== $comment) {
499
            $status = $this->setComment($whatToComment, $dictname, '', $comment);
500
501
            if (0 !== $status) {
502
                $this->rollbackTransaction();
503
504
                return -1;
505
            }
506
        }
507
508
        return $this->endTransaction();
509
    }
510
511
    // Role, User/Group functions
512
513
    /**
514
     * Alters FTS dictionary or dictionary template.
515
     *
516
     * @param string $dictname The dico's name
517
     * @param string $comment  The comment
518
     * @param string $name     The new dico's name
519
     *
520
     * @return bool|int 0 on success
521
     */
522
    public function updateFtsDictionary($dictname, $comment, $name)
523
    {
524
        $status = $this->beginTransaction();
525
526
        if (0 !== $status) {
527
            $this->rollbackTransaction();
528
529
            return -1;
530
        }
531
532
        $this->fieldClean($dictname);
533
        $status = $this->setComment('TEXT SEARCH DICTIONARY', $dictname, '', $comment);
534
535
        if (0 !== $status) {
536
            $this->rollbackTransaction();
537
538
            return -1;
539
        }
540
541
        // Only if the name has changed
542
        if ($name !== $dictname) {
543
            $f_schema = $this->_schema;
544
            $this->fieldClean($f_schema);
545
            $this->fieldClean($name);
546
547
            $sql = \sprintf(
548
                'ALTER TEXT SEARCH DICTIONARY "%s"."%s" RENAME TO "%s"',
549
                $f_schema,
550
                $dictname,
551
                $name
552
            );
553
            $status = $this->execute($sql);
554
555
            if (0 !== $status) {
556
                $this->rollbackTransaction();
557
558
                return -1;
559
            }
560
        }
561
562
        return $this->endTransaction();
563
    }
564
565
    /**
566
     * Return all information relating to a FTS dictionary.
567
     *
568
     * @param string $ftsdict The name of the FTS dictionary
569
     *
570
     * @return ADORecordSet|int
571
     */
572
    public function getFtsDictionaryByName($ftsdict)
573
    {
574
        $c_schema = $this->_schema;
575
        $this->clean($c_schema);
576
        $this->clean($ftsdict);
577
578
        $sql = \sprintf(
579
            'SELECT
580
               n.nspname as schema,
581
               d.dictname as name,
582
               ( SELECT COALESCE(nt.nspname, \'(null)\')::pg_catalog.text || \'.\' || t.tmplname FROM
583
                 pg_catalog.pg_ts_template t
584
                                      LEFT JOIN pg_catalog.pg_namespace nt ON nt.oid = t.tmplnamespace
585
                                      WHERE d.dicttemplate = t.oid ) AS  template,
586
               d.dictinitoption as init,
587
               pg_catalog.obj_description(d.oid, \'pg_ts_dict\') as comment
588
            FROM pg_catalog.pg_ts_dict d
589
                LEFT JOIN pg_catalog.pg_namespace n ON n.oid = d.dictnamespace
590
            WHERE d.dictname = \'%s\'
591
               AND pg_catalog.pg_ts_dict_is_visible(d.oid)
592
               AND n.nspname=\'%s\'
593
            ORDER BY name',
594
            $ftsdict,
595
            $c_schema
596
        );
597
598
        return $this->selectSet($sql);
599
    }
600
601
    /**
602
     * Creates/updates/deletes FTS mapping.
603
     *
604
     * @param string $ftscfg   The name of the FTS dictionary
605
     * @param array  $mapping  Array of tokens' names
606
     * @param string $action   What to do with the mapping: add, alter or drop
607
     * @param string $dictname Dictionary that will process tokens given or null in case of drop action
608
     *
609
     * @return ADORecordSet|int
610
     *
611
     * @internal param string $cfgname The name of the FTS configuration to alter
612
     */
613
    public function changeFtsMapping($ftscfg, $mapping, $action, $dictname = null)
614
    {
615
        if (0 < \count($mapping)) {
616
            $f_schema = $this->_schema;
617
            $this->fieldClean($f_schema);
618
            $this->fieldClean($ftscfg);
619
            $this->fieldClean($dictname);
620
            $this->arrayClean($mapping);
621
622
            switch ($action) {
623
                case 'alter':
624
                    $whatToDo = 'ALTER';
625
626
                    break;
627
                case 'drop':
628
                    $whatToDo = 'DROP';
629
630
                    break;
631
632
                default:
633
                    $whatToDo = 'ADD';
634
635
                    break;
636
            }
637
638
            $sql = \sprintf(
639
                'ALTER TEXT SEARCH CONFIGURATION "%s"."%s" %s MAPPING FOR ',
640
                $f_schema,
641
                $ftscfg,
642
                $whatToDo
643
            );
644
            $sql .= \implode(',', $mapping);
645
646
            if ('drop' !== $action && !empty($dictname)) {
647
                $sql .= \sprintf(
648
                    ' WITH %s',
649
                    $dictname
650
                );
651
            }
652
653
            return $this->execute($sql);
654
        }
655
656
        return -1;
657
    }
658
659
    /**
660
     * Return all information related to a given FTS configuration's mapping.
661
     *
662
     * @param string $ftscfg  The name of the FTS configuration
663
     * @param string $mapping The name of the mapping
664
     *
665
     * @return ADORecordSet|int
666
     */
667
    public function getFtsMappingByName($ftscfg, $mapping)
668
    {
669
        $c_schema = $this->_schema;
670
        $this->clean($c_schema);
671
        $this->clean($ftscfg);
672
        $this->clean($mapping);
673
674
        $oidSet = $this->selectSet(\sprintf(
675
            'SELECT c.oid, cfgparser
676
            FROM pg_catalog.pg_ts_config AS c
677
                LEFT JOIN pg_catalog.pg_namespace AS n ON n.oid = c.cfgnamespace
678
            WHERE c.cfgname = \'%s\'
679
                AND n.nspname=\'%s\'',
680
            $ftscfg,
681
            $c_schema
682
        ));
683
684
        $oid = $oidSet->fields['oid'];
685
        $cfgparser = $oidSet->fields['cfgparser'];
686
687
        $tokenIdSet = $this->selectSet(\sprintf(
688
            'SELECT tokid
689
            FROM pg_catalog.ts_token_type(%s)
690
            WHERE alias = \'%s\'',
691
            $cfgparser,
692
            $mapping
693
        ));
694
695
        $tokid = $tokenIdSet->fields['tokid'];
696
697
        $sql = \sprintf(
698
            'SELECT
699
                (SELECT t.alias FROM pg_catalog.ts_token_type(c.cfgparser) AS t WHERE t.tokid = m.maptokentype) AS name,
700
                    d.dictname as dictionaries
701
            FROM pg_catalog.pg_ts_config AS c, pg_catalog.pg_ts_config_map AS m, pg_catalog.pg_ts_dict d
702
            WHERE c.oid = %s AND m.mapcfg = c.oid AND m.maptokentype = %s AND m.mapdict = d.oid
703
            LIMIT 1;',
704
            $oid,
705
            $tokid
706
        );
707
708
        return $this->selectSet($sql);
709
    }
710
711
    /**
712
     * Return list of FTS mappings possible for given parser
713
     * (specified by given configuration since configuration can only have 1 parser).
714
     *
715
     * @param string $ftscfg The config's name that use the parser
716
     *
717
     * @return ADORecordSet|int
718
     */
719
    public function getFtsMappings($ftscfg)
720
    {
721
        $cfg = $this->getFtsConfigurationByName($ftscfg);
722
723
        $sql = \sprintf(
724
            'SELECT alias AS name, description
725
            FROM pg_catalog.ts_token_type(%s)
726
            ORDER BY name',
727
            $cfg->fields['parser_id']
728
        );
729
730
        return $this->selectSet($sql);
731
    }
732
733
    /**
734
     * Return all information related to a FTS configuration.
735
     *
736
     * @param string $ftscfg The name of the FTS configuration
737
     *
738
     * @return ADORecordSet|int
739
     */
740
    public function getFtsConfigurationByName($ftscfg)
741
    {
742
        $c_schema = $this->_schema;
743
        $this->clean($c_schema);
744
        $this->clean($ftscfg);
745
        $sql = \sprintf(
746
            '
747
            SELECT
748
                n.nspname as schema,
749
                c.cfgname as name,
750
                p.prsname as parser,
751
                c.cfgparser as parser_id,
752
                pg_catalog.obj_description(c.oid, \'pg_ts_config\') as comment
753
            FROM pg_catalog.pg_ts_config c
754
                LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.cfgnamespace
755
                LEFT JOIN pg_catalog.pg_ts_parser p ON p.oid = c.cfgparser
756
            WHERE pg_catalog.pg_ts_config_is_visible(c.oid)
757
                AND c.cfgname = \'%s\'
758
                AND n.nspname=\'%s\'',
759
            $ftscfg,
760
            $c_schema
761
        );
762
763
        return $this->selectSet($sql);
764
    }
765
766
    abstract public function fieldClean(&$str);
767
768
    abstract public function beginTransaction();
769
770
    abstract public function rollbackTransaction();
771
772
    abstract public function endTransaction();
773
774
    abstract public function execute($sql);
775
776
    abstract public function setComment($obj_type, $obj_name, $table, $comment, $basetype = null);
777
778
    abstract public function selectSet($sql);
779
780
    abstract public function clean(&$str);
781
782
    abstract public function arrayClean(&$arr);
783
}
784