FileDocCategorySizeDatePackage
DDLGenerator.javaAPI DocGlassfish v2 API21200Fri May 04 22:34:40 BST 2007com.sun.jdo.spi.persistence.generator.database

DDLGenerator

public class DDLGenerator extends Object
This class generates DDL for a given SchemaElement.
author
Jie Leng, Dave Bristor

Fields Summary
private static final char
SPACE
For writing DDL.
private static final char
START
For writing DDL.
private static final char
END
For writing DDL.
private static final String
COLUMN_SEPARATOR
For writing DDL.
private static final String
NOT_NULL_STRING
For writing DDL.
private static final String
NULL_STRING
For writing DDL.
Constructors Summary
Methods Summary
private static java.util.ListcreateAddConstraintsDDL(TableElement table)
Returns a List of Strings of "add constraint" DDL commands. Strings in the array have the format:
ALTER TABLE table_name ADD CONSTRAINT constraint_name FOREIGN KEY
(id, ..) REFERENCES table_name (id, ..)

param
table Table for which constraints are returned.
return
Array of constraints (as Strings), one for each constraint on the table.

        List alterTblDDL = new ArrayList();
        String[] fourParams = new String[4];
        String[] oneParam = { table.getName().getName() };

        // Add foreign keys
        ForeignKeyElement[] fkeys = table.getForeignKeys();
        if (fkeys != null) {
            String alterTblString =
                DDLTemplateFormatter.formatAlterTableAddConstraint(oneParam);
            
            for (int jj=0; jj < fkeys.length; jj++) {
                ForeignKeyElement fkey = fkeys[jj];
                fourParams[0] = fkey.getName().getName();
                fourParams[1] = getColumnNames(fkey.getLocalColumns());
                fourParams[2] = fkey.getReferencedTable().getName().getName();
                fourParams[3] = getColumnNames(fkey.getReferencedColumns());

                StringBuffer alterTblDDLString = new StringBuffer(
                    alterTblString);
                alterTblDDLString.append(SPACE);
                alterTblDDLString.append(
                        DDLTemplateFormatter.formatFKConstraint(fourParams));
                alterTblDDL.add(alterTblDDLString.toString());
            }
        }
        return alterTblDDL;
    
private static java.lang.String[]createCreateTableDDL(TableElement table, MappingPolicy mappingPolicy)
Returns DDL in String[] form to create a table. The returned String[] elements have the format:
CREATE TABLE table_name (
column_name type(precision, scale) null,
...
CONSTRAINT pk_name PRIMARY KEY (id, name)
)

param
table Table for which DDL is to be created.
param
mappingPolicy Policy that determines database- and user-supplied properties on generating DDL.
return
String[] containing DDL to create a table.


        List createTblList = new ArrayList();
        String[] oneParam = { table.getName().getName() };

        createTblList.add(
                DDLTemplateFormatter.formatCreateTable(oneParam));
        
	// add columns for each table
        ColumnElement[] columns = table.getColumns();
        String constraint = createPrimaryKeyConstraint(table);
        int size = columns.length;
        
	for (int i = 0; i < size; i++) {
            StringBuffer columnContent = new StringBuffer();
            columnContent.append(getColumnDef(columns[i], mappingPolicy));

            // If we haven't added the last column, or we have but there's a
            // constraint yet to be added, add a column separator.
            if ((i < size - 1) || ((i == size - 1) && (constraint != null))) {
	        columnContent.append(COLUMN_SEPARATOR);
            }
            createTblList.add(columnContent.toString());
	}

        if (constraint != null) {
            createTblList.add(constraint);
        }
        createTblList.add(mappingPolicy.getCreateTableEnd());

        return (String[]) createTblList.toArray(
                new String[createTblList.size()]);
    
private static java.util.ListcreateDropConstraintsDDL(TableElement table)
Returns a List of Strings of "drop constraint" DDL commands. Each String has the format:
DROP TABLE table_name

