public static EventBeanUpdateHelperForge Make( string updatedWindowOrTableName, EventTypeSPI eventTypeSPI, IList <OnTriggerSetAssignment> assignments, string updatedAlias, EventType optionalTriggeringEventType, bool isCopyOnWrite, string statementName, EventTypeAvroHandler avroHandler) { IList <EventBeanUpdateItemForge> updateItems = new List <EventBeanUpdateItemForge>(); IList <string> properties = new List <string>(); TypeWidenerCustomizer typeWidenerCustomizer = avroHandler.GetTypeWidenerCustomizer(eventTypeSPI); for (int i = 0; i < assignments.Count; i++) { OnTriggerSetAssignment desc = assignments[i]; ExprAssignment assignment = desc.Validated; if (assignment == null) { throw new IllegalStateException("Assignment has not been validated"); } try { EventBeanUpdateItemForge updateItem; if (assignment is ExprAssignmentStraight) { ExprAssignmentStraight straight = (ExprAssignmentStraight)assignment; // handle assignment "property = value" if (straight.Lhs is ExprAssignmentLHSIdent) { ExprAssignmentLHSIdent ident = (ExprAssignmentLHSIdent)straight.Lhs; string propertyName = ident.Ident; EventPropertyDescriptor writableProperty = eventTypeSPI.GetWritableProperty(propertyName); // check assignment to indexed or mapped property if (writableProperty == null) { Pair <string, EventPropertyDescriptor> nameWriteablePair = CheckIndexedOrMappedProp( propertyName, updatedWindowOrTableName, updatedAlias, eventTypeSPI); propertyName = nameWriteablePair.First; writableProperty = nameWriteablePair.Second; } ExprNode rhsExpr = straight.Rhs; ExprForge rhsForge = rhsExpr.Forge; EventPropertyWriterSPI writer = eventTypeSPI.GetWriter(propertyName); bool notNullableField = writableProperty.PropertyType.IsPrimitive; properties.Add(propertyName); TypeWidenerSPI widener; try { widener = TypeWidenerFactory.GetCheckPropertyAssignType( ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(rhsExpr), rhsForge.EvaluationType, writableProperty.PropertyType, propertyName, false, typeWidenerCustomizer, statementName); } catch (TypeWidenerException ex) { throw new ExprValidationException(ex.Message, ex); } // check event type assignment bool useUntypedAssignment = false; bool useTriggeringEvent = false; if (optionalTriggeringEventType != null) { // handle RHS is ident node if (rhsExpr is ExprIdentNode) { ExprIdentNode node = (ExprIdentNode)rhsExpr; FragmentEventType fragmentRHS = optionalTriggeringEventType.GetFragmentType(node.ResolvedPropertyName); FragmentEventType fragmentLHS = eventTypeSPI.GetFragmentType(propertyName); if (fragmentRHS != null && fragmentLHS != null) { if (!EventTypeUtility.IsTypeOrSubTypeOf(fragmentRHS.FragmentType, fragmentLHS.FragmentType)) { throw MakeEventTypeMismatch(propertyName, fragmentLHS.FragmentType, fragmentRHS.FragmentType); } } // we don't need to cast if it is a self-assignment and LHS is an event and target needs no writer if (node.StreamId == 0 && fragmentLHS != null && eventTypeSPI is BaseNestableEventType) { useUntypedAssignment = true; } } // handle RHS is a stream of the triggering event itself if (rhsExpr is ExprStreamUnderlyingNode) { ExprStreamUnderlyingNode und = (ExprStreamUnderlyingNode)rhsExpr; if (und.StreamId == 1) { FragmentEventType fragmentLHS = eventTypeSPI.GetFragmentType(propertyName); if (fragmentLHS != null && optionalTriggeringEventType is BaseNestableEventType && !EventTypeUtility.IsTypeOrSubTypeOf(optionalTriggeringEventType, fragmentLHS.FragmentType)) { throw MakeEventTypeMismatch(propertyName, fragmentLHS.FragmentType, optionalTriggeringEventType); } // we use the event itself for assignment and target needs no writer if (eventTypeSPI is BaseNestableEventType) { useUntypedAssignment = true; useTriggeringEvent = true; } } } } updateItem = new EventBeanUpdateItemForge( rhsForge, propertyName, writer, notNullableField, widener, useUntypedAssignment, useTriggeringEvent, null); } else if (straight.Lhs is ExprAssignmentLHSArrayElement) { // handle "property[expr] = value" ExprAssignmentLHSArrayElement arrayElementLHS = (ExprAssignmentLHSArrayElement)straight.Lhs; string arrayPropertyName = arrayElementLHS.Ident; ExprNode rhs = straight.Rhs; Type evaluationType = rhs.Forge.EvaluationType; Type propertyType = eventTypeSPI.GetPropertyType(arrayPropertyName); if (!eventTypeSPI.IsProperty(arrayPropertyName)) { throw new ExprValidationException("Property '" + arrayPropertyName + "' could not be found"); } if (propertyType == null || !propertyType.IsArray) { throw new ExprValidationException("Property '" + arrayPropertyName + "' is not an array"); } EventPropertyGetterSPI getter = eventTypeSPI.GetGetterSPI(arrayPropertyName); Type componentType = propertyType.GetElementType(); if (!TypeHelper.IsAssignmentCompatible(evaluationType, componentType)) { throw new ExprValidationException( "Invalid assignment to property '" + arrayPropertyName + "' component type '" + componentType.CleanName() + "' from expression returning '" + evaluationType.CleanName() + "'"); } TypeWidenerSPI widener; try { widener = TypeWidenerFactory.GetCheckPropertyAssignType( ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(straight.Rhs), evaluationType, componentType, arrayPropertyName, false, typeWidenerCustomizer, statementName); } catch (TypeWidenerException ex) { throw new ExprValidationException(ex.Message, ex); } EventBeanUpdateItemArray arrayInfo = new EventBeanUpdateItemArray( arrayPropertyName, arrayElementLHS.IndexExpression, propertyType, getter); updateItem = new EventBeanUpdateItemForge( rhs.Forge, arrayPropertyName, null, false, widener, false, false, arrayInfo); } else { throw new IllegalStateException("Unrecognized LHS assignment " + straight); } } else if (assignment is ExprAssignmentCurly) { // handle non-assignment, i.e. UDF or other expression ExprAssignmentCurly dot = (ExprAssignmentCurly)assignment; updateItem = new EventBeanUpdateItemForge( dot.Expression.Forge, null, null, false, null, false, false, null); } else { throw new IllegalStateException("Unrecognized assignment " + assignment); } updateItems.Add(updateItem); } catch (ExprValidationException ex) { throw new ExprValidationException( "Failed to validate assignment expression '" + ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(assignment.OriginalExpression) + "': " + ex.Message, ex); } } // copy-on-write is the default event semantics as events are immutable EventBeanCopyMethodForge copyMethod; if (isCopyOnWrite) { // obtain copy method List <string> propertiesUniqueList = new List <string>(new HashSet <string>(properties)); string[] propertiesArray = propertiesUniqueList.ToArray(); copyMethod = eventTypeSPI.GetCopyMethodForge(propertiesArray); if (copyMethod == null) { throw new ExprValidationException("Event type does not support event bean copy"); } } else { // for in-place update, determine assignment expressions to use "initial" to access prior-change values // the copy-method is optional copyMethod = null; ISet <string> propertiesInitialValue = DeterminePropertiesInitialValue(assignments); if (!propertiesInitialValue.IsEmpty()) { string[] propertiesInitialValueArray = propertiesInitialValue.ToArray(); copyMethod = eventTypeSPI.GetCopyMethodForge(propertiesInitialValueArray); } } EventBeanUpdateItemForge[] updateItemsArray = updateItems.ToArray(); return(new EventBeanUpdateHelperForge(eventTypeSPI, copyMethod, updateItemsArray)); }
private static ExprAssignment CheckGetStraightAssignment( ExprNode node, bool allowLHSVariables) { var prop = CheckGetAssignmentToProp(node); if (prop != null) { return new ExprAssignmentStraight(node, new ExprAssignmentLHSIdent(prop.First), prop.Second); } if (!(node is ExprEqualsNode)) { return null; } var equals = (ExprEqualsNode) node; var lhs = equals.ChildNodes[0]; var rhs = equals.ChildNodes[1]; if (lhs is ExprVariableNode) { var variableNode = (ExprVariableNode) equals.ChildNodes[0]; if (!allowLHSVariables) { throw new ExprValidationException( "Left-hand-side does not allow variables for variable '" + variableNode.VariableMetadata.VariableName + "'"); } var variableNameWSubprop = variableNode.VariableNameWithSubProp; var variableName = variableNameWSubprop; String subPropertyName = null; var indexOfDot = variableNameWSubprop.IndexOf('.'); if (indexOfDot != -1) { subPropertyName = variableNameWSubprop.Substring(indexOfDot + 1); variableName = variableNameWSubprop.Substring(0, indexOfDot); } ExprAssignmentLHS lhsAssign; if (subPropertyName != null) { lhsAssign = new ExprAssignmentLHSIdentWSubprop(variableName, subPropertyName); } else { lhsAssign = new ExprAssignmentLHSIdent(variableName); } return new ExprAssignmentStraight(node, lhsAssign, rhs); } if (lhs is ExprDotNode dot) { var chainables = dot.ChainSpec; if (chainables.Count == 2 && chainables[0] is ChainableName name && chainables[1] is ChainableArray array) { return new ExprAssignmentStraight(node, new ExprAssignmentLHSArrayElement(name.Name, array.Indexes), rhs); } if (allowLHSVariables && dot.ChildNodes[0] is ExprVariableNode variableNode && chainables.Count == 1 && chainables[0] is ChainableArray chainableArray) { return new ExprAssignmentStraight( node, new ExprAssignmentLHSArrayElement( variableNode.VariableMetadata.VariableName, chainableArray.Indexes), rhs); } throw new ExprValidationException( "Unrecognized left-hand-side assignment '" + ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(dot) + "'"); } if (lhs is ExprTableAccessNode) { throw new ExprValidationException("Table access expression not allowed on the left hand side, please remove the table prefix"); } return null; }