/** * @param paramsById * @param exprNode * @return */ private static AbstractExpression parseValueExpression( HashMap<Long, Integer> paramsById, VoltXMLElement exprNode) { String type = exprNode.attributes.get("valuetype"); String isParam = exprNode.attributes.get("isparam"); String isPlannerGenerated = exprNode.attributes.get("isplannergenerated"); VoltType vt = VoltType.typeFromString(type); int size = VoltType.MAX_VALUE_LENGTH; assert (vt != VoltType.VOLTTABLE); if ((vt != VoltType.STRING) && (vt != VoltType.VARBINARY)) { if (vt == VoltType.NULL) size = 0; else size = vt.getLengthInBytesForFixedTypes(); } // A ParameterValueExpression is needed to represent any user-provided or planner-injected // parameter. boolean needParameter = (isParam != null) && (isParam.equalsIgnoreCase("true")); // A ConstantValueExpression is needed to represent a constant in the statement, // EVEN if that constant has been "parameterized" by the plan caching code. ConstantValueExpression cve = null; boolean needConstant = (needParameter == false) || ((isPlannerGenerated != null) && (isPlannerGenerated.equalsIgnoreCase("true"))); if (needConstant) { cve = new ConstantValueExpression(); cve.setValueType(vt); cve.setValueSize(size); if (!needParameter && vt != VoltType.NULL) { String valueStr = exprNode.attributes.get("value"); cve.setValue(valueStr); } } if (needParameter) { ParameterValueExpression expr = new ParameterValueExpression(); long id = Long.parseLong(exprNode.attributes.get("id")); int paramIndex = paramIndexById(paramsById, id); expr.setValueType(vt); expr.setValueSize(size); expr.setParameterIndex(paramIndex); if (needConstant) { expr.setOriginalValue(cve); } return expr; } return cve; }
private AbstractExpression getParameterOrConstantAsExpression(long id, long value) { if (id != -1) { ParameterValueExpression parameter = new ParameterValueExpression(); assert (m_paramsById.containsKey(id)); int index = m_paramsById.get(id); parameter.setParameterIndex(index); parameter.setValueType(paramList[index]); parameter.setValueSize(paramList[index].getLengthInBytesForFixedTypes()); return parameter; } else { ConstantValueExpression constant = new ConstantValueExpression(); constant.setValue(Long.toString(value)); constant.setValueType(VoltType.INTEGER); return constant; } }
/** * Convert a HSQL VoltXML expression to an AbstractExpression tree. * * @param root * @return configured AbstractExpression */ AbstractExpression parseExpressionTree(VoltXMLElement root) { AbstractExpression exprTree = parseExpressionTree(m_paramsById, root); exprTree.resolveForDB(m_db); if (m_paramValues != null) { List<AbstractExpression> params = exprTree.findAllSubexpressionsOfClass(ParameterValueExpression.class); for (AbstractExpression ae : params) { ParameterValueExpression pve = (ParameterValueExpression) ae; ConstantValueExpression cve = pve.getOriginalValue(); if (cve != null) { cve.setValue(m_paramValues[pve.getParameterIndex()]); } } } return exprTree; }
// test that if someone provides their own inline projection // that the output schema of the scan node consists of the output // schema of the projection. Updates will do this so that the // inlined projection fills the values of the output tuples correctly // before it attempts to update them public void testOutputSchemaOverriddenProjection() { AbstractScanPlanNode dut = new SeqScanPlanNode(); dut.setTargetTableName(TABLE1); // Create an output schema like we might see for an inlined projection // generated for update. We'll have 4 output columns, the first will // be the tuple address, the second one a parameter expression, next // will be a constant, and the other will be a more complex expression // that uses some TVEs. NodeSchema proj_schema = new NodeSchema(); String[] cols = new String[4]; TupleAddressExpression col1_exp = new TupleAddressExpression(); proj_schema.addColumn(new SchemaColumn("", "tuple_address", "tuple_address", col1_exp)); cols[0] = "tuple_address"; // update column 1 with a parameter value ParameterValueExpression col2_exp = new ParameterValueExpression(); col2_exp.setParameterIndex(0); col2_exp.setValueType(COLTYPES[1]); col2_exp.setValueSize(COLTYPES[1].getLengthInBytesForFixedTypes()); // XXX I'm not sure what to do with the name for the updated column yet. // I think it should be an alias and not the original table name/col name proj_schema.addColumn(new SchemaColumn(TABLE1, COLS[1], COLS[1], col2_exp)); cols[1] = COLS[1]; // Update column 3 with a constant value ConstantValueExpression col3_exp = new ConstantValueExpression(); col3_exp.setValueType(COLTYPES[3]); col3_exp.setValueSize(COLTYPES[3].getLengthInBytesForFixedTypes()); col3_exp.setValue("3.14159"); proj_schema.addColumn(new SchemaColumn(TABLE1, COLS[3], COLS[3], col3_exp)); cols[2] = COLS[3]; // update column 4 with a sum of columns 0 and 2 OperatorExpression col4_exp = new OperatorExpression(); col4_exp.setValueType(COLTYPES[4]); col4_exp.setValueSize(COLTYPES[4].getLengthInBytesForFixedTypes()); col4_exp.setExpressionType(ExpressionType.OPERATOR_PLUS); TupleValueExpression left = new TupleValueExpression(); left.setTableName(TABLE1); left.setColumnName(COLS[0]); left.setColumnAlias(COLS[0]); left.setValueType(COLTYPES[0]); left.setValueSize(COLTYPES[0].getLengthInBytesForFixedTypes()); TupleValueExpression right = new TupleValueExpression(); right.setTableName(TABLE1); right.setColumnName(COLS[2]); right.setColumnAlias(COLS[2]); right.setValueType(COLTYPES[2]); right.setValueSize(COLTYPES[2].getLengthInBytesForFixedTypes()); col4_exp.setLeft(left); col4_exp.setRight(right); proj_schema.addColumn(new SchemaColumn(TABLE1, COLS[4], "C1", col4_exp)); cols[3] = COLS[4]; ProjectionPlanNode proj_node = new ProjectionPlanNode(); proj_node.setOutputSchema(proj_schema); dut.addInlinePlanNode(proj_node); System.out.println("ProjSchema: " + proj_schema.toString()); dut.generateOutputSchema(m_voltdb.getDatabase()); NodeSchema dut_schema = dut.getOutputSchema(); System.out.println(dut_schema.toString()); for (int i = 0; i < cols.length; i++) { SchemaColumn col = null; if (i == 0) { col = dut_schema.find("", cols[i], cols[i]); } else { col = dut_schema.find(TABLE1, cols[i], cols[i]); } assertNotNull(col); assertEquals(col.getExpression().getExpressionType(), ExpressionType.VALUE_TUPLE); } }