param
table Table for which constraints are to be dropped.
return
List of Strings, one per "drop constraint" command.

        List alterTbls = new ArrayList();
        String[] twoParams = new String[2];
        twoParams[0] = table.getName().getName();
        ForeignKeyElement[] fkeys = table.getForeignKeys();

        if (fkeys != null) {
            for (int i = 0; i < fkeys.length; i++) {
                twoParams[1] = fkeys[i].getName().getName();
                String alterTblString =
                    DDLTemplateFormatter.formatAlterTableDropConstraint(
                            twoParams);
                alterTbls.add(alterTblString);
            }
        }
        return alterTbls;
    
private static java.lang.StringcreateDropTableDDL(TableElement table)
Returns DDL in String form to drop a table. The returned string has the format:
DROP TABLE table_name

param
table Table for which dropping DDL is returned.
return
DDL to drop a table.

        String[] oneParam = { table.getName().getName() };
        return DDLTemplateFormatter.formatDropTable(oneParam);
    
private static java.lang.StringcreatePrimaryKeyConstraint(TableElement table)
Returns DDL in String form to create a primary key constraint. The string has the format:
CONSTRAINT pk_name PRIMARY KEY(id, name)

param
table Table for which constraint DDL is returned.
return
DDL to create a PK constraint or null if there is no PK.

        String rc = null;
        UniqueKeyElement pk = table.getPrimaryKey();
        
        if (pk != null) {
            String[] twoParams = new String[2];
            twoParams[0] = pk.getName().getName();
            twoParams[1] = getColumnNames(pk.getColumns());
            rc = DDLTemplateFormatter.formatPKConstraint(twoParams);
        }
        return rc;
    
public static voidgenerateDDL(SchemaElement schema, java.lang.String dbVendorName, java.io.OutputStream createDDLSql, java.io.OutputStream dropDDLSql, java.io.OutputStream dropDDLJdbc, java.io.OutputStream createDDLJdbc, java.io.OutputStream dbStream, boolean dropAndCreateTbl)
Generate DDL from schema and database vendor name. Up to four files containing DDL are created:
  • create table DDL destined for human readers
  • create table DDL destined for a JDBC connection
  • drop table DDL destined for human readers
  • drop table DDL destined for a JDBC connection
Furthermore, if the datbase output stream is not null, then create tables in database.

param
schema Database schema for which DDL is generated.
param
dbVendorName Name of database vendor, which must match one of the names of the .properties files in this package.
param
createDDLSql An OutputStream to which human-readable DDL for creating tables gets written.
param
dropDDLSql An OutputStream to which human-readable DDL for dropping tables gets written.
param
dropDDLJdbc An OutputStream to which DDL for dropping tables gets written. This parameter differs from dropDDLSql because the data written into it is supposed to be used with a JDBC connection.
param
createDDLJdbc An OutputStream to which DDL for creating tables gets written. This parameter differs from createDDLSql because the data written into it is supposed to be used with a JDBC connection.
param
dbStream DatabaseOutputStream which, if not null, is used to create tables in a live database during this method call.
param
dropAndCreateTbl If true, and dbStream is not null, then existing tables are dropped before new ones are created.
throws
DBException
throws
SQLException
throws
IOException

 //NOI18N


    // XXX The use of streams can be improved.  They probably should be
    // writers anyway, and the names should be consistent.
    
                                                                                                                                                                                                                                              
    // XXX Change param dbStream to be of type DatabaseOutputStream.
    // XXX Change names of all streams to indicate that they are streams.
    // XXX Consider changing this API to take the location of where the files
    // are to be written, and to create the streams here.
    // XXX Reorder params so they are in order create, drop, create, drop or
    // maybe create, create, drop, drop, but not create, drop, drop, create!
           
               
               
                
                

        if (schema != null) {
            MappingPolicy mappingPolicy = MappingPolicy.getMappingPolicy(
                    dbVendorName);
            DDLTemplateFormatter.reset(mappingPolicy);
            String schemaName = schema.getName().getName();
            List createAllTblDDL = new ArrayList();
            List alterAddConstraintsDDL = new ArrayList();
            List alterDropConstraintsDDL = new ArrayList();
            List dropAllTblDDL = new ArrayList();
            TableElement[] tables = schema.getTables();
            
            if (tables != null) { 
                for (int ii = 0; ii < tables.length; ii++) {
                    TableElement table = tables[ii];

                    createAllTblDDL.add(
                            createCreateTableDDL(table, mappingPolicy));
                    alterAddConstraintsDDL.addAll(
                            createAddConstraintsDDL(table));
                    alterDropConstraintsDDL.addAll(
                            createDropConstraintsDDL(table));
                    dropAllTblDDL.add(
                        createDropTableDDL(table));
                }
            }
            String stmtSeparator = mappingPolicy.getStatementSeparator();
            generateSQL(createDDLSql, dropDDLSql, dropDDLJdbc, createDDLJdbc, 
                (DatabaseOutputStream) dbStream, createAllTblDDL, 
                alterAddConstraintsDDL, alterDropConstraintsDDL, dropAllTblDDL,
                stmtSeparator, dropAndCreateTbl);
        }
    
