IASTNode CreateFromFilterElement(IASTNode filterEntity, IASTNode alias) { var fromElementFound = true; var fromElement = _currentFromClause.GetFromElement(alias.Text) ?? _currentFromClause.GetFromElementByClassName(filterEntity.Text); if (fromElement == null) { fromElementFound = false; fromElement = _currentFromClause.AddFromElement(filterEntity.Text, alias); } FromClause fromClause = fromElement.FromClause; IQueryableCollection persister = _sessionFactoryHelper.GetCollectionPersister(_collectionFilterRole); // Get the names of the columns used to link between the collection // owner and the collection elements. String[] keyColumnNames = persister.KeyColumnNames; String fkTableAlias = persister.IsOneToMany ? fromElement.TableAlias : fromClause.AliasGenerator.CreateName(_collectionFilterRole); JoinSequence join = _sessionFactoryHelper.CreateJoinSequence(); join.SetRoot(persister, fkTableAlias); if (!persister.IsOneToMany) { join.AddJoin((IAssociationType)persister.ElementType, fromElement.TableAlias, JoinType.InnerJoin, persister.GetElementColumnNames(fkTableAlias)); } join.AddCondition(fkTableAlias, keyColumnNames, " = ", true); fromElement.JoinSequence = join; fromElement.Filter = true; if (log.IsDebugEnabled()) { log.Debug("createFromFilterElement() : processed filter FROM element."); } if (fromElementFound) { return((IASTNode)adaptor.Nil()); } return(fromElement); }
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; }
public void Token(string token, QueryTranslator q) { if (token != null) { path.Append(token); } string alias = q.GetPathAlias(path.ToString()); if (alias != null) { Reset(q); //reset the dotcount (but not the path) currentName = alias; //after reset! currentPropertyMapping = q.GetPropertyMapping(currentName); if (!ignoreInitialJoin) { JoinSequence ojf = q.GetPathJoin(path.ToString()); try { joinSequence.AddCondition(ojf.ToJoinFragment(q.EnabledFilters, true).ToWhereFragmentString); //after reset! } catch (MappingException me) { throw new QueryException(me); } // we don't need to worry about any condition in the ON clause // here (toFromFragmentString), since anything in the ON condition // is already applied to the whole query } } else if (".".Equals(token)) { dotcount++; } else { if (dotcount == 0) { if (!continuation) { if (!q.IsName(token)) { throw new QueryException("undefined alias or unknown mapping: " + token); } currentName = token; currentPropertyMapping = q.GetPropertyMapping(currentName); } } else if (dotcount == 1) { if (currentName != null) { currentProperty = token; } else if (collectionName != null) { //IQueryableCollection p = q.GetCollectionPersister( collectionRole ); //DoCollectionProperty( token, p, collectionName ); continuation = false; } else { throw new QueryException("unexpected"); } } else { // dotcount>=2 // Do the corresponding RHS IType propertyType = PropertyType; if (propertyType == null) { throw new QueryException("unresolved property: " + currentProperty); } if (propertyType.IsComponentType) { DereferenceComponent(token); } else if (propertyType.IsEntityType) { DereferenceEntity(token, (EntityType)propertyType, q); } else if (propertyType.IsCollectionType) { DereferenceCollection(token, ((CollectionType)propertyType).Role, q); } else if (token != null) { throw new QueryException("dereferenced: " + currentProperty); } } } }