source: Dev/trunk/rdfapi/util/adodb/adodb-datadict.inc.php @ 12

Last change on this file since 12 was 12, checked in by basvannuland, 14 years ago

Added RAP RDF API
Added RDF reader writer for save and load survey

File size: 25.2 KB
RevLine 
[12]1<?php
2
3/**
4  V4.94 23 Jan 2007  (c) 2000-2007 John Lim (jlim#natsoft.com.my). All rights reserved.
5  Released under both BSD license and Lesser GPL library license.
6  Whenever there is any discrepancy between the two licenses,
7  the BSD license will take precedence.
8       
9  Set tabs to 4 for best viewing.
10 
11        DOCUMENTATION:
12       
13                See adodb/tests/test-datadict.php for docs and examples.
14*/
15
16/*
17        Test script for parser
18*/
19
20// security - hide paths
21if (!defined('ADODB_DIR')) die();
22
23function Lens_ParseTest()
24{
25$str = "`zcol ACOL` NUMBER(32,2) DEFAULT 'The \"cow\" (and Jim''s dog) jumps over the moon' PRIMARY, INTI INT AUTO DEFAULT 0, zcol2\"afs ds";
26print "<p>$str</p>";
27$a= Lens_ParseArgs($str);
28print "<pre>";
29print_r($a);
30print "</pre>";
31}
32
33
34if (!function_exists('ctype_alnum')) {
35        function ctype_alnum($text) {
36                return preg_match('/^[a-z0-9]*$/i', $text);
37        }
38}
39
40//Lens_ParseTest();
41
42/**
43        Parse arguments, treat "text" (text) and 'text' as quotation marks.
44        To escape, use "" or '' or ))
45       
46        Will read in "abc def" sans quotes, as: abc def
47        Same with 'abc def'.
48        However if `abc def`, then will read in as `abc def`
49       
50        @param endstmtchar    Character that indicates end of statement
51        @param tokenchars     Include the following characters in tokens apart from A-Z and 0-9
52        @returns 2 dimensional array containing parsed tokens.
53*/
54function Lens_ParseArgs($args,$endstmtchar=',',$tokenchars='_.-')
55{
56        $pos = 0;
57        $intoken = false;
58        $stmtno = 0;
59        $endquote = false;
60        $tokens = array();
61        $tokens[$stmtno] = array();
62        $max = strlen($args);
63        $quoted = false;
64        $tokarr = array();
65       
66        while ($pos < $max) {
67                $ch = substr($args,$pos,1);
68                switch($ch) {
69                case ' ':
70                case "\t":
71                case "\n":
72                case "\r":
73                        if (!$quoted) {
74                                if ($intoken) {
75                                        $intoken = false;
76                                        $tokens[$stmtno][] = implode('',$tokarr);
77                                }
78                                break;
79                        }
80                       
81                        $tokarr[] = $ch;
82                        break;
83               
84                case '`':
85                        if ($intoken) $tokarr[] = $ch;
86                case '(':
87                case ')':       
88                case '"':
89                case "'":
90                       
91                        if ($intoken) {
92                                if (empty($endquote)) {
93                                        $tokens[$stmtno][] = implode('',$tokarr);
94                                        if ($ch == '(') $endquote = ')';
95                                        else $endquote = $ch;
96                                        $quoted = true;
97                                        $intoken = true;
98                                        $tokarr = array();
99                                } else if ($endquote == $ch) {
100                                        $ch2 = substr($args,$pos+1,1);
101                                        if ($ch2 == $endquote) {
102                                                $pos += 1;
103                                                $tokarr[] = $ch2;
104                                        } else {
105                                                $quoted = false;
106                                                $intoken = false;
107                                                $tokens[$stmtno][] = implode('',$tokarr);
108                                                $endquote = '';
109                                        }
110                                } else
111                                        $tokarr[] = $ch;
112                                       
113                        }else {
114                       
115                                if ($ch == '(') $endquote = ')';
116                                else $endquote = $ch;
117                                $quoted = true;
118                                $intoken = true;
119                                $tokarr = array();
120                                if ($ch == '`') $tokarr[] = '`';
121                        }
122                        break;
123                       
124                default:
125                       
126                        if (!$intoken) {
127                                if ($ch == $endstmtchar) {
128                                        $stmtno += 1;
129                                        $tokens[$stmtno] = array();
130                                        break;
131                                }
132                       
133                                $intoken = true;
134                                $quoted = false;
135                                $endquote = false;
136                                $tokarr = array();
137       
138                        }
139                       
140                        if ($quoted) $tokarr[] = $ch;
141                        else if (ctype_alnum($ch) || strpos($tokenchars,$ch) !== false) $tokarr[] = $ch;
142                        else {
143                                if ($ch == $endstmtchar) {                     
144                                        $tokens[$stmtno][] = implode('',$tokarr);
145                                        $stmtno += 1;
146                                        $tokens[$stmtno] = array();
147                                        $intoken = false;
148                                        $tokarr = array();
149                                        break;
150                                }
151                                $tokens[$stmtno][] = implode('',$tokarr);
152                                $tokens[$stmtno][] = $ch;
153                                $intoken = false;
154                        }
155                }
156                $pos += 1;
157        }
158        if ($intoken) $tokens[$stmtno][] = implode('',$tokarr);
159       
160        return $tokens;
161}
162
163
164class ADODB_DataDict {
165        var $connection;
166        var $debug = false;
167        var $dropTable = 'DROP TABLE %s';
168        var $renameTable = 'RENAME TABLE %s TO %s';
169        var $dropIndex = 'DROP INDEX %s';
170        var $addCol = ' ADD';
171        var $alterCol = ' ALTER COLUMN';
172        var $dropCol = ' DROP COLUMN';
173        var $renameColumn = 'ALTER TABLE %s RENAME COLUMN %s TO %s';    // table, old-column, new-column, column-definitions (not used by default)
174        var $nameRegex = '\w';
175        var $nameRegexBrackets = 'a-zA-Z0-9_\(\)';
176        var $schema = false;
177        var $serverInfo = array();
178        var $autoIncrement = false;
179        var $dataProvider;
180        var $invalidResizeTypes4 = array('CLOB','BLOB','TEXT','DATE','TIME'); // for changetablesql
181        var $blobSize = 100;    /// any varchar/char field this size or greater is treated as a blob
182                                                        /// in other words, we use a text area for editting.
183       
184        function GetCommentSQL($table,$col)
185        {
186                return false;
187        }
188       
189        function SetCommentSQL($table,$col,$cmt)
190        {
191                return false;
192        }
193       
194        function MetaTables()
195        {
196                if (!$this->connection->IsConnected()) return array();
197                return $this->connection->MetaTables();
198        }
199       
200        function MetaColumns($tab, $upper=true, $schema=false)
201        {
202                if (!$this->connection->IsConnected()) return array();
203                return $this->connection->MetaColumns($this->TableName($tab), $upper, $schema);
204        }
205       
206        function MetaPrimaryKeys($tab,$owner=false,$intkey=false)
207        {
208                if (!$this->connection->IsConnected()) return array();
209                return $this->connection->MetaPrimaryKeys($this->TableName($tab), $owner, $intkey);
210        }
211       
212        function MetaIndexes($table, $primary = false, $owner = false)
213        {
214                if (!$this->connection->IsConnected()) return array();
215                return $this->connection->MetaIndexes($this->TableName($table), $primary, $owner);
216        }
217       
218        function MetaType($t,$len=-1,$fieldobj=false)
219        {
220                return ADORecordSet::MetaType($t,$len,$fieldobj);
221        }
222       
223        function NameQuote($name = NULL,$allowBrackets=false)
224        {
225                if (!is_string($name)) {
226                        return FALSE;
227                }
228               
229                $name = trim($name);
230               
231                if ( !is_object($this->connection) ) {
232                        return $name;
233                }
234               
235                $quote = $this->connection->nameQuote;
236               
237                // if name is of the form `name`, quote it
238                if ( preg_match('/^`(.+)`$/', $name, $matches) ) {
239                        return $quote . $matches[1] . $quote;
240                }
241               
242                // if name contains special characters, quote it
243                $regex = ($allowBrackets) ? $this->nameRegexBrackets : $this->nameRegex;
244               
245                if ( !preg_match('/^[' . $regex . ']+$/', $name) ) {
246                        return $quote . $name . $quote;
247                }
248               
249                return $name;
250        }
251       
252        function TableName($name)
253        {
254                if ( $this->schema ) {
255                        return $this->NameQuote($this->schema) .'.'. $this->NameQuote($name);
256                }
257                return $this->NameQuote($name);
258        }
259       
260        // Executes the sql array returned by GetTableSQL and GetIndexSQL
261        function ExecuteSQLArray($sql, $continueOnError = true)
262        {
263                $rez = 2;
264                $conn = &$this->connection;
265                $saved = $conn->debug;
266                foreach($sql as $line) {
267                       
268                        if ($this->debug) $conn->debug = true;
269                        $ok = $conn->Execute($line);
270                        $conn->debug = $saved;
271                        if (!$ok) {
272                                if ($this->debug) ADOConnection::outp($conn->ErrorMsg());
273                                if (!$continueOnError) return 0;
274                                $rez = 1;
275                        }
276                }
277                return $rez;
278        }
279       
280        /**
281                Returns the actual type given a character code.
282               
283                C:  varchar
284                X:  CLOB (character large object) or largest varchar size if CLOB is not supported
285                C2: Multibyte varchar
286                X2: Multibyte CLOB
287               
288                B:  BLOB (binary large object)
289               
290                D:  Date
291                T:  Date-time
292                L:  Integer field suitable for storing booleans (0 or 1)
293                I:  Integer
294                F:  Floating point number
295                N:  Numeric or decimal number
296        */
297       
298        function ActualType($meta)
299        {
300                return $meta;
301        }
302       
303        function CreateDatabase($dbname,$options=false)
304        {
305                $options = $this->_Options($options);
306                $sql = array();
307               
308                $s = 'CREATE DATABASE ' . $this->NameQuote($dbname);
309                if (isset($options[$this->upperName]))
310                        $s .= ' '.$options[$this->upperName];
311               
312                $sql[] = $s;
313                return $sql;
314        }
315       
316        /*
317         Generates the SQL to create index. Returns an array of sql strings.
318        */
319        function CreateIndexSQL($idxname, $tabname, $flds, $idxoptions = false)
320        {
321                if (!is_array($flds)) {
322                        $flds = explode(',',$flds);
323                }
324               
325                foreach($flds as $key => $fld) {
326                        # some indexes can use partial fields, eg. index first 32 chars of "name" with NAME(32)
327                        $flds[$key] = $this->NameQuote($fld,$allowBrackets=true);
328                }
329               
330                return $this->_IndexSQL($this->NameQuote($idxname), $this->TableName($tabname), $flds, $this->_Options($idxoptions));
331        }
332       
333        function DropIndexSQL ($idxname, $tabname = NULL)
334        {
335                return array(sprintf($this->dropIndex, $this->NameQuote($idxname), $this->TableName($tabname)));
336        }
337       
338        function SetSchema($schema)
339        {
340                $this->schema = $schema;
341        }
342       
343        function AddColumnSQL($tabname, $flds)
344        {
345                $tabname = $this->TableName ($tabname);
346                $sql = array();
347                list($lines,$pkey,$idxs) = $this->_GenFields($flds);
348                // genfields can return FALSE at times
349                if ($lines  == null) $lines = array();
350                $alter = 'ALTER TABLE ' . $tabname . $this->addCol . ' ';
351                foreach($lines as $v) {
352                        $sql[] = $alter . $v;
353                }
354                if (is_array($idxs)) {
355                        foreach($idxs as $idx => $idxdef) {
356                                $sql_idxs = $this->CreateIndexSql($idx, $tabname, $idxdef['cols'], $idxdef['opts']);
357                                $sql = array_merge($sql, $sql_idxs);
358                        }
359                }
360                return $sql;
361        }
362       
363        /**
364         * Change the definition of one column
365         *
366         * As some DBM's can't do that on there own, you need to supply the complete defintion of the new table,
367         * to allow, recreating the table and copying the content over to the new table
368         * @param string $tabname table-name
369         * @param string $flds column-name and type for the changed column
370         * @param string $tableflds='' complete defintion of the new table, eg. for postgres, default ''
371         * @param array/string $tableoptions='' options for the new table see CreateTableSQL, default ''
372         * @return array with SQL strings
373         */
374        function AlterColumnSQL($tabname, $flds, $tableflds='',$tableoptions='')
375        {
376                $tabname = $this->TableName ($tabname);
377                $sql = array();
378                list($lines,$pkey,$idxs) = $this->_GenFields($flds);
379                // genfields can return FALSE at times
380                if ($lines == null) $lines = array();
381                $alter = 'ALTER TABLE ' . $tabname . $this->alterCol . ' ';
382                foreach($lines as $v) {
383                        $sql[] = $alter . $v;
384                }
385                if (is_array($idxs)) {
386                        foreach($idxs as $idx => $idxdef) {
387                                $sql_idxs = $this->CreateIndexSql($idx, $tabname, $idxdef['cols'], $idxdef['opts']);
388                                $sql = array_merge($sql, $sql_idxs);
389                        }
390
391                }
392                return $sql;
393        }
394       
395        /**
396         * Rename one column
397         *
398         * Some DBM's can only do this together with changeing the type of the column (even if that stays the same, eg. mysql)
399         * @param string $tabname table-name
400         * @param string $oldcolumn column-name to be renamed
401         * @param string $newcolumn new column-name
402         * @param string $flds='' complete column-defintion-string like for AddColumnSQL, only used by mysql atm., default=''
403         * @return array with SQL strings
404         */
405        function RenameColumnSQL($tabname,$oldcolumn,$newcolumn,$flds='')
406        {
407                $tabname = $this->TableName ($tabname);
408                if ($flds) {
409                        list($lines,$pkey,$idxs) = $this->_GenFields($flds);
410                        // genfields can return FALSE at times
411                        if ($lines == null) $lines = array();
412                        list(,$first) = each($lines);
413                        list(,$column_def) = split("[\t ]+",$first,2);
414                }
415                return array(sprintf($this->renameColumn,$tabname,$this->NameQuote($oldcolumn),$this->NameQuote($newcolumn),$column_def));
416        }
417               
418        /**
419         * Drop one column
420         *
421         * Some DBM's can't do that on there own, you need to supply the complete defintion of the new table,
422         * to allow, recreating the table and copying the content over to the new table
423         * @param string $tabname table-name
424         * @param string $flds column-name and type for the changed column
425         * @param string $tableflds='' complete defintion of the new table, eg. for postgres, default ''
426         * @param array/string $tableoptions='' options for the new table see CreateTableSQL, default ''
427         * @return array with SQL strings
428         */
429        function DropColumnSQL($tabname, $flds, $tableflds='',$tableoptions='')
430        {
431                $tabname = $this->TableName ($tabname);
432                if (!is_array($flds)) $flds = explode(',',$flds);
433                $sql = array();
434                $alter = 'ALTER TABLE ' . $tabname . $this->dropCol . ' ';
435                foreach($flds as $v) {
436                        $sql[] = $alter . $this->NameQuote($v);
437                }
438                return $sql;
439        }
440       
441        function DropTableSQL($tabname)
442        {
443                return array (sprintf($this->dropTable, $this->TableName($tabname)));
444        }
445       
446        function RenameTableSQL($tabname,$newname)
447        {
448                return array (sprintf($this->renameTable, $this->TableName($tabname),$this->TableName($newname)));
449        }       
450       
451        /**
452         Generate the SQL to create table. Returns an array of sql strings.
453        */
454        function CreateTableSQL($tabname, $flds, $tableoptions=array())
455        {
456                list($lines,$pkey,$idxs) = $this->_GenFields($flds, true);
457                // genfields can return FALSE at times
458                if ($lines == null) $lines = array();
459               
460                $taboptions = $this->_Options($tableoptions);
461                $tabname = $this->TableName ($tabname);
462                $sql = $this->_TableSQL($tabname,$lines,$pkey,$taboptions);
463               
464                // ggiunta - 2006/10/12 - KLUDGE:
465        // if we are on autoincrement, and table options includes REPLACE, the
466        // autoincrement sequence has already been dropped on table creation sql, so
467        // we avoid passing REPLACE to trigger creation code. This prevents
468        // creating sql that double-drops the sequence
469        if ($this->autoIncrement && isset($taboptions['REPLACE']))
470                unset($taboptions['REPLACE']);
471                $tsql = $this->_Triggers($tabname,$taboptions);
472                foreach($tsql as $s) $sql[] = $s;
473               
474                if (is_array($idxs)) {
475                        foreach($idxs as $idx => $idxdef) {
476                                $sql_idxs = $this->CreateIndexSql($idx, $tabname,  $idxdef['cols'], $idxdef['opts']);
477                                $sql = array_merge($sql, $sql_idxs);
478                        }
479                }
480
481                return $sql;
482        }
483       
484        function _GenFields($flds,$widespacing=false)
485        {
486                if (is_string($flds)) {
487                        $padding = '     ';
488                        $txt = $flds.$padding;
489                        $flds = array();
490                        $flds0 = Lens_ParseArgs($txt,',');
491                        $hasparam = false;
492                        foreach($flds0 as $f0) {
493                                $f1 = array();
494                                foreach($f0 as $token) {
495                                        switch (strtoupper($token)) {
496                                        case 'INDEX':
497                                                $f1['INDEX'] = '';
498                                                // fall through intentionally
499                                        case 'CONSTRAINT':
500                                        case 'DEFAULT':
501                                                $hasparam = $token;
502                                                break;
503                                        default:
504                                                if ($hasparam) $f1[$hasparam] = $token;
505                                                else $f1[] = $token;
506                                                $hasparam = false;
507                                                break;
508                                        }
509                                }
510                                // 'index' token without a name means single column index: name it after column
511                                if (array_key_exists('INDEX', $f1) && $f1['INDEX'] == '') {
512                                        $f1['INDEX'] = isset($f0['NAME']) ? $f0['NAME'] : $f0[0];
513                                        // check if column name used to create an index name was quoted
514                                        if (($f1['INDEX'][0] == '"' || $f1['INDEX'][0] == "'" || $f1['INDEX'][0] == "`") &&
515                                                ($f1['INDEX'][0] == substr($f1['INDEX'], -1))) {
516                                                $f1['INDEX'] = $f1['INDEX'][0].'idx_'.substr($f1['INDEX'], 1, -1).$f1['INDEX'][0];
517                                        }
518                                        else
519                                                $f1['INDEX'] = 'idx_'.$f1['INDEX'];
520                                }
521                                // reset it, so we don't get next field 1st token as INDEX...
522                                $hasparam = false;
523
524                                $flds[] = $f1;
525                               
526                        }
527                }
528                $this->autoIncrement = false;
529                $lines = array();
530                $pkey = array();
531                $idxs = array();
532                foreach($flds as $fld) {
533                        $fld = _array_change_key_case($fld);
534                       
535                        $fname = false;
536                        $fdefault = false;
537                        $fautoinc = false;
538                        $ftype = false;
539                        $fsize = false;
540                        $fprec = false;
541                        $fprimary = false;
542                        $fnoquote = false;
543                        $fdefts = false;
544                        $fdefdate = false;
545                        $fconstraint = false;
546                        $fnotnull = false;
547                        $funsigned = false;
548                        $findex = '';
549                        $funiqueindex = false;
550                       
551                        //-----------------
552                        // Parse attributes
553                        foreach($fld as $attr => $v) {
554                                if ($attr == 2 && is_numeric($v)) $attr = 'SIZE';
555                                else if (is_numeric($attr) && $attr > 1 && !is_numeric($v)) $attr = strtoupper($v);
556                               
557                                switch($attr) {
558                                case '0':
559                                case 'NAME':    $fname = $v; break;
560                                case '1':
561                                case 'TYPE':    $ty = $v; $ftype = $this->ActualType(strtoupper($v)); break;
562                               
563                                case 'SIZE':   
564                                                                $dotat = strpos($v,'.'); if ($dotat === false) $dotat = strpos($v,',');
565                                                                if ($dotat === false) $fsize = $v;
566                                                                else {
567                                                                        $fsize = substr($v,0,$dotat);
568                                                                        $fprec = substr($v,$dotat+1);
569                                                                }
570                                                                break;
571                                case 'UNSIGNED': $funsigned = true; break;
572                                case 'AUTOINCREMENT':
573                                case 'AUTO':    $fautoinc = true; $fnotnull = true; break;
574                                case 'KEY':
575                // a primary key col can be non unique in itself (if key spans many cols...)
576                                case 'PRIMARY': $fprimary = $v; $fnotnull = true; /*$funiqueindex = true;*/ break;
577                                case 'DEF':
578                                case 'DEFAULT': $fdefault = $v; break;
579                                case 'NOTNULL': $fnotnull = $v; break;
580                                case 'NOQUOTE': $fnoquote = $v; break;
581                                case 'DEFDATE': $fdefdate = $v; break;
582                                case 'DEFTIMESTAMP': $fdefts = $v; break;
583                                case 'CONSTRAINT': $fconstraint = $v; break;
584                                // let INDEX keyword create a 'very standard' index on column
585                                case 'INDEX': $findex = $v; break;
586                                case 'UNIQUE': $funiqueindex = true; break;
587                                } //switch
588                        } // foreach $fld
589                       
590                        //--------------------
591                        // VALIDATE FIELD INFO
592                        if (!strlen($fname)) {
593                                if ($this->debug) ADOConnection::outp("Undefined NAME");
594                                return false;
595                        }
596                       
597                        $fid = strtoupper(preg_replace('/^`(.+)`$/', '$1', $fname));
598                        $fname = $this->NameQuote($fname);
599                       
600                        if (!strlen($ftype)) {
601                                if ($this->debug) ADOConnection::outp("Undefined TYPE for field '$fname'");
602                                return false;
603                        } else {
604                                $ftype = strtoupper($ftype);
605                        }
606                       
607                        $ftype = $this->_GetSize($ftype, $ty, $fsize, $fprec);
608                       
609                        if ($ty == 'X' || $ty == 'X2' || $ty == 'B') $fnotnull = false; // some blob types do not accept nulls
610                       
611                        if ($fprimary) $pkey[] = $fname;
612                       
613                        // some databases do not allow blobs to have defaults
614                        if ($ty == 'X') $fdefault = false;
615                       
616                        // build list of indexes
617                        if ($findex != '') {
618                                if (array_key_exists($findex, $idxs)) {
619                                        $idxs[$findex]['cols'][] = ($fname);
620                                        if (in_array('UNIQUE', $idxs[$findex]['opts']) != $funiqueindex) {
621                                                if ($this->debug) ADOConnection::outp("Index $findex defined once UNIQUE and once not");
622                                        }
623                                        if ($funiqueindex && !in_array('UNIQUE', $idxs[$findex]['opts']))
624                                                $idxs[$findex]['opts'][] = 'UNIQUE';
625                                }
626                                else
627                                {
628                                        $idxs[$findex] = array();
629                                        $idxs[$findex]['cols'] = array($fname);
630                                        if ($funiqueindex)
631                                                $idxs[$findex]['opts'] = array('UNIQUE');
632                                        else
633                                                $idxs[$findex]['opts'] = array();
634                                }
635                        }
636
637                        //--------------------
638                        // CONSTRUCT FIELD SQL
639                        if ($fdefts) {
640                                if (substr($this->connection->databaseType,0,5) == 'mysql') {
641                                        $ftype = 'TIMESTAMP';
642                                } else {
643                                        $fdefault = $this->connection->sysTimeStamp;
644                                }
645                        } else if ($fdefdate) {
646                                if (substr($this->connection->databaseType,0,5) == 'mysql') {
647                                        $ftype = 'TIMESTAMP';
648                                } else {
649                                        $fdefault = $this->connection->sysDate;
650                                }
651                        } else if ($fdefault !== false && !$fnoquote) {
652                                if ($ty == 'C' or $ty == 'X' or
653                                        ( substr($fdefault,0,1) != "'" && !is_numeric($fdefault))) {
654
655                                        if (($ty == 'D' || $ty == 'T') && strtolower($fdefault) != 'null') {
656                                                // convert default date into database-aware code
657                                                if ($ty == 'T')
658                                                {
659                                                        $fdefault = $this->connection->DBTimeStamp($fdefault);
660                                                }
661                                                else
662                                                {
663                                                        $fdefault = $this->connection->DBDate($fdefault);
664                                                }
665                                        }
666                                        else
667                                        if (strlen($fdefault) != 1 && substr($fdefault,0,1) == ' ' && substr($fdefault,strlen($fdefault)-1) == ' ')
668                                                $fdefault = trim($fdefault);
669                                        else if (strtolower($fdefault) != 'null')
670                                                $fdefault = $this->connection->qstr($fdefault);
671                                }
672                        }
673                        $suffix = $this->_CreateSuffix($fname,$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint,$funsigned);
674                       
675                        // add index creation
676                        if ($widespacing) $fname = str_pad($fname,24);
677                       
678                         // check for field names appearing twice
679            if (array_key_exists($fid, $lines)) {
680                 ADOConnection::outp("Field '$fname' defined twice");
681            }
682                       
683                        $lines[$fid] = $fname.' '.$ftype.$suffix;
684                       
685                        if ($fautoinc) $this->autoIncrement = true;
686                } // foreach $flds
687               
688                return array($lines,$pkey,$idxs);
689        }
690
691        /**
692                 GENERATE THE SIZE PART OF THE DATATYPE
693                        $ftype is the actual type
694                        $ty is the type defined originally in the DDL
695        */
696        function _GetSize($ftype, $ty, $fsize, $fprec)
697        {
698                if (strlen($fsize) && $ty != 'X' && $ty != 'B' && strpos($ftype,'(') === false) {
699                        $ftype .= "(".$fsize;
700                        if (strlen($fprec)) $ftype .= ",".$fprec;
701                        $ftype .= ')';
702                }
703                return $ftype;
704        }
705       
706       
707        // return string must begin with space
708        function _CreateSuffix($fname,$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint)
709        {       
710                $suffix = '';
711                if (strlen($fdefault)) $suffix .= " DEFAULT $fdefault";
712                if ($fnotnull) $suffix .= ' NOT NULL';
713                if ($fconstraint) $suffix .= ' '.$fconstraint;
714                return $suffix;
715        }
716       
717        function _IndexSQL($idxname, $tabname, $flds, $idxoptions)
718        {
719                $sql = array();
720               
721                if ( isset($idxoptions['REPLACE']) || isset($idxoptions['DROP']) ) {
722                        $sql[] = sprintf ($this->dropIndex, $idxname);
723                        if ( isset($idxoptions['DROP']) )
724                                return $sql;
725                }
726               
727                if ( empty ($flds) ) {
728                        return $sql;
729                }
730               
731                $unique = isset($idxoptions['UNIQUE']) ? ' UNIQUE' : '';
732       
733                $s = 'CREATE' . $unique . ' INDEX ' . $idxname . ' ON ' . $tabname . ' ';
734               
735                if ( isset($idxoptions[$this->upperName]) )
736                        $s .= $idxoptions[$this->upperName];
737               
738                if ( is_array($flds) )
739                        $flds = implode(', ',$flds);
740                $s .= '(' . $flds . ')';
741                $sql[] = $s;
742               
743                return $sql;
744        }
745       
746        function _DropAutoIncrement($tabname)
747        {
748                return false;
749        }
750       
751        function _TableSQL($tabname,$lines,$pkey,$tableoptions)
752        {
753                $sql = array();
754               
755                if (isset($tableoptions['REPLACE']) || isset ($tableoptions['DROP'])) {
756                        $sql[] = sprintf($this->dropTable,$tabname);
757                        if ($this->autoIncrement) {
758                                $sInc = $this->_DropAutoIncrement($tabname);
759                                if ($sInc) $sql[] = $sInc;
760                        }
761                        if ( isset ($tableoptions['DROP']) ) {
762                                return $sql;
763                        }
764                }
765                $s = "CREATE TABLE $tabname (\n";
766                $s .= implode(",\n", $lines);
767                if (sizeof($pkey)>0) {
768                        $s .= ",\n                 PRIMARY KEY (";
769                        $s .= implode(", ",$pkey).")";
770                }
771                if (isset($tableoptions['CONSTRAINTS']))
772                        $s .= "\n".$tableoptions['CONSTRAINTS'];
773               
774                if (isset($tableoptions[$this->upperName.'_CONSTRAINTS']))
775                        $s .= "\n".$tableoptions[$this->upperName.'_CONSTRAINTS'];
776               
777                $s .= "\n)";
778                if (isset($tableoptions[$this->upperName])) $s .= $tableoptions[$this->upperName];
779                $sql[] = $s;
780               
781                return $sql;
782        }
783       
784        /**
785                GENERATE TRIGGERS IF NEEDED
786                used when table has auto-incrementing field that is emulated using triggers
787        */
788        function _Triggers($tabname,$taboptions)
789        {
790                return array();
791        }
792       
793        /**
794                Sanitize options, so that array elements with no keys are promoted to keys
795        */
796        function _Options($opts)
797        {
798                if (!is_array($opts)) return array();
799                $newopts = array();
800                foreach($opts as $k => $v) {
801                        if (is_numeric($k)) $newopts[strtoupper($v)] = $v;
802                        else $newopts[strtoupper($k)] = $v;
803                }
804                return $newopts;
805        }
806       
807        /**
808        "Florian Buzin [ easywe ]" <florian.buzin#easywe.de>
809       
810        This function changes/adds new fields to your table. You don't
811        have to know if the col is new or not. It will check on its own.
812        */
813        function ChangeTableSQL($tablename, $flds, $tableoptions = false)
814        {
815        global $ADODB_FETCH_MODE;
816       
817                $save = $ADODB_FETCH_MODE;
818                $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
819                if ($this->connection->fetchMode !== false) $savem = $this->connection->SetFetchMode(false);
820               
821                // check table exists
822                $save_handler = $this->connection->raiseErrorFn;
823                $this->connection->raiseErrorFn = '';
824                $cols = $this->MetaColumns($tablename);
825                $this->connection->raiseErrorFn = $save_handler;
826               
827                if (isset($savem)) $this->connection->SetFetchMode($savem);
828                $ADODB_FETCH_MODE = $save;
829               
830                if ( empty($cols)) {
831                        return $this->CreateTableSQL($tablename, $flds, $tableoptions);
832                }
833               
834                if (is_array($flds)) {
835                // Cycle through the update fields, comparing
836                // existing fields to fields to update.
837                // if the Metatype and size is exactly the
838                // same, ignore - by Mark Newham
839                        $holdflds = array();
840                        foreach($flds as $k=>$v) {
841                                if ( isset($cols[$k]) && is_object($cols[$k]) ) {
842                                        // If already not allowing nulls, then don't change
843                                        $obj = $cols[$k];
844                                        if (isset($obj->not_null) && $obj->not_null)
845                                                $v = str_replace('NOT NULL','',$v);
846
847                                        $c = $cols[$k];
848                                        $ml = $c->max_length;
849                                        $mt = $this->MetaType($c->type,$ml);
850                                        if ($ml == -1) $ml = '';
851                                        if ($mt == 'X') $ml = $v['SIZE'];
852                                        if (($mt != $v['TYPE']) ||  $ml != $v['SIZE']) {
853                                                $holdflds[$k] = $v;
854                                        }
855                                } else {
856                                        $holdflds[$k] = $v;
857                                }               
858                        }
859                        $flds = $holdflds;
860                }
861       
862
863                // already exists, alter table instead
864                list($lines,$pkey,$idxs) = $this->_GenFields($flds);
865                // genfields can return FALSE at times
866                if ($lines == null) $lines = array();
867                $alter = 'ALTER TABLE ' . $this->TableName($tablename);
868                $sql = array();
869
870                foreach ( $lines as $id => $v ) {
871                        if ( isset($cols[$id]) && is_object($cols[$id]) ) {
872                       
873                                $flds = Lens_ParseArgs($v,',');
874                               
875                                //  We are trying to change the size of the field, if not allowed, simply ignore the request.
876                                if ($flds && in_array(strtoupper(substr($flds[0][1],0,4)),$this->invalidResizeTypes4)) {
877                                        echo "<h3>$this->alterCol cannot be changed to $flds currently</h3>";
878                                        continue;       
879                                }
880                                $sql[] = $alter . $this->alterCol . ' ' . $v;
881                        } else {
882                                $sql[] = $alter . $this->addCol . ' ' . $v;
883                        }
884                }
885               
886                return $sql;
887        }
888} // class
889?>
Note: See TracBrowser for help on using the repository browser.