001: /*
002: * The contents of this file are subject to the terms of the Common Development
003: * and Distribution License (the License). You may not use this file except in
004: * compliance with the License.
005: *
006: * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
007: * or http://www.netbeans.org/cddl.txt.
008: *
009: * When distributing Covered Code, include this CDDL Header Notice in each file
010: * and include the License file at http://www.netbeans.org/cddl.txt.
011: * If applicable, add the following below the CDDL Header, with the fields
012: * enclosed by brackets [] replaced by your own identifying information:
013: * "Portions Copyrighted [year] [name of copyright owner]"
014: *
015: * The Original Software is NetBeans. The Initial Developer of the Original
016: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
017: * Microsystems, Inc. All Rights Reserved.
018: */
019: package org.netbeans.modules.sql.framework.codegen.db2v7;
020:
021: import java.util.ArrayList;
022: import java.util.Iterator;
023: import java.util.List;
024: import java.util.Map;
025: import org.apache.velocity.VelocityContext;
026: import org.netbeans.modules.sql.framework.codegen.AbstractDB;
027: import org.netbeans.modules.sql.framework.codegen.ColumnIdentifier;
028: import org.netbeans.modules.sql.framework.codegen.ResolvedMapping;
029: import org.netbeans.modules.sql.framework.codegen.StatementContext;
030: import org.netbeans.modules.sql.framework.codegen.base.BaseStatements;
031: import org.netbeans.modules.sql.framework.model.ColumnRef;
032: import org.netbeans.modules.sql.framework.model.SQLCondition;
033: import org.netbeans.modules.sql.framework.model.SQLConnectableObject;
034: import org.netbeans.modules.sql.framework.model.SQLConstants;
035: import org.netbeans.modules.sql.framework.model.SQLInputObject;
036: import org.netbeans.modules.sql.framework.model.SQLObject;
037: import org.netbeans.modules.sql.framework.model.SQLPredicate;
038: import org.netbeans.modules.sql.framework.model.TargetColumn;
039: import org.netbeans.modules.sql.framework.model.TargetTable;
040: import com.sun.sql.framework.exception.BaseException;
041: import com.sun.sql.framework.jdbc.SQLPart;
042:
043: /**
044: * @author Jonathan Giron
045: * @version $Revision$
046: */
047: public class DB2V7Statements extends BaseStatements {
048:
049: public DB2V7Statements(AbstractDB database) {
050: super (database);
051: }
052:
053: @Override
054: @SuppressWarnings(value="fallthrough")
055: protected void populateContextForUpdate(TargetTable targetTable,
056: StatementContext context, VelocityContext vContext)
057: throws BaseException {
058: // Inherit settings from incoming context to allow for localized customization
059: StatementContext localContext = new StatementContext();
060: if (context != null) {
061: localContext.putAll(context);
062: }
063:
064: localContext.putClientProperty(
065: StatementContext.USE_SOURCE_TABLE_ALIAS_NAME,
066: Boolean.TRUE);
067: //localContext.putClientProperty(StatementContext.USE_TARGET_TABLE_ALIAS_NAME, Boolean.TRUE);
068: vContext.put("statementSeparator", Character
069: .toString(SQLPart.STATEMENT_SEPARATOR));
070:
071: // SELECT START
072: final boolean excludeJoinKeyColumns = false;
073: List rMappings = createResolvedMappings(targetTable,
074: excludeJoinKeyColumns, localContext);
075: List<ColumnIdentifier> selectIdentifiers = new ArrayList<ColumnIdentifier>();
076:
077: Iterator it = rMappings.iterator();
078: while (it.hasNext()) {
079: ResolvedMapping rm = (ResolvedMapping) it.next();
080: if (!rm.isKeyColumn()) {
081: selectIdentifiers.add(rm.getSource());
082: }
083: }
084:
085: String targetTableName = this .genFactory.generate(targetTable,
086: localContext);
087: vContext.put("targetTable", targetTableName);
088:
089: vContext.put("sourceColumnIdentifiers", selectIdentifiers);
090: vContext.put("aliasColumns", Boolean.TRUE);
091: //vContext.put("distinct", Boolean.FALSE);
092: vContext.put("distinct", areDistinctRowsRequired(targetTable));
093:
094: vContext.put("selectAliasName", "");
095:
096: List sourceTables = targetTable.getSourceTableList();
097: switch (sourceTables.size()) {
098: case 0:
099: break;
100: case 1:
101: vContext.put("fromContent", genFactory.generate(
102: (SQLObject) sourceTables.get(0), localContext));
103: default:
104: vContext.put("fromContent", getFromStatementContent(
105: targetTable, localContext));
106: }
107:
108: vContext.put("nestedIndent", " ");
109:
110: vContext.put("useUpdateWhere", Boolean.FALSE);
111:
112: String condition = getTargetWhereCondition(targetTable,
113: localContext);
114: if (condition != null && !condition.equals("")) {
115: vContext.put("useUpdateWhere", Boolean.TRUE);
116: vContext.put("condition", condition);
117: }
118: //SELECT END
119: //SET START
120: vContext.put("mappings", rMappings);
121: //SET END
122: // UPDATE statement WHERE clause.
123: SQLCondition tgtWhere = targetTable.getJoinCondition();
124: populateUpdateWhereVariables(tgtWhere, localContext, vContext);
125: }
126:
127: private boolean hasOnlyColType(SQLObject sqlObj, int colType) {
128: boolean ret = true;
129: SQLConnectableObject exp = null;
130: List list = null;
131: if (sqlObj.getObjectType() == SQLConstants.COLUMN_REF) {
132: sqlObj = ((ColumnRef) sqlObj).getColumn();
133: if (sqlObj.getObjectType() != colType) {
134: ret = false;
135: }
136: } else {
137: if (sqlObj instanceof SQLConnectableObject) {
138: exp = (SQLConnectableObject) sqlObj;
139: if (colType == SQLConstants.SOURCE_COLUMN) {
140: list = exp.getTargetColumnsUsed();
141: if (list.size() > 0) {
142: ret = false;
143: } else {
144: list = exp.getSourceColumnsUsed();
145: if (list.size() <= 0) {
146: ret = false;
147: }
148: }
149: } else {
150: list = exp.getSourceColumnsUsed();
151: if (list.size() > 0) {
152: ret = false;
153: } else {
154: list = exp.getTargetColumnsUsed();
155: if (list.size() <= 0) {
156: ret = false;
157: }
158: }
159: }
160: } else {
161: ret = false;
162: }
163: }
164:
165: return ret;
166: }
167:
168: @SuppressWarnings(value="unchecked")
169: private void findEqualsOperator(SQLPredicate predicate,
170: StatementContext sc, List srcExpList, List tgtExpList)
171: throws BaseException {
172: SQLObject srcColExpression = null;
173: SQLObject tgtColExpression = null;
174: Map inputMap = null;
175: boolean foundTarget = false;
176: boolean foundSource = false;
177: Iterator itr = null;
178: String argName = null;
179: SQLInputObject input = null;
180: SQLObject sqlObj = null;
181:
182: if (predicate != null) {
183: inputMap = predicate.getInputObjectMap();
184: if ("=".equals(predicate.getOperatorType())) {
185: itr = inputMap.keySet().iterator();
186: while (itr.hasNext()) {
187: argName = (String) itr.next();
188: input = (SQLInputObject) inputMap.get(argName);
189: sqlObj = input.getSQLObject();
190: if (sqlObj != null) {
191: // Get the first Expression available.
192: if ((!foundSource)
193: && (hasOnlyColType(sqlObj,
194: SQLConstants.SOURCE_COLUMN))) {
195: foundSource = true;
196: srcColExpression = sqlObj;
197: }
198:
199: if ((!foundTarget)
200: && (hasOnlyColType(sqlObj,
201: SQLConstants.TARGET_COLUMN))) {
202: foundTarget = true;
203: tgtColExpression = sqlObj;
204: }
205: }
206: }
207:
208: if (foundSource && foundTarget) {
209: String srcColExp = this .genFactory.generate(
210: srcColExpression, sc);
211: String tgtColExp = this .genFactory.generate(
212: tgtColExpression, sc);
213: srcExpList.add(srcColExp);
214: tgtExpList.add(tgtColExp);
215: }
216: } else {
217: itr = inputMap.keySet().iterator();
218: while (itr.hasNext()) {
219: argName = (String) itr.next();
220: input = (SQLInputObject) inputMap.get(argName);
221: sqlObj = input.getSQLObject();
222: if (sqlObj != null) {
223: if (sqlObj instanceof SQLPredicate) {
224: findEqualsOperator((SQLPredicate) sqlObj,
225: sc, srcExpList, tgtExpList);
226: }
227: }
228: }
229: }
230: }
231: }
232:
233: private void populateUpdateWhereVariables(
234: SQLCondition tgtCondition, StatementContext sc,
235: VelocityContext vc) throws BaseException {
236: // (fn1(tgtCol1) = func2(srcCOl)) AND (exp1 OR exp2)
237: SQLPredicate rootPred = null;
238: List srcExp = new ArrayList();
239: List tgtExp = new ArrayList();
240: if (tgtCondition != null) {
241: rootPred = tgtCondition.getRootPredicate();
242: findEqualsOperator(rootPred, sc, srcExp, tgtExp);
243: if (tgtExp.size() > 0) {
244: vc.put("updateOnlyMatchedRows", Boolean.TRUE);
245: vc.put("tgtCondCols", tgtExp);
246: vc.put("srcCondCols", srcExp);
247: }
248: }
249: }
250:
251: @Override
252: public List<ResolvedMapping> createResolvedMappings(
253: TargetTable targetTable, boolean excludeKeyColumns,
254: StatementContext context) throws BaseException {
255: List<ResolvedMapping> mappings = new ArrayList<ResolvedMapping>();
256: String targetJoin = getTargetJoinClause(targetTable,
257: SQLConstants.INNER_JOIN, context);
258:
259: Iterator it = targetTable.getMappedColumns().iterator();
260: int aliasCount = 1;
261:
262: StatementContext localContext = new StatementContext();
263: if (context != null) {
264: localContext.putAll(context);
265: }
266:
267: // Use the Table Qualification flag to suppress column prefix
268: localContext.setSuppressingTablePrefixForTargetColumn(true);
269:
270: while (it.hasNext()) {
271: TargetColumn column = (TargetColumn) it.next();
272: SQLObject obj = column.getValue();
273: if (obj != null) {
274: String tSql = this .genFactory.generate(column,
275: localContext);
276: if (targetJoin.indexOf(tSql) != -1 && excludeKeyColumns) {
277: continue;
278: }
279:
280: String sSql = this .genFactory.generate(column
281: .getValue(), localContext);
282: ColumnIdentifier sId = new ColumnIdentifier(
283: SOURCE_COLUMN_IDENTIFIER_ALIAS_PREFIX
284: + aliasCount, sSql);
285: ColumnIdentifier tId = new ColumnIdentifier(
286: TARGET_COLUMN_IDENTIFIER_ALIAS_PREFIX
287: + aliasCount, tSql);
288: ResolvedMapping rm = new ResolvedMapping(sId, tId);
289: rm.setKeyColumn(column.isPrimaryKey());
290: mappings.add(rm);
291: aliasCount++;
292: }
293: }
294:
295: return mappings;
296: }
297:
298: private String normalizeSQLForExecution(String sql) {
299: if (sql != null) {
300: sql = sql.replaceAll("\r", " ");
301: sql = sql.replaceAll("\n", " ");
302: }
303: return sql;
304: }
305:
306: @Override
307: public SQLPart normalizeSQLForExecution(SQLPart rawSQLPart) {
308: if ((rawSQLPart != null) && (rawSQLPart.getSQL() != null)) {
309: String sql = rawSQLPart.getSQL();
310: sql = normalizeSQLForExecution(sql);
311: rawSQLPart.setSQL(sql);
312: }
313: return rawSQLPart;
314: }
315:
316: @Override
317: protected SQLPart createSQLPart(String sqlString, String key) {
318: // Normalization is only required when DB2 Connect drivers are used.
319: // Since generator framework is currently specific to DB, we just
320: // normalize always till make it more flexible.
321: SQLPart sqlPart = new SQLPart(
322: normalizeSQLForExecution(sqlString), key, "");
323: return sqlPart;
324: }
325: }
|