private static SelectExprProcessorForge InitializeJoinWildcardInternal( EventType eventType, ISet<WriteablePropertyDescriptor> writables, string[] streamNames, EventType[] streamTypes, string statementName, ImportServiceCompileTime importService, EventTypeAvroHandler eventTypeAvroHandler) { var typeWidenerCustomizer = eventTypeAvroHandler.GetTypeWidenerCustomizer(eventType); IList<WriteablePropertyDescriptor> writablePropertiesList = new List<WriteablePropertyDescriptor>(); IList<ExprForge> forgesList = new List<ExprForge>(); IList<TypeWidenerSPI> widenersList = new List<TypeWidenerSPI>(); // loop over all columns selected, if any for (var i = 0; i < streamNames.Length; i++) { WriteablePropertyDescriptor selectedWritable = null; TypeWidenerSPI widener = null; foreach (var desc in writables) { if (!desc.PropertyName.Equals(streamNames[i])) { continue; } try { widener = TypeWidenerFactory.GetCheckPropertyAssignType( streamNames[i], streamTypes[i].UnderlyingType, desc.PropertyType, desc.PropertyName, false, typeWidenerCustomizer, statementName); } catch (TypeWidenerException ex) { throw new ExprValidationException(ex.Message, ex); } selectedWritable = desc; break; } if (selectedWritable == null) { var message = "Stream underlying object for stream '" + streamNames[i] + "' could not be assigned to any of the properties of the underlying type (missing column names, event property or setter method?)"; throw new ExprValidationException(message); } ExprForge forge = new ExprForgeStreamUnderlying(i, streamTypes[i].UnderlyingType); // add writablePropertiesList.Add(selectedWritable); forgesList.Add(forge); widenersList.Add(widener); } // assign var writableProperties = writablePropertiesList.ToArray(); var exprForges = forgesList.ToArray(); var wideners = widenersList.ToArray(); EventBeanManufacturerForge eventManufacturer; try { eventManufacturer = EventTypeUtility.GetManufacturer( eventType, writableProperties, importService, false, eventTypeAvroHandler); } catch (EventBeanManufactureException e) { throw new ExprValidationException(e.Message, e); } return new SelectExprInsertNativeWidening(eventType, eventManufacturer, exprForges, wideners); }
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 SelectExprProcessorForge InitializeSetterManufactor( EventType eventType, ISet<WriteablePropertyDescriptor> writables, bool isUsingWildcard, StreamTypeService typeService, ExprForge[] expressionForges, string[] columnNames, object[] expressionReturnTypes, string statementName, ImportServiceCompileTime importService, EventTypeAvroHandler eventTypeAvroHandler) { var typeWidenerCustomizer = eventTypeAvroHandler.GetTypeWidenerCustomizer(eventType); IList<WriteablePropertyDescriptor> writablePropertiesList = new List<WriteablePropertyDescriptor>(); IList<ExprForge> forgesList = new List<ExprForge>(); IList<TypeWidenerSPI> widenersList = new List<TypeWidenerSPI>(); // loop over all columns selected, if any for (var i = 0; i < columnNames.Length; i++) { WriteablePropertyDescriptor selectedWritable = null; TypeWidenerSPI widener = null; var forge = expressionForges[i]; foreach (var desc in writables) { if (!desc.PropertyName.Equals(columnNames[i])) { continue; } var columnType = expressionReturnTypes[i]; if (columnType == null) { try { TypeWidenerFactory.GetCheckPropertyAssignType( columnNames[i], null, desc.PropertyType, desc.PropertyName, false, typeWidenerCustomizer, statementName); } catch (TypeWidenerException ex) { throw new ExprValidationException(ex.Message, ex); } } else if (columnType is EventType) { var columnEventType = (EventType) columnType; var returnType = columnEventType.UnderlyingType; try { widener = TypeWidenerFactory.GetCheckPropertyAssignType( columnNames[i], columnEventType.UnderlyingType, desc.PropertyType, desc.PropertyName, false, typeWidenerCustomizer, statementName); } catch (TypeWidenerException ex) { throw new ExprValidationException(ex.Message, ex); } // handle evaluator returning an event if (TypeHelper.IsSubclassOrImplementsInterface(returnType, desc.PropertyType)) { selectedWritable = desc; widener = new ProxyTypeWidenerSPI { ProcWidenResultType = () => desc.PropertyType, ProcWiden = input => { if (input is EventBean eventBean) { return eventBean.Underlying; } return input; }, ProcWidenCodegen = ( expression, codegenMethodScope, codegenClassScope) => { var method = codegenMethodScope .MakeChild(typeof(object), typeof(TypeWidenerSPI), codegenClassScope) .AddParam(typeof(object), "input") .Block .IfCondition(InstanceOf(Ref("input"), typeof(EventBean))) .BlockReturn( ExprDotName(Cast(typeof(EventBean), Ref("input")), "Underlying")) .MethodReturn(Ref("input")); return LocalMethodBuild(method).Pass(expression).Call(); } }; continue; } // find stream var streamNum = 0; for (var j = 0; j < typeService.EventTypes.Length; j++) { if (typeService.EventTypes[j] == columnEventType) { streamNum = j; break; } } forge = new ExprForgeStreamUnderlying( streamNum, typeService.EventTypes[streamNum].UnderlyingType); } else if (columnType is EventType[]) { // handle case where the select-clause contains an fragment array var columnEventType = ((EventType[]) columnType)[0]; var componentReturnType = columnEventType.UnderlyingType; var arrayReturnType = componentReturnType.MakeArrayType(); var allowObjectArrayToCollectionConversion = eventType is AvroSchemaEventType; try { widener = TypeWidenerFactory.GetCheckPropertyAssignType( columnNames[i], arrayReturnType, desc.PropertyType, desc.PropertyName, allowObjectArrayToCollectionConversion, typeWidenerCustomizer, statementName); } catch (TypeWidenerException ex) { throw new ExprValidationException(ex.Message, ex); } var inner = forge; forge = new ExprForgeStreamWithInner(inner, componentReturnType); } else if (!(columnType is Type columnAsType)) { var message = "Invalid assignment of column '" + columnNames[i] + "' of type '" + columnType + "' to event property '" + desc.PropertyName + "' typed as '" + desc.PropertyType.CleanName() + "', column and parameter types mismatch"; throw new ExprValidationException(message); } else { try { widener = TypeWidenerFactory.GetCheckPropertyAssignType( columnNames[i], (Type) columnType, desc.PropertyType, desc.PropertyName, false, typeWidenerCustomizer, statementName); } catch (TypeWidenerException ex) { throw new ExprValidationException(ex.Message, ex); } } selectedWritable = desc; break; } if (selectedWritable == null) { var message = "Column '" + columnNames[i] + "' could not be assigned to any of the properties of the underlying type (missing column names, event property, setter method or constructor?)"; throw new ExprValidationException(message); } // add writablePropertiesList.Add(selectedWritable); forgesList.Add(forge); widenersList.Add(widener); } // handle wildcard if (isUsingWildcard) { var sourceType = typeService.EventTypes[0]; foreach (var eventPropDescriptor in sourceType.PropertyDescriptors) { if (eventPropDescriptor.IsRequiresIndex || eventPropDescriptor.IsRequiresMapKey) { continue; } WriteablePropertyDescriptor selectedWritable = null; TypeWidenerSPI widener = null; ExprForge forge = null; foreach (var writableDesc in writables) { if (!writableDesc.PropertyName.Equals(eventPropDescriptor.PropertyName)) { continue; } try { widener = TypeWidenerFactory.GetCheckPropertyAssignType( eventPropDescriptor.PropertyName, eventPropDescriptor.PropertyType, writableDesc.PropertyType, writableDesc.PropertyName, false, typeWidenerCustomizer, statementName); } catch (TypeWidenerException ex) { throw new ExprValidationException(ex.Message, ex); } selectedWritable = writableDesc; var propertyName = eventPropDescriptor.PropertyName; var getter = ((EventTypeSPI) sourceType).GetGetterSPI(propertyName); forge = new ExprForgeStreamWithGetter(getter); break; } if (selectedWritable == null) { var message = "Event property '" + eventPropDescriptor.PropertyName + "' could not be assigned to any of the properties of the underlying type (missing column names, event property, setter method or constructor?)"; throw new ExprValidationException(message); } writablePropertiesList.Add(selectedWritable); forgesList.Add(forge); widenersList.Add(widener); } } // assign var writableProperties = writablePropertiesList.ToArray(); var exprForges = forgesList.ToArray(); var wideners = widenersList.ToArray(); EventBeanManufacturerForge eventManufacturer; try { eventManufacturer = EventTypeUtility.GetManufacturer( eventType, writableProperties, importService, false, eventTypeAvroHandler); } catch (EventBeanManufactureException e) { throw new ExprValidationException(e.Message, e); } if (eventManufacturer == null) { return null; } return new SelectExprInsertNativeWidening(eventType, eventManufacturer, exprForges, wideners); }