public T CompileField(FieldTerm field) { if (field == null) { throw new ArgumentNullException(nameof(field)); } switch (field.Field) { case null: return(this.TextSearch(field.Value)); case "@": if (field.Operator != FieldTerm.EqualsOperator) { throw new NotSupportedException($"Cannot use operator '{field.Operator}' with field '{field.Field}'."); } if (int.TryParse(field.Value, out var personId)) { if (personId == 0) { return(this.NoPerson()); } else { return(this.PersonId(personId)); } } else { return(this.PersonName(field.Value)); } case "type": if (field.Operator != FieldTerm.EqualsOperator) { throw new NotSupportedException($"Cannot use operator '{field.Operator}' with field '{field.Field}'."); } var ix = field.Value.IndexOf('/'); if (ix < 0) { return(this.ParentCompiler.CompileDisjunction(new[] { this.TypeEquals(field.Value), this.TypePrefixed(field.Value + "/"), })); } else if (ix == field.Value.Length - 1) { return(this.TypePrefixed(field.Value)); } else { return(this.TypeEquals(field.Value)); } case "tag": { var tagInfo = this.TagEngine[field.Value]; if (this.ExcludeHidden && (tagInfo.Tag == "hidden" || tagInfo.Ancestors.Contains("hidden"))) { this.ExcludeHidden = false; } var tags = tagInfo.RelatedTags(TagDialect.TagRelationships[field.Operator]); tags = tags.Union(tags.SelectMany(this.TagEngine.GetTagAliases)); return(this.Tag(tags)); } case "rejected": { var tagInfo = this.TagEngine[field.Value]; var tags = tagInfo.RelatedTags(TagDialect.TagRelationships[field.Operator]); tags = tags.Union(tags.SelectMany(this.TagEngine.GetTagAliases)); return(this.RejectedTag(tags)); } case "~": { if (field.Operator != FieldTerm.EqualsOperator) { throw new NotSupportedException($"Cannot use operator '{field.Operator}' with field '{field.Field}'."); } return(this.ParentCompiler.CompileConjunction(new[] { this.ParentCompiler.CompileNegation(this.CompileField(new FieldTerm("tag", FieldTerm.LessThanOrEqualOperator, field.Value))), this.ParentCompiler.CompileNegation(this.CompileField(new FieldTerm("rejected", FieldTerm.GreaterThanOrEqualOperator, field.Value))), })); } case "?": case "suggested": if (field.Operator != FieldTerm.EqualsOperator) { throw new NotSupportedException($"Cannot use operator '{field.Operator}' with field '{field.Field}'."); } return(this.CompileTagRelation(TagOperator.Suggestion, field.Value)); case "^": case "missing": if (field.Operator != FieldTerm.EqualsOperator) { throw new NotSupportedException($"Cannot use operator '{field.Operator}' with field '{field.Field}'."); } return(this.CompileTagRelation(TagOperator.Implication, field.Value)); case "similar": { if (field.Operator != FieldTerm.EqualsOperator) { throw new NotSupportedException($"Cannot use operator '{field.Operator}' with field '{field.Field}'."); } var visualHash = Convert.ToUInt64(field.Value, 16); return(this.ParentCompiler.CompileDisjunction( AverageIntensityHash.Expand(visualHash, mode: 1).Select(h => this.Details(ImageDetailRecognizer.Properties.AverageIntensityHash, FieldTerm.EqualsOperator, (long)h)))); } case "copies": if (!int.TryParse(field.Value, out var copies)) { throw new NotSupportedException($"Cannot use non-numeric value '{field.Value}' with field '{field.Field}'."); } return(this.Copies(field.Operator, copies)); case "tags": if (!int.TryParse(field.Value, out var tagCount)) { throw new NotSupportedException($"Cannot use non-numeric value '{field.Value}' with field '{field.Field}'."); } return(this.TagCount(field.Operator, tagCount)); case "people": if (!int.TryParse(field.Value, out var peopleCount)) { throw new NotSupportedException($"Cannot use non-numeric value '{field.Value}' with field '{field.Field}'."); } return(this.PersonCount(field.Operator, peopleCount)); case "rating": if (!double.TryParse(field.Value, out var rating)) { throw new NotSupportedException($"Cannot use non-numeric value '{field.Value}' with field '{field.Field}'."); } return(this.Rating(field.Operator, rating)); case "stars": if (!int.TryParse(field.Value, out var stars)) { throw new NotSupportedException($"Cannot use non-numeric value '{field.Value}' with field '{field.Field}'."); } else if (stars < 1 || stars > 5) { throw new NotSupportedException($"Field '{field.Field}' expects a value between 1 and 5."); } return(this.Stars(field.Operator, stars)); case "hash": return(this.Hash(field.Operator, field.Value)); default: throw new NotSupportedException(); } }
/// <inheritdoc/> public override string CompileField(FieldTerm field) { return(this.dialect.CompileField(field)); }
/// <inheritdoc/> public override string CompileField(FieldTerm field) { if (field == null) { throw new ArgumentNullException(nameof(field)); } switch (field.Field) { case "@": if (field.Operator != FieldTerm.EqualsOperator) { throw new NotSupportedException($"Cannot use operator '{field.Operator}' with field '{field.Field}'."); } if (int.TryParse(field.Value, out var personId)) { if (personId == 0) { return($"NOT EXISTS (SELECT 1 FROM HashPerson p WHERE h.Hash = p.Hash)"); } else { return($"EXISTS (SELECT 1 FROM HashPerson p WHERE h.Hash = p.Hash AND p.PersonId = {personId})"); } } else { return($"EXISTS (SELECT 1 FROM HashPerson hp INNER JOIN Names p ON hp.PersonId = p.PersonId WHERE h.Hash = hp.Hash AND {Contains("p.Name", field.Value)})"); } case "type": if (field.Operator != FieldTerm.EqualsOperator) { throw new NotSupportedException($"Cannot use operator '{field.Operator}' with field '{field.Field}'."); } var ix = field.Value.IndexOf('/'); return (ix < 0 ? $"FileType = {Literal(field.Value)} OR {StartsWith("FileType", field.Value + "/")}" : ix == field.Value.Length - 1 ? StartsWith("FileType", field.Value) : $"FileType = {Literal(field.Value)}"); case "tag": if (field.Operator != FieldTerm.EqualsOperator) { throw new NotSupportedException($"Cannot use operator '{field.Operator}' with field '{field.Field}'."); } if (this.excludeHidden && (field.Value == "hidden" || this.tagEngine.GetTagAncestors(field.Value).Contains("hidden"))) { this.excludeHidden = false; } var tags = this.tagEngine.GetTagDescendants(field.Value).Add(field.Value); return($"EXISTS (SELECT 1 FROM HashTag t WHERE h.Hash = t.Hash AND t.Tag IN ({string.Join(", ", tags.Select(Literal))}))"); case "copies": this.joinCopies = true; if (!int.TryParse(field.Value, out var copies)) { throw new NotSupportedException($"Cannot use non-numeric value '{field.Value}' with field '{field.Field}'."); } return($"COALESCE(c.Copies, 0) {ConvertOperator(field.Operator)} {copies}"); default: throw new NotSupportedException(); } }
/// <inheritdoc/> public override Predicate <SearchResult> CompileField(FieldTerm field) { return(this.dialect.CompileField(field)); }