/** * @return <code>false</code> if sub-expression represented the specified ParseNode definitely * cannot appear on either side of the range (':') operator */ private static boolean isValidRangeOperand(ParseNode a) { Ptg tkn = a.getToken(); // Note - order is important for these instance-of checks if (tkn instanceof OperandPtg) { // notably cell refs and area refs return true; } // next 2 are special cases of OperationPtg if (tkn instanceof AbstractFunctionPtg) { AbstractFunctionPtg afp = (AbstractFunctionPtg) tkn; byte returnClass = afp.getDefaultOperandClass(); return Ptg.CLASS_REF == returnClass; } if (tkn instanceof ValueOperatorPtg) { return false; } if (tkn instanceof OperationPtg) { return true; } // one special case of ControlPtg if (tkn instanceof ParenthesisPtg) { // parenthesis Ptg should have only one child return isValidRangeOperand(a.getChildren()[0]); } // one special case of ScalarConstantPtg if (tkn == ErrPtg.REF_INVALID) { return true; } // All other ControlPtgs and ScalarConstantPtgs cannot be used with ':' return false; }
private ParseNode parseUnary(boolean isPlus) { boolean numberFollows = IsDigit(look) || look == '.'; ParseNode factor = powerFactor(); if (numberFollows) { // + or - directly next to a number is parsed with the number Ptg token = factor.getToken(); if (token instanceof NumberPtg) { if (isPlus) { return factor; } token = new NumberPtg(-((NumberPtg) token).getValue()); return new ParseNode(token); } if (token instanceof IntPtg) { if (isPlus) { return factor; } int intVal = ((IntPtg) token).getValue(); // note - cannot use IntPtg for negatives token = new NumberPtg(-intVal); return new ParseNode(token); } } return new ParseNode(isPlus ? UnaryPlusPtg.instance : UnaryMinusPtg.instance, factor); }
/** * From OOO doc: "Whenever one operand of the reference subexpression is a function, a defined * name, a 3D reference, or an external reference (and no error occurs), a tMemFunc token is used" */ private static boolean needsMemFunc(ParseNode root) { Ptg token = root.getToken(); if (token instanceof AbstractFunctionPtg) { return true; } if (token instanceof ExternSheetReferenceToken) { // 3D refs return true; } if (token instanceof NamePtg || token instanceof NameXPtg) { // 3D refs return true; } if (token instanceof OperationPtg || token instanceof ParenthesisPtg) { // expect RangePtg, but perhaps also UnionPtg, IntersectionPtg etc for (ParseNode child : root.getChildren()) { if (needsMemFunc(child)) { return true; } } return false; } if (token instanceof OperandPtg) { return false; } if (token instanceof OperationPtg) { return true; } return false; }
/** * @param callerForceArrayFlag <code>true</code> if one of the current node's parents is a * function Ptg which has been changed from default 'V' to 'A' type (due to requirements on * the function return value). */ private void transformNode( ParseNode node, byte desiredOperandClass, boolean callerForceArrayFlag) { Ptg token = node.getToken(); ParseNode[] children = node.getChildren(); boolean isSimpleValueFunc = isSimpleValueFunction(token); if (isSimpleValueFunc) { boolean localForceArray = desiredOperandClass == Ptg.CLASS_ARRAY; for (int i = 0; i < children.length; i++) { transformNode(children[i], desiredOperandClass, localForceArray); } setSimpleValueFuncClass( (AbstractFunctionPtg) token, desiredOperandClass, callerForceArrayFlag); return; } if (isSingleArgSum(token)) { // Need to process the argument of SUM with transformFunctionNode below // so make a dummy FuncVarPtg for that call. token = FuncVarPtg.SUM; // Note - the tAttrSum token (node.getToken()) is a base // token so does not need to have its operand class set } if (token instanceof ValueOperatorPtg || token instanceof ControlPtg || token instanceof MemFuncPtg || token instanceof MemAreaPtg || token instanceof UnionPtg) { // Value Operator Ptgs and Control are base tokens, so token will be unchanged // but any child nodes are processed according to desiredOperandClass and callerForceArrayFlag // As per OOO documentation Sec 3.2.4 "Token Class Transformation", "Step 1" // All direct operands of value operators that are initially 'R' type will // be converted to 'V' type. byte localDesiredOperandClass = desiredOperandClass == Ptg.CLASS_REF ? Ptg.CLASS_VALUE : desiredOperandClass; for (int i = 0; i < children.length; i++) { transformNode(children[i], localDesiredOperandClass, callerForceArrayFlag); } return; } if (token instanceof AbstractFunctionPtg) { transformFunctionNode( (AbstractFunctionPtg) token, children, desiredOperandClass, callerForceArrayFlag); return; } if (children.length > 0) { if (token == RangePtg.instance) { // TODO is any token transformation required under the various ref operators? return; } throw new IllegalStateException("Node should not have any children"); } if (token.isBaseToken()) { // nothing to do return; } token.setClass(transformClass(token.getPtgClass(), desiredOperandClass, callerForceArrayFlag)); }
private void elaborate(ParseNode newRoot) { (root = newRoot).doParent(); if (root.badFlag) return; variables = new Hashtable<Object, Hashtable>(); legalVariables = new Hashtable<String, Integer>(); knowns = new Hashtable<String, Double>(); knowns.put("pi", new Double(Math.PI)); knowns.put("Pi", new Double(Math.PI)); knowns.put("PI", new Double(Math.PI)); parameters = new Hashtable<String, Double>(); make_legalVariables(); fixImpliedMultiplication(root); if (find_variables(root) == null) { theValue = null; variables = null; legalVariables = null; knowns = null; parameters = null; root = null; return; } // end if Hashtable h = (Hashtable) (variables.get(root)); Enumeration k = h.keys(); while (k.hasMoreElements()) { String var = (String) k.nextElement(); // System.out.println(var); Double t = (Double) knowns.get(var); // System.out.println(t); if (t == null) continue; Vector v = (Vector) h.get(var); Enumeration e = v.elements(); while (e.hasMoreElements()) { ParseNode pn = (ParseNode) e.nextElement(); pn.value = t; } // end while } // end while for (Enumeration e = variables.keys(); e.hasMoreElements(); ) { Object r; h = (Hashtable) (variables.get(r = e.nextElement())); for (k = knowns.keys(); k.hasMoreElements(); ) h.remove(k.nextElement()); variables.put(r, h); } // end for condenseConstants(root); if ((theValue = root.value) != null) { valueString = MathUtil.trimDouble(theValue.doubleValue(), 12); } // end if else valueString = null; varStrings = new SortedKeyStrings((Hashtable) (variables.get(root))).theKeys; } // end elaborate
private static ParseNode augmentWithMemPtg(ParseNode root) { Ptg memPtg; if (needsMemFunc(root)) { memPtg = new MemFuncPtg(root.getEncodedSize()); } else { memPtg = new MemAreaPtg(root.getEncodedSize()); } return new ParseNode(memPtg, root); }
public SClassParseNode( ISourcePosition position, ParseNode recvNode, StaticScope scope, ParseNode bodyNode) { super(position, recvNode.containsVariableAssignment() || bodyNode.containsVariableAssignment()); assert scope != null : "scope is not null"; assert recvNode != null : "receiverNode is not null"; this.receiverNode = recvNode; this.scope = scope; this.bodyNode = bodyNode; }
private void condenseConstants(ParseNode r) { if (r.value != null) return; Hashtable h = (Hashtable) variables.get(r); if (h.isEmpty()) { r.value = new Double(r.eval()); return; } // end if if (r.children != null) for (int i = 0; i < r.children.length; i++) condenseConstants(r.children[i]); } // end condenseConstants
private Hashtable<String, Vector> find_variables(ParseNode r) { Hashtable<String, Vector> leavesOfR = new Hashtable<String, Vector>(); // System.out.println("in find_varibles"); if (r.operator == Action.NO_OP) { // no children if (legalVariables.get(r.theString) != null) { Vector<ParseNode> v = new Vector<ParseNode>(); v.addElement(r); leavesOfR.put(r.theString, v); } // end if else try { r.value = new Double(r.theString); } // end try catch (NumberFormatException NFE) { return null; } // end catch } // end if operator else { Hashtable childLeaves; for (int i = 0; i < r.children.length; i++) { if ((childLeaves = find_variables(r.children[i])) == null) return null; combine(childLeaves, leavesOfR); } // end for i } // end else variables.put(r, leavesOfR); return leavesOfR; } // end find_variables
public ParseNode not(ParseNode child) { if (child instanceof ExistsParseNode) { return exists(child.getChildren().get(0), !((ExistsParseNode) child).isNegate()); } return new NotParseNode(child); }
private Ptg[] getRPNPtg(int formulaType) { OperandClassTransformer oct = new OperandClassTransformer(formulaType); // RVA is for 'operand class': 'reference', 'value', 'array' oct.transformFormula(_rootNode); return ParseNode.toTokenArray(_rootNode); }
public MutationPlan compile(UpsertStatement upsert, List<Object> binds) throws SQLException { final PhoenixConnection connection = statement.getConnection(); ConnectionQueryServices services = connection.getQueryServices(); final int maxSize = services .getProps() .getInt( QueryServices.MAX_MUTATION_SIZE_ATTRIB, QueryServicesOptions.DEFAULT_MAX_MUTATION_SIZE); final ColumnResolver resolver = FromCompiler.getResolver(upsert, connection); final TableRef tableRef = resolver.getTables().get(0); PTable table = tableRef.getTable(); if (table.getType() == PTableType.VIEW) { throw new ReadOnlyTableException("Mutations not allowed for a view (" + tableRef + ")"); } Scan scan = new Scan(); final StatementContext context = new StatementContext(connection, resolver, binds, upsert.getBindCount(), scan); // Setup array of column indexes parallel to values that are going to be set List<ColumnName> columnNodes = upsert.getColumns(); List<PColumn> allColumns = table.getColumns(); int[] columnIndexesToBe; int[] pkSlotIndexesToBe; PColumn[] targetColumns; // Allow full row upsert if no columns or only dynamic one are specified and values count match if (columnNodes.isEmpty() || columnNodes.size() == upsert.getTable().getDynamicColumns().size()) { columnIndexesToBe = new int[allColumns.size()]; pkSlotIndexesToBe = new int[columnIndexesToBe.length]; targetColumns = new PColumn[columnIndexesToBe.length]; int j = table.getBucketNum() == null ? 0 : 1; // Skip over the salting byte. for (int i = 0; i < allColumns.size(); i++) { columnIndexesToBe[i] = i; targetColumns[i] = allColumns.get(i); if (SchemaUtil.isPKColumn(allColumns.get(i))) { pkSlotIndexesToBe[i] = j++; } } } else { columnIndexesToBe = new int[columnNodes.size()]; pkSlotIndexesToBe = new int[columnIndexesToBe.length]; targetColumns = new PColumn[columnIndexesToBe.length]; Arrays.fill( columnIndexesToBe, -1); // TODO: necessary? So we'll get an AIOB exception if it's not replaced Arrays.fill( pkSlotIndexesToBe, -1); // TODO: necessary? So we'll get an AIOB exception if it's not replaced BitSet pkColumnsSet = new BitSet(table.getPKColumns().size()); for (int i = 0; i < columnNodes.size(); i++) { ColumnName colName = columnNodes.get(i); ColumnRef ref = resolver.resolveColumn(null, colName.getFamilyName(), colName.getColumnName()); columnIndexesToBe[i] = ref.getColumnPosition(); targetColumns[i] = ref.getColumn(); if (SchemaUtil.isPKColumn(ref.getColumn())) { pkColumnsSet.set(pkSlotIndexesToBe[i] = ref.getPKSlotPosition()); } } int i = table.getBucketNum() == null ? 0 : 1; for (; i < table.getPKColumns().size(); i++) { PColumn pkCol = table.getPKColumns().get(i); if (!pkColumnsSet.get(i)) { if (!pkCol.isNullable()) { throw new ConstraintViolationException( table.getName().getString() + "." + pkCol.getName().getString() + " may not be null"); } } } } List<ParseNode> valueNodes = upsert.getValues(); QueryPlan plan = null; RowProjector projector = null; int nValuesToSet; boolean runOnServer = false; if (valueNodes == null) { SelectStatement select = upsert.getSelect(); assert (select != null); TableRef selectTableRef = FromCompiler.getResolver(select, connection).getTables().get(0); boolean sameTable = tableRef.equals(selectTableRef); // Pass scan through if same table in upsert and select so that projection is computed // correctly QueryCompiler compiler = new QueryCompiler(connection, 0, sameTable ? scan : new Scan(), targetColumns); plan = compiler.compile(select, binds); projector = plan.getProjector(); nValuesToSet = projector.getColumnCount(); // Cannot auto commit if doing aggregation or topN or salted // Salted causes problems because the row may end up living on a different region runOnServer = plan.getGroupBy() == null && sameTable && select.getOrderBy().isEmpty() && table.getBucketNum() == null; } else { nValuesToSet = valueNodes.size(); } final QueryPlan queryPlan = plan; // Resize down to allow a subset of columns to be specifiable if (columnNodes.isEmpty()) { columnIndexesToBe = Arrays.copyOf(columnIndexesToBe, nValuesToSet); pkSlotIndexesToBe = Arrays.copyOf(pkSlotIndexesToBe, nValuesToSet); } if (nValuesToSet != columnIndexesToBe.length) { throw new SQLExceptionInfo.Builder(SQLExceptionCode.UPSERT_COLUMN_NUMBERS_MISMATCH) .setMessage( "Numbers of columns: " + columnIndexesToBe.length + ". Number of values: " + nValuesToSet) .build() .buildException(); } final int[] columnIndexes = columnIndexesToBe; final int[] pkSlotIndexes = pkSlotIndexesToBe; // TODO: break this up into multiple functions //////////////////////////////////////////////////////////////////// // UPSERT SELECT ///////////////////////////////////////////////////////////////////// if (valueNodes == null) { /* We can run the upsert in a coprocessor if: * 1) the into table matches from table * 2) the select query isn't doing aggregation * 3) autoCommit is on * 4) not topN * Otherwise, run the query to pull the data from the server * and populate the MutationState (upto a limit). */ final boolean isAutoCommit = connection.getAutoCommit(); runOnServer &= isAutoCommit; //////////////////////////////////////////////////////////////////// // UPSERT SELECT run server-side (maybe) ///////////////////////////////////////////////////////////////////// if (runOnServer) { // At most this array will grow bigger by the number of PK columns int[] allColumnsIndexes = Arrays.copyOf(columnIndexes, columnIndexes.length + nValuesToSet); int[] reverseColumnIndexes = new int[table.getColumns().size()]; List<Expression> projectedExpressions = Lists.newArrayListWithExpectedSize(reverseColumnIndexes.length); Arrays.fill(reverseColumnIndexes, -1); for (int i = 0; i < nValuesToSet; i++) { projectedExpressions.add(projector.getColumnProjector(i).getExpression()); reverseColumnIndexes[columnIndexes[i]] = i; } /* * Order projected columns and projected expressions with PK columns * leading order by slot position */ int offset = table.getBucketNum() == null ? 0 : 1; for (int i = 0; i < table.getPKColumns().size() - offset; i++) { PColumn column = table.getPKColumns().get(i + offset); int pos = reverseColumnIndexes[column.getPosition()]; if (pos == -1) { // Last PK column may be fixed width and nullable // We don't want to insert a null expression b/c // it's not valid to set a fixed width type to null. if (column.getDataType().isFixedWidth()) { continue; } // Add literal null for missing PK columns pos = projectedExpressions.size(); Expression literalNull = LiteralExpression.newConstant(null, column.getDataType()); projectedExpressions.add(literalNull); allColumnsIndexes[pos] = column.getPosition(); } // Swap select expression at pos with i Collections.swap(projectedExpressions, i, pos); // Swap column indexes and reverse column indexes too int tempPos = allColumnsIndexes[i]; allColumnsIndexes[i] = allColumnsIndexes[pos]; allColumnsIndexes[pos] = tempPos; reverseColumnIndexes[tempPos] = reverseColumnIndexes[i]; reverseColumnIndexes[i] = i; } // If any pk slots are changing, be conservative and don't run this server side. // If the row ends up living in a different region, we'll get an error otherwise. for (int i = 0; i < table.getPKColumns().size(); i++) { PColumn column = table.getPKColumns().get(i); Expression source = projectedExpressions.get(i); if (source == null || !source.equals( new ColumnRef(tableRef, column.getPosition()).newColumnExpression())) { // TODO: we could check the region boundaries to see if the pk will still be in it. runOnServer = false; // bail on running server side, since PK may be changing break; } } //////////////////////////////////////////////////////////////////// // UPSERT SELECT run server-side ///////////////////////////////////////////////////////////////////// if (runOnServer) { // Iterate through columns being projected List<PColumn> projectedColumns = Lists.newArrayListWithExpectedSize(projectedExpressions.size()); for (int i = 0; i < projectedExpressions.size(); i++) { // Must make new column if position has changed PColumn column = allColumns.get(allColumnsIndexes[i]); projectedColumns.add(column.getPosition() == i ? column : new PColumnImpl(column, i)); } // Build table from projectedColumns PTable projectedTable = PTableImpl.makePTable( table.getName(), table.getType(), table.getTimeStamp(), table.getSequenceNumber(), table.getPKName(), table.getBucketNum(), projectedColumns); // Remove projection of empty column, since it can lead to problems when building another // projection // using this same scan. TODO: move projection code to a later stage, like // QueryPlan.newScanner to // prevent having to do this. ScanUtil.removeEmptyColumnFamily(context.getScan(), table); List<AliasedNode> select = Collections.<AliasedNode>singletonList( NODE_FACTORY.aliasedNode( null, NODE_FACTORY.function( CountAggregateFunction.NORMALIZED_NAME, LiteralParseNode.STAR))); // Ignore order by - it has no impact final RowProjector aggProjector = ProjectionCompiler.getRowProjector( context, select, false, GroupBy.EMPTY_GROUP_BY, OrderBy.EMPTY_ORDER_BY, null); /* * Transfer over PTable representing subset of columns selected, but all PK columns. * Move columns setting PK first in pkSlot order, adding LiteralExpression of null for any missing ones. * Transfer over List<Expression> for projection. * In region scan, evaluate expressions in order, collecting first n columns for PK and collection non PK in mutation Map * Create the PRow and get the mutations, adding them to the batch */ scan.setAttribute( UngroupedAggregateRegionObserver.UPSERT_SELECT_TABLE, UngroupedAggregateRegionObserver.serialize(projectedTable)); scan.setAttribute( UngroupedAggregateRegionObserver.UPSERT_SELECT_EXPRS, UngroupedAggregateRegionObserver.serialize(projectedExpressions)); final QueryPlan aggPlan = new AggregatePlan( context, tableRef, projector, null, GroupBy.EMPTY_GROUP_BY, false, null, OrderBy.EMPTY_ORDER_BY); return new MutationPlan() { @Override public PhoenixConnection getConnection() { return connection; } @Override public ParameterMetaData getParameterMetaData() { return context.getBindManager().getParameterMetaData(); } @Override public MutationState execute() throws SQLException { Scanner scanner = aggPlan.getScanner(); ResultIterator iterator = scanner.iterator(); try { Tuple row = iterator.next(); ImmutableBytesWritable ptr = context.getTempPtr(); final long mutationCount = (Long) aggProjector.getColumnProjector(0).getValue(row, PDataType.LONG, ptr); return new MutationState(maxSize, connection) { @Override public long getUpdateCount() { return mutationCount; } }; } finally { iterator.close(); } } @Override public ExplainPlan getExplainPlan() throws SQLException { List<String> queryPlanSteps = aggPlan.getExplainPlan().getPlanSteps(); List<String> planSteps = Lists.newArrayListWithExpectedSize(queryPlanSteps.size() + 1); planSteps.add("UPSERT ROWS"); planSteps.addAll(queryPlanSteps); return new ExplainPlan(planSteps); } }; } } //////////////////////////////////////////////////////////////////// // UPSERT SELECT run client-side ///////////////////////////////////////////////////////////////////// final int batchSize = Math.min(connection.getMutateBatchSize(), maxSize); return new MutationPlan() { @Override public PhoenixConnection getConnection() { return connection; } @Override public ParameterMetaData getParameterMetaData() { return context.getBindManager().getParameterMetaData(); } @Override public MutationState execute() throws SQLException { byte[][] values = new byte[columnIndexes.length][]; Scanner scanner = queryPlan.getScanner(); int estSize = scanner.getEstimatedSize(); int rowCount = 0; Map<ImmutableBytesPtr, Map<PColumn, byte[]>> mutation = Maps.newHashMapWithExpectedSize(estSize); ResultSet rs = new PhoenixResultSet(scanner, statement); PTable table = tableRef.getTable(); PColumn column; while (rs.next()) { for (int i = 0; i < values.length; i++) { column = table.getColumns().get(columnIndexes[i]); byte[] byteValue = rs.getBytes(i + 1); Object value = rs.getObject(i + 1); int rsPrecision = rs.getMetaData().getPrecision(i + 1); Integer precision = rsPrecision == 0 ? null : rsPrecision; int rsScale = rs.getMetaData().getScale(i + 1); Integer scale = rsScale == 0 ? null : rsScale; // If ColumnModifier from expression in SELECT doesn't match the // column being projected into then invert the bits. if (column.getColumnModifier() == ColumnModifier.SORT_DESC) { byte[] tempByteValue = Arrays.copyOf(byteValue, byteValue.length); byteValue = ColumnModifier.SORT_DESC.apply(byteValue, tempByteValue, 0, byteValue.length); } // We are guaranteed that the two column will have compatible types, // as we checked that before. if (!column .getDataType() .isSizeCompatible( column.getDataType(), value, byteValue, precision, column.getMaxLength(), scale, column.getScale())) { throw new SQLExceptionInfo.Builder(SQLExceptionCode.DATA_INCOMPATIBLE_WITH_TYPE) .setColumnName(column.getName().getString()) .build() .buildException(); } values[i] = column .getDataType() .coerceBytes( byteValue, value, column.getDataType(), precision, scale, column.getMaxLength(), column.getScale()); } setValues(values, pkSlotIndexes, columnIndexes, table, mutation); rowCount++; // Commit a batch if auto commit is true and we're at our batch size if (isAutoCommit && rowCount % batchSize == 0) { MutationState state = new MutationState(tableRef, mutation, 0, maxSize, connection); connection.getMutationState().join(state); connection.commit(); mutation.clear(); } } // If auto commit is true, this last batch will be committed upon return return new MutationState( tableRef, mutation, rowCount / batchSize * batchSize, maxSize, connection); } @Override public ExplainPlan getExplainPlan() throws SQLException { List<String> queryPlanSteps = queryPlan.getExplainPlan().getPlanSteps(); List<String> planSteps = Lists.newArrayListWithExpectedSize(queryPlanSteps.size() + 1); planSteps.add("UPSERT SELECT"); planSteps.addAll(queryPlanSteps); return new ExplainPlan(planSteps); } }; } //////////////////////////////////////////////////////////////////// // UPSERT VALUES ///////////////////////////////////////////////////////////////////// int nodeIndex = 0; // Allocate array based on size of all columns in table, // since some values may not be set (if they're nullable). UpsertValuesCompiler expressionBuilder = new UpsertValuesCompiler(context); final byte[][] values = new byte[nValuesToSet][]; for (ParseNode valueNode : valueNodes) { if (!valueNode.isConstant()) { throw new SQLExceptionInfo.Builder(SQLExceptionCode.VALUE_IN_UPSERT_NOT_CONSTANT) .build() .buildException(); } PColumn column = allColumns.get(columnIndexes[nodeIndex]); expressionBuilder.setColumn(column); LiteralExpression literalExpression = (LiteralExpression) valueNode.accept(expressionBuilder); byte[] byteValue = literalExpression.getBytes(); if (literalExpression.getDataType() != null) { // If ColumnModifier from expression in SELECT doesn't match the // column being projected into then invert the bits. if (literalExpression.getColumnModifier() != column.getColumnModifier()) { byte[] tempByteValue = Arrays.copyOf(byteValue, byteValue.length); byteValue = ColumnModifier.SORT_DESC.apply(byteValue, tempByteValue, 0, byteValue.length); } if (!literalExpression .getDataType() .isCoercibleTo(column.getDataType(), literalExpression.getValue())) { throw new TypeMismatchException( literalExpression.getDataType(), column.getDataType(), "expression: " + literalExpression.toString() + " in column " + column); } if (!column .getDataType() .isSizeCompatible( literalExpression.getDataType(), literalExpression.getValue(), byteValue, literalExpression.getMaxLength(), column.getMaxLength(), literalExpression.getScale(), column.getScale())) { throw new SQLExceptionInfo.Builder(SQLExceptionCode.DATA_INCOMPATIBLE_WITH_TYPE) .setColumnName(column.getName().getString()) .setMessage("value=" + literalExpression.toString()) .build() .buildException(); } } byteValue = column .getDataType() .coerceBytes( byteValue, literalExpression.getValue(), literalExpression.getDataType(), literalExpression.getMaxLength(), literalExpression.getScale(), column.getMaxLength(), column.getScale()); values[nodeIndex] = byteValue; nodeIndex++; } return new MutationPlan() { @Override public PhoenixConnection getConnection() { return connection; } @Override public ParameterMetaData getParameterMetaData() { return context.getBindManager().getParameterMetaData(); } @Override public MutationState execute() { Map<ImmutableBytesPtr, Map<PColumn, byte[]>> mutation = Maps.newHashMapWithExpectedSize(1); setValues(values, pkSlotIndexes, columnIndexes, tableRef.getTable(), mutation); return new MutationState(tableRef, mutation, 0, maxSize, connection); } @Override public ExplainPlan getExplainPlan() throws SQLException { return new ExplainPlan(Collections.singletonList("PUT SINGLE ROW")); } }; }
public List<ParseNode> childNodes() { return ParseNode.createList(receiverNode, bodyNode); }
private void fixImpliedMultiplication(ParseNode r) { int i; if (r.operator == Action.NO_OP) { if (legalVariables.get(r.theString) != null) return; Vector<String> v = splitIM(r.theString); if (v.size() == 1) return; r.operator = Action.PRODUCT; r.children = new ParseNode[v.size()]; Enumeration<String> e = v.elements(); for (i = 0; e.hasMoreElements(); i++) r.children[i] = new ParseNode((String) e.nextElement()); } // end if else if (r.operator == Action.POWER) { int n0 = 0, n1 = 1; ParseNode r0 = r.children[0], r1 = r.children[1]; StringBuffer b0 = new StringBuffer(), b1 = new StringBuffer(); if (r0.operator == Action.NO_OP) { Vector<String> v = splitIM(r0.theString); if ((n0 = v.size() - 1) < 0) { root.badFlag = true; return; } // end if for (i = 0; i < n0; i++) b0.append((String) v.elementAt(i) + "*"); b0.append((String) v.elementAt(n0) + "^"); } // end if else b0.append(new Expression(r0).toString() + "^"); switch (r1.operator) { case Action.NO_OP: { Vector<String> v = splitIM(r1.theString); if ((n1 = v.size()) < 1) { root.badFlag = true; return; } // end if b1.append((String) v.elementAt(0)); if (n1 > 1) b1.append("*"); for (i = 1; i < n1; i++) b1.append((String) v.elementAt(i)); break; } // end block case Action.PRODUCT: case Action.SUM: b1.append("(" + new Expression(r1).toString() + ")"); break; default: b1.append(new Expression(r1).toString()); } // end switch if (n0 == 0 && n1 == 1) return; ParseNode t = new Expression(b0.toString() + b1.toString()).root; if (t == null) { root.badFlag = true; return; } // end if r.children = t.children; r.operator = t.operator; } // end if else for (i = 0; i < r.children.length; i++) fixImpliedMultiplication(r.children[i]); } // end fixImpliedMultiplication