private static voidgenerateSQL(java.io.OutputStream createSql, java.io.OutputStream dropSql, java.io.OutputStream dropTxt, java.io.OutputStream createTxt, DatabaseOutputStream dbStream, java.util.List createAllTblDDL, java.util.List alterAddConstraintsDDL, java.util.List alterDropConstraintsDDL, java.util.List dropAllTblDDL, java.lang.String stmtSeparator, boolean dropAndCreateTbl)
Write DDL to files or drop or create table in database

param
createDDLSql a file for writing create DDL
param
dropDDLSql a file for writing drop DDL
param
dropDDLTxt a file for writing drop DDL and can be easily executes drop in undeployment time
param
dbStream for creating table in database
param
createAllTblDDL a list of create table statement
param
alterAddConstraintsDDL a list of adding constraints statement
param
alterDropConstraintDDL a list of droping constrains statement
param
dropAllTblDDL a list of droping tables statement
param
stmtSeparator for separating each statement
param
dropAndCreateTbl true for dropping tables first
throws
DBException
throws
SQLException


        PrintStream workStream = null;
        PrintStream txtStream = null;

        try {
            // drop constraints first 
            workStream = new PrintStream(dropSql);
            if (dropTxt != null) {
                txtStream = new PrintStream(dropTxt);
            }
            for (int i = 0; i < alterDropConstraintsDDL.size(); i++) {
                String dropConstStmt = (String) alterDropConstraintsDDL.get(i);
                writeDDL(workStream, txtStream, stmtSeparator, dropConstStmt);
                if ((dbStream != null) && dropAndCreateTbl) {
                    dbStream.write(dropConstStmt);
                }
            }

            // drop tables
            for (int i = 0; i < dropAllTblDDL.size(); i++) {
                String dropTblStmt = (String) dropAllTblDDL.get(i);
                writeDDL(workStream, txtStream, stmtSeparator, dropTblStmt);
                if ((dbStream != null) && dropAndCreateTbl) {
                    dbStream.write(dropTblStmt);
                }
            }
            workStream.close();
            if (txtStream != null) {
                txtStream.close();
            }

            // create tables and constraints
            workStream = new PrintStream(createSql);
            if (createTxt != null) {
                txtStream = new PrintStream(createTxt);
            }

            // First create tables...
            for (int i = 0; i < createAllTblDDL.size(); i++) {
                StringBuffer createStmt = new StringBuffer();
                String[] createTbl = (String []) createAllTblDDL.get(i);

                for (int j = 0; j < createTbl.length; j++) {
                    workStream.println(createTbl[j]);
                    createStmt.append(createTbl[j]);
                }
                workStream.println(stmtSeparator);
                if (txtStream != null) {
                    txtStream.println(createStmt);
                }
                if (dbStream != null) {
                   dbStream.write(createStmt.toString());
                }
            }

            // ...then create constraints
            for (int i = 0; i < alterAddConstraintsDDL.size(); i++) {
                String stmt = (String)alterAddConstraintsDDL.get(i);
                writeDDL(workStream, txtStream, stmtSeparator, stmt);
                if (dbStream != null) {
                    dbStream.write(stmt);
                }
            }
            
            workStream.close();
            if (txtStream != null) {
                txtStream.close();
            }

            if (dbStream != null) {
                dbStream.flush();
            }
        } finally {
            if (workStream != null) {
                workStream.close();
            }
            if (txtStream != null) {
                txtStream.close();
            }
        }
    
