All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.agimatec.sql.meta.script.DDLScriptSqlMetaFactory Maven / Gradle / Ivy

There is a newer version: 2.5.27
Show newest version
package com.agimatec.sql.meta.script;

import com.agimatec.commons.config.MapNode;
import com.agimatec.sql.meta.*;
import com.agimatec.sql.script.SQLScriptParser;
import com.agimatec.sql.script.ScriptVisitor;
import freemarker.template.TemplateException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.IOException;
import java.net.URL;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Description: 
* User: roman.stumm
* Date: 24.04.2007
* Time: 19:01:18
* Copyright: Agimatec GmbH */ public class DDLScriptSqlMetaFactory implements SqlMetaFactory, ScriptVisitor { private static final Log log = LogFactory.getLog(DDLScriptSqlMetaFactory.class); private CatalogDescription catalog; private final PropertiesExtractor extractor; private final Map builders = new HashMap(); private final DDLExpressions ddlSpec; public DDLScriptSqlMetaFactory(DDLExpressions ddlSpecification) { init(); ddlSpec = ddlSpecification; if (ddlSpec.getExpressions() == null) throw new IllegalStateException( "DDL class not ready - initialization failed"); extractor = new PropertiesExtractor(); if (log.isDebugEnabled()) { log.debug("using " + ddlSpecification); } } protected void init() { builders.put("table-add-columns", new TableAddColumnsBuilder()); builders.put("table-alter-columns", new TableAlterColumnsBuilder()); builders.put("table-add-constraint", new TableAddConstraintBuilder()); builders.put("create-index", new CreateIndexBuilder()); builders.put("table-add-foreign-key", new TableAddForeignKeyBuilder()); builders.put("create-sequence", new CreateSequenceBuilder()); builders.put("create-table", new CreateTableBuilder()); builders.put("drop-table", new DropTableBuilder()); builders.put("drop-sequence", new DropSequenceBuilder()); builders.put("dezign-create-table", new DezignCreateTableBuilder()); builders.put("table-add-primary-key", new TableAddPrimaryKey()); builders.put("table-comment", new TableCommentBuilder()); builders.put("column-comment", new ColumnCommentBuilder()); } public static ExtractExpr[] compileExpressions(String[] statementFormats) { final ExtractExpr[] expressions = new ExtractExpr[statementFormats.length]; for (int i = 0; i < expressions.length; i++) { String format = statementFormats[i]; try { expressions[i] = ExtractExprBuilder.buildExpr(format); } catch (ParseException e) { log.error("cannot initialize expression: " + format, e); return null; } } return expressions; } protected Map getBuilders() { return builders; } protected DDLExpressions getDdlSpec() { return ddlSpec; } protected PropertiesExtractor getExtractor() { return extractor; } protected abstract class CatalogBuilder { public abstract void process(MapNode values, CatalogDescription catalog) throws IOException, TemplateException; /** * remove \" * @param value - value or null to strip * @return stripped value or null */ protected String strip(String value) { if (value == null) return null; int start = 0, end = value.length(); if (value.startsWith("\"")) { start++; } if (value.endsWith("\"")) { end--; } return value.substring(start, end); } protected int getInt(MapNode values, String path) { String s = values.getString(path); if (s != null && s.length() > 0) try { return Integer.parseInt(s); } catch (NumberFormatException ex) { return 0; } else return 0; } protected boolean getBool(MapNode values, String path) { String v = values.getString(path); return v != null && v.length() > 0; } protected ColumnDescription buildColumnDescription(MapNode aColDef, TableDescription aTd) { ColumnDescription cd = new ColumnDescription(); cd.setColumnName(strip(aColDef.getString("column"))); cd.setNullable(!getBool(aColDef, "mandatory")); setColType(aColDef, cd); aTd.addColumn(cd); return cd; } protected void setColType(MapNode aColDef, ColumnDescription cd) { Map precision = aColDef.getMap("precision"); if (precision != null) { cd.setPrecisionEnabled(true); List numbers = (List) precision.get("numbers"); if (numbers.size() > 0) { cd.setPrecision(getInt(aColDef, "precision/numbers/0/value")); } if (numbers.size() > 1) { cd.setScale(getInt(aColDef, "precision/numbers/1/value")); } } cd.setTypeName(aColDef.getString("typeName")); if (aColDef.getString("varying") != null) { cd.setTypeName(cd.getTypeName() + " " + aColDef.getString("varying")); } cd.setDefaultValue(aColDef.getString("default/defaultValue")); ddlSpec.equalizeColumn(cd); } protected TableDescription getTable(CatalogDescription aCatalog, String aTableName) { TableDescription td = aCatalog.getTable(aTableName); if (td == null) { td = new TableDescription(); td.setTableName(strip(aTableName)); aCatalog.addTable(td); } return td; } } class TableAddColumnsBuilder extends CatalogBuilder { // {table=customer, columndefinition=[{typeName=varchar, // column=ClientUserNumber, precision={numbers=[{value=37}]}}]} public void process(MapNode values, CatalogDescription catalog) { TableDescription td = getTable(catalog, values.getString("table")); List columns = values.getList("columndefinition"); for (Object column : columns) { MapNode eachCol = new MapNode((Map) column); buildColumnDescription(eachCol, td); } } } class TableAlterColumnsBuilder extends CatalogBuilder { public void process(MapNode values, CatalogDescription catalog) { TableDescription td = getTable(catalog, values.getString("table")); List columns = values.getList("tableElement"); for (Object column : columns) { Map map = (Map) column; if (map.containsKey("add-column")) { // add column buildColumnDescription(new MapNode((Map) map.get("add-column")), td); } else if (map.containsKey("alter-column-type")) { // alter-column-type MapNode node = new MapNode((Map) map.get("alter-column-type")); String colName = strip(node.getString("column")); ColumnDescription colDef = td.getColumn(colName); setColType(node, colDef); } else if (map.containsKey("alter-column-drop-notnull")) { // alter-column-drop-notnull MapNode node = new MapNode((Map) map.get("alter-column-drop-notnull")); String colName = strip(node.getString("column")); ColumnDescription colDef = td.getColumn(colName); colDef.setNullable(true); } else if (map.containsKey("alter-column-set-notnull")) { // alter-column-set-notnull MapNode node = new MapNode((Map) map.get("alter-column-set-notnull")); String colName = strip(node.getString("column")); ColumnDescription colDef = td.getColumn(colName); colDef.setNullable(false); } else if (map.containsKey("drop-column")) { String colName = strip(new MapNode((Map) map.get("add-column")).getString("column")); td.removeColumn(colName); } else if (map.containsKey("drop-constraint")) { String consName = strip(new MapNode((Map) map.get("drop-constraint")).getString("constraintName")); td.removeConstraint(consName); } else if (map.containsKey("alter-column-drop-notnull")) { MapNode node = new MapNode((Map) map.get("alter-column-drop-notnull")); String colName = strip(node.getString("column")); ColumnDescription colDef = td.getColumn(colName); colDef.setNullable(true); } } } } class TableCommentBuilder extends CatalogBuilder { // {table=customer, columndefinition=[{typeName=varchar, // column=ClientUserNumber, precision={numbers=[{value=37}]}}]} public void process(MapNode values, CatalogDescription catalog) { TableDescription td = getTable(catalog, values.getString("table")); td.setComment((String) values.get("comment")); } } class ColumnCommentBuilder extends CatalogBuilder { // {table=customer, columndefinition=[{typeName=varchar, // column=ClientUserNumber, precision={numbers=[{value=37}]}}]} public void process(MapNode values, CatalogDescription catalog) { String qualifiedColumn = (String) values.get("tableColumn"); String tableName = qualifiedColumn.substring(0, qualifiedColumn.indexOf('.')); String columnName = strip(qualifiedColumn.substring(tableName.length() + 1)); TableDescription td = getTable(catalog, tableName); ColumnDescription col = td.getColumn(columnName); if (col == null) { col = new ColumnDescription(); col.setColumnName(columnName); td.addColumn(col); } col.setComment((String) values.get("comment")); } } class TableAddConstraintBuilder extends CatalogBuilder { // {table=PHONENUMBER, constraint={tableSpace={tableSpace="DB_INDEX"}, unique=UNIQUE, // constraintName="PHONENUMBER_ATTR", columns=[{column="ATTROID"}, {column="TYPE"}]}} public void process(MapNode values, CatalogDescription catalog) { IndexDescription id = new IndexDescription(); id.setTableName(strip(values.getString("table"))); id.setTableSpace(strip(values.getString("constraint/tableSpace/tableSpace"))); id.setIndexName(strip(values.getString("constraint/constraintName"))); id.setUnique(getBool(values, "constraint/unique")); List columns = values.getList("constraint/columns"); for (Object column : columns) { Map eachCol = (Map) column; id.addColumn(strip((String) eachCol.get("column"))); } TableDescription td = getTable(catalog, id.getTableName()); td.addIndex(id); } } class CreateIndexBuilder extends CatalogBuilder { // {table=RENTALCARSTATION, tableSpace={tableSpace="DB_INDEX"}, unique=UNIQUE, // indexName=RENTALCARSTAT_IDX_CRS_STAT, columns=[{column="CRSTYPE"}, {column="STATIONID"}]} public void process(MapNode values, CatalogDescription catalog) { IndexDescription id = new IndexDescription(); id.setTableName(strip(values.getString("table"))); id.setTableSpace(strip(values.getString("tableSpace/tableSpace"))); id.setIndexName(strip(values.getString("indexName"))); id.setUnique(getBool(values, "unique")); List columns = values.getList("columns"); for (Object column : columns) { Map eachCol = (Map) column; id.addColumn(strip((String) eachCol.get("column"))); if (!id.isFunctionBased()) { id.setFunctionBased(eachCol.get("func") != null); } // todo [RSt] missing build from "func" } getTable(catalog, id.getTableName()).addIndex(id); } } class TableAddForeignKeyBuilder extends CatalogBuilder { // {table=Customer, constraint={refcolumns=[{column="OBJECTIDENTIFIER"}], // refTable=CLIENTORGUNIT, constraintName="Customer_Company", columns=[{column="COMPANYID"}]}} public void process(MapNode values, CatalogDescription catalog) { ForeignKeyDescription fk = new ForeignKeyDescription(); fk.setTableName(strip(values.getString("table"))); fk.setConstraintName(strip(values.getString("constraint/constraintName"))); fk.setRefTableName(strip(values.getString("constraint/refTable"))); fk.setTableSpace(strip(values.getString("tableSpace/tableSpace"))); fk.setOnDeleteRule(values.getString("constraint/onDeleteRule")); List columns = values.getList("constraint/columns"); List refcolumns = values.getList("constraint/refcolumns/refcolumns"); for (int i = 0; i < columns.size(); i++) { Map eachCol = (Map) columns.get(i); Map refCol = (refcolumns != null) ? (Map) refcolumns.get(i) : null; fk.addColumnPair(strip((String) eachCol.get("column")), refCol != null ? strip((String) refCol.get("column")) : null); } TableDescription td = getTable(catalog, fk.getTableName()); td.addForeignKey(fk); } } class DropSequenceBuilder extends CatalogBuilder { public void process(MapNode values, CatalogDescription catalog) throws IOException, TemplateException { String seqName = values.getString("sequence"); catalog.removeSequence(seqName); } } class CreateSequenceBuilder extends CatalogBuilder { // {cache={value=100}, nominvalue=NOMINVALUE, increment=1, start=1, // noorder=NOORDER, nocycle=NOCYCLE, sequence=SEQ_NLSBundle, nomaxvalue=NOMAXVALUE} public void process(MapNode values, CatalogDescription catalog) { SequenceDescription sd = new SequenceDescription(); sd.setSequenceName(strip(values.getString("sequence"))); sd.setCache(getInt(values, "attributes/cache/value")); sd.setCycle(!getBool(values, "attributes/nocycle")); sd.setIncrement(getInt(values, "attributes/increment")); if (sd.getIncrement() == 0) sd.setIncrement(1); sd.setStart(getInt(values, "attributes/start")); if (sd.getStart() == 0) sd.setStart(1); //sd.setMaxValue(); //sd.setMinValue(); sd.setOrder(!getBool(values, "attributes/noorder")); catalog.addSequence(sd); } } class DropTableBuilder extends CatalogBuilder { public void process(MapNode values, CatalogDescription catalog) throws IOException, TemplateException { final String tableName = strip(values.getString("table")); catalog.removeTable(tableName); } } class CreateTableBuilder extends CatalogBuilder { // {table=NLSBUNDLE, columndefinition=[ // {typeName=VARCHAR, column=DOMAIN, mandatory=NOT NULL, precision={numbers=[{value=500}]}}]} public void process(MapNode values, CatalogDescription catalog) throws IOException, TemplateException { final String tableName = strip(values.getString("table")); final TableDescription td = getTable(catalog, tableName); final List elements = values.getList("tableElement"); for (Object element : elements) { MapNode theColDef = new MapNode((Map) element); if (theColDef.getMap().containsKey("columndefinition")) { buildColumnDescription( new MapNode((Map) theColDef.get("columndefinition")), td); } else if (theColDef.getMap().containsKey("primaryKey")) { buildPrimaryKey(theColDef, td); } else if (theColDef.getMap().containsKey("foreignKey")) { buildForeignKey(theColDef, td); } } } protected void buildForeignKey(MapNode aColDef, TableDescription aTd) { ForeignKeyDescription fk = new ForeignKeyDescription(); fk.setTableName(aTd.getTableName()); //fk.setConstraintName(strip(values.getString("constraint/constraintName"))); fk.setRefTableName(strip(aColDef.getString("foreignKey/refTable"))); fk.setTableSpace( strip(aColDef.getString("foreignKey/tableSpace/tableSpace"))); List columns = aColDef.getList("foreignKey/columns"); List refcolumns = aColDef.getList("foreignKey/refcolumns/refcolumns"); for (int j = 0; j < columns.size(); j++) { Map eachCol = (Map) columns.get(j); Map refCol = (refcolumns != null) ? (Map) refcolumns.get(j) : null; fk.addColumnPair(strip((String) eachCol.get("column")), refCol != null ? strip((String) refCol.get("column")) : null); } aTd.addForeignKey(fk); } protected void buildPrimaryKey(MapNode aColDef, TableDescription aTd) { IndexDescription pk = new IndexDescription(); pk.setTableName(aTd.getTableName()); pk.setTableSpace( strip(aColDef.getString("primaryKey/tableSpace/tableSpace"))); //pk.setIndexName(strip(values.getString("constraint/constraintName"))); pk.setUnique(true); List columns = aColDef.getList("primaryKey/columns"); for (Object column : columns) { Map eachCol = (Map) column; pk.addColumn(strip((String) eachCol.get("column"))); } aTd.setPrimaryKey(pk); } } // using syntax preferred by the DeZign ER Tool protected class DezignCreateTableBuilder extends CreateTableBuilder { // {table=NLSBUNDLE, columndefinition=[ // {typeName=VARCHAR, column=DOMAIN, mandatory=NOT NULL, precision={numbers=[{value=500}]}}]} public void process(MapNode values, CatalogDescription catalog) throws IOException, TemplateException { super.process(values, catalog); final String tableName = strip(values.getString("table")); final TableDescription td = getTable(catalog, tableName); final List elements = values.getList("tableElement"); for (Object element : elements) { MapNode theColDef = new MapNode((Map) element); if (theColDef.getMap().containsKey("tableConstraint")) { buildTableConstraint(theColDef, td); } if (theColDef.getString("columndefinition/isUnique") != null) { // unique column IndexDescription index = new IndexDescription(); index.setTableName(td.getTableName()); index.addColumn(strip(theColDef.getString("columndefinition/column"))); index.setUnique(true); // index.setIndexName(td.getTableName() + "_" + index.getColumn(0) + "_key"); // default for Postgres td.addIndex(index); } } } protected void buildTableConstraint(MapNode aColDef, TableDescription aTd) { IndexDescription index = new IndexDescription(); index.setTableName(aTd.getTableName()); index.setTableSpace( strip(aColDef.getString("tableConstraint/tableSpace/tableSpace"))); index.setIndexName(strip(aColDef.getString( "tableConstraint/constraint/constraintName"))); List columns = aColDef.getList("tableConstraint/columns"); for (Object column : columns) { Map eachCol = (Map) column; index.addColumn(strip((String) eachCol.get("column"))); } if (aColDef.getString("tableConstraint/isPK") != null) { index.setUnique(true); aTd.setPrimaryKey(index); } else { if (aColDef.getString("tableConstraint/isUnique") != null) { index.setUnique(true); } aTd.addConstraint(index); } } } class TableAddPrimaryKey extends CatalogBuilder { // {table=NLSTEXT, constraint={tableSpace="DB_INDEX", constraintName="NLSTEXT_PK", // columns=[{column=BUNDLEID}, {column=LOCALE}, {column=KEY}]}} public void process(MapNode values, CatalogDescription catalog) { TableDescription td = getTable(catalog, values.getString("table")); IndexDescription pk = new IndexDescription(); pk.setTableName(strip(td.getTableName())); pk.setTableSpace(strip(values.getString("constraint/tableSpace/tableSpace"))); pk.setIndexName(strip(values.getString("constraint/constraintName"))); pk.setUnique(true); List columns = values.getList("constraint/columns"); for (Object column : columns) { Map eachCol = (Map) column; pk.addColumn(strip((String) eachCol.get("column"))); } td.setPrimaryKey(pk); } } public CatalogDescription getCatalog() { if (catalog == null) { setCatalog(new CatalogDescription()); } return catalog; } public void setCatalog(CatalogDescription aCatalog) { catalog = aCatalog; } /** * API - * not thread-safe. only fill one catalog at the same time with this instance. * @param scriptURL - URL to a script to parse * @throws java.io.IOException - url not found * @throws java.sql.SQLException - error executing SQL */ public void fillCatalog(URL scriptURL) throws SQLException, IOException { SQLScriptParser parser = new SQLScriptParser(log); parser.iterateSQLScript(this, scriptURL); } /** * parse the statement and create the adequate parts of the Catalog * * @param statement - a DDL statement (Oracle syntax) * @return 0 * @throws SQLException */ public int visitStatement(String statement) throws SQLException { int found = 0; for (ExtractExpr theExpr : ddlSpec.getExpressions()) { Map values = extractor.extract(statement, theExpr); if (values != null) { found++; if (log.isDebugEnabled()) { log.debug("FOUND " + theExpr.getName() + " in: " + statement); log.debug(values); } CatalogBuilder builder = builders.get(theExpr.getName()); if (builder != null) { try { builder.process(new MapNode(values), getCatalog()); } catch (Exception e) { log.error("error processing " + values, e); } } break; // we stop when the first expression matches. maybe we want to change this in the future...? } } if (found == 0) { if (log.isDebugEnabled()) log.debug("IGNORE: " + statement); } return 0; } public void visitComment(String theComment) throws SQLException { // intentionally empty, do nothing } public void doCommit() throws SQLException { // intentionally empty, do nothing } public void doRollback() throws SQLException { // intentionally empty, do nothing } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy