001: package com.quadcap.sql;
002:
003: /* Copyright 1999 - 2003 Quadcap Software. All rights reserved.
004: *
005: * This software is distributed under the Quadcap Free Software License.
006: * This software may be used or modified for any purpose, personal or
007: * commercial. Open Source redistributions are permitted. Commercial
008: * redistribution of larger works derived from, or works which bundle
009: * this software requires a "Commercial Redistribution License"; see
010: * http://www.quadcap.com/purchase.
011: *
012: * Redistributions qualify as "Open Source" under one of the following terms:
013: *
014: * Redistributions are made at no charge beyond the reasonable cost of
015: * materials and delivery.
016: *
017: * Redistributions are accompanied by a copy of the Source Code or by an
018: * irrevocable offer to provide a copy of the Source Code for up to three
019: * years at the cost of materials and delivery. Such redistributions
020: * must allow further use, modification, and redistribution of the Source
021: * Code under substantially the same terms as this license.
022: *
023: * Redistributions of source code must retain the copyright notices as they
024: * appear in each source code file, these license terms, and the
025: * disclaimer/limitation of liability set forth as paragraph 6 below.
026: *
027: * Redistributions in binary form must reproduce this Copyright Notice,
028: * these license terms, and the disclaimer/limitation of liability set
029: * forth as paragraph 6 below, in the documentation and/or other materials
030: * provided with the distribution.
031: *
032: * The Software is provided on an "AS IS" basis. No warranty is
033: * provided that the Software is free of defects, or fit for a
034: * particular purpose.
035: *
036: * Limitation of Liability. Quadcap Software shall not be liable
037: * for any damages suffered by the Licensee or any third party resulting
038: * from use of the Software.
039: */
040:
041: import java.util.Vector;
042:
043: import java.sql.SQLException;
044:
045: import com.quadcap.sql.types.Op;
046:
047: import com.quadcap.util.Debug;
048:
049: /**
050: * Join planner.
051: *
052: * @author Stan Bailes
053: */
054: public class Analyze {
055: Session session;
056: Expression expr;
057: BinaryExpression b = null;
058: NameExpression n = null;
059: ValueExpression v = null;
060: //#ifdef DEBUG
061: String prefix = "";
062:
063: //#endif
064:
065: public Analyze(Session session, Expression expr) {
066: this .session = session;
067: this .expr = expr;
068: if (expr instanceof BinaryExpression)
069: b = (BinaryExpression) expr;
070: if (expr instanceof NameExpression)
071: n = (NameExpression) expr;
072: if (expr instanceof ValueExpression)
073: v = (ValueExpression) expr;
074: }
075:
076: public void getConjunctives(Vector v) {
077: if (b != null) {
078: if (b.not) {
079: // XXX could get fancy and try to DeMorgan'ize it.
080: v.addElement(expr);
081: } else {
082: if (b.op == Op.AND) {
083: analyze(b.e).getConjunctives(v);
084: analyze(b.f).getConjunctives(v);
085: } else {
086: v.addElement(expr);
087: }
088: }
089: } else {
090: v.addElement(expr);
091: }
092: }
093:
094: public boolean isConstant() {
095: return expr instanceof ValueExpression;
096: }
097:
098: public boolean isName() {
099: return n != null;
100: }
101:
102: public boolean refersTo(Tuple table) throws SQLException {
103: boolean ret = false;
104: if (n != null) {
105: if (table.getColumn(n.name) != null)
106: ret = true;
107: }
108: return ret;
109: }
110:
111: public Analyze analyze(Expression e) {
112: Analyze z = new Analyze(session, e);
113: //#ifdef DEBUG
114: z.prefix = prefix + " ";
115: //#endif
116: return z;
117: }
118:
119: public boolean isConstantCompareToTable(Tuple table)
120: throws SQLException {
121: boolean ret = false;
122: if (b != null) {
123: Analyze be = analyze(b.e);
124: Analyze bf = analyze(b.f);
125: if (be.isConstant()) {
126: if (bf.refersTo(table)) {
127: ret = true;
128: }
129: } else if (bf.isConstant()) {
130: if (be.refersTo(table)) {
131: ret = true;
132: }
133: }
134: }
135: //Debug.println("Analyze[" + expr + "].isConstantCompareToTable(" +
136: // table.getName() + ") = " + ret);
137: return ret;
138: }
139:
140: public boolean isTermOrConstant(Tuple table) throws SQLException {
141: boolean ret = false;
142: if (n != null) {
143: ret = refersTo(table);
144: } else if (b != null) {
145: Analyze be = analyze(b.e);
146: Analyze bf = analyze(b.f);
147: ret = be.isTermOrConstant(table)
148: && bf.isTermOrConstant(table);
149: } else if (v != null) {
150: ret = true;
151: }
152: return ret;
153: }
154:
155: public int[][] getJoinColumns(Cursor ca, Cursor cb)
156: throws SQLException {
157: Vector vec = new Vector();
158: Vector aCols = new Vector();
159: Vector bCols = new Vector();
160: int cnt = 0;
161: int[][] ret = null;
162: getConjunctives(vec);
163: for (int i = 0; i < vec.size(); i++) {
164: Expression ei = (Expression) vec.elementAt(i);
165: if (analyze(ei).isJoinColumn(ca, aCols, cb, bCols)) {
166: cnt++;
167: }
168: }
169: if (cnt > 0) {
170: ret = new int[2][cnt];
171: for (int i = 0; i < cnt; i++) {
172: ret[0][i] = ((Column) aCols.elementAt(i)).getColumn();
173: ret[1][i] = ((Column) bCols.elementAt(i)).getColumn();
174: }
175: }
176: return ret;
177: }
178:
179: boolean isJoinColumn(Cursor ca, Vector aCols, Cursor cb,
180: Vector bCols) throws SQLException {
181: if (b == null)
182: return false;
183: if (b.op != Op.EQ)
184: return false;
185: if (!(b.e instanceof NameExpression))
186: return false;
187: String ename = ((NameExpression) b.e).name;
188: if (!(b.f instanceof NameExpression))
189: return false;
190: String fname = ((NameExpression) b.f).name;
191: Column cea = ca.getColumn(ename);
192: if (cea != null) {
193: Column cfb = cb.getColumn(fname);
194: if (cfb != null) {
195: aCols.addElement(cea);
196: bCols.addElement(cfb);
197: return true;
198: }
199: }
200: Column ceb = cb.getColumn(ename);
201: if (ceb != null) {
202: Column cfa = ca.getColumn(fname);
203: if (cfa != null) {
204: aCols.addElement(cfa);
205: bCols.addElement(ceb);
206: return true;
207: }
208: }
209: return false;
210: }
211:
212: public Expression factorTable(Tuple table) throws SQLException {
213: Expression ret = null;
214: if (table != null) {
215: Vector vec = new Vector();
216: getConjunctives(vec);
217: for (int i = 0; i < vec.size(); i++) {
218: Expression ei = (Expression) vec.elementAt(i);
219: if (analyze(ei).isTermOrConstant(table)) {
220: if (ret == null) {
221: ret = ei;
222: } else {
223: ret = new BinaryExpression(Op.AND, ret, ei);
224: }
225: }
226: }
227: }
228: // Debug.println("Analyze[" + expr + "].factorTable(" +
229: // (table == null ? "null" : table.getName()) + ") => " +
230: // ret);
231: return ret;
232:
233: }
234:
235: public boolean isJoinExpression(Tuple c) throws SQLException {
236: boolean ret = false;
237: if (isConstant()) {
238: ret = true;
239: } else if (n != null) {
240: if (c.getColumn(n.name) != null)
241: ret = true;
242: } else if (b != null) {
243: if (analyze(b.e).isJoinExpression(c)
244: && analyze(b.f).isJoinExpression(c))
245: ret = true;
246: }
247: return ret;
248: }
249:
250: public Expression factorJoinExpression(Tuple c) throws SQLException {
251: Expression ret = null;
252: Vector vec = new Vector();
253: getConjunctives(vec);
254: for (int i = 0; i < vec.size(); i++) {
255: Expression ei = (Expression) vec.elementAt(i);
256: if (analyze(ei).isJoinExpression(c)) {
257: if (ret == null) {
258: ret = ei;
259: } else {
260: ret = new BinaryExpression(Op.AND, ret, ei);
261: }
262: }
263: }
264: return ret;
265: }
266:
267: //#ifdef DEBUG
268: public String toString() {
269: return prefix + "Analyze[" + expr + "]";
270: }
271: //#endif
272: }
|