private static java.lang.StringgetColumnDef(ColumnElement column, MappingPolicy mappingPolicy)
Returns a String which indicates how a column should be declared in DDL. It has the format:
column_name column_type(length, precision, scale) null
length, precision, scale, and null are optional, and depend on properties of the given column.

param
column Column to be declared in DDL.
param
mappingPolicy Policy that determines database- and user-supplied properties on generating DDL.
return
String containing DDL to create column in database.


        int jdbcType = column.getType();
        Integer scale = column.getScale();
        Integer precision = column.getPrecision();
        Integer length = column.getLength();
        String sqlType = mappingPolicy.getSQLTypeName(jdbcType);
        StringBuffer columnContent = new StringBuffer();
        
        columnContent.append(column.getName().getName());
        columnContent.append(SPACE);
        columnContent.append(sqlType);
        if (column.isCharacterType() && length != null) {
            columnContent.append(START);
            columnContent.append(length.toString());
            columnContent.append(END);

        } else if (column.isNumericType() && precision != null) {
            columnContent.append(START);
            columnContent.append(precision.toString());
            if (scale != null) {
                columnContent.append(COLUMN_SEPARATOR);
                columnContent.append(scale.toString());
            }
            columnContent.append(END);

        } else if (column.isBlobType() && length != null) {
            columnContent.append(START);
            columnContent.append(length.toString());
            columnContent.append(END);
        }
            
        // Add extra information required by LOB columns.
        if (jdbcType == Types.BLOB || jdbcType == Types.CLOB) {
            String lobText = mappingPolicy.getLobLogging();
            if (lobText != null && lobText.length() > 0) {
                columnContent.append(SPACE).append(lobText);
            }
        }

        // Add information about nullability.
        if (column.isNullable()) {
            String nullText =  mappingPolicy.getColumnNullability();
            if (nullText != null && nullText.length() > 0) {
                columnContent.append(SPACE).append(nullText);
            }
        } else {
            columnContent.append(SPACE).append(NOT_NULL_STRING);
        }

        return columnContent.toString();
    
private static java.lang.StringgetColumnNames(ColumnElement[] columns)
Returns a comma-separated list of column names.

param
columns Array of ColumnElements
return
String of form "columnA, columnB", with as many named columns as there are in given array.

        StringBuffer columnNames = new StringBuffer();
        for (int i = 0; i < columns.length; i++) {
            if (i > 0) {
                columnNames.append(COLUMN_SEPARATOR);
            }
            columnNames.append(columns[i].getName().getName());
        }
        return columnNames.toString();
    
private static voidwriteDDL(java.io.PrintStream sql, java.io.PrintStream txt, java.lang.String stmtSeparator, java.lang.String stmt)
Writes string to given streams.

param
sqlFile Stream representing human-readable DDL.
param
txtFile Stream representing DDL to be used via JDBC statements.
param
stmtSeparator Separator between DDL statements in human-readable DDL.


        sql.println(stmt);
        sql.println(stmtSeparator);

        // Could be null, if null was passed to generateDDL.
        if (txt != null) {
            txt.println(stmt);
        }