/** * Mutate the subtree relating to a row-value-constructor to instead use * a series of ANDed predicates. This allows multi-column type comparisons * and explicit row-value-constructor syntax even on databases which do * not support row-value-constructor. * <p/> * For example, here we'd mutate "... where (col1, col2) = ('val1', 'val2) ..." to * "... where col1 = 'val1' and col2 = 'val2' ..." * * @param valueElements The number of elements in the row value constructor list. */ private void MutateRowValueConstructorSyntax(int valueElements) { // Reduce the new tree in just one SqlFragment, to manage parameters // mutation depends on the types of nodes invloved... string comparisonText = "==".Equals(Text) ? "=" : Text; Type = HqlSqlWalker.SQL_TOKEN; string[] lhsElementTexts = ExtractMutationTexts(LeftHandOperand, valueElements); string[] rhsElementTexts = ExtractMutationTexts(RightHandOperand, valueElements); var lho = LeftHandOperand as ParameterNode; IParameterSpecification lhsEmbeddedCompositeParameterSpecification = (lho == null) ? null : lho.HqlParameterSpecification; var rho = RightHandOperand as ParameterNode; IParameterSpecification rhsEmbeddedCompositeParameterSpecification = (rho == null) ? null : rho.HqlParameterSpecification; var multicolumnComparisonClause = Translate(valueElements, comparisonText, lhsElementTexts, rhsElementTexts); if (lhsEmbeddedCompositeParameterSpecification != null) { AddEmbeddedParameter(lhsEmbeddedCompositeParameterSpecification); } if (rhsEmbeddedCompositeParameterSpecification != null) { AddEmbeddedParameter(rhsEmbeddedCompositeParameterSpecification); } ClearChildren(); Text = multicolumnComparisonClause; }
public void AddEmbeddedParameter(IParameterSpecification specification) { if (_embeddedParameters == null) { _embeddedParameters = new List <IParameterSpecification>(); } _embeddedParameters.Add(specification); }
public void AddEmbeddedParameter(IParameterSpecification specification) { if ( _embeddedParameters == null ) { _embeddedParameters = new List<IParameterSpecification>(); } _embeddedParameters.Add( specification ); }
public void SetIndexCollectionSelectorParamSpec(IParameterSpecification indexCollectionSelectorParamSpec) { if (indexCollectionSelectorParamSpec == null) { if (_elementType.IndexCollectionSelectorParamSpec != null) { _embeddedParameters.Remove(_elementType.IndexCollectionSelectorParamSpec); _elementType.IndexCollectionSelectorParamSpec = null; } } else { _elementType.IndexCollectionSelectorParamSpec = indexCollectionSelectorParamSpec; AddEmbeddedParameter(indexCollectionSelectorParamSpec); } }
private IEnumerable<IParameterSpecification> CreateParameterSpecificationsAndAssignBackTrack(IEnumerable<Parameter> sqlPatameters) { var specifications = new IParameterSpecification[] { new PositionalParameterSpecification(1, 0, 0) {ExpectedType = keyType}, new PositionalParameterSpecification(1, 0, 1) {ExpectedType = indexType}, }; Parameter[] parameters = sqlPatameters.ToArray(); int sqlParameterPos = 0; IEnumerable<string> paramTrackers = specifications.SelectMany(specification => specification.GetIdsForBackTrack(Factory)); foreach (string paramTracker in paramTrackers) { parameters[sqlParameterPos++].BackTrack = paramTracker; } return specifications; }
private IEnumerable <IParameterSpecification> CreateParameterSpecificationsAndAssignBackTrack(IEnumerable <Parameter> sqlPatameters) { var specifications = new IParameterSpecification[] { new PositionalParameterSpecification(1, 0, 0) { ExpectedType = keyType }, new PositionalParameterSpecification(1, 0, 1) { ExpectedType = indexType }, }; Parameter[] parameters = sqlPatameters.ToArray(); int sqlParameterPos = 0; IEnumerable <string> paramTrackers = specifications.SelectMany(specification => specification.GetIdsForBackTrack(Factory)); foreach (string paramTracker in paramTrackers) { parameters[sqlParameterPos++].BackTrack = paramTracker; } return(specifications); }
private void ApplyParameterSpecification(IParameterSpecification paramSpec) { _joinFragment.AddEmbeddedParameter(paramSpec); }
public override void Resolve(bool generateJoin, bool implicitJoin, string classAlias, IASTNode parent) { if (IsResolved) { return; } FromReferenceNode collectionNode = ( FromReferenceNode )GetChild(0); SessionFactoryHelperExtensions sessionFactoryHelper = SessionFactoryHelper; collectionNode.ResolveIndex(this); // Fully resolve the map reference, create implicit joins. IType type = collectionNode.DataType; if (!type.IsCollectionType) { throw new SemanticException("The [] operator cannot be applied to type " + type); } string collectionRole = (( CollectionType )type).Role; IQueryableCollection queryableCollection = sessionFactoryHelper.RequireQueryableCollection(collectionRole); if (!queryableCollection.HasIndex) { throw new QueryException("unindexed fromElement before []: " + collectionNode.Path); } // Generate the inner join -- The elements need to be joined to the collection they are in. FromElement fromElement = collectionNode.FromElement; String elementTable = fromElement.TableAlias; FromClause fromClause = fromElement.FromClause; String path = collectionNode.Path; FromElement elem = fromClause.FindCollectionJoin(path); if (elem == null) { FromElementFactory factory = new FromElementFactory(fromClause, fromElement, path); elem = factory.CreateCollectionElementsJoin(queryableCollection, elementTable); if (Log.IsDebugEnabled) { Log.Debug("No FROM element found for the elements of collection join path " + path + ", created " + elem); } } else { if (Log.IsDebugEnabled) { Log.Debug("FROM element found for collection join path " + path); } } // The 'from element' that represents the elements of the collection. FromElement = fromElement; // Add the condition to the join sequence that qualifies the indexed element. IASTNode selector = GetChild(1); if (selector == null) { throw new QueryException("No index value!"); } // Sometimes use the element table alias, sometimes use the... umm... collection table alias (many to many) String collectionTableAlias = elementTable; if (elem.CollectionTableAlias != null) { collectionTableAlias = elem.CollectionTableAlias; } // TODO: get SQL rendering out of here, create an AST for the join expressions. // Use the SQL generator grammar to generate the SQL text for the index expression. JoinSequence joinSequence = fromElement.JoinSequence; string[] indexCols = queryableCollection.IndexColumnNames; if (indexCols.Length != 1) { throw new QueryException("composite-index appears in []: " + collectionNode.Path); } SqlGenerator gen = new SqlGenerator(SessionFactoryHelper.Factory, new CommonTreeNodeStream(selector)); try { gen.simpleExpr(); //TODO: used to be exprNoParens! was this needed? } catch (RecognitionException e) { throw new QueryException(e.Message, e); } string selectorExpression = gen.GetSQL().ToString(); joinSequence.AddCondition(new SqlString(collectionTableAlias + '.' + indexCols[0] + " = " + selectorExpression)); //joinSequence.AddCondition(collectionTableAlias, new string[] { indexCols[0] }, selectorExpression, false); IList <IParameterSpecification> paramSpecs = gen.GetCollectedParameters(); if (paramSpecs != null) { switch (paramSpecs.Count) { case 0: // nothing to do break; case 1: IParameterSpecification paramSpec = paramSpecs[0]; paramSpec.ExpectedType = queryableCollection.IndexType; fromElement.SetIndexCollectionSelectorParamSpec(paramSpec); break; default: fromElement.SetIndexCollectionSelectorParamSpec( new AggregatedIndexCollectionSelectorParameterSpecifications(paramSpecs) ); break; } } // Now, set the text for this node. It should be the element columns. String[] elementColumns = queryableCollection.GetElementColumnNames(elementTable); Text = elementColumns[0]; IsResolved = true; }
/** * Mutate the subtree relating to a row-value-constructor to instead use * a series of ANDed predicates. This allows multi-column type comparisons * and explicit row-value-constructor syntax even on databases which do * not support row-value-constructor. * <p/> * For example, here we'd mutate "... where (col1, col2) = ('val1', 'val2) ..." to * "... where col1 = 'val1' and col2 = 'val2' ..." * * @param valueElements The number of elements in the row value constructor list. */ private void MutateRowValueConstructorSyntax(int valueElements) { // mutation depends on the types of nodes invloved... int comparisonType = Type; string comparisonText = Text; Type = HqlSqlWalker.AND; Text = "AND"; String[] lhsElementTexts = ExtractMutationTexts(LeftHandOperand, valueElements); String[] rhsElementTexts = ExtractMutationTexts(RightHandOperand, valueElements); IParameterSpecification lhsEmbeddedCompositeParameterSpecification = LeftHandOperand == null || (!(LeftHandOperand is ParameterNode)) ? null : (( ParameterNode )LeftHandOperand).HqlParameterSpecification; IParameterSpecification rhsEmbeddedCompositeParameterSpecification = RightHandOperand == null || (!(RightHandOperand is ParameterNode)) ? null : (( ParameterNode )RightHandOperand).HqlParameterSpecification; IASTNode container = this; for (int i = valueElements - 1; i > 0; i--) { if (i == 1) { container.ClearChildren(); container.AddChildren( ASTFactory.CreateNode( comparisonType, comparisonText, ASTFactory.CreateNode(HqlSqlWalker.SQL_TOKEN, lhsElementTexts[0]), ASTFactory.CreateNode(HqlSqlWalker.SQL_TOKEN, rhsElementTexts[0]) ), ASTFactory.CreateNode( comparisonType, comparisonText, ASTFactory.CreateNode(HqlSqlWalker.SQL_TOKEN, lhsElementTexts[1]), ASTFactory.CreateNode(HqlSqlWalker.SQL_TOKEN, rhsElementTexts[1]) )); // "pass along" our initial embedded parameter node(s) to the first generated // sql fragment so that it can be handled later for parameter binding... SqlFragment fragment = ( SqlFragment )container.GetChild(0).GetChild(0); if (lhsEmbeddedCompositeParameterSpecification != null) { fragment.AddEmbeddedParameter(lhsEmbeddedCompositeParameterSpecification); } if (rhsEmbeddedCompositeParameterSpecification != null) { fragment.AddEmbeddedParameter(rhsEmbeddedCompositeParameterSpecification); } } else { container.ClearChildren(); container.AddChildren( ASTFactory.CreateNode(HqlSqlWalker.AND, "AND"), ASTFactory.CreateNode( comparisonType, comparisonText, ASTFactory.CreateNode(HqlSqlWalker.SQL_TOKEN, lhsElementTexts[i]), ASTFactory.CreateNode(HqlSqlWalker.SQL_TOKEN, rhsElementTexts[i]) )); container = container.GetChild(0); } } }