001: /*
002: * Copyright (c) 1998 - 2005 Versant Corporation
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * Versant Corporation - initial API and implementation
010: */
011: package com.versant.core.jdbc.sql.exp;
012:
013: import com.versant.core.util.CharBuf;
014: import com.versant.core.jdbc.sql.SqlDriver;
015:
016: import com.versant.core.common.BindingSupportImpl;
017:
018: /**
019: * An 'and' expression.
020: */
021: public class AndExp extends SqlExp {
022:
023: public AndExp() {
024: }
025:
026: public AndExp(SqlExp children) {
027: super (children);
028: }
029:
030: public SqlExp createInstance() {
031: return new AndExp();
032: }
033:
034: /**
035: * Append SQL for this node to s.
036: *
037: * @param driver The driver being used
038: * @param s Append the SQL here
039: * @param leftSibling
040: */
041: public void appendSQLImp(SqlDriver driver, CharBuf s,
042: SqlExp leftSibling) {
043: appendSQL(childList, driver, s, null);
044: SqlExp prev = childList;
045: for (SqlExp e = childList.next; e != null; prev = e, e = e.next) {
046: s.append(" AND ");
047: appendSQL(e, driver, s, prev);
048: }
049: }
050:
051: private void appendSQL(SqlExp e, SqlDriver driver, CharBuf s,
052: SqlExp leftSibling) {
053: boolean p = e.requiresParensInAnd();
054: if (p)
055: s.append('(');
056: e.appendSQL(driver, s, leftSibling);
057: if (p)
058: s.append(')');
059: }
060:
061: /**
062: * Normalize this node i.e. transform it into its simplist possible form.
063: * This will turn sub selects into joins and so on. Return expression to
064: * replace us with or null if no change.
065: */
066: public SqlExp normalize(SqlDriver driver, SelectExp sel,
067: boolean convertExists) {
068: super .normalize(driver, sel, convertExists);
069:
070: if (!driver.isConvertExistsToDistinctJoin())
071: return null;
072:
073: SqlExp p = null;
074: for (SqlExp e = childList; e != null;) {
075: int cj = e.getConvertToJoin();
076: if (cj >= SqlExp.YES) {
077: // convert to join with distinct
078: boolean not = cj == SqlExp.YES_DISTINCT_NOT;
079: SelectExp sub;
080: if (not) {
081: sub = (SelectExp) (e.childList.childList);
082: } else {
083: sub = (SelectExp) (e.childList);
084: }
085: Join j = new Join();
086: j.selectExp = sub;
087: j.exp = sub.subSelectJoinExp;
088: sub.subSelectJoinExp = null;
089: sel.addJoinMerge(j);
090: if (!sel.distinct) {
091: sel.distinct = cj >= SqlExp.YES_DISTINCT;
092: }
093: if (not) {
094: sub.setOuterRec();
095: if (sub.whereExp != null) {
096: throw BindingSupportImpl.getInstance()
097: .fatalDatastore(
098: "Query too complex for "
099: + driver.getName());
100: }
101: // replace us in childlist with exp to check row not matched
102: SqlExp ne = sub.getOuterJoinNotMatchedExp();
103: if (p == null) {
104: p = childList = ne;
105: } else {
106: p = p.next = ne;
107: }
108: e = ne.next = e.next;
109: } else {
110: SqlExp ne = sub.whereExp;
111: if (ne == null) {
112: ne = sub.getOuterJoinMatchedExp();
113: } else {
114: sub.whereExp = null;
115: }
116: // replace us in childlist with ne
117: if (p == null) {
118: p = childList = ne;
119: } else {
120: p = p.next = ne;
121: }
122: e = ne.next = e.next;
123: }
124: } else {
125: p = e;
126: e = e.next;
127: }
128: }
129:
130: // see if we can get rid of the AndExp
131: if (childList == null)
132: return null; // should return dummy exp
133: if (childList.next == null)
134: return childList;
135: return null;
136: }
137:
138: }
|