/** * The constructor is protected, to ensure that instances can only be created using the * compileQuery() methods of StaticQueryContext * * @param exp an expression to be wrapped as an XQueryExpression * @param exec the executable * @param mainModule the static context of the main module * @param config the configuration * @throws XPathException if an error occurs */ protected XQueryExpression( Expression exp, Executable exec, QueryModule mainModule, Configuration config) throws XPathException { stackFrameMap = config.makeSlotManager(); executable = exec; exp.setContainer(this); try { ExpressionVisitor visitor = ExpressionVisitor.make(mainModule); visitor.setExecutable(exec); exp = visitor.simplify(exp); exp.checkForUpdatingSubexpressions(); exp = visitor.typeCheck(exp, mainModule.getUserQueryContext().getRequiredContextItemType()); // ExpressionPresenter presenter = new ExpressionPresenter(config, // ExpressionPresenter.defaultDestination(config, new // FileOutputStream("c:/projects/montreal/before50.xml"))); // exp.explain(presenter); // presenter.close(); exp = exp.optimize(visitor, Type.ITEM_TYPE); } catch (XPathException err) { // err.printStackTrace(); mainModule.reportFatalError(err); throw err; } ExpressionTool.allocateSlots(exp, 0, stackFrameMap); expression = exp; executable.setConfiguration(config); executable.setDefaultCollationName(mainModule.getDefaultCollationName()); executable.setCollationTable(mainModule.getUserQueryContext().getAllCollations()); staticContext = mainModule; isUpdating = exp.isUpdatingExpression(); }
@Override public Expression optimize(Session session) { left = left.optimize(session); boolean constant = left.isConstant(); if (constant && left == ValueExpression.getNull()) { return left; } boolean allValuesConstant = true; boolean allValuesNull = true; int size = valueList.size(); for (int i = 0; i < size; i++) { Expression e = valueList.get(i); e = e.optimize(session); if (e.isConstant() && e.getValue(session) != ValueNull.INSTANCE) { allValuesNull = false; } if (allValuesConstant && !e.isConstant()) { allValuesConstant = false; } if (left instanceof ExpressionColumn && e instanceof Parameter) { ((Parameter) e).setColumn(((ExpressionColumn) left).getColumn()); } valueList.set(i, e); } if (constant && allValuesConstant) { return ValueExpression.get(getValue(session)); } if (size == 1) { Expression right = valueList.get(0); Expression expr = new Comparison(session, Comparison.EQUAL, left, right); expr = expr.optimize(session); return expr; } if (allValuesConstant && !allValuesNull) { int leftType = left.getType(); if (leftType == Value.UNKNOWN) { return this; } Expression expr = new ConditionInConstantSet(session, left, valueList); expr = expr.optimize(session); return expr; } return this; }
@Override public Expression optimize(Session session) { userConnection = session.createConnection(false); int len = args.length; argTypes = new int[len]; for (int i = 0; i < len; i++) { Expression expr = args[i]; args[i] = expr.optimize(session); int type = expr.getType(); argTypes[i] = type; } try { Aggregate aggregate = getInstance(); dataType = aggregate.getInternalType(argTypes); } catch (SQLException e) { throw DbException.convert(e); } return this; }
@Override public Expression optimize(Session session) { if (on != null) { on = on.optimize(session); dataType = on.getType(); scale = on.getScale(); precision = on.getPrecision(); displaySize = on.getDisplaySize(); } if (groupConcatOrderList != null) { for (SelectOrderBy o : groupConcatOrderList) { o.expression = o.expression.optimize(session); } groupConcatSort = initOrder(session); } if (groupConcatSeparator != null) { groupConcatSeparator = groupConcatSeparator.optimize(session); } switch (type) { case GROUP_CONCAT: dataType = Value.STRING; scale = 0; precision = displaySize = Integer.MAX_VALUE; break; case COUNT_ALL: case COUNT: dataType = Value.LONG; scale = 0; precision = ValueLong.PRECISION; displaySize = ValueLong.DISPLAY_SIZE; break; case SELECTIVITY: dataType = Value.INT; scale = 0; precision = ValueInt.PRECISION; displaySize = ValueInt.DISPLAY_SIZE; break; case HISTOGRAM: dataType = Value.ARRAY; scale = 0; precision = displaySize = Integer.MAX_VALUE; break; case SUM: if (dataType == Value.BOOLEAN) { // example: sum(id > 3) (count the rows) dataType = Value.LONG; } else if (!DataType.supportsAdd(dataType)) { throw DbException.get(ErrorCode.SUM_OR_AVG_ON_WRONG_DATATYPE_1, getSQL()); } else { dataType = DataType.getAddProofType(dataType); } break; case AVG: if (!DataType.supportsAdd(dataType)) { throw DbException.get(ErrorCode.SUM_OR_AVG_ON_WRONG_DATATYPE_1, getSQL()); } break; case MIN: case MAX: break; case STDDEV_POP: case STDDEV_SAMP: case VAR_POP: case VAR_SAMP: dataType = Value.DOUBLE; precision = ValueDouble.PRECISION; displaySize = ValueDouble.DISPLAY_SIZE; scale = 0; break; case BOOL_AND: case BOOL_OR: dataType = Value.BOOLEAN; precision = ValueBoolean.PRECISION; displaySize = ValueBoolean.DISPLAY_SIZE; scale = 0; break; default: DbException.throwInternalError("type=" + type); } return this; }
@Override public Statement semantic(Scope sc, SemanticContext context) { SwitchStatement sw = sc.sw; this.sw = sw; exp = exp.semantic(sc, context); if (sw != null) { int i; exp = exp.implicitCastTo(sc, sw.condition.type, context); exp = exp.optimize(WANTvalue | WANTinterpret, context); boolean gotoL1 = false; if (context.isD2()) { /* This is where variables are allowed as case expressions. */ if (exp.op == TOKvar) { VarExp ve = (VarExp) exp; VarDeclaration v = ve.var.isVarDeclaration(); Type t = exp.type.toBasetype(context); if (v != null && (t.isintegral() || t.ty == Tclass)) { /* Flag that we need to do special code generation * for this, i.e. generate a sequence of if-then-else */ sw.hasVars = 1; // goto L1; gotoL1 = true; } } } if (!gotoL1) { if (exp.op != TOKstring && exp.op != TOKint64) { if (context.acceptsErrors()) { context.acceptProblem( Problem.newSemanticTypeError( IProblem.CaseMustBeAnIntegralOrStringConstant, sourceExp, exp.toChars(context))); } exp = new IntegerExp(0); } } // L1: for (i = 0; i < sw.cases.size(); i++) { CaseStatement cs = (CaseStatement) sw.cases.get(i); if (cs.exp.equals(exp, context)) { if (context.acceptsErrors()) { context.acceptProblem( Problem.newSemanticTypeErrorLoc( IProblem.DuplicateCaseInSwitchStatement, this, exp.toChars(context))); } break; } } sw.cases.add(this); // Resolve any goto case's with no exp to this case statement if (sw.gotoCases != null) { for (i = 0; i < sw.gotoCases.size(); i++) { GotoCaseStatement gcs = (GotoCaseStatement) sw.gotoCases.get(i); if (gcs.exp == null) { gcs.cs = this; sw.gotoCases.remove(i); // remove from array } } } if (context.isD2()) { if (sc.sw.tf != sc.tf) { if (context.acceptsErrors()) { context.acceptProblem( Problem.newSemanticTypeErrorLoc( IProblem.SwitchAndCaseAreInDifferentFinallyBlocks, this)); } } } } else { if (context.acceptsErrors()) { context.acceptProblem(Problem.newSemanticTypeError(IProblem.CaseIsNotInSwitch, this)); } } statement = statement.semantic(sc, context); return this; }