1 2 12 package com.versant.core.jdbc.ejbql; 13 14 import com.versant.core.ejb.query.*; 15 import com.versant.core.jdbc.sql.exp.*; 16 import com.versant.core.jdbc.sql.SqlDriver; 17 import com.versant.core.jdbc.metadata.JdbcClass; 18 import com.versant.core.jdbc.metadata.JdbcField; 19 import com.versant.core.jdbc.metadata.JdbcPolyRefField; 20 import com.versant.core.jdbc.fetch.FetchSpec; 21 import com.versant.core.jdbc.fetch.FopGetOID; 22 import com.versant.core.jdbc.fetch.FetchOpDataMainRS; 23 import com.versant.core.jdbc.fetch.FopGetState; 24 import com.versant.core.metadata.ClassMetaData; 25 import com.versant.core.metadata.FieldMetaData; 26 import com.versant.core.common.BindingSupportImpl; 27 import com.versant.core.common.Debug; 28 29 import java.util.ArrayList ; 30 31 34 public class EJBQLNodeToSqlExp extends NodeVisitorAdapter { 35 36 private ResolveContext rc; 37 private SqlDriver sqlDriver; 38 39 private static final Object [] EMPTY = new Object [0]; 40 41 public EJBQLNodeToSqlExp(ResolveContext rc, SqlDriver sqlDriver) { 42 this.rc = rc; 43 this.sqlDriver = sqlDriver; 44 } 45 46 49 protected Object defaultArrive(Node node, Object msg) { 50 throw rc.createUserException("Not implemented: " + node.getClass(), 51 node); 52 } 53 54 57 public SqlExp toSqlExp(Node node, Object msg) { 58 if (node == null) { 59 return null; 60 } else { 61 return (SqlExp)node.arrive(this, msg); 62 } 63 } 64 65 private RuntimeException notImplemented() { 66 return notImplemented("not implemented"); 67 } 68 69 private RuntimeException notImplemented(String msg) { 70 return BindingSupportImpl.getInstance().internal(msg); 71 } 72 73 77 private Object [] invokeArriveOnList(Node list, Object msg) { 78 if (list == null) { 79 return EMPTY; 80 } 81 if (list.getNext() == null) { return new Object []{toSqlExp(list, msg)}; 83 } else { 84 ArrayList a = new ArrayList (); 85 for (; list != null; list = list.getNext()) { 86 a.add(toSqlExp(list, msg)); 87 } 88 return a.toArray(); 89 } 90 } 91 92 96 public Object arriveSelectNode(SelectNode node, Object msg) { 97 Object [] fromList = invokeArriveOnList(node.getFromList(), msg); 98 SelectExp se = (SelectExp)fromList[0]; 99 if (fromList.length > 1) { 100 throw notImplemented(); 102 } 103 se.fetchSpec = new FetchSpec(se, sqlDriver); 104 invokeArriveOnList(node.getSelectList(), msg); 105 se.whereExp = toSqlExp(node.getWhere(), msg); 106 return se; 107 } 108 109 113 public Object arriveIdentificationVarNode(IdentificationVarNode node, 114 Object msg) { 115 NavRoot root = node.getNavRoot(); 117 ClassMetaData cmd = root.getNavClassMetaData(); 118 JdbcClass jdbcClass = (JdbcClass)cmd.storeClass; 119 SelectExp se = new SelectExp(); 120 se.table = jdbcClass.table; 121 root.storeObject = se; 122 return se; 123 } 124 125 128 public Object arrivePathNode(PathNode node, Object msg) { 129 switch (node.getParentType()) { 130 case PathNode.SELECT: 131 return pathNodeSelect(node); 132 case PathNode.WHERE: 133 return pathNodeWhere(node); 134 case PathNode.GROUP_BY: 135 case PathNode.ORDER_BY: 136 case PathNode.AGGREGATE: 137 case PathNode.CONSTRUCTOR: 138 case PathNode.JOIN: 139 case PathNode.COLLECTION_MEMBER: 140 } 141 return super.arrivePathNode(node, msg); 142 } 143 144 private Object pathNodeSelect(PathNode node) { 145 FieldMetaData fmd = node.getFmd(); 146 if (fmd == null) { return arriveObjectNodeImp(node.getNavBase()); 148 } else { throw notImplemented(); 150 } 151 } 152 153 public Object arriveObjectNode(ObjectNode node, Object msg) { 154 return arriveObjectNodeImp(node.getNavBase()); 155 } 156 157 private Object arriveObjectNodeImp(NavBase navBase) { 158 SelectExp se = (SelectExp)navBase.storeObject; 159 FetchSpec fetchSpec = se.fetchSpec; 160 ClassMetaData cmd = navBase.getNavClassMetaData(); 161 FopGetOID fopGetOid = new FopGetOID(fetchSpec, 162 FetchOpDataMainRS.INSTANCE, cmd); 163 FopGetState fopGetState = new FopGetState(fetchSpec, 164 fopGetOid.getOutputData(), cmd.fetchGroups[0], true); 165 fetchSpec.addFetchOp(fopGetOid, true); 166 fetchSpec.addFetchOp(fopGetState, true); 167 return se; 170 } 171 172 177 private SelectExp getNodeSelectExp(PathNode node) { 178 NavBase nav = node.getNavBase(); 179 SelectExp se = (SelectExp)nav.storeObject; 180 if (se == null) { 181 createJoins(nav.getRoot()); 182 se = (SelectExp)nav.storeObject; 183 if (Debug.DEBUG) { 184 if (se == null) { 185 throw BindingSupportImpl.getInstance().internal( 186 "nav.storeObject == null: " + node); 187 } 188 } 189 } 190 return se; 191 } 192 193 196 private void createJoins(NavBase from) { 197 SelectExp fromSE = (SelectExp)from.storeObject; 198 for (NavField to = from.getChildren(); to != null; to = to.getNext()) { 199 if (to.storeObject != null) { 200 continue; 201 } 202 JdbcField jdbcField = (JdbcField)to.getFmd().storeField; 203 JdbcClass targetClass = (JdbcClass)to.getNavClassMetaData().storeClass; 204 SelectExp se = new SelectExp(); 205 se.table = targetClass.table; 206 se.jdbcField = jdbcField; 207 if (jdbcField instanceof JdbcPolyRefField) { 208 JdbcPolyRefField pf = (JdbcPolyRefField)jdbcField; 209 Join j = fromSE.addJoin(pf.refCols, se.table.pk, se); 210 j.appendJoinExp( 213 pf.createClassIdMatchExp(fromSE, targetClass.cmd)); 214 } else { 215 fromSE.addJoin(jdbcField.mainTableCols, se.table.pk, se); 216 } 217 se.outer = to.isOuter(); 218 to.storeObject = se; 219 createJoins(to); 220 } 221 } 222 223 private Object pathNodeWhere(PathNode node) { 224 FieldMetaData fmd = node.getFmd(); 225 if (fmd != null) { 226 JdbcField jdbcField = (JdbcField)fmd.storeField; 227 SelectExp se = getNodeSelectExp(node); 228 ColumnExp columnExp = jdbcField.toColumnExp( 229 SelectExp.createJoinToSuperTable(se, jdbcField), true); 230 return columnExp; 231 } else { 232 throw notImplemented(); 233 } 234 } 235 236 public Object arriveCompNode(CompNode node, Object msg) { 237 SqlExp left = toSqlExp(node.getLeft(), msg); 238 SqlExp right = toSqlExp(node.getRight(), left); 239 int op = node.getOp(); 240 if (op == CompNode.EQ || op == CompNode.NE) { 241 if (op == CompNode.EQ) { 242 op = BinaryOpExp.EQUAL; 243 } else { 244 op = BinaryOpExp.NOT_EQUAL; 245 } 246 return SqlExp.createBinaryOpExp(left, op, right); 247 } else { 248 if (left.next == null && right.next == null) { 249 switch (op) { 250 case CompNode.GT: op = BinaryOpExp.GT; break; 251 case CompNode.LT: op = BinaryOpExp.LT; break; 252 case CompNode.GE: op = BinaryOpExp.GE; break; 253 case CompNode.LE: op = BinaryOpExp.LE; break; 254 default: 255 throw BindingSupportImpl.getInstance().internal( 256 "Unknown op: " + op); 257 } 258 return new BinaryOpExp(left, op, right); 259 } 260 throw BindingSupportImpl.getInstance().runtime( 261 "Expressions consisting of multiple columns may not be compared " + 262 "with >, <, >= or <=\n"); 263 } 264 } 265 266 public Object arriveLiteralNode(LiteralNode node, Object msg) { 267 String value; 268 int t; 269 switch (node.getType()) { 270 case LiteralNode.DOUBLE: 271 t = LiteralExp.TYPE_OTHER; 272 value = sqlDriver.toSqlLiteral(node.getDoubleValue()); 273 break; 274 case LiteralNode.LONG: 275 t = LiteralExp.TYPE_OTHER; 276 value = sqlDriver.toSqlLiteral(node.getLongValue()); 277 break; 278 case LiteralNode.STRING: 279 t = LiteralExp.TYPE_STRING; 280 value = node.getStringValue(); 281 break; 282 case LiteralNode.BOOLEAN: 283 t = LiteralExp.TYPE_OTHER; 284 value = sqlDriver.toSqlLiteral(node.getBooleanValue()); 285 break; 286 default: 287 throw BindingSupportImpl.getInstance().internal( 288 "Unknown literal type: " + node.getType()); 289 } 290 return new LiteralExp(t, value); 291 } 292 293 public Object arriveParameterNode(ParameterNode node, Object msg) { 294 if (msg != null && !(msg instanceof SqlExp)) { 295 throw BindingSupportImpl.getInstance().internal( 296 "expected SqlExp for msg"); 297 } 298 SqlExp leftSibling = (SqlExp)msg; 299 SqlParamUsage u = new SqlParamUsage(); 300 node.getUsage().storeObject = u; 301 if (leftSibling instanceof ColumnExp) { 302 ColumnExp left = (ColumnExp)leftSibling; 303 u.jdbcField = left.jdbcField; 304 u.col = left.col; 305 SqlExp pos = u.expList = new ParamExp(u.jdbcType, u); 309 for (;;) { 310 if ((left = (ColumnExp)left.next) == null) break; 311 pos = pos.next = new ParamExp(left.getJdbcType(), u); 312 } 313 } else { 314 if (leftSibling.next != null) { 315 throw BindingSupportImpl.getInstance().internal( 316 "Expression on left has more than one column and no " + 317 "field information"); 318 } 319 u.expList = new ParamExp(leftSibling.getJdbcType(), u); 320 } 321 if (u.jdbcField == null) { 322 u.jdbcType = leftSibling.getJdbcType(); 323 u.javaTypeCode = leftSibling.getJavaTypeCode(); 324 u.classIndex = leftSibling.getClassIndex(); 325 } 326 return u.expList; 327 } 328 329 public Object arriveAndNode(AndNode node, Object msg) { 330 SqlExp prev = null, first = null; 332 for (Node cn = node.getArgsList(); cn != null; cn = cn.getNext()) { 333 SqlExp e = toSqlExp(cn, prev); 334 if (first == null) { 335 first = e; 336 } else if ( prev != null ) { 337 prev.next = e; 338 } 339 prev = e; 340 } 341 342 if (first.next == null) { 345 return first; 346 } else { 347 return new AndExp(first); 348 } 349 } 350 351 public Object arriveOrNode(OrNode node, Object msg) { 352 SqlExp prev = null, first = null; 354 for (Node cn = node.getArgsList(); cn != null; cn = cn.getNext()) { 355 SqlExp e = toSqlExp(cn, prev); 356 if (first == null) { 357 first = e; 358 } else if ( prev != null ) { 359 prev.next = e; 360 } 361 prev = e; 362 } 363 364 if (first.next == null) { 367 return first; 368 } else { 369 return new OrExp(first); 370 } 371 } 372 373 public Object arriveAddNode(AddNode node, Object msg) { 374 SqlExp left = processAddNodeChild(node.getLeft()); 375 SqlExp right = processAddNodeChild(node.getRight()); 376 left.next = right; 377 return new AddExp(left, new int[]{node.getOp()}); 378 } 379 380 private SqlExp processAddNodeChild(Node c) { 381 SqlExp e = toSqlExp(c, null); 382 if (e.next != null) { 383 throw BindingSupportImpl.getInstance().runtime( 384 "Expressions consisting of multiple columns may not be used" + 385 "with + or -"); 386 } 387 return e; 388 } 389 390 public Object arriveMultiplyNode(MultiplyNode node, Object msg) { 391 SqlExp left = processMultiplyNodeChild(node.getLeft()); 392 SqlExp right = processMultiplyNodeChild(node.getLeft()); 393 left.next = right; 394 return new AddExp(left, new int[]{node.getOp()}); 395 } 396 397 private SqlExp processMultiplyNodeChild(Node c) { 398 SqlExp e = toSqlExp(c, null); 399 if (e.next != null) { 400 throw BindingSupportImpl.getInstance().runtime( 401 "Expressions consisting of multiple columns may not be used" + 402 "with * or /"); 403 } 404 return e; 405 } 406 407 public Object arriveParenNode(ParenNode node, Object msg) { 408 SqlExp e = toSqlExp(node, msg); 409 if (e instanceof ParenExp) { 410 return e; 411 } else { 412 return new ParenExp(e); 413 } 414 } 415 416 public Object arriveBetweenNode(BetweenNode node, Object msg) { 417 SqlExp arg = toSqlExp(node.getArg(), null); 418 SqlExp from = toSqlExp(node.getFrom(), null); 419 SqlExp to = toSqlExp(node.getTo(), null); 420 arg.next = from; 421 from.next = to; 422 return new BetweenExp(arg); 423 } 424 425 public Object arriveNotNode(NotNode node, Object msg) { 426 SqlExp arg = toSqlExp(node.getExp(), null); 427 return new UnaryOpExp(arg, UnaryOpExp.OP_NOT); 428 } 429 430 public Object arriveLikeNode(LikeNode node, Object msg) { 431 SqlExp arg = toSqlExp(node.getPath(), null); 432 SqlExp pattern = toSqlExp(node.getPattern(), null); 433 if (node.getEscape() != null) { 434 throw notImplemented( 435 "Escape character argument to LIKE is not implemented"); 436 } 437 return new BinaryOpExp(arg, BinaryOpExp.LIKE, pattern); 438 } 439 440 public Object arriveUnaryMinusNode(UnaryMinusNode node, Object msg) { 441 SqlExp e = toSqlExp(node, msg); 442 if (e.next != null) { 443 throw BindingSupportImpl.getInstance().runtime( 444 "Expressions consisting of multiple columns may not be used" + 445 "with unary -"); 446 } 447 return new UnaryOpExp(e, UnaryOpExp.OP_MINUS); 448 } 449 450 } 451 452 | Popular Tags |