| [ Index ] |
PHP Cross Reference of Moodle 1.9.3 [Build 15-Oct-2008] |
[Summary view] [Print] [Text view]
1 <?php // $Id: mssql.class.php,v 1.41 2007/10/10 05:25:18 nicolasconnault Exp $ 2 3 /////////////////////////////////////////////////////////////////////////// 4 // // 5 // NOTICE OF COPYRIGHT // 6 // // 7 // Moodle - Modular Object-Oriented Dynamic Learning Environment // 8 // http://moodle.com // 9 // // 10 // Copyright (C) 1999 onwards Martin Dougiamas http://dougiamas.com // 11 // (C) 2001-3001 Eloy Lafuente (stronk7) http://contiento.com // 12 // // 13 // This program is free software; you can redistribute it and/or modify // 14 // it under the terms of the GNU General Public License as published by // 15 // the Free Software Foundation; either version 2 of the License, or // 16 // (at your option) any later version. // 17 // // 18 // This program is distributed in the hope that it will be useful, // 19 // but WITHOUT ANY WARRANTY; without even the implied warranty of // 20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // 21 // GNU General Public License for more details: // 22 // // 23 // http://www.gnu.org/copyleft/gpl.html // 24 // // 25 /////////////////////////////////////////////////////////////////////////// 26 27 /// This class generate SQL code to be used against MSSQL 28 /// It extends XMLDBgenerator so everything can be 29 /// overriden as needed to generate correct SQL. 30 31 class XMLDBmssql extends XMLDBgenerator { 32 33 /// Only set values that are different from the defaults present in XMLDBgenerator 34 35 var $statement_end = "\ngo"; // String to be automatically added at the end of each statement 36 37 var $number_type = 'DECIMAL'; // Proper type for NUMBER(x) in this DB 38 39 var $unsigned_allowed = false; // To define in the generator must handle unsigned information 40 var $default_for_char = ''; // To define the default to set for NOT NULLs CHARs without default (null=do nothing) 41 42 var $specify_nulls = true; //To force the generator if NULL clauses must be specified. It shouldn't be necessary 43 //but some mssql drivers require them or everything is created as NOT NULL :-( 44 45 var $sequence_extra_code = false; //Does the generator need to add extra code to generate the sequence fields 46 var $sequence_name = 'IDENTITY(1,1)'; //Particular name for inline sequences in this generator 47 var $sequence_only = false; //To avoid to output the rest of the field specs, leaving only the name and the sequence_name variable 48 49 var $enum_inline_code = false; //Does the generator need to add inline code in the column definition 50 51 var $add_table_comments = false; // Does the generator need to add code for table comments 52 53 var $concat_character = '+'; //Characters to be used as concatenation operator. If not defined 54 //MySQL CONCAT function will be use 55 56 var $rename_table_sql = "sp_rename 'OLDNAME', 'NEWNAME'"; //SQL sentence to rename one table, both 57 //OLDNAME and NEWNAME are dinamically replaced 58 59 var $rename_table_extra_code = true; //Does the generator need to add code after table rename 60 61 var $rename_column_extra_code = true; //Does the generator need to add code after field rename 62 63 var $rename_column_sql = "sp_rename 'TABLENAME.OLDFIELDNAME', 'NEWFIELDNAME', 'COLUMN'"; 64 ///TABLENAME, OLDFIELDNAME and NEWFIELDNAME are dianmically replaced 65 66 var $drop_index_sql = 'DROP INDEX TABLENAME.INDEXNAME'; //SQL sentence to drop one index 67 //TABLENAME, INDEXNAME are dinamically replaced 68 69 var $rename_index_sql = "sp_rename 'TABLENAME.OLDINDEXNAME', 'NEWINDEXNAME', 'INDEX'"; //SQL sentence to rename one index 70 //TABLENAME, OLDINDEXNAME, NEWINDEXNAME are dinamically replaced 71 72 var $rename_key_sql = null; //SQL sentence to rename one key 73 //TABLENAME, OLDKEYNAME, NEWKEYNAME are dinamically replaced 74 75 /** 76 * Creates one new XMLDBmssql 77 */ 78 function XMLDBmssql() { 79 parent::XMLDBgenerator(); 80 $this->prefix = ''; 81 $this->reserved_words = $this->getReservedWords(); 82 } 83 84 /** 85 * Given one XMLDB Type, lenght and decimals, returns the DB proper SQL type 86 */ 87 function getTypeSQL ($xmldb_type, $xmldb_length=null, $xmldb_decimals=null) { 88 89 switch ($xmldb_type) { 90 case XMLDB_TYPE_INTEGER: // From http://msdn.microsoft.com/library/en-us/tsqlref/ts_da-db_7msw.asp?frame=true 91 if (empty($xmldb_length)) { 92 $xmldb_length = 10; 93 } 94 if ($xmldb_length > 9) { 95 $dbtype = 'BIGINT'; 96 } else if ($xmldb_length > 4) { 97 $dbtype = 'INTEGER'; 98 } else { 99 $dbtype = 'SMALLINT'; 100 } 101 break; 102 case XMLDB_TYPE_NUMBER: 103 $dbtype = $this->number_type; 104 if (!empty($xmldb_length)) { 105 /// 38 is the max allowed 106 if ($xmldb_length > 38) { 107 $xmldb_length = 38; 108 } 109 $dbtype .= '(' . $xmldb_length; 110 if (!empty($xmldb_decimals)) { 111 $dbtype .= ',' . $xmldb_decimals; 112 } 113 $dbtype .= ')'; 114 } 115 break; 116 case XMLDB_TYPE_FLOAT: 117 $dbtype = 'FLOAT'; 118 if (!empty($xmldb_decimals)) { 119 if ($xmldb_decimals < 6) { 120 $dbtype = 'REAL'; 121 } 122 } 123 break; 124 case XMLDB_TYPE_CHAR: 125 $dbtype = 'NVARCHAR'; 126 if (empty($xmldb_length)) { 127 $xmldb_length='255'; 128 } 129 $dbtype .= '(' . $xmldb_length . ')'; 130 break; 131 case XMLDB_TYPE_TEXT: 132 $dbtype = 'NTEXT'; 133 break; 134 case XMLDB_TYPE_BINARY: 135 $dbtype = 'IMAGE'; 136 break; 137 case XMLDB_TYPE_DATETIME: 138 $dbtype = 'DATETIME'; 139 break; 140 } 141 return $dbtype; 142 } 143 144 /** 145 * Returns the code needed to create one enum for the xmldb_table and xmldb_field passes 146 */ 147 function getEnumExtraSQL ($xmldb_table, $xmldb_field) { 148 149 $sql = 'CONSTRAINT ' . $this->getNameForObject($xmldb_table->getName(), $xmldb_field->getName(), 'ck'); 150 $sql.= ' CHECK (' . $this->getEncQuoted($xmldb_field->getName()) . ' IN (' . implode(', ', $xmldb_field->getEnumValues()) . '))'; 151 152 return $sql; 153 } 154 155 /** 156 * Given one XMLDBTable and one XMLDBField, return the SQL statements needded to drop the field from the table 157 * MSSQL overwrites the standard sentence because it needs to do some extra work dropping the default and 158 * check constraints 159 */ 160 function getDropFieldSQL($xmldb_table, $xmldb_field) { 161 162 global $db; 163 164 $results = array(); 165 166 /// Get the quoted name of the table and field 167 $tablename = $this->getTableName($xmldb_table); 168 $fieldname = $this->getEncQuoted($xmldb_field->getName()); 169 170 /// Look for any default constraint in this field and drop it 171 if ($defaultname = $this->getDefaultConstraintName($xmldb_table, $xmldb_field)) { 172 $results[] = 'ALTER TABLE ' . $tablename . ' DROP CONSTRAINT ' . $defaultname; 173 } 174 175 /// Look for any check constraint in this field and drop it 176 if ($drop_check = $this->getDropEnumSQL($xmldb_table, $xmldb_field)) { 177 $results = array_merge($results, $drop_check); 178 } 179 180 /// Build the standard alter table drop column 181 $results[] = 'ALTER TABLE ' . $tablename . ' DROP COLUMN ' . $fieldname; 182 183 return $results; 184 } 185 186 /** 187 * Given one correct XMLDBField and the new name, returns the SQL statements 188 * to rename it (inside one array) 189 * MSSQL is special, so we overload the function here. It needs to 190 * drop the constraints BEFORE renaming the field 191 */ 192 function getRenameFieldSQL($xmldb_table, $xmldb_field, $newname) { 193 194 $results = array(); //Array where all the sentences will be stored 195 196 /// Although this is checked in ddllib - rename_field() - double check 197 /// that we aren't trying to rename one "id" field. Although it could be 198 /// implemented (if adding the necessary code to rename sequences, defaults, 199 /// triggers... and so on under each getRenameFieldExtraSQL() function, it's 200 /// better to forbide it, mainly because this field is the default PK and 201 /// in the future, a lot of FKs can be pointing here. So, this field, more 202 /// or less, must be considered inmutable! 203 if ($xmldb_field->getName() == 'id') { 204 return array(); 205 } 206 207 /// Drop the check constraint if exists 208 if ($xmldb_field->getEnum()) { 209 $results = array_merge($results, $this->getDropEnumSQL($xmldb_table, $xmldb_field)); 210 } 211 212 /// Call to standard (parent) getRenameFieldSQL() function 213 $results = array_merge($results, parent::getRenameFieldSQL($xmldb_table, $xmldb_field, $newname)); 214 215 return $results; 216 } 217 218 /** 219 * Returns the code (array of statements) needed to execute extra statements on field rename 220 */ 221 function getRenameFieldExtraSQL ($xmldb_table, $xmldb_field, $newname) { 222 223 $results = array(); 224 225 /// If the field is enum, drop and re-create the check constraint 226 if ($xmldb_field->getEnum()) { 227 /// Drop the current enum (not needed, it has been dropped before for msqql (in getRenameFieldSQL) 228 //$results = array_merge($results, $this->getDropEnumSQL($xmldb_table, $xmldb_field)); 229 /// Change field name (over a clone to avoid some potential problems later) 230 $new_xmldb_field = clone($xmldb_field); 231 $new_xmldb_field->setName($newname); 232 233 /// Recreate the enum 234 $results = array_merge($results, $this->getCreateEnumSQL($xmldb_table, $new_xmldb_field)); 235 } 236 237 return $results; 238 } 239 240 /** 241 * Returns the code (array of statements) needed to execute extra statements on table rename 242 */ 243 function getRenameTableExtraSQL ($xmldb_table, $newname) { 244 245 $results = array(); 246 247 $newt = new XMLDBTable($newname); //Temporal table for name calculations 248 249 $oldtablename = $this->getTableName($xmldb_table); 250 $newtablename = $this->getTableName($newt); 251 252 /// Rename all the check constraints in the table 253 $oldconstraintprefix = $this->getNameForObject($xmldb_table->getName(), ''); 254 $newconstraintprefix = $this->getNameForObject($newt->getName(), '', ''); 255 256 if ($constraints = $this->getCheckConstraintsFromDB($xmldb_table)) { 257 foreach ($constraints as $constraint) { 258 /// Drop the old constraint 259 $results[] = 'ALTER TABLE ' . $newtablename . ' DROP CONSTRAINT ' . $constraint->name; 260 /// Calculate the new constraint name 261 $newconstraintname = str_replace($oldconstraintprefix, $newconstraintprefix, $constraint->name); 262 /// Add the new constraint 263 $results[] = 'ALTER TABLE ' . $newtablename . ' ADD CONSTRAINT ' . $newconstraintname . 264 ' CHECK ' . $constraint->description; 265 } 266 } 267 268 return $results; 269 } 270 271 /** 272 * Given one XMLDBTable and one XMLDBField, return the SQL statements needded to alter the field in the table 273 */ 274 function getAlterFieldSQL($xmldb_table, $xmldb_field) { 275 276 global $db; 277 278 $results = array(); /// To store all the needed SQL commands 279 280 /// Get the quoted name of the table and field 281 $tablename = $this->getTableName($xmldb_table); 282 $fieldname = $this->getEncQuoted($xmldb_field->getName()); 283 284 /// Take a look to field metadata 285 $meta = array_change_key_case($db->MetaColumns($tablename)); 286 $metac = $meta[$fieldname]; 287 $oldtype = strtolower($metac->type); 288 $oldmetatype = column_type($xmldb_table->getName(), $fieldname); 289 $oldlength = $metac->max_length; 290 $olddecimals = empty($metac->scale) ? null : $metac->scale; 291 $oldnotnull = empty($metac->not_null) ? false : $metac->not_null; 292 $olddefault = empty($metac->has_default) ? null : strtok($metac->default_value, ':'); 293 294 $typechanged = true; //By default, assume that the column type has changed 295 $lengthchanged = true; //By default, assume that the column length has changed 296 297 /// Detect if we are changing the type of the column 298 if (($xmldb_field->getType() == XMLDB_TYPE_INTEGER && substr($oldmetatype, 0, 1) == 'I') || 299 ($xmldb_field->getType() == XMLDB_TYPE_NUMBER && $oldmetatype == 'N') || 300 ($xmldb_field->getType() == XMLDB_TYPE_FLOAT && $oldmetatype == 'F') || 301 ($xmldb_field->getType() == XMLDB_TYPE_CHAR && substr($oldmetatype, 0, 1) == 'C') || 302 ($xmldb_field->getType() == XMLDB_TYPE_TEXT && substr($oldmetatype, 0, 1) == 'X') || 303 ($xmldb_field->getType() == XMLDB_TYPE_BINARY && $oldmetatype == 'B')) { 304 $typechanged = false; 305 } 306 307 /// Detect if we are changing the length of the column, not always necessary to drop defaults 308 /// if only the length changes, but it's safe to do it always 309 if ($xmldb_field->getLength() == $oldlength) { 310 $lengthchanged = false; 311 } 312 313 /// If type or length have changed drop the default if exists 314 if ($typechanged || $lengthchanged) { 315 $results = $this->getDropDefaultSQL($xmldb_table, $xmldb_field); 316 } 317 318 /// Just prevent default clauses in this type of sentences for mssql and launch the parent one 319 $this->alter_column_skip_default = true; 320 $results = array_merge($results, parent::getAlterFieldSQL($xmldb_table, $xmldb_field)); // Call parent 321 322 /// Finally, process the default clause to add it back if necessary 323 if ($typechanged || $lengthchanged) { 324 $results = array_merge($results, $this->getCreateDefaultSQL($xmldb_table, $xmldb_field)); 325 } 326 327 /// Return results 328 return $results; 329 } 330 331 /** 332 * Given one XMLDBTable and one XMLDBField, return the SQL statements needded to modify the default of the field in the table 333 */ 334 function getModifyDefaultSQL($xmldb_table, $xmldb_field) { 335 /// MSSQL is a bit special with default constraints because it implements them as external constraints so 336 /// normal ALTER TABLE ALTER COLUMN don't work to change defaults. Because this, we have this method overloaded here 337 338 $results = array(); 339 340 /// Get the quoted name of the table and field 341 $tablename = $this->getTableName($xmldb_table); 342 $fieldname = $this->getEncQuoted($xmldb_field->getName()); 343 344 /// Decide if we are going to create/modify or to drop the default 345 if ($xmldb_field->getDefault() === null) { 346 $results = $this->getDropDefaultSQL($xmldb_table, $xmldb_field); //Drop but, under some circumptances, re-enable 347 if ($this->getDefaultClause($xmldb_field)) { //If getDefaultClause() it must have one default, create it 348 $results = array_merge($results, $this->getCreateDefaultSQL($xmldb_table, $xmldb_field)); //Create/modify 349 } 350 } else { 351 $results = $this->getDropDefaultSQL($xmldb_table, $xmldb_field); //Drop (only if exists) 352 $results = array_merge($results, $this->getCreateDefaultSQL($xmldb_table, $xmldb_field)); //Create/modify 353 } 354 355 return $results; 356 } 357 358 /** 359 * Given one XMLDBTable and one XMLDBField, return the SQL statements needded to create its enum 360 * (usually invoked from getModifyEnumSQL() 361 */ 362 function getCreateEnumSQL($xmldb_table, $xmldb_field) { 363 /// All we have to do is to create the check constraint 364 return array('ALTER TABLE ' . $this->getTableName($xmldb_table) . 365 ' ADD ' . $this->getEnumExtraSQL($xmldb_table, $xmldb_field)); 366 } 367 368 /** 369 * Given one XMLDBTable and one XMLDBField, return the SQL statements needded to drop its enum 370 * (usually invoked from getModifyEnumSQL() 371 */ 372 function getDropEnumSQL($xmldb_table, $xmldb_field) { 373 /// Let's introspect to know the real name of the check constraint 374 if ($check_constraints = $this->getCheckConstraintsFromDB($xmldb_table, $xmldb_field)) { 375 $check_constraint = array_shift($check_constraints); /// Get the 1st (should be only one) 376 $constraint_name = strtolower($check_constraint->name); /// Extract the REAL name 377 /// All we have to do is to drop the check constraint 378 return array('ALTER TABLE ' . $this->getTableName($xmldb_table) . 379 ' DROP CONSTRAINT ' . $constraint_name); 380 } else { /// Constraint not found. Nothing to do 381 return array(); 382 } 383 } 384 385 /** 386 * Given one XMLDBTable and one XMLDBField, return the SQL statements needded to create its default 387 * (usually invoked from getModifyDefaultSQL() 388 */ 389 function getCreateDefaultSQL($xmldb_table, $xmldb_field) { 390 /// MSSQL is a bit special and it requires the corresponding DEFAULT CONSTRAINT to be dropped 391 392 $results = array(); 393 394 /// Get the quoted name of the table and field 395 $tablename = $this->getTableName($xmldb_table); 396 $fieldname = $this->getEncQuoted($xmldb_field->getName()); 397 398 /// Now, check if, with the current field attributes, we have to build one default 399 if ($default_clause = $this->getDefaultClause($xmldb_field)) { 400 /// We need to build the default (Moodle) default, so do it 401 $results[] = 'ALTER TABLE ' . $tablename . ' ADD' . $default_clause . ' FOR ' . $fieldname; 402 } 403 404 return $results; 405 } 406 407 /** 408 * Given one XMLDBTable and one XMLDBField, return the SQL statements needded to drop its default 409 * (usually invoked from getModifyDefaultSQL() 410 */ 411 function getDropDefaultSQL($xmldb_table, $xmldb_field) { 412 /// MSSQL is a bit special and it requires the corresponding DEFAULT CONSTRAINT to be dropped 413 414 $results = array(); 415 416 /// Get the quoted name of the table and field 417 $tablename = $this->getTableName($xmldb_table); 418 $fieldname = $this->getEncQuoted($xmldb_field->getName()); 419 420 /// Look for the default contraint and, if found, drop it 421 if ($defaultname = $this->getDefaultConstraintName($xmldb_table, $xmldb_field)) { 422 $results[] = 'ALTER TABLE ' . $tablename . ' DROP CONSTRAINT ' . $defaultname; 423 } 424 425 return $results; 426 } 427 428 /** 429 * Given one XMLDBTable and one XMLDBField, returns the name of its default constraint in DB 430 * or false if not found 431 * This function should be considered internal and never used outside from generator 432 */ 433 function getDefaultConstraintName($xmldb_table, $xmldb_field) { 434 435 /// Get the quoted name of the table and field 436 $tablename = $this->getTableName($xmldb_table); 437 $fieldname = $this->getEncQuoted($xmldb_field->getName()); 438 439 /// Look for any default constraint in this field and drop it 440 if ($default = get_record_sql("SELECT id, object_name(cdefault) AS defaultconstraint 441 FROM syscolumns 442 WHERE id = object_id('{$tablename}') 443 AND name = '{$fieldname}'")) { 444 return $default->defaultconstraint; 445 } else { 446 return false; 447 } 448 } 449 450 /** 451 * Given one XMLDBTable returns one array with all the check constrainsts 452 * in the table (fetched from DB) 453 * Optionally the function allows one xmldb_field to be specified in 454 * order to return only the check constraints belonging to one field. 455 * Each element contains the name of the constraint and its description 456 * If no check constraints are found, returns an empty array 457 */ 458 function getCheckConstraintsFromDB($xmldb_table, $xmldb_field = null) { 459 460 $results = array(); 461 462 $tablename = $this->getTableName($xmldb_table); 463 464 if ($constraints = get_records_sql("SELECT o.name, c.text AS description 465 FROM sysobjects o, 466 sysobjects p, 467 syscomments c 468 WHERE p.id = o.parent_obj 469 AND o.id = c.id 470 AND o.xtype = 'C' 471 AND p.name = '{$tablename}'")) { 472 foreach ($constraints as $constraint) { 473 $results[$constraint->name] = $constraint; 474 } 475 } 476 477 /// Filter by the required field if specified 478 if ($xmldb_field) { 479 $filtered_results = array(); 480 $filter = $xmldb_field->getName(); 481 /// Lets clean a bit each constraint description, looking for the filtered field 482 foreach ($results as $key => $result) { 483 $description = trim(preg_replace('/[\(\)]/', '', $result->description)); // Parenthesis out & trim 484 /// description starts by [$filter] assume it's a constraint beloging to the field 485 if (preg_match("/^\[{$filter}\]/i", $description)) { 486 $filtered_results[$key] = $result; 487 } 488 } 489 /// Assign filtered results to the final results array 490 $results = $filtered_results; 491 } 492 493 return $results; 494 } 495 496 /** 497 * Given one object name and it's type (pk, uk, fk, ck, ix, uix, seq, trg) 498 * return if such name is currently in use (true) or no (false) 499 * (invoked from getNameForObject() 500 */ 501 function isNameInUse($object_name, $type, $table_name) { 502 switch($type) { 503 case 'seq': 504 case 'trg': 505 case 'pk': 506 case 'uk': 507 case 'fk': 508 case 'ck': 509 if ($check = get_records_sql("SELECT name 510 FROM sysobjects 511 WHERE lower(name) = '" . strtolower($object_name) . "'")) { 512 return true; 513 } 514 break; 515 case 'ix': 516 case 'uix': 517 if ($check = get_records_sql("SELECT name 518 FROM sysindexes 519 WHERE lower(name) = '" . strtolower($object_name) . "'")) { 520 return true; 521 } 522 break; 523 } 524 return false; //No name in use found 525 } 526 527 /** 528 * Returns an array of reserved words (lowercase) for this DB 529 */ 530 function getReservedWords() { 531 /// This file contains the reserved words for MSSQL databases 532 /// from http://msdn2.microsoft.com/en-us/library/ms189822.aspx 533 $reserved_words = array ( 534 'add', 'all', 'alter', 'and', 'any', 'as', 'asc', 'authorization', 535 'avg', 'backup', 'begin', 'between', 'break', 'browse', 'bulk', 536 'by', 'cascade', 'case', 'check', 'checkpoint', 'close', 'clustered', 537 'coalesce', 'collate', 'column', 'commit', 'committed', 'compute', 538 'confirm', 'constraint', 'contains', 'containstable', 'continue', 539 'controlrow', 'convert', 'count', 'create', 'cross', 'current', 540 'current_date', 'current_time', 'current_timestamp', 'current_user', 541 'cursor', 'database', 'dbcc', 'deallocate', 'declare', 'default', 'delete', 542 'deny', 'desc', 'disk', 'distinct', 'distributed', 'double', 'drop', 'dummy', 543 'dump', 'else', 'end', 'errlvl', 'errorexit', 'escape', 'except', 'exec', 544 'execute', 'exists', 'exit', 'external', 'fetch', 'file', 'fillfactor', 'floppy', 545 'for', 'foreign', 'freetext', 'freetexttable', 'from', 'full', 'function', 546 'goto', 'grant', 'group', 'having', 'holdlock', 'identity', 'identitycol', 547 'identity_insert', 'if', 'in', 'index', 'inner', 'insert', 'intersect', 'into', 548 'is', 'isolation', 'join', 'key', 'kill', 'left', 'level', 'like', 'lineno', 549 'load', 'max', 'min', 'mirrorexit', 'national', 'nocheck', 'nonclustered', 550 'not', 'null', 'nullif', 'of', 'off', 'offsets', 'on', 'once', 'only', 'open', 551 'opendatasource', 'openquery', 'openrowset', 'openxml', 'option', 'or', 'order', 552 'outer', 'over', 'percent', 'perm', 'permanent', 'pipe', 'pivot', 'plan', 'precision', 553 'prepare', 'primary', 'print', 'privileges', 'proc', 'procedure', 'processexit', 554 'public', 'raiserror', 'read', 'readtext', 'reconfigure', 'references', 555 'repeatable', 'replication', 'restore', 'restrict', 'return', 'revoke', 556 'right', 'rollback', 'rowcount', 'rowguidcol', 'rule', 'save', 'schema', 557 'select', 'serializable', 'session_user', 'set', 'setuser', 'shutdown', 'some', 558 'statistics', 'sum', 'system_user', 'table', 'tape', 'temp', 'temporary', 559 'textsize', 'then', 'to', 'top', 'tran', 'transaction', 'trigger', 'truncate', 560 'tsequal', 'uncommitted', 'union', 'unique', 'update', 'updatetext', 'use', 561 'user', 'values', 'varying', 'view', 'waitfor', 'when', 'where', 'while', 562 'with', 'work', 'writetext' 563 ); 564 return $reserved_words; 565 } 566 } 567 568 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Wed Jan 14 11:33:29 2009 | Cross-referenced by PHPXref 0.7 |