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 'or' expression.
020: */
021: public class OrExp extends SqlExp {
022:
023: public OrExp(SqlExp children) {
024: super (children);
025: }
026:
027: public OrExp() {
028: }
029:
030: public SqlExp createInstance() {
031: return new OrExp();
032: }
033:
034: /**
035: * If this expression is added to an AndExp should it be enclosed in
036: * parenthesis?
037: */
038: public boolean requiresParensInAnd() {
039: return true;
040: }
041:
042: /**
043: * Append SQL for this node to s.
044: *
045: * @param driver The driver being used
046: * @param s Append the SQL here
047: * @param leftSibling
048: */
049: public void appendSQLImp(SqlDriver driver, CharBuf s,
050: SqlExp leftSibling) {
051: childList.appendSQL(driver, s, null);
052: SqlExp prev = childList;
053: for (SqlExp e = childList.next; e != null; prev = e, e = e.next) {
054: s.append(" OR ");
055: e.appendSQL(driver, s, prev);
056: }
057: }
058:
059: /**
060: * Normalize this node i.e. transform it into its simplist possible form.
061: * This will turn sub selects into joins and so on. Return expression to
062: * replace us with or null if no change.
063: */
064: public SqlExp normalize(SqlDriver driver, SelectExp sel,
065: boolean convertExists) {
066: super .normalize(driver, sel, convertExists);
067:
068: if (!driver.isConvertExistsToDistinctJoin())
069: return null;
070:
071: SqlExp p = null;
072: for (SqlExp e = childList; e != null;) {
073: int cj = e.getConvertToJoin();
074: if (cj >= SqlExp.YES) {
075: // convert to outer join with distinct
076: boolean not = cj == SqlExp.YES_DISTINCT_NOT;
077: SelectExp sub;
078: if (not)
079: sub = (SelectExp) (e.childList.childList);
080: else
081: sub = (SelectExp) (e.childList);
082: Join j = new Join();
083: j.selectExp = sub;
084: j.exp = sub.subSelectJoinExp;
085: sub.subSelectJoinExp = null;
086: sel.addJoinMerge(j);
087: if (!sel.distinct) {
088: sel.distinct = cj >= SqlExp.YES_DISTINCT;
089: }
090: sub.setOuterRec();
091: if (not) {
092: if (sub.whereExp != null) {
093: throw BindingSupportImpl.getInstance()
094: .fatalDatastore(
095: "Query too complex for "
096: + driver.getName());
097: }
098: // replace us in childlist with exp to check row not matched
099: SqlExp ne = sub.getOuterJoinNotMatchedExp();
100: if (p == null) {
101: p = childList = ne;
102: } else {
103: p = p.next = ne;
104: }
105: e = ne.next = e.next;
106: } else {
107: SqlExp ne = sub.whereExp;
108: if (ne == null)
109: ne = sub.getOuterJoinMatchedExp();
110: else
111: sub.whereExp = null;
112: // replace us in childlist with ne
113: if (p == null)
114: p = childList = ne;
115: else
116: p = p.next = ne;
117: e = ne.next = e.next;
118: }
119: } else {
120: p = e;
121: e = e.next;
122: }
123: }
124:
125: // see if we can get rid of the OrExp
126: if (childList == null)
127: return null; // should return dummy exp
128: if (childList.next == null)
129: return childList;
130: return null;
131: }
132:
133: }
|