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.jdbc.sql.SqlDriver;
014: import com.versant.core.jdbc.sql.conv.DummyPreparedStmt;
015: import com.versant.core.util.CharBuf;
016: import com.versant.core.jdo.query.UnaryOpNode;
017:
018: import java.util.Map;
019: import java.sql.SQLException;
020:
021: import com.versant.core.common.BindingSupportImpl;
022:
023: /**
024: * An unary operator (+, -, ~, !) expression.
025: */
026: public class UnaryOpExp extends UnaryExp {
027:
028: public static final int OP_MINUS = UnaryOpNode.OP_MINUS;
029: public static final int OP_PLUS = UnaryOpNode.OP_PLUS;
030: public static final int OP_COMPLEMENT = UnaryOpNode.OP_TILDE;
031: public static final int OP_NOT = UnaryOpNode.OP_BANG;
032:
033: private int op;
034:
035: public UnaryOpExp(SqlExp child, int op) {
036: super (child);
037: this .op = op;
038: }
039:
040: public UnaryOpExp() {
041: }
042:
043: public SqlExp createInstance() {
044: return new UnaryOpExp();
045: }
046:
047: public SqlExp getClone(SqlExp clone, Map cloneMap) {
048: super .getClone(clone, cloneMap);
049:
050: ((UnaryOpExp) clone).op = op;
051:
052: return clone;
053: }
054:
055: public String toString() {
056: String s = super .toString() + " ";
057: switch (op) {
058: case OP_PLUS:
059: return s + "+";
060: case OP_MINUS:
061: return s + "-";
062: case OP_NOT:
063: return s + "not";
064: case OP_COMPLEMENT:
065: return s + "~";
066: }
067: return s + "unknown(" + op + ")";
068: }
069:
070: /**
071: * Normalize this node i.e. transform it into its simplist possible form.
072: * This will turn sub selects into joins and so on.
073: */
074: public SqlExp normalize(SqlDriver driver, SelectExp sel,
075: boolean convertExists) {
076: if (childList instanceof UnaryOpExp
077: && ((UnaryOpExp) childList).op == op) {
078: // if our child is the same as us then skip both of us as the
079: // operations will cancel each other out
080: SqlExp r = childList.childList.normalize(driver, sel,
081: convertExists);
082: if (r != null) {
083: return r;
084: } else {
085: return childList.childList;
086: }
087: } else {
088: SqlExp r = null;
089: if (childList != null)
090: r = childList.normalize(driver, sel, convertExists);
091: if (r != null)
092: childList = r;
093: return null;
094: }
095: }
096:
097: /**
098: * Append SQL for this node to s.
099: *
100: * @param driver The driver being used
101: * @param s Append the SQL here
102: * @param leftSibling
103: */
104: public void appendSQLImp(SqlDriver driver, CharBuf s,
105: SqlExp leftSibling) {
106: // if our child is the same as us then skip both of us as the
107: // operations will cancel each other out
108: if (childList instanceof UnaryOpExp
109: && ((UnaryOpExp) childList).op == op) {
110: childList.childList.appendSQL(driver, s, null);
111: return;
112: }
113:
114: boolean brackets;
115: switch (op) {
116: case OP_PLUS:
117: // do not need to do anything else
118: childList.appendSQL(driver, s, null);
119: break;
120: case OP_MINUS:
121: s.append('-');
122: s.append(' ');
123: // SAP DB does not like extra brackets around numbers
124: brackets = !(childList instanceof LiteralExp);
125: if (brackets)
126: s.append('(');
127: childList.appendSQL(driver, s, null);
128: if (brackets)
129: s.append(')');
130: break;
131: case OP_NOT:
132: if (childList instanceof ColumnExp) {
133: ColumnExp cExp = (ColumnExp) childList;
134: childList.appendSQL(driver, s, null);
135: s.append(" = ");
136: if (cExp.col.converter != null) {
137: DummyPreparedStmt pstmt = new DummyPreparedStmt();
138: try {
139: cExp.col.converter.set(pstmt, 0, cExp.col,
140: new Boolean("false"));
141: } catch (SQLException e) {
142: //ignore
143: }
144: if (pstmt.toQuote) {
145: s.append("'" + pstmt.value + "'");
146: } else {
147: s.append(pstmt.value);
148: }
149: } else {
150: s.append("false");
151: }
152: } else {
153: s.append("not ");
154: s.append('(');
155: childList.appendSQL(driver, s, null);
156: s.append(')');
157: }
158: break;
159: case OP_COMPLEMENT:
160: s.append('(');
161: s.append('-');
162: s.append(' ');
163: // SAP DB does not like extra brackets around numbers
164: brackets = !(childList instanceof LiteralExp);
165: if (brackets)
166: s.append('(');
167: childList.appendSQL(driver, s, null);
168: if (brackets)
169: s.append(')');
170: s.append(')');
171: s.append(' ');
172: s.append('-');
173: s.append(' ');
174: s.append('1');
175: break;
176: default:
177: throw BindingSupportImpl.getInstance().internal(
178: "Unknown UnaryOpExp op: " + op);
179: }
180: }
181:
182: /**
183: * Can this expression be removed and its child be converted into a join?
184: *
185: * @see ExistsExp
186: * @see #NO
187: * @see #YES
188: * @see #YES_DISTINCT
189: */
190: public int getConvertToJoin() {
191: if (childList == null)
192: return YES;
193: if (op == OP_NOT) {
194: int ans = childList.getConvertToJoin();
195: if (ans == YES_DISTINCT)
196: return YES_DISTINCT_NOT;
197: return ans;
198: } else {
199: return NO;
200: }
201: }
202:
203: }
|