00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 define( 'SHOW_TABLES_QUERY', <<<END
00037 SELECT n.nspname as "Schema",
00038 c.relname as "Name",
00039 CASE c.relkind
00040 WHEN 'r' THEN 'table'
00041 WHEN 'v' THEN 'view'
00042 WHEN 'i' THEN 'index'
00043 WHEN 'S' THEN 'sequence'
00044 WHEN 's' THEN 'special'
00045 END as "Type",
00046 u.usename as "Owner"
00047 FROM pg_catalog.pg_class c
00048 LEFT JOIN pg_catalog.pg_user u ON u.usesysid = c.relowner
00049 LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
00050 WHERE c.relkind IN ('r','')
00051 AND n.nspname NOT IN ('pg_catalog', 'pg_toast')
00052 AND pg_catalog.pg_table_is_visible(c.oid)
00053 ORDER BY 1,2
00054 END
00055 );
00056
00057 define( 'FETCH_TABLE_OID_QUERY', <<<END
00058 SELECT c.oid,
00059 n.nspname,
00060 c.relname
00061 FROM pg_catalog.pg_class c
00062 LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
00063 WHERE pg_catalog.pg_table_is_visible(c.oid)
00064 AND c.relname ~ '^<<tablename>>$'
00065 ORDER BY 2, 3;
00066 END
00067 );
00068
00069 define( 'FETCH_TABLE_DEF_QUERY', <<<END
00070 SELECT a.attname,
00071 pg_catalog.format_type(a.atttypid, a.atttypmod),
00072 (SELECT substring(d.adsrc for 128) FROM pg_catalog.pg_attrdef d
00073 WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef) as default,
00074 a.attnotnull, a.attnum
00075 FROM pg_catalog.pg_attribute a
00076 WHERE a.attrelid = '<<oid>>' AND a.attnum > 0 AND NOT a.attisdropped
00077 ORDER BY a.attnum
00078 END
00079 );
00080
00081 define( 'FETCH_INDEX_DEF_QUERY', <<<END
00082 SELECT c.relname, i.*
00083 FROM pg_catalog.pg_index i, pg_catalog.pg_class c
00084 WHERE indrelid = '<<oid>>'
00085 AND i.indexrelid = c.oid
00086 END
00087 );
00088
00089 define( 'FETCH_INDEX_COL_NAMES_QUERY', <<<END
00090 SELECT a.attnum, a.attname
00091 FROM pg_catalog.pg_attribute a
00092 WHERE a.attrelid = '<<indexrelid>>' AND a.attnum IN (<<attids>>) AND NOT a.attisdropped
00093 ORDER BY a.attnum
00094 END
00095 );
00096
00097 include_once( 'lib/ezdbschema/classes/ezdbschemainterface.php' );
00098
00099 class eZPgsqlSchema extends eZDBSchemaInterface
00100 {
00101
00102
00103
00104
00105
00106
00107 function eZPgsqlSchema( $db )
00108 {
00109 $this->eZDBSchemaInterface( $db );
00110 }
00111
00112
00113
00114
00115 function schema( $params = array() )
00116 {
00117 $params = array_merge( array( 'meta_data' => false,
00118 'format' => 'generic' ),
00119 $params );
00120 $schema = array();
00121
00122 if ( $this->Schema === false )
00123 {
00124 $resultArray = $this->DBInstance->arrayQuery( SHOW_TABLES_QUERY );
00125
00126 foreach( $resultArray as $row )
00127 {
00128 $table_name = $row['Name'];
00129 $schema_table['name'] = $table_name;
00130 $schema_table['fields'] = $this->fetchTableFields( $table_name, $params );
00131 $schema_table['indexes'] = $this->fetchTableIndexes( $table_name, $params );
00132
00133 $schema[$table_name] = $schema_table;
00134 }
00135 $this->transformSchema( $schema, $params['format'] == 'local' );
00136 ksort( $schema );
00137 $this->Schema = $schema;
00138 }
00139 else
00140 {
00141 $this->transformSchema( $this->Schema, $params['format'] == 'local' );
00142 $schema = $this->Schema;
00143 }
00144 return $schema;
00145 }
00146
00147
00148
00149
00150 function fetchTableFields( $table, $params )
00151 {
00152 $fields = array();
00153
00154 $resultArray = $this->DBInstance->arrayQuery( str_replace( '<<tablename>>', $table, FETCH_TABLE_OID_QUERY ) );
00155 $row = $resultArray[0];
00156 $oid = $row['oid'];
00157
00158 $resultArray = $this->DBInstance->arrayQuery( str_replace( '<<oid>>', $oid, FETCH_TABLE_DEF_QUERY ) );
00159 foreach( $resultArray as $row )
00160 {
00161 $field = array();
00162 $autoinc = false;
00163 $field['type'] = $this->parseType( $row['format_type'], $field['length'] );
00164 if ( !$field['length'] )
00165 {
00166 unset( $field['length'] );
00167 }
00168
00169 $field['not_null'] = 0;
00170 if ( $row['attnotnull'] == 't' )
00171 {
00172 $field['not_null'] = '1';
00173 }
00174
00175 $field['default'] = false;
00176 if ( !$field['not_null'] )
00177 {
00178 if ( $row['default'] === null )
00179 $field['default'] = null;
00180 else
00181 $field['default'] = (string)$this->parseDefault ( $row['default'], $autoinc );
00182 }
00183 else
00184 {
00185 $field['default'] = (string)$this->parseDefault ( $row['default'], $autoinc );
00186 }
00187
00188 $numericTypes = array( 'float', 'int' );
00189 $blobTypes = array( 'tinytext', 'text', 'mediumtext', 'longtext' );
00190 $charTypes = array( 'varchar', 'char' );
00191 if ( in_array( $field['type'], $charTypes ) )
00192 {
00193 if ( !$field['not_null'] )
00194 {
00195 if ( $field['default'] === null )
00196 {
00197 $field['default'] = null;
00198 }
00199 else if ( $field['default'] === false )
00200 {
00201 $field['default'] = '';
00202 }
00203 }
00204 }
00205 else if ( in_array( $field['type'], $numericTypes ) )
00206 {
00207 if ( $field['default'] === false )
00208 {
00209 if ( $field['not_null'] )
00210 {
00211 $field['default'] = 0;
00212 }
00213 }
00214 else if ( $field['type'] == 'int' )
00215 {
00216 if ( $field['not_null'] or
00217 is_numeric( $field['default'] ) )
00218 {
00219 $field['default'] = (int)$field['default'];
00220 }
00221 }
00222 else if ( $field['type'] == 'float' )
00223 {
00224 if ( $field['not_null'] or
00225 is_numeric( $field['default'] ) )
00226 {
00227 $field['default'] = (float)$field['default'];
00228 }
00229 }
00230 }
00231 else if ( in_array( $field['type'], $blobTypes ) )
00232 {
00233
00234 $field['default'] = false;
00235 }
00236
00237 if ( $autoinc )
00238 {
00239 unset( $field['length'] );
00240 $field['not_null'] = 0;
00241 $field['default'] = false;
00242 $field['type'] = 'auto_increment';
00243 }
00244
00245 if ( !$field['not_null'] )
00246 unset( $field['not_null'] );
00247
00248 $fields[$row['attname']] = $field;
00249 }
00250 ksort( $fields );
00251
00252 return $fields;
00253 }
00254
00255
00256
00257
00258 function fetchTableIndexes( $table, $params )
00259 {
00260 $metaData = false;
00261 if ( isset( $params['meta_data'] ) )
00262 {
00263 $metaData = $params['meta_data'];
00264 }
00265
00266 $indexes = array();
00267
00268 $resultArray = $this->DBInstance->arrayQuery( str_replace( '<<tablename>>', $table, FETCH_TABLE_OID_QUERY ) );
00269 $row = $resultArray[0];
00270 $oid = $row['oid'];
00271
00272 $resultArray = $this->DBInstance->arrayQuery( str_replace( '<<oid>>', $oid, FETCH_INDEX_DEF_QUERY ) );
00273
00274 foreach( $resultArray as $row )
00275 {
00276 $fields = array();
00277 $kn = $row['relname'];
00278
00279 $column_id_array = split( ' ', $row['indkey'] );
00280 if ( $row['indisprimary'] == 't' )
00281 {
00282
00283
00284
00285 $correctName = $this->primaryKeyIndexName( $table, $kn, $column_id_array );
00286 if ( strlen( $correctName ) > 63 )
00287 {
00288 eZDebug::writeError( "The index name '$correctName' (" . strlen( $correctName ) . ") exceeds 63 characters which is the PostgreSQL limit for names" );
00289 }
00290 if ( $kn == $correctName )
00291 {
00292 $kn = 'PRIMARY';
00293 }
00294
00295
00296
00297 if ( $metaData )
00298 {
00299 $indexes[$kn]['postgresql:name'] = $correctName;
00300 }
00301
00302 $indexes[$kn]['type'] = 'primary';
00303 }
00304 else
00305 {
00306 $indexes[$kn]['type'] = $row['indisunique'] == 't' ? 'unique' : 'non-unique';
00307 }
00308
00309
00310
00311 $att_ids = join( ', ', $column_id_array );
00312 $query = str_replace( '<<indexrelid>>', $row['indrelid'], FETCH_INDEX_COL_NAMES_QUERY );
00313 $query = str_replace( '<<attids>>', $att_ids, $query );
00314
00315 $fieldsArray = $this->DBInstance->arrayQuery( $query );
00316 foreach( $fieldsArray as $fields_row )
00317 {
00318 $fields[$fields_row['attnum']] = $fields_row['attname'];
00319 }
00320 foreach ( $column_id_array as $rank => $id )
00321 {
00322 $indexes[$kn]['fields'][$rank] = $fields[$id];
00323 }
00324 }
00325 ksort( $indexes );
00326
00327 return $indexes;
00328 }
00329
00330 function parseType( $type_info, &$length_info )
00331 {
00332 preg_match ( "@([a-z ]*)(\(([0-9]*|[0-9]*,[0-9]*)\))?@", $type_info, $matches );
00333 if ( isset( $matches[3] ) )
00334 {
00335 $length_info = $matches[3];
00336 if ( is_numeric( $length_info ) )
00337 $length_info = (int)$length_info;
00338 }
00339 $type = $this->convertToStandardType ( $matches[1], $length_info );
00340 return $type;
00341 }
00342
00343 function isTypeLengthSupported( $pgType )
00344 {
00345 switch ( $pgType )
00346 {
00347 case 'integer':
00348 case 'double precision':
00349 case 'real':
00350 {
00351 return false;
00352 } break;
00353 }
00354 return true;
00355 }
00356
00357 function convertFromStandardType( $type, &$length )
00358 {
00359 switch ( $type )
00360 {
00361 case 'char':
00362 {
00363 if ( $length == 1 )
00364 {
00365 return 'character';
00366 }
00367 else
00368 {
00369 return 'character varying';
00370 }
00371 } break;
00372 case 'int':
00373 {
00374 return 'integer';
00375 } break;
00376 case 'varchar':
00377 {
00378 return 'character varying';
00379 } break;
00380 case 'longtext':
00381 {
00382 return 'text';
00383 } break;
00384 case 'mediumtext':
00385 {
00386 return 'text';
00387 } break;
00388 case 'text':
00389 {
00390 return 'text';
00391 } break;
00392 case 'float':
00393 case 'double':
00394 {
00395 return 'double precision';
00396 } break;
00397 case 'decimal':
00398 {
00399 return 'numeric';
00400 } break;
00401
00402 default:
00403 die ( "ERROR UNHANDLED TYPE: $type\n" );
00404 }
00405 }
00406
00407
00408
00409
00410
00411
00412
00413
00414 function primaryKeyIndexName( $tableName, $indexName, $fields )
00415 {
00416 return $tableName . '_pkey';
00417 }
00418
00419 function convertToStandardType( $type, &$length )
00420 {
00421 switch ( $type )
00422 {
00423 case 'bigint':
00424 {
00425 return 'int';
00426 } break;
00427 case 'integer':
00428 {
00429 $length = 11;
00430 return 'int';
00431 } break;
00432 case 'character varying':
00433 {
00434 return 'varchar';
00435 } break;
00436 case 'text':
00437 {
00438 return 'longtext';
00439 } break;
00440 case 'double precision':
00441 {
00442 return 'float';
00443 } break;
00444 case 'character':
00445 {
00446 $lenght = 1;
00447 return 'char';
00448 } break;
00449 case 'numeric':
00450 {
00451 return 'decimal';
00452 } break;
00453
00454 default:
00455 die ( "ERROR UNHANDLED TYPE: $type\n" );
00456 }
00457 }
00458
00459 function parseDefault( $default, &$autoinc )
00460 {
00461
00462
00463 if ( preg_match( "@^nextval\(\(?'([a-z_]+_s)'::text\)@", $default, $matches ) )
00464 {
00465 $autoinc = 1;
00466 return '';
00467 }
00468
00469 if ( preg_match( "@^\(?([^()]*)\)?::double precision@", $default, $matches ) )
00470 {
00471 return $matches[1];
00472 }
00473
00474 if ( preg_match( "@^(.*)::bigint@", $default, $matches ) )
00475 {
00476 return $matches[1];
00477 }
00478
00479 if ( preg_match( "@^'(.*)'::character\ varying$@", $default, $matches ) )
00480 {
00481 return $matches[1];
00482 }
00483
00484 if ( preg_match( "@^'(.*)'::[a-zA-Z ]+$@", $default, $matches ) )
00485 {
00486 return $matches[1];
00487 }
00488
00489 if ( preg_match( "@^'(.*)'$@", $default, $matches ) )
00490 {
00491 return $matches[1];
00492 }
00493
00494 return $default;
00495 }
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505 function generateAddIndexSql( $table_name, $index_name, $def, $params, $withClosure )
00506 {
00507 $diffFriendly = isset( $params['diff_friendly'] ) ? $params['diff_friendly'] : false;
00508 $postgresqlCompatible = isset( $params['compatible_sql'] ) ? $params['compatible_sql'] : false;
00509
00510 $spacing = $postgresqlCompatible ? "\n " : " ";
00511 switch ( $def['type'] )
00512 {
00513 case 'primary':
00514 {
00515 $pkeyName = $this->primaryKeyIndexName( $table_name, $index_name, $def['fields'] );
00516 if ( strlen( $pkeyName ) > 63 )
00517 {
00518 eZDebug::writeError( "The primary key '$pkeyName' (" . strlen( $pkeyName ) . ") exceeds 63 characters which is the PostgreSQL limit for names" );
00519 }
00520 $sql = "ALTER TABLE ONLY $table_name" . $spacing . "ADD CONSTRAINT $pkeyName PRIMARY KEY";
00521 } break;
00522
00523 case 'non-unique':
00524 {
00525 $sql = "CREATE INDEX $index_name ON $table_name USING btree";
00526 } break;
00527
00528 case 'unique':
00529 {
00530 $sql = "CREATE UNIQUE INDEX $index_name ON $table_name USING btree";
00531 } break;
00532 }
00533
00534 $sql .= ( $diffFriendly ? " (\n " : ( $postgresqlCompatible ? ' (' : ' ( ' ) );
00535 $i = 0;
00536 foreach ( $def['fields'] as $fieldDef )
00537 {
00538 if ( $i > 0 )
00539 {
00540 $sql .= $diffFriendly ? ",\n " : ', ';
00541 }
00542 if ( is_array( $fieldDef ) )
00543 {
00544 $fieldName = $fieldDef['name'];
00545 }
00546 else
00547 {
00548 $fieldName = $fieldDef;
00549 }
00550 if ( in_array( $fieldName, $this->reservedKeywordList() ) )
00551 {
00552 $sql .= '"' . $fieldName . '"';
00553 }
00554 else
00555 {
00556 $sql .= $fieldName;
00557 }
00558 ++$i;
00559 }
00560
00561 $sql .= ( $diffFriendly ? "\n)" : ( $postgresqlCompatible ? ')' : ' )' ) );
00562
00563 return $sql . ( $withClosure ? ";\n" : "" );
00564 }
00565
00566
00567
00568
00569 function generateDropIndexSql( $table_name, $index_name, $def, $withClosure )
00570 {
00571 if ($def['type'] == 'primary' )
00572 {
00573 $sql = "ALTER TABLE $table_name DROP CONSTRAINT $index_name";
00574 }
00575 else
00576 {
00577 $sql = "DROP INDEX $index_name";
00578 }
00579 return $sql . ( $withClosure ? ";\n" : "" );
00580 }
00581
00582
00583
00584
00585 function generateFieldDef( $table_name, $field_name, $def, $add_default_not_null = true, $params )
00586 {
00587 $diffFriendly = isset( $params['diff_friendly'] ) ? $params['diff_friendly'] : false;
00588
00589 if ( in_array( $field_name, $this->reservedKeywordList() ) )
00590 {
00591 $sql_def = '"' . $field_name . '"';
00592 }
00593 else
00594 {
00595 $sql_def = $field_name;
00596 }
00597
00598 $sql_def .= ( $diffFriendly ? "\n " : " " );
00599 if ( $def['type'] != 'auto_increment' )
00600 {
00601 $pgType = eZPgsqlSchema::convertFromStandardType( $def['type'], $def['length'] );
00602 $sql_def .= $pgType;
00603 if ( eZPgsqlSchema::isTypeLengthSupported( $pgType ) and isset( $def['length'] ) && $def['length'] )
00604 {
00605 $sql_def .= "({$def['length']})";
00606 }
00607 if ( $add_default_not_null )
00608 {
00609 $defaultDef = eZPGSQLSchema::generateDefaultDef( false, false, $def, $params );
00610 if ( $defaultDef )
00611 {
00612 $sql_def .= ( $diffFriendly ? "\n " : " " );
00613 $sql_def .= rtrim( $defaultDef );
00614 }
00615 $nullDef = eZPGSQLSchema::generateNullDef( false, false, $def, $params );
00616 if ( $nullDef )
00617 {
00618 $sql_def .= ( $diffFriendly ? "\n " : " " );
00619 $sql_def .= trim( $nullDef );
00620 }
00621 }
00622 }
00623 else
00624 {
00625 if ( $diffFriendly )
00626 {
00627 $sql_def .= "integer\n DEFAULT nextval('{$table_name}_s'::text)\n NOT NULL";
00628 }
00629 else
00630 {
00631 $sql_def .= "integer DEFAULT nextval('{$table_name}_s'::text) NOT NULL";
00632 }
00633 }
00634 return $sql_def;
00635 }
00636
00637
00638
00639
00640 function generateDefaultDef( $table_name, $field_name, $def, $params )
00641 {
00642 $postgresqlCompatible = isset( $params['compatible_sql'] ) ? $params['compatible_sql'] : false;
00643 $sql_def = '';
00644 if ( $table_name and $field_name )
00645 {
00646 $sql_def .= "ALTER TABLE $table_name ALTER $field_name SET ";
00647 }
00648 if ( array_key_exists( 'default', $def ) and
00649 $def['default'] !== false )
00650 {
00651 if ( $def['default'] === null )
00652 {
00653 if ( !$postgresqlCompatible )
00654 $sql_def .= "DEFAULT NULL ";
00655 }
00656 else if ( $def['default'] !== false )
00657 {
00658 if ( $def['type'] == 'int' )
00659 {
00660 $sql_def .= "DEFAULT {$def['default']} ";
00661 }
00662 else if ( $def['type'] == 'float' )
00663 {
00664 $sql_def .= "DEFAULT {$def['default']}::double precision ";
00665 }
00666 else if ( $def['type'] == 'varchar' )
00667 {
00668 $sql_def .= "DEFAULT '{$def['default']}'::character varying ";
00669 }
00670 else if ( $def['type'] == 'char' )
00671 {
00672 $sql_def .= "DEFAULT '{$def['default']}'::bpchar ";
00673 }
00674 else
00675 {
00676 $sql_def .= "DEFAULT '{$def['default']}' ";
00677 }
00678 }
00679 }
00680 else if ( $table_name and $field_name )
00681 {
00682 return false;
00683 }
00684 return $sql_def;
00685 }
00686
00687
00688
00689
00690 function generateNullDef( $table_name, $field_name, $def, $params )
00691 {
00692 $sql_def = '';
00693 if ( $table_name and $field_name )
00694 {
00695 $sql_def .= "ALTER TABLE $table_name ALTER $field_name SET ";
00696 }
00697 if ( isset( $def['not_null'] ) && ( $def['not_null'] ) )
00698 {
00699 $sql_def .= 'NOT NULL ';
00700 }
00701 else if ( $table_name and $field_name )
00702 {
00703 return false;
00704 }
00705 return $sql_def;
00706 }
00707
00708
00709
00710
00711 function generateAddFieldSql( $table_name, $field_name, $def, $params )
00712 {
00713 $sql = "ALTER TABLE $table_name ADD COLUMN ";
00714 $sql .= eZPgsqlSchema::generateFieldDef( $table_name, $field_name, $def, false, $params ) . ";\n";
00715 $defaultSQL = eZPGSQLSchema::generateDefaultDef( $table_name, $field_name, $def, $params );
00716 if ( $defaultSQL )
00717 $sql .= $defaultSQL . ";\n";
00718 $nullSQL = eZPGSQLSchema::generateNullDef( $table_name, $field_name, $def, $params );
00719 if ( $nullSQL )
00720 $sql .= $nullSQL . ";\n";
00721 $sql .= "\n";
00722 return $sql;
00723 }
00724
00725
00726
00727
00728 function generateAlterFieldSql( $table_name, $field_name, $def, $params )
00729 {
00730 $sql = "ALTER TABLE $table_name RENAME COLUMN $field_name TO " . $field_name . "_tmp;\n";
00731 $sql .= "ALTER TABLE $table_name ADD COLUMN ";
00732 $sql .= eZPgsqlSchema::generateFieldDef( $table_name, $field_name, $def, false, $params ) . ";\n";
00733 $defaultSQL = eZPGSQLSchema::generateDefaultDef( $table_name, $field_name, $def, $params );
00734 if ( $defaultSQL )
00735 $sql .= $defaultSQL . ";\n";
00736 $nullSQL = eZPGSQLSchema::generateNullDef( $table_name, $field_name, $def, $params );
00737 if ( $nullSQL )
00738 $sql .= $nullSQL . ";\n";
00739 $sql .= "UPDATE $table_name SET $field_name=" . $field_name . "_tmp;\n";
00740 $sql .= "ALTER TABLE $table_name DROP COLUMN " . $field_name . "_tmp;\n\n";
00741 return $sql;
00742 }
00743
00744
00745
00746
00747 function generateTableSchema( $table, $table_def, $params )
00748 {
00749 $arrays = $this->generateTableArrays( $table, $table_def, $params, true );
00750 return ( join( "\n\n", $arrays['sequences'] ) . "\n" .
00751 join( "\n\n", $arrays['tables'] ) . "\n" .
00752 join( "\n\n", $arrays['indexes'] ) . "\n" .
00753 join( "\n\n", $arrays['constraints'] ) . "\n" );
00754 }
00755
00756
00757
00758
00759 function generateTableSQLList( $table, $table_def, $params, $separateTypes )
00760 {
00761 $arrays = $this->generateTableArrays( $table, $table_def, $params, false );
00762
00763
00764 if ( $separateTypes )
00765 return $arrays;
00766 return array_merge( $arrays['sequences'],
00767 $arrays['tables'],
00768 $arrays['indexes'],
00769 $arrays['constraints'] );
00770 }
00771
00772
00773
00774
00775
00776
00777
00778
00779 function generateTableArrays( $table, $table_def, $params, $withClosure )
00780 {
00781 $diffFriendly = isset( $params['diff_friendly'] ) ? $params['diff_friendly'] : false;
00782 $postgresqlCompatible = isset( $params['compatible_sql'] ) ? $params['compatible_sql'] : false;
00783
00784 $arrays = array( 'sequences' => array(),
00785 'tables' => array(),
00786 'indexes' => array(),
00787 'constraints' => array() );
00788
00789 $sql_fields = array();
00790
00791 $spacing = $postgresqlCompatible ? ' ' : ' ';
00792
00793
00794
00795 foreach ( $table_def['fields'] as $field_name => $field_def )
00796 {
00797 if ( $field_def['type'] == 'auto_increment' )
00798 {
00799 $sequenceFields = array( "CREATE SEQUENCE {$table}_s",
00800 "START 1",
00801 "INCREMENT 1",
00802 "MAXVALUE 9223372036854775807",
00803 "MINVALUE 1",
00804 "CACHE 1" );
00805 $arrays['sequences'][] = join( "\n$spacing", $sequenceFields ) . ( $withClosure ? ';' : '' );
00806 }
00807 }
00808
00809 $sql = "CREATE TABLE $table (\n";
00810 $fields = $table_def['fields'];
00811 foreach ( $fields as $field_name => $field_def )
00812 {
00813 $sql_fields[] = $spacing . eZPgsqlSchema::generateFieldDef( $table, $field_name, $field_def, true, $params );
00814 }
00815 $sql .= join( ",\n", $sql_fields ) . ( $withClosure ? "\n);" : "\n)" );
00816 $arrays['tables'][] = $sql;
00817
00818 foreach ( $table_def['indexes'] as $index_name => $index_def )
00819 {
00820 if ( $index_def['type'] != 'primary' )
00821 {
00822 $arrays['indexes'][] = eZPgsqlSchema::generateAddIndexSql( $table, $index_name, $index_def, $params, $withClosure );
00823 }
00824 }
00825 foreach ( $table_def['indexes'] as $index_name => $index_def )
00826 {
00827 if ( $index_def['type'] == 'primary' )
00828 {
00829 $arrays['constraints'][] = eZPgsqlSchema::generateAddIndexSql( $table, $index_name, $index_def, $params, $withClosure );
00830 }
00831 }
00832
00833 return $arrays;
00834 }
00835
00836
00837
00838
00839
00840
00841
00842
00843 function generateTableInsertSQLList( $tableName, $tableDef, $dataEntries, $params, $withClosure = true )
00844 {
00845 $sqlList = eZDBSchemaInterface::generateTableInsertSQLList( $tableName, $tableDef, $dataEntries, $params, $withClosure );
00846
00847 foreach ( $tableDef['fields'] as $fieldName => $fieldDef )
00848 {
00849 if ( $fieldDef['type'] == 'auto_increment' )
00850 {
00851 $sql = "SELECT setval('" . $tableName . "_s',max(" . $fieldName . ")+1) FROM " . $tableName;
00852 if ( $withClosure )
00853 $sql .= ";";
00854 $sqlList[] = $sql;
00855 }
00856 }
00857 return $sqlList;
00858 }
00859
00860
00861
00862
00863 function generateSchemaFile( $schema, $params = array() )
00864 {
00865 $sql = '';
00866 $postgresqlCompatible = isset( $params['compatible_sql'] ) ? $params['compatible_sql'] : false;
00867
00868 $i = 0;
00869 $allArrays = array( 'sequences' => array(),
00870 'tables' => array(),
00871 'indexes' => array(),
00872 'constraints' => array() );
00873
00874 foreach ( $schema as $table => $tableDef )
00875 {
00876
00877 if ( $table == '_info' )
00878 continue;
00879
00880 $arrays = $this->generateTableArrays( $table, $tableDef, $params, true );
00881 if ( $postgresqlCompatible )
00882 {
00883 $allArrays['sequences'] = array_merge( $allArrays['sequences'],
00884 $arrays['sequences'] );
00885 $allArrays['tables'] = array_merge( $allArrays['tables'],
00886 $arrays['tables'] );
00887 $allArrays['indexes'] = array_merge( $allArrays['indexes'],
00888 $arrays['indexes'] );
00889 $allArrays['constraints'] = array_merge( $allArrays['constraints'],
00890 $arrays['constraints'] );
00891 }
00892 else
00893 {
00894 if ( $i > 0 )
00895 $sql .= "\n\n";
00896 ++$i;
00897
00898 $sql .= ( join( "\n", $arrays['sequences'] ) . "\n" .
00899 join( "\n", $arrays['tables'] ) . "\n" .
00900 join( "\n", $arrays['indexes'] ) . "\n" .
00901 join( "\n", $arrays['constraints'] ) . "\n" );
00902 }
00903 }
00904
00905 if ( $postgresqlCompatible )
00906 {
00907 $sql = ( str_repeat( "\n", 11 ) .
00908 join( str_repeat( "\n", 8 ), $allArrays['sequences'] ) . str_repeat( "\n", 8 ) .
00909 join( str_repeat( "\n", 8 ), $allArrays['tables'] ) . str_repeat( "\n", 8 ) .
00910 join( str_repeat( "\n", 7 ), $allArrays['indexes'] ) . str_repeat( "\n", 8 ) .
00911 join( str_repeat( "\n", 7 ), $allArrays['constraints'] ) . str_repeat( "\n", 8 ) );
00912 }
00913
00914 return $sql;
00915 }
00916
00917
00918
00919
00920 function generateDropTable( $table )
00921 {
00922 return "DROP TABLE $table;\n";
00923 }
00924
00925
00926
00927
00928 function escapeSQLString( $value )
00929 {
00930 $value = str_replace( "'", "\'", $value );
00931 $value = str_replace( "\"", "\\\"", $value );
00932 return $value;
00933 }
00934
00935
00936
00937
00938 function schemaType()
00939 {
00940 return 'postgresql';
00941 }
00942
00943
00944
00945
00946 function schemaName()
00947 {
00948 return 'PostgreSQL';
00949 }
00950
00951
00952
00953
00954 function reservedKeywordList()
00955 {
00956 return array( 'abort',
00957 'absolute',
00958 'access',
00959 'action',
00960 'add',
00961 'after',
00962 'aggregate',
00963 'all',
00964 'alter',
00965 'analyse',
00966 'analyze',
00967 'and',
00968 'any',
00969 'as',
00970 'asc',
00971 'assertion',
00972 'assignment',
00973 'at',
00974 'authorization',
00975 'backward',
00976 'before',
00977 'begin',
00978 'between',
00979 'bigint',
00980 'binary',
00981 'bit',
00982 'boolean',
00983 'both',
00984 'by',
00985 'cache',
00986 'called',
00987 'cascade',
00988 'case',
00989 'cast',
00990 'chain',
00991 'char',
00992 'character',
00993 'characteristics',
00994 'check',
00995 'checkpoint',
00996 'class',
00997 'close',
00998 'cluster',
00999 'coalesce',
01000 'collate',
01001 'column',
01002 'comment',
01003 'commit',
01004 'committed',
01005 'constraint',
01006 'constraints',
01007 'conversion',
01008 'convert',
01009 'copy',
01010 'create',
01011 'createdb',
01012 'createuser',
01013 'cross',
01014 'current_date',
01015 'current_time',
01016 'current_timestamp',
01017 'current_user',
01018 'cursor',
01019 'cycle',
01020 'database',
01021 'day',
01022 'deallocate',
01023 'dec',
01024 'decimal',
01025 'declare',
01026 'default',
01027 'deferrable',
01028 'deferred',
01029 'definer',
01030 'delete',
01031 'delimiter',
01032 'delimiters',
01033 'desc',
01034 'distinct',
01035 'do',
01036 'domain',
01037 'double',
01038 'drop',
01039 'each',
01040 'else',
01041 'encoding',
01042 'encrypted',
01043 'end',
01044 'escape',
01045 'except',
01046 'exclusive',
01047 'execute',
01048 'exists',
01049 'explain',
01050 'external',
01051 'extract',
01052 'false',
01053 'fetch',
01054 'float',
01055 'for',
01056 'force',
01057 'foreign',
01058 'forward',
01059 'freeze',
01060 'from',
01061 'full',
01062 'function',
01063 'get',
01064 'global',
01065 'grant',
01066 'group',
01067 'handler',
01068 'having',
01069 'hour',
01070 'ilike',
01071 'immediate',
01072 'immutable',
01073 'implicit',
01074 'in',
01075 'increment',
01076 'index',
01077 'inherits',
01078 'initially',
01079 'inner',
01080 'inout',
01081 'input',
01082 'insensitive',
01083 'insert',
01084 'instead',
01085 'int',
01086 'integer',
01087 'intersect',
01088 'interval',
01089 'into',
01090 'invoker',
01091 'is',
01092 'isnull',
01093 'isolation',
01094 'join',
01095 'key',
01096 'lancompiler',
01097 'language',
01098 'leading',
01099 'left',
01100 'level',
01101 'like',
01102 'limit',
01103 'listen',
01104 'load',
01105 'local',
01106 'localtime',
01107 'localtimestamp',
01108 'location',
01109 'lock',
01110 'match',
01111 'maxvalue',
01112 'minute',
01113 'minvalue',
01114 'mode',
01115 'month',
01116 'move',
01117 'names',
01118 'national',
01119 'natural',
01120 'nchar',
01121 'new',
01122 'next',
01123 'no',
01124 'nocreatedb',
01125 'nocreateuser',
01126 'none',
01127 'not',
01128 'nothing',
01129 'notify',
01130 'notnull',
01131 'null',
01132 'nullif',
01133 'numeric',
01134 'of',
01135 'off',
01136 'offset',
01137 'oids',
01138 'old',
01139 'on',
01140 'only',
01141 'operator',
01142 'option',
01143 'or',
01144 'order',
01145 'out',
01146 'outer',
01147 'overlaps',
01148 'overlay',
01149 'owner',
01150 'partial',
01151 'password',
01152 'path',
01153 'pendant',
01154 'placing',
01155 'position',
01156 'precision',
01157 'prepare',
01158 'primary',
01159 'prior',
01160 'privileges',
01161 'procedural',
01162 'procedure',
01163 'read',
01164 'real',
01165 'recheck',
01166 'references',
01167 'reindex',
01168 'relative',
01169 'rename',
01170 'replace',
01171 'reset',
01172 'restrict',
01173 'returns',
01174 'revoke',
01175 'right',
01176 'rollback',
01177 'row',
01178 'rule',
01179 'schema',
01180 'scroll',
01181 'second',
01182 'security',
01183 'select',
01184 'sequence',
01185 'serializable',
01186 'session',
01187 'session_user',
01188 'set',
01189 'setof',
01190 'share',
01191 'show',
01192 'similar',
01193 'simple',
01194 'smallint',
01195 'some',
01196 'stable',
01197 'start',
01198 'statement',
01199 'statistics',
01200 'stdin',
01201 'stdout',
01202 'storage',
01203 'strict',
01204 'substring',
01205 'sysid',
01206 'table',
01207 'temp',
01208 'template',
01209 'temporary',
01210 'then',
01211 'time',
01212 'timestamp',
01213 'to',
01214 'toast',
01215 'trailing',
01216 'transaction',
01217 'treat',
01218 'trigger',
01219 'trim',
01220 'true',
01221 'truncate',
01222 'trusted',
01223 'type',
01224 'unencrypted',
01225 'union',
01226 'unique',
01227 'unknown',
01228 'unlisten',
01229 'until',
01230 'update',
01231 'usage',
01232 'user',
01233 'using',
01234 'vacuum',
01235 'valid',
01236 'validator',
01237 'values',
01238 'varchar',
01239 'varying',
01240 'verbose',
01241 'version',
01242 'view',
01243 'volatile',
01244 'when',
01245 'where',
01246 'with',
01247 'without',
01248 'work',
01249 'write',
01250 'year',
01251 'zone' );
01252 }
01253 }
01254 ?>