public static SoqlBooleanExpression ClassRestriction(SoqlPathExpression path, SchemaInfo schema, ClassInfo classInfo) { // returns no additional filter clause for parent (master-parent) class if (classInfo.InheritsFromClass == null) return null; SoqlExpressionCollection literals = new SoqlExpressionCollection(); foreach (ClassInfo subclass in classInfo.GetSubclassesForSchema(schema)) { if (subclass.SubclassSelectorValue != null) { literals.Add(new SoqlLiteralExpression(subclass.SubclassSelectorValue)); } } if (classInfo.SubclassSelectorValue != null) { literals.Add(new SoqlLiteralExpression(classInfo.SubclassSelectorValue)); } // returns false when class is abstract (no SubClassSelectorValue) and there is no subclasses if (literals.Count == 0) return new SoqlBooleanLiteralExpression(false); SoqlBooleanExpression restriction = new SoqlBooleanInExpression( new SoqlPathExpression(path, classInfo.SubclassSelectorField.Name), literals ); return restriction; }
public static SoqlBooleanExpression ClassRestriction(SoqlPathExpression path, SchemaInfo schema, ClassInfo classInfo) { // returns no additional filter clause for parent (master-parent) class if (classInfo.InheritsFromClass == null) { return(null); } SoqlExpressionCollection literals = new SoqlExpressionCollection(); foreach (ClassInfo subclass in classInfo.GetSubclassesForSchema(schema)) { if (subclass.SubclassSelectorValue != null) { literals.Add(new SoqlLiteralExpression(subclass.SubclassSelectorValue)); } } if (classInfo.SubclassSelectorValue != null) { literals.Add(new SoqlLiteralExpression(classInfo.SubclassSelectorValue)); } // returns false when class is abstract (no SubClassSelectorValue) and there is no subclasses if (literals.Count == 0) { return(new SoqlBooleanLiteralExpression(false)); } SoqlBooleanExpression restriction = new SoqlBooleanInExpression( new SoqlPathExpression(path, classInfo.SubclassSelectorField.Name), literals ); return(restriction); }
private SoqlExpression ParsePathLikeExpression(string firstKeyword) { if (0 == String.Compare(firstKeyword, "soodaclass", true, System.Globalization.CultureInfo.InvariantCulture)) return new SoqlSoodaClassExpression(); SoqlPathExpression prop = new SoqlPathExpression(firstKeyword); while (tokenizer.TokenType == SoqlTokenType.Dot) { tokenizer.GetNextToken(); if (tokenizer.TokenType == SoqlTokenType.Asterisk) { tokenizer.GetNextToken(); return new SoqlAsteriskExpression(prop); } else if (tokenizer.IsKeyword("contains")) // lowercase { string collectionName = prop.PropertyName; tokenizer.EatKeyword(); if (tokenizer.TokenType != SoqlTokenType.LeftParen) throw new SoqlException("'(' expected on Contains()", tokenizer.TokenPosition); SoqlExpression expr = ParseLiteralExpression(); return new SoqlContainsExpression(prop.Left, collectionName, expr); } else if (tokenizer.IsKeyword("count")) // lowercase { string collectionName = prop.PropertyName; tokenizer.EatKeyword(); return new SoqlCountExpression(prop.Left, collectionName); } else if (tokenizer.IsKeyword("soodaclass")) // lowercase { tokenizer.EatKeyword(); return new SoqlSoodaClassExpression(prop); } else { string keyword = tokenizer.EatKeyword(); prop = new SoqlPathExpression(prop, keyword); } } if (tokenizer.TokenType == SoqlTokenType.LeftParen) { tokenizer.GetNextToken(); string functionName = prop.PropertyName; while ((prop = prop.Left) != null) functionName = prop.PropertyName + "." + functionName; if (0 == String.Compare(functionName, "rawquery", true, System.Globalization.CultureInfo.InvariantCulture)) return ParseRawExpression(); return ParseFunctionCall(functionName); } return prop; }
public virtual void Visit(SoqlPathExpression v) { if (v.Left != null) { v.Left.Accept(this); Output.Write('.'); } Output.Write(v.PropertyName); }
public SoqlPathExpression(string[] parts) { SoqlPathExpression l = null; for (int i = 0; i < parts.Length - 1; ++i) { l = new SoqlPathExpression(l, parts[i]); } this.PropertyName = parts[parts.Length - 1]; this.Left = l; }
public static SoqlBooleanExpression CollectionFor(CollectionManyToManyInfo coll, SoodaObject parent) { SoqlPathExpression needle = new SoqlPathExpression(coll.GetItemClass().GetFirstPrimaryKeyField().Name); RelationInfo relation = coll.GetRelationInfo(); SoqlQueryExpression query = new SoqlQueryExpression(); query.SelectExpressions.Add(new SoqlPathExpression(relation.Table.Fields[coll.MasterField].Name)); query.SelectAliases.Add(string.Empty); query.From.Add(relation.Name); query.FromAliases.Add(string.Empty); query.WhereClause = FieldEquals(relation.Table.Fields[1 - coll.MasterField].Name, parent); SoqlExpressionCollection haystack = new SoqlExpressionCollection(); haystack.Add(query); return(new SoqlBooleanInExpression(needle, haystack)); }
public SoqlSoodaClassExpression(SoqlPathExpression path) { this.Path = path; }
private IFieldContainer GenerateTableJoins(SoqlPathExpression expr, out string p, out string firstTableAlias) { // logger.Debug("GenerateTableJoins({0})", expr); IFieldContainer currentContainer; SoqlPathExpression e; // make the list bi-directional for (e = expr; e.Left != null; e = e.Left) { e.Left.Next = e; } SoqlPathExpression firstToken = e; SoqlPathExpression startingToken; // check if the first name on the list is an alias in current context if (TableAliases.ContainsKey(firstToken.PropertyName)) { string ta = TableAliases[firstToken.PropertyName]; currentContainer = Schema.FindContainerByName(ta); p = firstToken.PropertyName; startingToken = firstToken.Next; } else { if (Parent != null && Parent.TableAliases.ContainsKey(firstToken.PropertyName)) return Parent.GenerateTableJoins(expr, out p, out firstTableAlias); // artificial first token // TODO - find default container for current field currentContainer = FindStartingContainerByFieldName(firstToken.PropertyName, out p); startingToken = firstToken; } string lastTableAlias = GetTableAliasForExpressionPrefix(p); firstTableAlias = lastTableAlias; bool nullable = false; for (SoqlPathExpression currentToken = startingToken; currentToken != null; currentToken = currentToken.Next) { lastTableAlias = GetTableAliasForExpressionPrefix(p); // logger.Trace("Container: {0} Prop: {1} {2} {3}", currentContainer.Name, currentToken.PropertyName, currentContainer.GetType().FullName, currentToken.GetType().FullName); FieldInfo fi = currentContainer.FindFieldByName(currentToken.PropertyName); if (fi == null) { throw new Exception(String.Format("{0} not found in {1}", currentToken.PropertyName, currentContainer.Name)); } if (p.Length > 0) p += '.'; p += currentToken.PropertyName; if (fi.ReferencedClass == null) { currentContainer = null; continue; }; if (fi.IsNullable) nullable = true; if (fi.Table.OrdinalInClass > 0) { string extPrefix = AddPrimaryKeyJoin(firstTableAlias, (ClassInfo)currentContainer, lastTableAlias, fi); AddRefJoin(firstTableAlias, p, extPrefix, fi, nullable); } else { AddRefJoin(firstTableAlias, p, lastTableAlias, fi, nullable); } currentContainer = fi.ReferencedClass; } return currentContainer; }
public static SoqlBooleanExpression CollectionFor(CollectionManyToManyInfo coll, SoodaObject parent) { SoqlPathExpression needle = new SoqlPathExpression(coll.GetItemClass().GetFirstPrimaryKeyField().Name); RelationInfo relation = coll.GetRelationInfo(); SoqlQueryExpression query = new SoqlQueryExpression(); query.SelectExpressions.Add(new SoqlPathExpression(relation.Table.Fields[coll.MasterField].Name)); query.SelectAliases.Add(string.Empty); query.From.Add(relation.Name); query.FromAliases.Add(string.Empty); query.WhereClause = FieldEquals(relation.Table.Fields[1 - coll.MasterField].Name, parent); SoqlExpressionCollection haystack = new SoqlExpressionCollection(); haystack.Add(query); return new SoqlBooleanInExpression(needle, haystack); }
public SoqlContainsExpression(SoqlPathExpression path, string collectionName, SoqlExpression expr) { this.Path = path; this.CollectionName = collectionName; this.Expr = expr; }
public SoqlAsteriskExpression(SoqlPathExpression left) { this.Left = left; }
private SoqlExpression ParsePathLikeExpression(string firstKeyword) { if (0 == String.Compare(firstKeyword, "soodaclass", true, System.Globalization.CultureInfo.InvariantCulture)) { return(new SoqlSoodaClassExpression()); } SoqlPathExpression prop = new SoqlPathExpression(firstKeyword); while (tokenizer.TokenType == SoqlTokenType.Dot) { tokenizer.GetNextToken(); if (tokenizer.TokenType == SoqlTokenType.Asterisk) { tokenizer.GetNextToken(); return(new SoqlAsteriskExpression(prop)); } else if (tokenizer.IsKeyword("contains")) // lowercase { string collectionName = prop.PropertyName; tokenizer.EatKeyword(); if (tokenizer.TokenType != SoqlTokenType.LeftParen) { throw new SoqlException("'(' expected on Contains()", tokenizer.TokenPosition); } SoqlExpression expr = ParseLiteralExpression(); return(new SoqlContainsExpression(prop.Left, collectionName, expr)); } else if (tokenizer.IsKeyword("count")) // lowercase { string collectionName = prop.PropertyName; tokenizer.EatKeyword(); return(new SoqlCountExpression(prop.Left, collectionName)); } else if (tokenizer.IsKeyword("soodaclass")) // lowercase { tokenizer.EatKeyword(); return(new SoqlSoodaClassExpression(prop)); } else { string keyword = tokenizer.EatKeyword(); prop = new SoqlPathExpression(prop, keyword); } } if (tokenizer.TokenType == SoqlTokenType.LeftParen) { tokenizer.GetNextToken(); string functionName = prop.PropertyName; while ((prop = prop.Left) != null) { functionName = prop.PropertyName + "." + functionName; } if (0 == String.Compare(functionName, "rawquery", true, System.Globalization.CultureInfo.InvariantCulture)) { return(ParseRawExpression()); } return(ParseFunctionCall(functionName)); } return(prop); }
public SoqlPathExpression(SoqlPathExpression left, string propertyName) { this.Left = left; this.PropertyName = propertyName; }
public override IDataReader LoadObjectList(SchemaInfo schemaInfo, ClassInfo classInfo, SoodaWhereClause whereClause, SoodaOrderBy orderBy, int startIdx, int pageCount, SoodaSnapshotOptions options, out TableInfo[] tables) { try { Queue<_QueueItem> queue = new Queue<_QueueItem>(); List<TableInfo> tablesArrayList = new List<TableInfo>(classInfo.UnifiedTables.Count); SoqlQueryExpression queryExpression = new SoqlQueryExpression(); queryExpression.StartIdx = startIdx; queryExpression.PageCount = pageCount; queryExpression.From.Add(classInfo.Name); queryExpression.FromAliases.Add(""); foreach (TableInfo ti in classInfo.UnifiedTables) { tablesArrayList.Add(ti); foreach (FieldInfo fi in ti.Fields) { SoqlPathExpression pathExpr = new SoqlPathExpression(fi.Name); queryExpression.SelectExpressions.Add(pathExpr); queryExpression.SelectAliases.Add(""); if (fi.ReferencedClass != null && fi.PrefetchLevel > 0 && ((options & SoodaSnapshotOptions.PrefetchRelated) != 0)) { _QueueItem item = new _QueueItem(); item.classInfo = fi.ReferencedClass; item.level = fi.PrefetchLevel; item.prefix = pathExpr; queue.Enqueue(item); } } } while (queue.Count > 0) { _QueueItem it = queue.Dequeue(); foreach (TableInfo ti in it.classInfo.UnifiedTables) { tablesArrayList.Add(ti); foreach (FieldInfo fi in ti.Fields) { // TODO - this relies on the fact that path expressions // are never reconstructed or broken. We simply share previous prefix // perhaps it's cleaner to Clone() the expression here SoqlPathExpression extendedExpression = new SoqlPathExpression(it.prefix, fi.Name); queryExpression.SelectExpressions.Add(extendedExpression); queryExpression.SelectAliases.Add(""); if (it.level >= 1 && fi.PrefetchLevel > 0 && fi.ReferencedClass != null) { _QueueItem newItem = new _QueueItem(); newItem.classInfo = fi.ReferencedClass; newItem.prefix = extendedExpression; newItem.level = it.level - 1; queue.Enqueue(newItem); } } } } if (whereClause != null && whereClause.WhereExpression != null) { queryExpression.WhereClause = whereClause.WhereExpression; } if (orderBy != null) { queryExpression.SetOrderBy(orderBy); } string query = SoqlToSql(queryExpression, schemaInfo, false); IDbCommand cmd = Connection.CreateCommand(); try { cmd.CommandTimeout = CommandTimeout; } catch (NotSupportedException e) { logger.Debug("CommandTimeout not supported. {0}", e.Message); } if (Transaction != null) cmd.Transaction = this.Transaction; SqlBuilder.BuildCommandWithParameters(cmd, false, query, whereClause.Parameters, false); tables = tablesArrayList.ToArray(); return TimedExecuteReader(cmd); } catch (Exception ex) { logger.Error("Exception in LoadObjectList: {0}", ex); throw; } }
public SoqlCountExpression(SoqlPathExpression path, string collectionName) { this.Path = path; this.CollectionName = collectionName; }
public SoqlPathExpression(string p1, string p2, string p3) { this.Left = new SoqlPathExpression(p1, p2); this.PropertyName = p3; }
void Sooda.QL.ISoqlVisitor.Visit(SoqlPathExpression v) { v.GetAndAddClassInfo(_rootClass, _result); }
private string GetLoadingSelectStatement(ClassInfo classInfo, TableInfo tableInfo, out TableInfo[] loadedTables) { TableLoadingCache cache; if (tableLoadingCache.TryGetValue(tableInfo, out cache)) { loadedTables = cache.LoadedTables; return cache.SelectStatement; } Queue<_QueueItem> queue = new Queue<_QueueItem>(); List<TableInfo> additional = new List<TableInfo>(); additional.Add(tableInfo); SoqlQueryExpression queryExpression = new SoqlQueryExpression(); queryExpression.From.Add(classInfo.Name); queryExpression.FromAliases.Add(""); foreach (FieldInfo fi in tableInfo.Fields) { SoqlPathExpression pathExpr = new SoqlPathExpression(fi.Name); queryExpression.SelectExpressions.Add(pathExpr); queryExpression.SelectAliases.Add(""); if (fi.ReferencedClass != null && fi.PrefetchLevel > 0) { _QueueItem item = new _QueueItem(); item.classInfo = fi.ReferencedClass; item.level = fi.PrefetchLevel; item.prefix = pathExpr; queue.Enqueue(item); } } // TODO - add prefetching while (queue.Count > 0) { _QueueItem it = queue.Dequeue(); foreach (TableInfo ti in it.classInfo.UnifiedTables) { additional.Add(ti); foreach (FieldInfo fi in ti.Fields) { // TODO - this relies on the fact that path expressions // are never reconstructed or broken. We simply share previous prefix // perhaps it's cleaner to Clone() the expression here SoqlPathExpression extendedExpression = new SoqlPathExpression(it.prefix, fi.Name); queryExpression.SelectExpressions.Add(extendedExpression); queryExpression.SelectAliases.Add(""); if (it.level >= 1 && fi.PrefetchLevel > 0 && fi.ReferencedClass != null) { _QueueItem newItem = new _QueueItem(); newItem.classInfo = fi.ReferencedClass; newItem.prefix = extendedExpression; newItem.level = it.level - 1; queue.Enqueue(newItem); } } } } queryExpression.WhereClause = null; int parameterPos = 0; foreach (FieldInfo fi in tableInfo.Fields) { if (fi.IsPrimaryKey) { SoqlBooleanRelationalExpression expr = Soql.FieldEqualsParam(fi.Name, parameterPos); if (parameterPos == 0) { queryExpression.WhereClause = expr; } else { queryExpression.WhereClause = new SoqlBooleanAndExpression(queryExpression.WhereClause, expr); } parameterPos++; } } string query = SoqlToSql(queryExpression, tableInfo.OwnerClass.Schema, false); // logger.Debug("Loading statement for table {0}: {1}", tableInfo.NameToken, query); loadedTables = additional.ToArray(); tableLoadingCache[tableInfo] = new TableLoadingCache(query, loadedTables); return query; }
public override void Visit(SoqlPathExpression v) { VisitAndGetFieldInfo(v, true); }
private FieldInfo VisitAndGetFieldInfo(SoqlPathExpression v, bool doOutput) { if (v.Left != null && v.Left.Left == null) { string firstToken = v.Left.PropertyName; string secondToken = v.PropertyName; ClassInfo ci = Schema.FindClassByName(firstToken); if (ci != null && ci.Constants != null) { foreach (ConstantInfo constInfo in ci.Constants) { if (constInfo.Name == secondToken) { switch (ci.GetFirstPrimaryKeyField().DataType) { case FieldDataType.Integer: OutputLiteral(Convert.ToInt32(constInfo.Key), null); break; case FieldDataType.String: OutputLiteral(constInfo.Key, null); break; case FieldDataType.AnsiString: OutputLiteral(constInfo.Key, SoqlLiteralValueModifiers.AnsiString); break; default: throw new NotSupportedException("Constant of type: " + ci.GetFirstPrimaryKeyField().DataType + " not supported in SOQL"); } return null; } } } } IFieldContainer currentContainer; string firstTableAlias; string p; if (v.Left != null) { currentContainer = GenerateTableJoins(v.Left, out p, out firstTableAlias); } else { currentContainer = FindStartingContainerByFieldName(v.PropertyName, out p); firstTableAlias = p; firstTableAlias = GetTableAliasForExpressionPrefix(p); } FieldInfo fi = currentContainer.FindFieldByName(v.PropertyName); if (fi == null) { throw new Exception(String.Format("{0} not found in {1}", v.PropertyName, currentContainer.Name)); } if (doOutput) { if (_generatingOrderBy) Output.Write(_builder.GetSQLOrderBy(fi, true)); string extPrefix = GetTableAliasForExpressionPrefix(p); if (fi.Table.OrdinalInClass > 0) extPrefix = AddPrimaryKeyJoin(firstTableAlias, (ClassInfo)currentContainer, extPrefix, fi); OutputColumn(extPrefix, fi); if (_generatingOrderBy) Output.Write( _builder.GetSQLOrderBy(fi, false)); } return fi; }