├── .gitignore ├── Deployment ├── NuGet.exe └── publish-SQL-generation.bat ├── README.md ├── SQLGeneration.Tests ├── CommandBuilderTester.cs ├── FormatterTester.cs ├── Properties │ └── AssemblyInfo.cs └── SQLGeneration.Tests.csproj ├── SQLGeneration.sln ├── SQLGeneration ├── Builders │ ├── Addition.cs │ ├── AliasedProjection.cs │ ├── AliasedSource.cs │ ├── AllColumns.cs │ ├── ArithmeticExpression.cs │ ├── BetweenFilter.cs │ ├── BetweenWindowFrame.cs │ ├── BinaryJoin.cs │ ├── BoundFrame.cs │ ├── BuilderVisitor.cs │ ├── Column.cs │ ├── CommandOptions.cs │ ├── ConditionalCase.cs │ ├── ConditionalCaseBranch.cs │ ├── ConjunctionConverter.cs │ ├── CrossJoin.cs │ ├── CurrentRowFrame.cs │ ├── DeleteBuilder.cs │ ├── DistinctQualifierConverter.cs │ ├── Division.cs │ ├── EqualToFilter.cs │ ├── EqualToQuantifierFilter.cs │ ├── Except.cs │ ├── ExistsFilter.cs │ ├── Filter.cs │ ├── FilterGroup.cs │ ├── FilteredJoin.cs │ ├── FollowingBoundFrame.cs │ ├── FollowingUnboundFrame.cs │ ├── FrameTypeConverter.cs │ ├── FullOuterJoin.cs │ ├── Function.cs │ ├── FunctionWindow.cs │ ├── GreaterThanEqualToFilter.cs │ ├── GreaterThanEqualToQuantifierFilter.cs │ ├── GreaterThanFilter.cs │ ├── GreaterThanQuantifierFilter.cs │ ├── ICommand.cs │ ├── IComparisonFilter.cs │ ├── IFilter.cs │ ├── IFilterItem.cs │ ├── IFilteredCommand.cs │ ├── IFollowingFrame.cs │ ├── IGroupByItem.cs │ ├── IJoinItem.cs │ ├── IPreceedingFrame.cs │ ├── IProjectionItem.cs │ ├── IRightJoinItem.cs │ ├── ISelectBuilder.cs │ ├── IValueProvider.cs │ ├── IVisitableBuilder.cs │ ├── InFilter.cs │ ├── InnerJoin.cs │ ├── InsertBuilder.cs │ ├── Intersect.cs │ ├── Join.cs │ ├── JoinStart.cs │ ├── LeftOuterJoin.cs │ ├── LessThanEqualToFilter.cs │ ├── LessThanEqualToQuantifierFilter.cs │ ├── LessThanFilter.cs │ ├── LessThanQuantifierFilter.cs │ ├── LikeFilter.cs │ ├── Literal.cs │ ├── MatchCase.cs │ ├── MatchCaseBranch.cs │ ├── Minus.cs │ ├── Modulus.cs │ ├── Multiplication.cs │ ├── Namespace.cs │ ├── Negation.cs │ ├── NotEqualToFilter.cs │ ├── NotEqualToQuantifierFilter.cs │ ├── NotFilter.cs │ ├── NullFilter.cs │ ├── NullLiteral.cs │ ├── NullPlacementConverter.cs │ ├── NumericLiteral.cs │ ├── OrderBy.cs │ ├── OrderConverter.cs │ ├── OrderFilter.cs │ ├── Placeholder.cs │ ├── PrecedingBoundFrame.cs │ ├── PrecedingOnlyWindowFrame.cs │ ├── PrecedingUnboundFrame.cs │ ├── QuantifierConverter.cs │ ├── QuantifierFilter.cs │ ├── RightOuterJoin.cs │ ├── SelectBuilder.cs │ ├── SelectCombiner.cs │ ├── Setter.cs │ ├── SourceCollection.cs │ ├── StringLiteral.cs │ ├── Subtraction.cs │ ├── Table.cs │ ├── Top.cs │ ├── UnboundFrame.cs │ ├── Union.cs │ ├── UpdateBuilder.cs │ ├── ValueList.cs │ └── WindowFrame.cs ├── Generators │ ├── CommandBuilder.cs │ ├── CommandBuilderOptions.cs │ ├── Formatter.cs │ ├── FormattingVisitor.cs │ └── SqlGenerator.cs ├── Parsing │ ├── Expression.cs │ ├── ExpressionDefinition.cs │ ├── ExpressionItem.cs │ ├── Grammar.cs │ ├── IExpressionItem.cs │ ├── IParseAttempt.cs │ ├── ITokenRegistry.cs │ ├── ITokenSource.cs │ ├── MatchResult.cs │ ├── MatchResultCollection.cs │ ├── Options.cs │ ├── Parser.cs │ ├── SqlGrammar.cs │ ├── SqlTokenRegistry.cs │ ├── Token.cs │ ├── TokenRegistry.cs │ ├── TokenResult.cs │ ├── TokenSource.cs │ └── TokenStream.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ └── Resources.resx ├── SQLGeneration.csproj ├── SQLGeneration.nuspec ├── SQLGenerationException.cs └── key.pfx └── UNLICENSE.txt /.gitignore: -------------------------------------------------------------------------------- 1 | # Build Folders (you can keep bin if you'd like, to store dlls and pdbs) 2 | [Bb]in/ 3 | [Oo]bj/ 4 | 5 | # mstest test results 6 | TestResults 7 | 8 | ## Ignore Visual Studio temporary files, build results, and 9 | ## files generated by popular Visual Studio add-ons. 10 | 11 | # User-specific files 12 | *.suo 13 | *.user 14 | *.sln.docstates 15 | 16 | # Build results 17 | [Dd]ebug/ 18 | [Rr]elease/ 19 | x64/ 20 | *_i.c 21 | *_p.c 22 | *.ilk 23 | *.meta 24 | *.obj 25 | *.pch 26 | *.pdb 27 | *.pgc 28 | *.pgd 29 | *.rsp 30 | *.sbr 31 | *.tlb 32 | *.tli 33 | *.tlh 34 | *.tmp 35 | *.log 36 | *.vspscc 37 | *.vssscc 38 | .builds 39 | 40 | # Visual C++ cache files 41 | ipch/ 42 | *.aps 43 | *.ncb 44 | *.opensdf 45 | *.sdf 46 | 47 | # Visual Studio profiler 48 | *.psess 49 | *.vsp 50 | *.vspx 51 | 52 | # Guidance Automation Toolkit 53 | *.gpState 54 | 55 | # ReSharper is a .NET coding add-in 56 | _ReSharper* 57 | 58 | # NCrunch 59 | *.ncrunch* 60 | .*crunch*.local.xml 61 | 62 | # Installshield output folder 63 | [Ee]xpress 64 | 65 | # DocProject is a documentation generator add-in 66 | DocProject/buildhelp/ 67 | DocProject/Help/*.HxT 68 | DocProject/Help/*.HxC 69 | DocProject/Help/*.hhc 70 | DocProject/Help/*.hhk 71 | DocProject/Help/*.hhp 72 | DocProject/Help/Html2 73 | DocProject/Help/html 74 | 75 | # Click-Once directory 76 | publish 77 | 78 | # Publish Web Output 79 | *.Publish.xml 80 | 81 | # NuGet Packages Directory 82 | packages 83 | 84 | # Windows Azure Build Output 85 | csx 86 | *.build.csdef 87 | 88 | # Windows Store app package directory 89 | AppPackages/ 90 | 91 | # Others 92 | [Bb]in 93 | [Oo]bj 94 | sql 95 | TestResults 96 | [Tt]est[Rr]esult* 97 | *.Cache 98 | ClientBin 99 | [Ss]tyle[Cc]op.* 100 | ~$* 101 | *.dbmdl 102 | Generated_Code #added for RIA/Silverlight projects 103 | 104 | # Backup & report files from converting an old project file to a newer 105 | # Visual Studio version. Backup files are not needed, because we have git ;-) 106 | _UpgradeReport_Files/ 107 | Backup*/ 108 | UpgradeLog*.XML 109 | -------------------------------------------------------------------------------- /Deployment/NuGet.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jehugaleahsa/SQLGeneration/deadcb3a0beaa738bd678ae5ebe3052f5c313470/Deployment/NuGet.exe -------------------------------------------------------------------------------- /Deployment/publish-SQL-generation.bat: -------------------------------------------------------------------------------- 1 | msbuild ../SQLGeneration.sln /p:Configuration=Release 2 | nuget pack ../SQLGeneration/SQLGeneration.csproj -Properties Configuration=Release 3 | nuget push *.nupkg 4 | del *.nupkg 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SQLGeneration 2 | 3 | Provides core classes for generating SQL at runtime. 4 | 5 | Download using NuGet: [SQLGeneration](https://nuget.org/packages/SQLGeneration) 6 | 7 | ## Recent Updates 8 | Please view the [Recent Updates Wiki](https://github.com/jehugaleahsa/SQLGeneration/wiki/Recent-Updates) to learn the latest news. 9 | 10 | ## Overview 11 | With all the ORMs out there today, it's amazing how many systems have their own micro-ORMs. We've all been there. We start writing SQL by hand and using core ADO.NET classes. The better of us try to use parameters whenever possible; others just concatenate strings. Even those virtuous enough to stick with parameters eventually run into problems... an IN filter, for example, or a screen that allows users to sort and filter columns. 12 | 13 | At this point even really experienced programmers start to sweat. "I can build my IN filter, because all the values are integers... right?", or "I just have to build my WHERE and ORDER BY clauses, I just have to remember to check for zero items first..." This is where the trouble starts for a lot of projects. It's very easy to introduce a bug that makes your code vulnerable to malicious users, especially if you have entry-level developers working on your data layer. On a much less serious note, most developers forget simple things like handling empty lists, escaping strings, handling NULL values and making sure there's whitespace where it's needed. 14 | 15 | SQLGeneration is meant to alleviate some of the headache involved in building SQL in you code. It handles all of the formatting issues for you, so you can concentrate on what your SQL is supposed to be doing. Whether you're just handling that one troublesome SQL statement or you've decided to build your own micro-ORM, SQLGeneration will make your job easier. 16 | 17 | It sports an extremely flexible object model that supports generating fairly standard SQL for different vendors. It doesn't support everything, of course, but it covers a lot of ground for everyday development, especially for SQL Server, Oracle, MySQL, PostgresSQL and even MS Access. Support for new features are added regularly. 18 | 19 | ## A Simple SELECT 20 | Here is a simple example that selects some columns from a table: 21 | 22 | // SELECT CustomerId, FirstName, LastName, Created FROM Customer WHERE CustomerId = @CustomerId 23 | SelectBuilder builder = new SelectBuilder(); 24 | 25 | AliasedSource customer = builder.AddTable(new Table("Customer")); 26 | 27 | Column customerId = customer.Column("CustomerId"); 28 | Column firstName = customer.Column("FirstName"); 29 | Column lastName = customer.Column("LastName"); 30 | Column created = customer.Column("Created"); 31 | builder.AddProjection(customerId); 32 | builder.AddProjection(firstName); 33 | builder.AddProjection(lastName); 34 | builder.AddProjection(created); 35 | 36 | Placeholder parameter = new Placeholder("@CustomerId"); 37 | EqualToFilter filter = new EqualToFilter(customerId, parameter); 38 | builder.AddWhere(filter); 39 | 40 | Formatter formatter = new Formatter(); 41 | string commandText = formatter.GetCommandText(builder); 42 | 43 | As you can see from this example, generating commands requires a lot of typing. Most of the time, this type of code would be replaced with an automated process. For instance, you might loop through `DataColumn`s in a `DataTable` or use reflection to visit `Attribute`s in a class to configure the builder. 44 | 45 | Note the use of the `Placeholder` class in the example. `Placeholder` allows you to place arbitrary values in the SQL statement. You could use this, for instance, to create an number with an exponent (`new Placeholder("6.02214078E23")`). It's more common use is to indicate parameters, like in the example. It's really a shortcut when you want to avoid the object model. Just keep in mind that invalid values will cause errors. 46 | 47 | ## SELECT for the Lazy and Arthritic 48 | If you had to do that much typing for every SELECT statement, you'd probably just stick to concatenating strings. Not everyone is building an ORM, so I made it possible to build command builders from plain SQL. Here's the same example, simplified: 49 | 50 | string commandText = "SELECT CustomerId, FirstName, LastName, Created FROM Customer"; 51 | CommandBuilder commandBuilder = new CommandBuilder(); 52 | SelectBuilder builder = (SelectBuilder)commandBuilder.GetCommand(commandText); 53 | 54 | Column customerId = builder.Source["Customer"].Column("CustomerId"); 55 | Placeholder parameter = new Placeholder("@CustomerId"); 56 | EqualToFilter filter = new EqualToFilter(customerId, parameter); 57 | builder.AddWhere(filter); 58 | 59 | Formatter formatter = new Formatter(); 60 | commandText = formatter.GetCommandText(builder); 61 | 62 | ## License 63 | This is free and unencumbered software released into the public domain. 64 | 65 | Anyone is free to copy, modify, publish, use, compile, sell, or 66 | distribute this software, either in source code form or as a compiled 67 | binary, for any purpose, commercial or non-commercial, and by any 68 | means. 69 | 70 | In jurisdictions that recognize copyright laws, the author or authors 71 | of this software dedicate any and all copyright interest in the 72 | software to the public domain. We make this dedication for the benefit 73 | of the public at large and to the detriment of our heirs and 74 | successors. We intend this dedication to be an overt act of 75 | relinquishment in perpetuity of all present and future rights to this 76 | software under copyright law. 77 | 78 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 79 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 80 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 81 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 82 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 83 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 84 | OTHER DEALINGS IN THE SOFTWARE. 85 | 86 | For more information, please refer to 87 | -------------------------------------------------------------------------------- /SQLGeneration.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("SQLGeneration.Tests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Truncon")] 12 | [assembly: AssemblyProduct("SQLGeneration.Tests")] 13 | [assembly: AssemblyCopyright("Copyright © 2013")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("d4995682-46a8-470d-a509-9f7e21c00dc1")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("0.0.0.0")] 35 | [assembly: AssemblyFileVersion("0.0.0.0")] 36 | [assembly: NeutralResourcesLanguageAttribute("en-US")] 37 | -------------------------------------------------------------------------------- /SQLGeneration.Tests/SQLGeneration.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 7 | 8 | 2.0 9 | {0B721A48-59F1-4D97-A321-5C1A56BC68A1} 10 | Library 11 | Properties 12 | SQLGeneration.Tests 13 | SQLGeneration.Tests 14 | v4.0 15 | 512 16 | {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 17 | 18 | 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | true 27 | bin\Debug\SQLGeneration.Tests.XML 28 | 29 | 30 | pdbonly 31 | true 32 | bin\Release\ 33 | TRACE 34 | prompt 35 | 4 36 | 37 | 38 | 39 | 40 | 41 | 3.5 42 | 43 | 44 | 45 | 46 | False 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | {A57BC336-3100-415B-91A5-B779CC64EF91} 57 | SQLGeneration 58 | 59 | 60 | 61 | 68 | -------------------------------------------------------------------------------- /SQLGeneration.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLGeneration", "SQLGeneration\SQLGeneration.csproj", "{A57BC336-3100-415B-91A5-B779CC64EF91}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLGeneration.Tests", "SQLGeneration.Tests\SQLGeneration.Tests.csproj", "{0B721A48-59F1-4D97-A321-5C1A56BC68A1}" 7 | EndProject 8 | Global 9 | GlobalSection(TestCaseManagementSettings) = postSolution 10 | CategoryFile = SQLGeneration.vsmdi 11 | EndGlobalSection 12 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 13 | Debug|Any CPU = Debug|Any CPU 14 | Release|Any CPU = Release|Any CPU 15 | EndGlobalSection 16 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 17 | {A57BC336-3100-415B-91A5-B779CC64EF91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 18 | {A57BC336-3100-415B-91A5-B779CC64EF91}.Debug|Any CPU.Build.0 = Debug|Any CPU 19 | {A57BC336-3100-415B-91A5-B779CC64EF91}.Release|Any CPU.ActiveCfg = Release|Any CPU 20 | {A57BC336-3100-415B-91A5-B779CC64EF91}.Release|Any CPU.Build.0 = Release|Any CPU 21 | {0B721A48-59F1-4D97-A321-5C1A56BC68A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 22 | {0B721A48-59F1-4D97-A321-5C1A56BC68A1}.Debug|Any CPU.Build.0 = Debug|Any CPU 23 | {0B721A48-59F1-4D97-A321-5C1A56BC68A1}.Release|Any CPU.ActiveCfg = Release|Any CPU 24 | {0B721A48-59F1-4D97-A321-5C1A56BC68A1}.Release|Any CPU.Build.0 = Release|Any CPU 25 | EndGlobalSection 26 | GlobalSection(SolutionProperties) = preSolution 27 | HideSolutionNode = FALSE 28 | EndGlobalSection 29 | EndGlobal 30 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/Addition.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents the addition of two items in a command. 8 | /// 9 | public class Addition : ArithmeticExpression 10 | { 11 | /// 12 | /// Initializes a new instance of a Addition. 13 | /// 14 | /// The left hand side of the expression. 15 | /// The right hand side of the expression. 16 | public Addition(IProjectionItem leftHand, IProjectionItem rightHand) 17 | : base(leftHand, rightHand) 18 | { 19 | } 20 | 21 | /// 22 | /// Provides information to the given visitor about the current builder. 23 | /// 24 | /// The visitor requesting information. 25 | protected override void OnAccept(BuilderVisitor visitor) 26 | { 27 | visitor.VisitAddition(this); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/AliasedProjection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Allows a column to be optionally referred to using an alias. 8 | /// 9 | public class AliasedProjection 10 | { 11 | /// 12 | /// Initializes a new instance of an AliasedProjection. 13 | /// 14 | /// The projection item. 15 | /// The alias to refer to the item with. 16 | internal AliasedProjection(IProjectionItem item, string alias = null) 17 | { 18 | ProjectionItem = item; 19 | Alias = alias; 20 | } 21 | 22 | /// 23 | /// Gets the projection item. 24 | /// 25 | public IProjectionItem ProjectionItem 26 | { 27 | get; 28 | private set; 29 | } 30 | 31 | /// 32 | /// Gets or sets the alias for the projection item. 33 | /// 34 | public string Alias 35 | { 36 | get; 37 | private set; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/AliasedSource.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | using SQLGeneration.Properties; 4 | 5 | namespace SQLGeneration.Builders 6 | { 7 | /// 8 | /// Allows a table or select statement to be referred to by an alias. 9 | /// 10 | public class AliasedSource : IJoinItem 11 | { 12 | /// 13 | /// Initializes a new instance of an AliasedSource. 14 | /// 15 | /// The table or SELECT statement acting as the source. 16 | /// The alias to refer to the source with. 17 | internal AliasedSource(IRightJoinItem source, string alias) 18 | { 19 | Source = source; 20 | Alias = alias; 21 | } 22 | 23 | /// 24 | /// Gets the source. 25 | /// 26 | public IRightJoinItem Source 27 | { 28 | get; 29 | private set; 30 | } 31 | 32 | /// 33 | /// Gets the alias for the source. 34 | /// 35 | public string Alias 36 | { 37 | get; 38 | private set; 39 | } 40 | 41 | /// 42 | /// Creates a column that can refer qualify its name with source. 43 | /// 44 | /// The name of the column. 45 | /// The column. 46 | public Column Column(string columnName) 47 | { 48 | if (String.IsNullOrWhiteSpace(columnName)) 49 | { 50 | throw new ArgumentException(Resources.BlankColumnName, "columnName"); 51 | } 52 | return new Column(this, columnName); 53 | } 54 | 55 | /// 56 | /// Gets the name used to refer to the source. 57 | /// 58 | /// The name used to refer to the source. 59 | internal string GetSourceName() 60 | { 61 | if (String.IsNullOrWhiteSpace(Alias)) 62 | { 63 | return Source.GetSourceName(); 64 | } 65 | else 66 | { 67 | return Alias; 68 | } 69 | } 70 | 71 | void IVisitableBuilder.Accept(BuilderVisitor visitor) 72 | { 73 | visitor.VisitAliasedSource(this); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/AllColumns.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Selects all of the columns in a table or a join. 8 | /// 9 | public class AllColumns : IProjectionItem 10 | { 11 | private readonly AliasedSource source; 12 | 13 | /// 14 | /// Initializes a new instacne of an AllColumns 15 | /// that doesn't have a table or join. 16 | /// 17 | public AllColumns() 18 | { 19 | } 20 | 21 | /// 22 | /// Initializes a new instance of an AllColumns 23 | /// that selects all the columns from the given table or join. 24 | /// 25 | /// The table or join to select all the columns from. 26 | public AllColumns(AliasedSource source) 27 | { 28 | this.source = source; 29 | } 30 | 31 | /// 32 | /// Gets the source that the columns belongs to. 33 | /// 34 | public AliasedSource Source 35 | { 36 | get { return source; } 37 | } 38 | 39 | void IVisitableBuilder.Accept(BuilderVisitor visitor) 40 | { 41 | visitor.VisitAllColumns(this); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/ArithmeticExpression.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents an arithmetic expression in a command. 8 | /// 9 | public abstract class ArithmeticExpression : IProjectionItem, IFilterItem, IGroupByItem 10 | { 11 | private readonly IProjectionItem _leftHand; 12 | private readonly IProjectionItem _rightHand; 13 | 14 | /// 15 | /// Initializes a new instance of a ArithmeticExpression. 16 | /// 17 | /// The left hand side of the expression. 18 | /// The right hand side of the expression. 19 | protected ArithmeticExpression(IProjectionItem leftHand, IProjectionItem rightHand) 20 | { 21 | if (leftHand == null) 22 | { 23 | throw new ArgumentNullException("leftHand"); 24 | } 25 | if (rightHand == null) 26 | { 27 | throw new ArgumentNullException("rightHand"); 28 | } 29 | _leftHand = leftHand; 30 | _rightHand = rightHand; 31 | } 32 | 33 | /// 34 | /// Gets or sets whether to wrap the expression in parentheses. 35 | /// 36 | public bool? WrapInParentheses 37 | { 38 | get; 39 | set; 40 | } 41 | 42 | /// 43 | /// Gets the left hand operand of the expression. 44 | /// 45 | public IProjectionItem LeftHand 46 | { 47 | get 48 | { 49 | return _leftHand; 50 | } 51 | } 52 | 53 | /// 54 | /// Gets the right hand operand of the expression. 55 | /// 56 | public IProjectionItem RightHand 57 | { 58 | get 59 | { 60 | return _rightHand; 61 | } 62 | } 63 | 64 | void IVisitableBuilder.Accept(BuilderVisitor visitor) 65 | { 66 | OnAccept(visitor); 67 | } 68 | 69 | /// 70 | /// Provides information to the given visitor about the current builder. 71 | /// 72 | /// The visitor requesting information. 73 | protected abstract void OnAccept(BuilderVisitor visitor); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/BetweenFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents a comparison that checks that an item is between two values. 8 | /// 9 | public class BetweenFilter : Filter 10 | { 11 | private readonly IFilterItem _value; 12 | private readonly IFilterItem _lowerBound; 13 | private readonly IFilterItem _upperBound; 14 | 15 | /// 16 | /// Initializes a new instance of a NullFilter. 17 | /// 18 | /// The item to check whether is within a range. 19 | /// The smallest value the item can be. 20 | /// The largest value the item can be. 21 | public BetweenFilter(IFilterItem value, IFilterItem lowerBound, IFilterItem upperBound) 22 | { 23 | if (value == null) 24 | { 25 | throw new ArgumentNullException("item"); 26 | } 27 | if (lowerBound == null) 28 | { 29 | throw new ArgumentNullException("lowerBound"); 30 | } 31 | if (upperBound == null) 32 | { 33 | throw new ArgumentNullException("upperBound"); 34 | } 35 | _value = value; 36 | _lowerBound = lowerBound; 37 | _upperBound = upperBound; 38 | } 39 | 40 | /// 41 | /// Gets the value being checked. 42 | /// 43 | public IFilterItem Value 44 | { 45 | get { return _value; } 46 | } 47 | 48 | /// 49 | /// Gets the least the value can be. 50 | /// 51 | public IFilterItem LowerBound 52 | { 53 | get { return _lowerBound; } 54 | } 55 | 56 | /// 57 | /// Gets the most the value can be. 58 | /// 59 | public IFilterItem UpperBound 60 | { 61 | get { return _upperBound; } 62 | } 63 | 64 | /// 65 | /// Gets or sets whether to negate the results of the filter. 66 | /// 67 | public bool Not 68 | { 69 | get; 70 | set; 71 | } 72 | 73 | /// 74 | /// Provides information to the given visitor about the current builder. 75 | /// 76 | /// The visitor requesting information. 77 | protected override void OnAccept(BuilderVisitor visitor) 78 | { 79 | visitor.VisitBetweenFilter(this); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/BetweenWindowFrame.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Defines the limits of a function window whose frame ranges before and after the current row. 8 | /// 9 | public class BetweenWindowFrame : WindowFrame 10 | { 11 | /// 12 | /// Initializes a new instance of a BetweenWindowFrame. 13 | /// 14 | /// The object describing the preceding frame. 15 | /// The object describing the following frame. 16 | public BetweenWindowFrame(IPrecedingFrame precedingFrame, IFollowingFrame followingFrame) 17 | { 18 | if (precedingFrame == null) 19 | { 20 | throw new ArgumentNullException("precedingFrame"); 21 | } 22 | if (followingFrame == null) 23 | { 24 | throw new ArgumentNullException("followingFrame"); 25 | } 26 | PrecedingFrame = precedingFrame; 27 | FollowingFrame = followingFrame; 28 | } 29 | 30 | /// 31 | /// Gets the preceding window frame. 32 | /// 33 | public IPrecedingFrame PrecedingFrame 34 | { 35 | get; 36 | private set; 37 | } 38 | 39 | /// 40 | /// Gets the following window frame. 41 | /// 42 | public IFollowingFrame FollowingFrame 43 | { 44 | get; 45 | private set; 46 | } 47 | 48 | /// 49 | /// Provides information to the given visitor about the current builder. 50 | /// 51 | /// The visitor requesting information. 52 | protected override void OnAccept(BuilderVisitor visitor) 53 | { 54 | visitor.VisitBetweenWindowFrame(this); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/BinaryJoin.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents a join between two tables or sub-queries. 8 | /// 9 | public abstract class BinaryJoin : Join 10 | { 11 | /// 12 | /// Initializes a new instance of a BinaryJoin. 13 | /// 14 | /// The left hand item or join. 15 | /// The right hand item in the join. 16 | protected BinaryJoin(Join leftHand, AliasedSource rightHand) 17 | : base(leftHand, rightHand) 18 | { 19 | if (leftHand == null) 20 | { 21 | throw new ArgumentNullException("leftHand"); 22 | } 23 | if (rightHand == null) 24 | { 25 | throw new ArgumentNullException("rightHand"); 26 | } 27 | LeftHand = leftHand; 28 | RightHand = rightHand; 29 | } 30 | 31 | /// 32 | /// Gets the item on the left hand side of the join. 33 | /// 34 | public Join LeftHand 35 | { 36 | get; 37 | private set; 38 | } 39 | 40 | /// 41 | /// Gets the table on the right hand side of the join. 42 | /// 43 | public AliasedSource RightHand 44 | { 45 | get; 46 | private set; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/BoundFrame.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | using SQLGeneration.Properties; 4 | 5 | namespace SQLGeneration.Builders 6 | { 7 | /// 8 | /// Describes a window frame that is limited to a specific number of rows in one direction. 9 | /// 10 | public abstract class BoundFrame : IVisitableBuilder 11 | { 12 | /// 13 | /// Initializes a new instance of a BoundFrame. 14 | /// 15 | /// The limit to the number of rows to include in the frame. 16 | protected BoundFrame(int rowCount) 17 | { 18 | if (rowCount < 0) 19 | { 20 | throw new ArgumentOutOfRangeException("rowCount", rowCount, Resources.NegativeRowCount); 21 | } 22 | RowCount = rowCount; 23 | } 24 | 25 | /// 26 | /// Gets the number of rows to include in the frame in one direction. 27 | /// 28 | public int RowCount 29 | { 30 | get; 31 | private set; 32 | } 33 | 34 | void IVisitableBuilder.Accept(BuilderVisitor visitor) 35 | { 36 | OnAccept(visitor); 37 | } 38 | 39 | /// 40 | /// Provides information to the given visitor about the current builder. 41 | /// 42 | /// The visitor requesting information. 43 | protected abstract void OnAccept(BuilderVisitor visitor); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/Column.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents a database column. 8 | /// 9 | public class Column : IProjectionItem, IGroupByItem, IFilterItem 10 | { 11 | /// 12 | /// Initializes a new instance of a Column that is not associated 13 | /// with a specific table. 14 | /// 15 | /// The name of the column. 16 | public Column(string name) 17 | { 18 | Name = name; 19 | } 20 | 21 | /// 22 | /// Initializes a new instance of a Column. 23 | /// 24 | /// The column source that the column belongs to. 25 | /// The name of the column. 26 | internal Column(AliasedSource source, string name) 27 | { 28 | Source = source; 29 | Name = name; 30 | } 31 | 32 | /// 33 | /// Gets the table that the column belongs to. 34 | /// 35 | public AliasedSource Source 36 | { 37 | get; 38 | private set; 39 | } 40 | 41 | /// 42 | /// Gets or sets whether the column should be qualified with the source. 43 | /// 44 | public bool? Qualify 45 | { 46 | get; 47 | set; 48 | } 49 | 50 | /// 51 | /// Gets the name of the column. 52 | /// 53 | public string Name 54 | { 55 | get; 56 | private set; 57 | } 58 | 59 | void IVisitableBuilder.Accept(BuilderVisitor visitor) 60 | { 61 | visitor.VisitColumn(this); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/CommandOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SQLGeneration.Builders 4 | { 5 | /// 6 | /// Holds configuration setting for building commands. 7 | /// 8 | public class CommandOptions 9 | { 10 | /// 11 | /// Initializes a new instance of a CommandOptions with the default configurations. 12 | /// 13 | public CommandOptions() 14 | { 15 | AliasProjectionsUsingAs = true; 16 | WrapArithmeticExpressionsInParentheses = true; 17 | VerboseDeleteStatement = true; 18 | VerboseInnerJoin = true; 19 | VerboseOuterJoin = true; 20 | } 21 | 22 | /// 23 | /// Creates a copy of the current options. 24 | /// 25 | /// The copy. 26 | public CommandOptions Clone() 27 | { 28 | return (CommandOptions)MemberwiseClone(); 29 | } 30 | 31 | /// 32 | /// Gets or sets whether to include the optional keyword AS when aliasing projection items. 33 | /// 34 | public bool AliasProjectionsUsingAs { get; set; } 35 | 36 | /// 37 | /// Gets or sets whether to include the optional keyword AS when aliasing join items. 38 | /// 39 | public bool AliasColumnSourcesUsingAs { get; set; } 40 | 41 | /// 42 | /// Gets or sets whether to wrap filters in parentheses by default. 43 | /// 44 | public bool WrapFiltersInParentheses { get; set; } 45 | 46 | /// 47 | /// Gets or sets whether to wrap arithmetic expressions in parentheses by default. 48 | /// 49 | public bool WrapArithmeticExpressionsInParentheses { get; set; } 50 | 51 | /// 52 | /// Gets or sets whether to wrap joins in parentheses by default. 53 | /// 54 | public bool WrapJoinsInParentheses { get; set; } 55 | 56 | /// 57 | /// Gets or sets whether DELETE statements should print the FROM keyword. 58 | /// 59 | public bool VerboseDeleteStatement { get; set; } 60 | 61 | /// 62 | /// Gets or sets whether inner joins should specify INNER explicitly. 63 | /// 64 | public bool VerboseInnerJoin { get; set; } 65 | 66 | /// 67 | /// Gets or sets whether outer joins should specify OUTER explicitly. 68 | /// 69 | public bool VerboseOuterJoin { get; set; } 70 | 71 | /// 72 | /// Gets or sets whether columns should be fully qualified within an INSERT statement. 73 | /// 74 | public bool QualifyInsertColumns { get; set; } 75 | 76 | /// 77 | /// Gets or sets whether columns should be fully qualified within an UPDATE statement. 78 | /// 79 | public bool QualifyUpdateColumns { get; set; } 80 | 81 | /// 82 | /// Gets or sets whether columns should be fully qualified within a DELETE statement. 83 | /// 84 | public bool QualifyDeleteColumns { get; set; } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/ConditionalCase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using SQLGeneration.Parsing; 5 | using SQLGeneration.Properties; 6 | 7 | namespace SQLGeneration.Builders 8 | { 9 | /// 10 | /// Represents a conditional statement. 11 | /// 12 | public class ConditionalCase : IProjectionItem, IFilterItem, IGroupByItem 13 | { 14 | private readonly List branches; 15 | 16 | /// 17 | /// Initializes a new instance of a ConditionalCase. 18 | /// 19 | public ConditionalCase() 20 | { 21 | branches = new List(); 22 | } 23 | 24 | /// 25 | /// Gets the conditions and values of each branch. 26 | /// 27 | public IEnumerable Branches 28 | { 29 | get { return branches; } 30 | } 31 | 32 | /// 33 | /// Adds the case option to the case expression. 34 | /// 35 | /// The value that the case item must equal for given the result to be returned. 36 | /// The value to return when the item equals the option. 37 | public ConditionalCaseBranch AddBranch(IFilter filter, IProjectionItem result) 38 | { 39 | if (filter == null) 40 | { 41 | throw new ArgumentNullException("filter"); 42 | } 43 | if (result == null) 44 | { 45 | throw new ArgumentNullException("result"); 46 | } 47 | ConditionalCaseBranch branch = new ConditionalCaseBranch(); 48 | branch.Condition = filter; 49 | branch.Value = result; 50 | branches.Add(branch); 51 | return branch; 52 | } 53 | 54 | /// 55 | /// Removes the case branch. 56 | /// 57 | /// The branch to be removed. 58 | /// True if branch was found; otherwise, false. 59 | public bool RemoveBranch(ConditionalCaseBranch branch) 60 | { 61 | if (branch == null) 62 | { 63 | throw new ArgumentNullException("branch"); 64 | } 65 | return branches.Remove(branch); 66 | } 67 | 68 | /// 69 | /// Gets or sets the default value to return if no options match the item. 70 | /// 71 | public IProjectionItem Default 72 | { 73 | get; 74 | set; 75 | } 76 | 77 | void IVisitableBuilder.Accept(BuilderVisitor visitor) 78 | { 79 | visitor.VisitConditionalCase(this); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/ConditionalCaseBranch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SQLGeneration.Builders 4 | { 5 | /// 6 | /// Represents a branch in a condition case expression. 7 | /// 8 | public class ConditionalCaseBranch 9 | { 10 | /// 11 | /// The condition that must evaluate to true for the value to be chosen. 12 | /// 13 | public IFilter Condition { get; internal set; } 14 | 15 | /// 16 | /// The value that will be returned if the condition evaluated to true. 17 | /// 18 | public IProjectionItem Value { get; internal set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/ConjunctionConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | using SQLGeneration.Properties; 4 | 5 | namespace SQLGeneration.Builders 6 | { 7 | /// 8 | /// Affects the logic of how two filters will be applied. 9 | /// 10 | public enum Conjunction 11 | { 12 | /// 13 | /// Joins two filters with an 'and'. 14 | /// 15 | And, 16 | /// 17 | /// Joins two filters with an 'or'. 18 | /// 19 | Or 20 | } 21 | 22 | /// 23 | /// Converts conjunctions to their string representations. 24 | /// 25 | internal class ConjunctionConverter 26 | { 27 | /// 28 | /// Initializes a new instance of a ConjunctionConverter. 29 | /// 30 | public ConjunctionConverter() 31 | { 32 | } 33 | 34 | /// 35 | /// Gets a string representation of the given conjunction. 36 | /// 37 | /// The conjunction to convert to a string. 38 | /// The string representation. 39 | public string ToString(Conjunction conjunction) 40 | { 41 | switch (conjunction) 42 | { 43 | case Conjunction.And: 44 | return "AND"; 45 | case Conjunction.Or: 46 | return "OR"; 47 | default: 48 | throw new ArgumentException(Resources.UnknownConjunction, "conjunction"); 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/CrossJoin.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents a cross join. 8 | /// 9 | public class CrossJoin : BinaryJoin 10 | { 11 | /// 12 | /// Initializes a new instance of a CrossJoin. 13 | /// 14 | /// The left hand item in the join. 15 | /// The right hand table in the join. 16 | internal CrossJoin(Join leftHand, AliasedSource rightHand) 17 | : base(leftHand, rightHand) 18 | { 19 | } 20 | 21 | /// 22 | /// Provides information to the given visitor about the current builder. 23 | /// 24 | /// The visitor requesting information. 25 | protected override void OnAccept(BuilderVisitor visitor) 26 | { 27 | visitor.VisitCrossJoin(this); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/CurrentRowFrame.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Describes a window frame that is limited to the current row in one direction. 8 | /// 9 | public class CurrentRowFrame : IPrecedingFrame, IFollowingFrame 10 | { 11 | /// 12 | /// Initializes a new instance of a CurrentRowFrame. 13 | /// 14 | public CurrentRowFrame() 15 | { 16 | } 17 | 18 | void IVisitableBuilder.Accept(BuilderVisitor visitor) 19 | { 20 | visitor.VisitCurrentRowFrame(this); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/DeleteBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using SQLGeneration.Parsing; 4 | 5 | namespace SQLGeneration.Builders 6 | { 7 | /// 8 | /// Builds a string of a delete statement. 9 | /// 10 | public class DeleteBuilder : IFilteredCommand 11 | { 12 | private readonly AliasedSource _table; 13 | private readonly FilterGroup _where; 14 | 15 | /// 16 | /// Initializes a new instance of a DeleteBuilder. 17 | /// 18 | /// The table being deleted from. 19 | /// The alias to use to refer to the table. 20 | public DeleteBuilder(Table table, string alias = null) 21 | { 22 | if (table == null) 23 | { 24 | throw new ArgumentNullException("table"); 25 | } 26 | _table = new AliasedSource(table, alias); 27 | _where = new FilterGroup(); 28 | } 29 | 30 | /// 31 | /// Gets the table being deleted from. 32 | /// 33 | public AliasedSource Table 34 | { 35 | get { return _table; } 36 | } 37 | 38 | /// 39 | /// Gets the filters in the where clause. 40 | /// 41 | public IEnumerable Where 42 | { 43 | get { return _where.Filters; } 44 | } 45 | 46 | /// 47 | /// Gets the filter group used to build the where clause. 48 | /// 49 | public FilterGroup WhereFilterGroup 50 | { 51 | get { return _where; } 52 | } 53 | 54 | /// 55 | /// Adds the filter to the where clause. 56 | /// 57 | /// The filter to add. 58 | public void AddWhere(IFilter filter) 59 | { 60 | _where.AddFilter(filter); 61 | } 62 | 63 | /// 64 | /// Removes the filter from the where clause. 65 | /// 66 | /// The filter to remove. 67 | /// True if the filter was removed; otherwise, false. 68 | public bool RemoveWhere(IFilter filter) 69 | { 70 | return _where.RemoveFilter(filter); 71 | } 72 | 73 | void IVisitableBuilder.Accept(BuilderVisitor visitor) 74 | { 75 | visitor.VisitDelete(this); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/DistinctQualifierConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | using SQLGeneration.Properties; 4 | 5 | namespace SQLGeneration.Builders 6 | { 7 | /// 8 | /// Specifies how duplicate records will be treated in a SELECT statement. 9 | /// 10 | public enum DistinctQualifier 11 | { 12 | /// 13 | /// Specifies that the select statement should use the default rules when handling duplicates. 14 | /// 15 | Default, 16 | /// 17 | /// Specifies that the select statement should return duplicate records. 18 | /// 19 | All, 20 | /// 21 | /// Specifies that the select statement should remove duplicate records. 22 | /// 23 | Distinct, 24 | } 25 | 26 | /// 27 | /// Converts between the DistinctQualifier enumeration and strings. 28 | /// 29 | internal class DistinctQualifierConverter 30 | { 31 | /// 32 | /// Initializes a new instance of a DistinctQualifierConverter. 33 | /// 34 | public DistinctQualifierConverter() 35 | { 36 | } 37 | 38 | /// 39 | /// Gets a string representation of the given distinct qualifier. 40 | /// 41 | /// The qualifier to convert to a string. 42 | /// The string representation. 43 | public string ToString(DistinctQualifier qualifier) 44 | { 45 | switch (qualifier) 46 | { 47 | case DistinctQualifier.All: 48 | case DistinctQualifier.Default: 49 | return "ALL"; 50 | case DistinctQualifier.Distinct: 51 | return "DISTINCT"; 52 | default: 53 | throw new ArgumentException(Resources.UnknownDistinctQualifier, "qualifier"); 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/Division.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents the division of two items in a command. 8 | /// 9 | public class Division : ArithmeticExpression 10 | { 11 | /// 12 | /// Initializes a new instance of a Division. 13 | /// 14 | /// The left hand side of the expression. 15 | /// The right hand side of the expression. 16 | public Division(IProjectionItem leftHand, IProjectionItem rightHand) 17 | : base(leftHand, rightHand) 18 | { 19 | } 20 | 21 | /// 22 | /// Provides information to the given visitor about the current builder. 23 | /// 24 | /// The visitor requesting information. 25 | protected override void OnAccept(BuilderVisitor visitor) 26 | { 27 | visitor.VisitDivision(this); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/EqualToFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents a comparison between two items for equality. 8 | /// 9 | public class EqualToFilter : OrderFilter 10 | { 11 | /// 12 | /// Initializes a new instance of a EqualToFilter. 13 | /// 14 | /// The left hand item. 15 | /// The right hand item. 16 | public EqualToFilter(IFilterItem leftHand, IFilterItem rightHand) 17 | : base(leftHand, rightHand) 18 | { 19 | } 20 | 21 | /// 22 | /// Provides information to the given visitor about the current builder. 23 | /// 24 | /// The visitor requesting information. 25 | protected override void OnAccept(BuilderVisitor visitor) 26 | { 27 | visitor.VisitEqualToFilter(this); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/EqualToQuantifierFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents a filter that see that a value is equal to all or some of the values. 8 | /// 9 | public class EqualToQuantifierFilter : QuantifierFilter 10 | { 11 | /// 12 | /// Initializes a new insstance of an EqualToQuantifierFilter. 13 | /// 14 | /// The value being compared to the set of values. 15 | /// The quantifier to use to compare the value to the set of values. 16 | /// The source of values. 17 | public EqualToQuantifierFilter(IFilterItem leftHand, Quantifier quantifier, IValueProvider valueProvider) 18 | : base(leftHand, quantifier, valueProvider) 19 | { 20 | } 21 | 22 | /// 23 | /// Provides information to the given visitor about the current builder. 24 | /// 25 | /// The visitor requesting information. 26 | protected override void OnAccept(BuilderVisitor visitor) 27 | { 28 | visitor.VisitEqualToQuantifierFilter(this); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/Except.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Removes the items returned by the second query from the first query. 8 | /// 9 | public class Except : SelectCombiner 10 | { 11 | /// 12 | /// Initializes a new instance of a Except. 13 | /// 14 | /// The left hand SELECT command. 15 | /// The right hand SELECT command. 16 | public Except(ISelectBuilder leftHand, ISelectBuilder rightHand) 17 | : base(leftHand, rightHand) 18 | { 19 | } 20 | 21 | /// 22 | /// Provides information to the given visitor about the current builder. 23 | /// 24 | /// The visitor requesting information. 25 | protected override void OnAccept(BuilderVisitor visitor) 26 | { 27 | visitor.VisitExcept(this); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/ExistsFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents a test for the presence of a record in a sub-query. 8 | /// 9 | public class ExistsFilter : Filter 10 | { 11 | /// 12 | /// Initializes a new instance of an ExistsFilter. 13 | /// 14 | /// 15 | public ExistsFilter(ISelectBuilder select) 16 | { 17 | if (select == null) 18 | { 19 | throw new ArgumentNullException("select"); 20 | } 21 | Select = select; 22 | } 23 | 24 | /// 25 | /// Gets the select builder used to test for the existance of a record. 26 | /// 27 | public ISelectBuilder Select 28 | { 29 | get; 30 | private set; 31 | } 32 | 33 | /// 34 | /// Provides information to the given visitor about the current builder. 35 | /// 36 | /// The visitor requesting information. 37 | protected override void OnAccept(BuilderVisitor visitor) 38 | { 39 | visitor.VisitExistsFilter(this); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/Filter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents a filter in a where clause. 8 | /// 9 | public abstract class Filter : IFilter 10 | { 11 | /// 12 | /// Initializes a new instance of a Filter. 13 | /// 14 | protected Filter() 15 | { 16 | } 17 | 18 | /// 19 | /// Gets or sets whether to wrap the filter in parentheses. 20 | /// 21 | public bool? WrapInParentheses 22 | { 23 | get; 24 | set; 25 | } 26 | 27 | void IVisitableBuilder.Accept(BuilderVisitor visitor) 28 | { 29 | OnAccept(visitor); 30 | } 31 | 32 | /// 33 | /// Provides information to the given visitor about the current builder. 34 | /// 35 | /// The visitor requesting information. 36 | protected abstract void OnAccept(BuilderVisitor visitor); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/FilteredJoin.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using SQLGeneration.Parsing; 4 | 5 | namespace SQLGeneration.Builders 6 | { 7 | /// 8 | /// Represents a join that is filtered with an ON expression. 9 | /// 10 | public abstract class FilteredJoin : BinaryJoin 11 | { 12 | private readonly FilterGroup on; 13 | 14 | /// 15 | /// Initializes a new instance of a FilteredJoin. 16 | /// 17 | /// The left hand item in the join. 18 | /// The right hand item in the join. 19 | protected FilteredJoin(Join left, AliasedSource right) 20 | : base(left, right) 21 | { 22 | on = new FilterGroup(Conjunction.And); 23 | } 24 | 25 | /// 26 | /// Sets the condition on which the source is joined with the other tables. 27 | /// 28 | /// A function that creates the join. 29 | /// The current join. 30 | public Join On(Func filterGenerator) 31 | { 32 | if (filterGenerator == null) 33 | { 34 | throw new ArgumentNullException("filterGenerator"); 35 | } 36 | on.Clear(); 37 | IFilter filter = filterGenerator(this); 38 | on.AddFilter(filter); 39 | return this; 40 | } 41 | 42 | /// 43 | /// Gets the filters by which the left and right hand items are joined. 44 | /// 45 | public IEnumerable OnFilters 46 | { 47 | get { return on.Filters; } 48 | } 49 | 50 | /// 51 | /// Gets the filter group. 52 | /// 53 | public FilterGroup OnFilterGroup 54 | { 55 | get { return on; } 56 | } 57 | 58 | /// 59 | /// Adds the filter to the group. 60 | /// 61 | /// The filter to add. 62 | public void AddOnFilter(IFilter filter) 63 | { 64 | on.AddFilter(filter); 65 | } 66 | 67 | /// 68 | /// Removes the filter from the group. 69 | /// 70 | /// The filter to remove. 71 | /// True if the filter was removed; otherwise, false. 72 | public bool RemoveOnFilter(IFilter filter) 73 | { 74 | return on.RemoveFilter(filter); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/FollowingBoundFrame.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Describes a window frame that is limited to a specific number of rows preceding in one direction. 8 | /// 9 | public class FollowingBoundFrame : BoundFrame, IFollowingFrame 10 | { 11 | /// 12 | /// Initializes a new instance of a FollowingBoundFrame. 13 | /// 14 | /// The limit to the number of rows to include in the frame. 15 | public FollowingBoundFrame(int rowCount) 16 | : base(rowCount) 17 | { 18 | } 19 | 20 | /// 21 | /// Provides information to the given visitor about the current builder. 22 | /// 23 | /// The visitor requesting information. 24 | protected override void OnAccept(BuilderVisitor visitor) 25 | { 26 | visitor.VisitFollowingBoundFrame(this); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/FollowingUnboundFrame.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Describes a window frame that is unbounded in one direction. 8 | /// 9 | public class FollowingUnboundFrame : UnboundFrame, IFollowingFrame 10 | { 11 | /// 12 | /// Initializes a new instance of an FollowingUnboundFrame. 13 | /// 14 | public FollowingUnboundFrame() 15 | { 16 | } 17 | 18 | /// 19 | /// Provides information to the given visitor about the current builder. 20 | /// 21 | /// The visitor requesting information. 22 | protected override void OnAccept(BuilderVisitor visitor) 23 | { 24 | visitor.VisitFollowingUnboundFrame(this); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/FrameTypeConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | using SQLGeneration.Properties; 4 | 5 | namespace SQLGeneration.Builders 6 | { 7 | /// 8 | /// Defines which keyword will be used when framing a function window. 9 | /// 10 | public enum FrameType 11 | { 12 | /// 13 | /// Specifies that the default frame type will be used, which is ROWS. 14 | /// 15 | Default, 16 | /// 17 | /// Specifies that the ROWS keyword will be used. 18 | /// 19 | Row, 20 | /// 21 | /// Specifies that the RANGE keyword will be used. 22 | /// 23 | Range, 24 | } 25 | 26 | /// 27 | /// Converts between representations of frame types. 28 | /// 29 | internal sealed class FrameTypeConverter 30 | { 31 | /// 32 | /// Initializes a new instance of a FrameTypeConverter. 33 | /// 34 | public FrameTypeConverter() 35 | { 36 | } 37 | 38 | /// 39 | /// Converts the given value to its string representation. 40 | /// 41 | /// The type of the frame. 42 | /// The string representing the given frame type. 43 | public string ToString(FrameType value) 44 | { 45 | switch (value) 46 | { 47 | case FrameType.Default: 48 | case FrameType.Row: 49 | return "ROWS"; 50 | case FrameType.Range: 51 | return "RANGE"; 52 | default: 53 | throw new ArgumentException(Resources.UnknownFrameType, "value"); 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/FullOuterJoin.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using SQLGeneration.Parsing; 4 | 5 | namespace SQLGeneration.Builders 6 | { 7 | /// 8 | /// Represents a full-outer join in a select statement. 9 | /// 10 | public class FullOuterJoin : FilteredJoin 11 | { 12 | /// 13 | /// Initializes a new instance of a FullOuterJoin. 14 | /// 15 | /// The left hand item in the join. 16 | /// The right hand table in the join. 17 | internal FullOuterJoin(Join leftHand, AliasedSource rightHand) 18 | : base(leftHand, rightHand) 19 | { 20 | } 21 | 22 | /// 23 | /// Provides information to the given visitor about the current builder. 24 | /// 25 | /// The visitor requesting information. 26 | protected override void OnAccept(BuilderVisitor visitor) 27 | { 28 | visitor.VisitFullOuterJoin(this); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/Function.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using SQLGeneration.Parsing; 4 | using SQLGeneration.Properties; 5 | 6 | namespace SQLGeneration.Builders 7 | { 8 | /// 9 | /// Adds a function call to a command. 10 | /// 11 | public class Function : Filter, IProjectionItem, IRightJoinItem, IFilterItem, IGroupByItem, IValueProvider 12 | { 13 | private readonly Namespace qualifier; 14 | private readonly List arguments; 15 | 16 | /// 17 | /// Initializes a new instance of a Function. 18 | /// 19 | /// The name of the function. 20 | public Function(string name) 21 | : this(null, name, new IProjectionItem[0]) 22 | { 23 | } 24 | 25 | /// 26 | /// Initializes a new instance of a Function. 27 | /// 28 | /// The schema the function exists in. 29 | /// The name of the function. 30 | public Function(Namespace qualifier, string name) 31 | : this(qualifier, name, new IProjectionItem[0]) 32 | { 33 | } 34 | 35 | /// 36 | /// Initializes a new instance of a Function. 37 | /// 38 | /// The name of the function. 39 | /// The arguments being passed to the function. 40 | public Function(string name, params IProjectionItem[] arguments) 41 | : this(null, name, arguments) 42 | { 43 | } 44 | 45 | /// 46 | /// Initializes a new instance of a Function. 47 | /// 48 | /// The schema the function exists in. 49 | /// The name of the function. 50 | /// The arguments being passed to the function. 51 | public Function(Namespace qualifier, string name, params IProjectionItem[] arguments) 52 | { 53 | if (String.IsNullOrWhiteSpace(name)) 54 | { 55 | throw new ArgumentException(Resources.BlankFunctionName, "name"); 56 | } 57 | this.qualifier = qualifier; 58 | Name = name; 59 | this.arguments = new List(arguments); 60 | } 61 | 62 | /// 63 | /// Gets or sets the schema the functions belongs to. 64 | /// 65 | public Namespace Qualifier 66 | { 67 | get { return qualifier; } 68 | } 69 | 70 | /// 71 | /// Gets the name of the function. 72 | /// 73 | public string Name 74 | { 75 | get; 76 | private set; 77 | } 78 | 79 | /// 80 | /// Gets a list of the arguments being passed to the function. 81 | /// 82 | public IEnumerable Arguments 83 | { 84 | get { return arguments; } 85 | } 86 | 87 | /// 88 | /// Adds the given projection item to the arguments list. 89 | /// 90 | /// The value to add. 91 | public void AddArgument(IProjectionItem item) 92 | { 93 | arguments.Add(item); 94 | } 95 | 96 | /// 97 | /// Removes the given projection item from the arguments list. 98 | /// 99 | /// The item to remove. 100 | /// True if the item was removed; otherwise, false. 101 | public bool RemoveArgument(IProjectionItem item) 102 | { 103 | return arguments.Remove(item); 104 | } 105 | 106 | /// 107 | /// Gets or sets the window to apply the function over. 108 | /// 109 | public FunctionWindow FunctionWindow 110 | { 111 | get; 112 | set; 113 | } 114 | 115 | bool IRightJoinItem.IsAliasRequired 116 | { 117 | get { return true; } 118 | } 119 | 120 | string IRightJoinItem.GetSourceName() 121 | { 122 | return null; 123 | } 124 | 125 | bool IValueProvider.IsValueList 126 | { 127 | get { return false; } 128 | } 129 | 130 | /// 131 | /// Provides information to the given visitor about the current builder. 132 | /// 133 | /// The visitor requesting information. 134 | protected override void OnAccept(BuilderVisitor visitor) 135 | { 136 | visitor.VisitFunction(this); 137 | } 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/FunctionWindow.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using SQLGeneration.Parsing; 4 | 5 | namespace SQLGeneration.Builders 6 | { 7 | /// 8 | /// Describes the window that a function is applied to. 9 | /// 10 | public class FunctionWindow : IVisitableBuilder 11 | { 12 | private readonly List partitionItems; 13 | private readonly List orderByItems; 14 | 15 | /// 16 | /// Initializes a new instance of a FunctionWindow. 17 | /// 18 | public FunctionWindow() 19 | { 20 | this.partitionItems = new List(); 21 | this.orderByItems = new List(); 22 | } 23 | 24 | /// 25 | /// Gets the items making up the partitioning. 26 | /// 27 | public IEnumerable Partition 28 | { 29 | get { return partitionItems; } 30 | } 31 | 32 | /// 33 | /// Adds the item as a partitioner. 34 | /// 35 | /// The item to partition the records on. 36 | /// An aliased projection wrapping the given item. 37 | public AliasedProjection AddPartition(IProjectionItem item) 38 | { 39 | if (item == null) 40 | { 41 | throw new ArgumentNullException("item"); 42 | } 43 | AliasedProjection projection = new AliasedProjection(item, null); 44 | partitionItems.Add(projection); 45 | return projection; 46 | } 47 | 48 | /// 49 | /// Adds the item as a partitioner. 50 | /// 51 | /// The aliased projection to add. 52 | public void AddPartition(AliasedProjection item) 53 | { 54 | if (item == null) 55 | { 56 | throw new ArgumentNullException("item"); 57 | } 58 | partitionItems.Add(item); 59 | } 60 | 61 | /// 62 | /// Removes the item from the partition. 63 | /// 64 | /// The item to remove. 65 | /// True if the item was removed; otherwise, false. 66 | public bool RemovePartition(AliasedProjection item) 67 | { 68 | if (item == null) 69 | { 70 | throw new ArgumentNullException("item"); 71 | } 72 | return partitionItems.Remove(item); 73 | } 74 | 75 | /// 76 | /// Gets the order by items. 77 | /// 78 | public IEnumerable OrderBy 79 | { 80 | get { return orderByItems; } 81 | } 82 | 83 | /// 84 | /// Gets the order by items. 85 | /// 86 | internal List OrderByList 87 | { 88 | get { return orderByItems; } 89 | } 90 | 91 | /// 92 | /// Adds the item as a sort condition to the window. 93 | /// 94 | /// The order by to add. 95 | public void AddOrderBy(OrderBy orderBy) 96 | { 97 | if (orderBy == null) 98 | { 99 | throw new ArgumentNullException("orderBy"); 100 | } 101 | orderByItems.Add(orderBy); 102 | } 103 | 104 | /// 105 | /// Removes the item as a sort condition to the window. 106 | /// 107 | /// The order by to remove. 108 | /// True if the order by was removed; otherwise, false. 109 | public bool RemoveOrderBy(OrderBy orderBy) 110 | { 111 | if (orderBy == null) 112 | { 113 | throw new ArgumentNullException("orderBy"); 114 | } 115 | return orderByItems.Remove(orderBy); 116 | } 117 | 118 | /// 119 | /// Gets or sets the window framing. 120 | /// 121 | public WindowFrame Frame 122 | { 123 | get; 124 | set; 125 | } 126 | 127 | void IVisitableBuilder.Accept(BuilderVisitor visitor) 128 | { 129 | visitor.VisitFunctionWindow(this); 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/GreaterThanEqualToFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents a comparison where the left hand item is greater than or equal to the right hand item. 8 | /// 9 | public class GreaterThanEqualToFilter : OrderFilter 10 | { 11 | /// 12 | /// Initializes a new instance of a GreaterThanEqualToFilter. 13 | /// 14 | /// The left hand item. 15 | /// The right hand item. 16 | public GreaterThanEqualToFilter(IFilterItem leftHand, IFilterItem rightHand) 17 | : base(leftHand, rightHand) 18 | { 19 | } 20 | 21 | /// 22 | /// Provides information to the given visitor about the current builder. 23 | /// 24 | /// The visitor requesting information. 25 | protected override void OnAccept(BuilderVisitor visitor) 26 | { 27 | visitor.VisitGreaterThanEqualToFilter(this); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/GreaterThanEqualToQuantifierFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents a filter that see that a value is greater than or equal to all or some of the values. 8 | /// 9 | public class GreaterThanEqualToQuantifierFilter : QuantifierFilter 10 | { 11 | /// 12 | /// Initializes a new insstance of an GreaterThanEqualToQuantifierFilter. 13 | /// 14 | /// The value being compared to the set of values. 15 | /// The quantifier to use to compare the value to the set of values. 16 | /// The source of values. 17 | public GreaterThanEqualToQuantifierFilter(IFilterItem leftHand, Quantifier quantifier, IValueProvider valueProvider) 18 | : base(leftHand, quantifier, valueProvider) 19 | { 20 | } 21 | 22 | /// 23 | /// Provides information to the given visitor about the current builder. 24 | /// 25 | /// The visitor requesting information. 26 | protected override void OnAccept(BuilderVisitor visitor) 27 | { 28 | visitor.VisitGreaterThanEqualToQuantifierFilter(this); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/GreaterThanFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents a comparison where the left hand item is greater than the right hand item. 8 | /// 9 | public class GreaterThanFilter : OrderFilter 10 | { 11 | /// 12 | /// Initializes a new instance of a GreaterThanFilter. 13 | /// 14 | /// The left hand item. 15 | /// The right hand item. 16 | public GreaterThanFilter(IFilterItem leftHand, IFilterItem rightHand) 17 | : base(leftHand, rightHand) 18 | { 19 | } 20 | 21 | /// 22 | /// Provides information to the given visitor about the current builder. 23 | /// 24 | /// The visitor requesting information. 25 | protected override void OnAccept(BuilderVisitor visitor) 26 | { 27 | visitor.VisitGreaterThanFilter(this); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/GreaterThanQuantifierFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents a filter that see that a value is greater than all or some of the values. 8 | /// 9 | public class GreaterThanQuantifierFilter : QuantifierFilter 10 | { 11 | /// 12 | /// Initializes a new insstance of an GreaterThanQuantifierFilter. 13 | /// 14 | /// The value being compared to the set of values. 15 | /// The quantifier to use to compare the value to the set of values. 16 | /// The source of values. 17 | public GreaterThanQuantifierFilter(IFilterItem leftHand, Quantifier quantifier, IValueProvider valueProvider) 18 | : base(leftHand, quantifier, valueProvider) 19 | { 20 | } 21 | 22 | /// 23 | /// Provides information to the given visitor about the current builder. 24 | /// 25 | /// The visitor requesting information. 26 | protected override void OnAccept(BuilderVisitor visitor) 27 | { 28 | visitor.VisitGreaterThanQuantifierFilter(this); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/ICommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents a SQL statement. 8 | /// 9 | public interface ICommand : IVisitableBuilder 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/IComparisonFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SQLGeneration.Builders 4 | { 5 | /// 6 | /// Adds a filter comparison two items together. 7 | /// 8 | public interface IComparisonFilter : IFilter 9 | { 10 | /// 11 | /// Gets the left hand operand of the filter. 12 | /// 13 | IFilterItem LeftHand 14 | { 15 | get; 16 | } 17 | 18 | /// 19 | /// Gets the right hand operand of the comparison. 20 | /// 21 | IFilterItem RightHand 22 | { 23 | get; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/IFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Adds a condition to a where clause. 8 | /// 9 | public interface IFilter : IVisitableBuilder 10 | { 11 | /// 12 | /// Gets or sets whether to wrap the filter in parentheses. 13 | /// 14 | bool? WrapInParentheses 15 | { 16 | get; 17 | set; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/IFilterItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents an item that can appear in a filter. 8 | /// 9 | public interface IFilterItem : IVisitableBuilder 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/IFilteredCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents a command that can be filtered. 8 | /// 9 | public interface IFilteredCommand : ICommand 10 | { 11 | /// 12 | /// Gets the filters in the where clause. 13 | /// 14 | IEnumerable Where 15 | { 16 | get; 17 | } 18 | 19 | /// 20 | /// Gets the filter group used to build the command's where clause. 21 | /// 22 | FilterGroup WhereFilterGroup 23 | { 24 | get; 25 | } 26 | 27 | /// 28 | /// Adds the filter to the where clause. 29 | /// 30 | /// The filter to add. 31 | void AddWhere(IFilter filter); 32 | 33 | /// 34 | /// Removes the filter from the where clause. 35 | /// 36 | /// The filter to remove. 37 | /// True if the filter was removed; otherwise, false. 38 | bool RemoveWhere(IFilter filter); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/IFollowingFrame.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Specifies where a windowed function's frame should stop. 8 | /// 9 | public interface IFollowingFrame : IVisitableBuilder 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/IGroupByItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents an item that can appear in a group by clause in a select statement. 8 | /// 9 | public interface IGroupByItem : IVisitableBuilder 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/IJoinItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents an item that can appear in a join statement. 8 | /// 9 | public interface IJoinItem : IVisitableBuilder 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/IPreceedingFrame.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Specifies where a windowed function's frame should start. 8 | /// 9 | public interface IPrecedingFrame : IVisitableBuilder 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/IProjectionItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents an item that can appear in the projection-clause of a select statement. 8 | /// 9 | public interface IProjectionItem : IVisitableBuilder 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/IRightJoinItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SQLGeneration.Builders 4 | { 5 | /// 6 | /// Represents the right hand side of a join. 7 | /// 8 | public interface IRightJoinItem : IJoinItem 9 | { 10 | /// 11 | /// Gets whether the join item is a SELECT statement. 12 | /// 13 | bool IsAliasRequired 14 | { 15 | get; 16 | } 17 | 18 | /// 19 | /// Gets the name of the table -or- null if the item is a SELECT statement. 20 | /// 21 | /// 22 | string GetSourceName(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/ISelectBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Builds SELECT statements. 8 | /// 9 | public interface ISelectBuilder : ICommand, IRightJoinItem, IProjectionItem, IValueProvider 10 | { 11 | /// 12 | /// Gets the source collection for the builder. 13 | /// 14 | SourceCollection Sources { get; } 15 | 16 | /// 17 | /// Gets the items used to sort the results. 18 | /// 19 | IEnumerable OrderBy 20 | { 21 | get; 22 | } 23 | 24 | /// 25 | /// Gets the order by items. 26 | /// 27 | List OrderByList 28 | { 29 | get; 30 | } 31 | 32 | /// 33 | /// Adds a sort criteria to the query. 34 | /// 35 | /// The sort criteria to add. 36 | void AddOrderBy(OrderBy item); 37 | 38 | /// 39 | /// Removes the sort criteria from the query. 40 | /// 41 | /// The order by item to remove. 42 | /// True if the item was removed; otherwise, false. 43 | bool RemoveOrderBy(OrderBy item); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/IValueProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SQLGeneration.Builders 4 | { 5 | /// 6 | /// Represents a source of values in an insert statement. 7 | /// 8 | public interface IValueProvider : IFilterItem 9 | { 10 | /// 11 | /// Gets or sets whether the value provider gets its values from a value list. 12 | /// 13 | bool IsValueList 14 | { 15 | get; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/IVisitableBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SQLGeneration.Builders 4 | { 5 | /// 6 | /// An item that can be visited by a builder visitor. 7 | /// 8 | public interface IVisitableBuilder 9 | { 10 | /// 11 | /// Provides information to the given visitor about the current builder. 12 | /// 13 | /// The visitor requesting information. 14 | void Accept(BuilderVisitor visitor); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/InFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents a filter where the values on the left hand must be in the values on the right hand. 8 | /// 9 | public class InFilter : Filter 10 | { 11 | /// 12 | /// Initializes a new instance of a InFilter. 13 | /// 14 | /// The left hand value that must exist in the list of values. 15 | /// The list of values the left hand must exist in. 16 | public InFilter(IFilterItem leftHand, IValueProvider values) 17 | { 18 | if (leftHand == null) 19 | { 20 | throw new ArgumentNullException("leftHand"); 21 | } 22 | if (values == null) 23 | { 24 | throw new ArgumentNullException("values"); 25 | } 26 | LeftHand = leftHand; 27 | Values = values; 28 | } 29 | 30 | /// 31 | /// Gets or sets whether to negate the comparison. 32 | /// 33 | public bool Not 34 | { 35 | get; 36 | set; 37 | } 38 | 39 | /// 40 | /// Gets the left hand operand of the filter. 41 | /// 42 | public IFilterItem LeftHand 43 | { 44 | get; 45 | private set; 46 | } 47 | 48 | /// 49 | /// Gets the value provider. 50 | /// 51 | public IValueProvider Values 52 | { 53 | get; 54 | private set; 55 | } 56 | 57 | /// 58 | /// Provides information to the given visitor about the current builder. 59 | /// 60 | /// The visitor requesting information. 61 | protected override void OnAccept(BuilderVisitor visitor) 62 | { 63 | visitor.VisitInFilter(this); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/InnerJoin.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using SQLGeneration.Parsing; 4 | 5 | namespace SQLGeneration.Builders 6 | { 7 | /// 8 | /// Represents an inner join in a select statement. 9 | /// 10 | public class InnerJoin : FilteredJoin 11 | { 12 | /// 13 | /// Initializes a new instance of a InnerJoin. 14 | /// 15 | /// The left hand item in the join. 16 | /// The right hand item in the join. 17 | internal InnerJoin(Join leftHand, AliasedSource rightHand) 18 | : base(leftHand, rightHand) 19 | { 20 | } 21 | 22 | /// 23 | /// Provides information to the given visitor about the current builder. 24 | /// 25 | /// The visitor requesting information. 26 | protected override void OnAccept(BuilderVisitor visitor) 27 | { 28 | visitor.VisitInnerJoin(this); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/InsertBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using SQLGeneration.Parsing; 4 | 5 | namespace SQLGeneration.Builders 6 | { 7 | /// 8 | /// Builds a string of an insert statement. 9 | /// 10 | public class InsertBuilder : ICommand 11 | { 12 | private readonly AliasedSource _table; 13 | private readonly List _columns; 14 | private readonly IValueProvider _values; 15 | 16 | /// 17 | /// Initializes a new instance of a InsertBuilder. 18 | /// 19 | /// The table being inserted into. 20 | /// The values to insert into the table. 21 | /// The alias to use to refer to the table. 22 | public InsertBuilder(Table table, IValueProvider values, string alias = null) 23 | { 24 | if (table == null) 25 | { 26 | throw new ArgumentNullException("table"); 27 | } 28 | if (values == null) 29 | { 30 | throw new ArgumentNullException("values"); 31 | } 32 | _table = new AliasedSource(table, alias); 33 | _columns = new List(); 34 | _values = values; 35 | } 36 | 37 | /// 38 | /// Gets the table that is being inserted into. 39 | /// 40 | public AliasedSource Table 41 | { 42 | get { return _table; } 43 | } 44 | 45 | /// 46 | /// Gets the columns being inserted into. 47 | /// 48 | public IEnumerable Columns 49 | { 50 | get { return _columns; } 51 | } 52 | 53 | /// 54 | /// Adds the column to the insert statement. 55 | /// 56 | /// The column to add. 57 | public void AddColumn(Column column) 58 | { 59 | if (column == null) 60 | { 61 | throw new ArgumentNullException("column"); 62 | } 63 | _columns.Add(column); 64 | } 65 | 66 | /// 67 | /// Removes the column from the insert statement. 68 | /// 69 | /// The column to remove. 70 | /// True if the column was removed; otherwise, false. 71 | public bool RemoveColumn(Column column) 72 | { 73 | if (column == null) 74 | { 75 | throw new ArgumentNullException("column"); 76 | } 77 | return _columns.Remove(column); 78 | } 79 | 80 | /// 81 | /// Gets the list of values or select statement that populates the insert. 82 | /// 83 | public IValueProvider Values 84 | { 85 | get { return _values; } 86 | } 87 | 88 | void IVisitableBuilder.Accept(BuilderVisitor visitor) 89 | { 90 | visitor.VisitInsert(this); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/Intersect.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Generates the intersection among all of the queries. 8 | /// 9 | public class Intersect : SelectCombiner 10 | { 11 | /// 12 | /// Initializes a new instance of a Intersect. 13 | /// 14 | /// The left hand SELECT command. 15 | /// The right hand SELECT command. 16 | public Intersect(ISelectBuilder leftHand, ISelectBuilder rightHand) 17 | : base(leftHand, rightHand) 18 | { 19 | } 20 | 21 | /// 22 | /// Provides information to the given visitor about the current builder. 23 | /// 24 | /// The visitor requesting information. 25 | protected override void OnAccept(BuilderVisitor visitor) 26 | { 27 | visitor.VisitIntersect(this); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/Join.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents a portion of a series of joins. 8 | /// 9 | public abstract class Join : IJoinItem 10 | { 11 | private readonly SourceCollection sources; 12 | 13 | /// 14 | /// Initializes a new instance of a Join. 15 | /// 16 | /// The source for the current 17 | protected Join(AliasedSource source) 18 | : this(new SourceCollection(), source) 19 | { 20 | } 21 | 22 | /// 23 | /// Initializes a new instance of a Join. 24 | /// 25 | /// The previous join in the sequence. 26 | /// The source for the current 27 | protected Join(Join other, AliasedSource source) 28 | : this(new SourceCollection(other.sources), source) 29 | { 30 | } 31 | 32 | private Join(SourceCollection sourceCollection, AliasedSource source) 33 | { 34 | this.sources = sourceCollection; 35 | string newSourceName = source.GetSourceName(); 36 | if (newSourceName != null) 37 | { 38 | this.sources.AddSource(newSourceName, source); 39 | } 40 | } 41 | 42 | /// 43 | /// Starts creating a BinaryJoin. 44 | /// 45 | /// The table or select statement to start the join series with. 46 | /// The alias to give the item. 47 | /// The first join item. 48 | public static Join From(IRightJoinItem source, string alias = null) 49 | { 50 | if (source == null) 51 | { 52 | throw new ArgumentNullException("source"); 53 | } 54 | AliasedSource start = new AliasedSource(source, alias); 55 | return new JoinStart(start); 56 | } 57 | 58 | /// 59 | /// Gets or sets whether the join should be wrapped in parentheses. 60 | /// 61 | public bool? WrapInParentheses 62 | { 63 | get; 64 | set; 65 | } 66 | 67 | /// 68 | /// Gets a collection of the table and SELECT statements within the join. 69 | /// 70 | public SourceCollection Sources 71 | { 72 | get { return sources; } 73 | } 74 | 75 | void IVisitableBuilder.Accept(BuilderVisitor visitor) 76 | { 77 | OnAccept(visitor); 78 | } 79 | 80 | /// 81 | /// Provides information to the given visitor about the current builder. 82 | /// 83 | /// The visitor requesting information. 84 | protected abstract void OnAccept(BuilderVisitor visitor); 85 | 86 | /// 87 | /// Creates a new join where the given item is inner joined with the existing join items. 88 | /// 89 | /// The item to join with. 90 | /// The alias to give the item. 91 | /// The new join. 92 | public FilteredJoin InnerJoin(IRightJoinItem item, string alias = null) 93 | { 94 | AliasedSource source = new AliasedSource(item, alias); 95 | return new InnerJoin(this, source); 96 | } 97 | 98 | /// 99 | /// Creates a new join where the given item is left outer joined with the existing join items. 100 | /// 101 | /// The item to join with. 102 | /// The alias to give the item. 103 | /// The new join. 104 | public FilteredJoin LeftOuterJoin(IRightJoinItem item, string alias = null) 105 | { 106 | AliasedSource source = new AliasedSource(item, alias); 107 | return new LeftOuterJoin(this, source); 108 | } 109 | 110 | /// 111 | /// Creates a new join where the given item is right outer joined with the existing join items. 112 | /// 113 | /// The item to join with. 114 | /// The alias to give the item. 115 | /// The new join. 116 | public FilteredJoin RightOuterJoin(IRightJoinItem item, string alias = null) 117 | { 118 | AliasedSource source = new AliasedSource(item, alias); 119 | return new RightOuterJoin(this, source); 120 | } 121 | 122 | /// 123 | /// Creates a new join where the given item is full outer joined with the existing join items. 124 | /// 125 | /// The item to join with. 126 | /// The alias to give the item. 127 | /// The new join. 128 | public FilteredJoin FullOuterJoin(IRightJoinItem item, string alias = null) 129 | { 130 | AliasedSource source = new AliasedSource(item, alias); 131 | return new FullOuterJoin(this, source); 132 | } 133 | 134 | /// 135 | /// Creates a new join where the given item is cross joined with the existing join items. 136 | /// 137 | /// The item to join with. 138 | /// The alias to give the item. 139 | /// The new join. 140 | public Join CrossJoin(IRightJoinItem item, string alias = null) 141 | { 142 | AliasedSource source = new AliasedSource(item, alias); 143 | return new CrossJoin(this, source); 144 | } 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/JoinStart.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents the first source in a series of joins. 8 | /// 9 | internal class JoinStart : Join 10 | { 11 | private readonly AliasedSource source; 12 | 13 | /// 14 | /// Initializes a new instance of a JoinStart. 15 | /// 16 | /// The first source in a series of joins. 17 | public JoinStart(AliasedSource source) 18 | : base(source) 19 | { 20 | this.source = source; 21 | } 22 | 23 | /// 24 | /// Gets the source. 25 | /// 26 | internal AliasedSource Source 27 | { 28 | get { return source; } 29 | } 30 | 31 | /// 32 | /// Provides information to the given visitor about the current builder. 33 | /// 34 | /// The visitor requesting information. 35 | protected override void OnAccept(BuilderVisitor visitor) 36 | { 37 | IJoinItem joinItem = source; 38 | joinItem.Accept(visitor); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/LeftOuterJoin.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using SQLGeneration.Parsing; 4 | 5 | namespace SQLGeneration.Builders 6 | { 7 | /// 8 | /// Represents an left-outer join in a select statement. 9 | /// 10 | public class LeftOuterJoin : FilteredJoin 11 | { 12 | /// 13 | /// Initializes a new instance of a LeftOuterJoin. 14 | /// 15 | /// The left hand item in the join. 16 | /// The right hand table in the join. 17 | internal LeftOuterJoin(Join leftHand, AliasedSource rightHand) 18 | : base(leftHand, rightHand) 19 | { 20 | } 21 | 22 | /// 23 | /// Provides information to the given visitor about the current builder. 24 | /// 25 | /// The visitor requesting information. 26 | protected override void OnAccept(BuilderVisitor visitor) 27 | { 28 | visitor.VisitLeftOuterJoin(this); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/LessThanEqualToFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents a comparison where the left hand item is less than or equal to the right hand item. 8 | /// 9 | public class LessThanEqualToFilter : OrderFilter 10 | { 11 | /// 12 | /// Initializes a new instance of a LessThanEqualToFilter. 13 | /// 14 | /// The left hand item. 15 | /// The right hand item. 16 | public LessThanEqualToFilter(IFilterItem leftHand, IFilterItem rightHand) 17 | : base(leftHand, rightHand) 18 | { 19 | } 20 | 21 | /// 22 | /// Provides information to the given visitor about the current builder. 23 | /// 24 | /// The visitor requesting information. 25 | protected override void OnAccept(BuilderVisitor visitor) 26 | { 27 | visitor.VisitLessThanEqualToFilter(this); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/LessThanEqualToQuantifierFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents a filter that see that a value is less than or equal to all or some of the values. 8 | /// 9 | public class LessThanEqualToQuantifierFilter : QuantifierFilter 10 | { 11 | /// 12 | /// Initializes a new insstance of an LessThanEqualToQuantifierFilter. 13 | /// 14 | /// The value being compared to the set of values. 15 | /// The quantifier to use to compare the value to the set of values. 16 | /// The source of values. 17 | public LessThanEqualToQuantifierFilter(IFilterItem leftHand, Quantifier quantifier, IValueProvider valueProvider) 18 | : base(leftHand, quantifier, valueProvider) 19 | { 20 | } 21 | 22 | /// 23 | /// Provides information to the given visitor about the current builder. 24 | /// 25 | /// The visitor requesting information. 26 | protected override void OnAccept(BuilderVisitor visitor) 27 | { 28 | visitor.VisitLessThanEqualToQuantifierFilter(this); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/LessThanFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents a comparison where the left hand item is less than the right hand item. 8 | /// 9 | public class LessThanFilter : OrderFilter 10 | { 11 | /// 12 | /// Initializes a new instance of a LessThanFilter. 13 | /// 14 | /// The left hand item. 15 | /// The right hand item. 16 | public LessThanFilter(IFilterItem leftHand, IFilterItem rightHand) 17 | : base(leftHand, rightHand) 18 | { 19 | } 20 | 21 | /// 22 | /// Provides information to the given visitor about the current builder. 23 | /// 24 | /// The visitor requesting information. 25 | protected override void OnAccept(BuilderVisitor visitor) 26 | { 27 | visitor.VisitLessThanFilter(this); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/LessThanQuantifierFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents a filter that see that a value is less than all or some of the values. 8 | /// 9 | public class LessThanQuantifierFilter : QuantifierFilter 10 | { 11 | /// 12 | /// Initializes a new insstance of an LessThanQuantifierFilter. 13 | /// 14 | /// The value being compared to the set of values. 15 | /// The quantifier to use to compare the value to the set of values. 16 | /// The source of values. 17 | public LessThanQuantifierFilter(IFilterItem leftHand, Quantifier quantifier, IValueProvider valueProvider) 18 | : base(leftHand, quantifier, valueProvider) 19 | { 20 | } 21 | 22 | /// 23 | /// Provides information to the given visitor about the current builder. 24 | /// 25 | /// The visitor requesting information. 26 | protected override void OnAccept(BuilderVisitor visitor) 27 | { 28 | visitor.VisitLessThanQuantifierFilter(this); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/LikeFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents a comparison where the left hand item is greater than or equal to the right hand item. 8 | /// 9 | public class LikeFilter : OrderFilter 10 | { 11 | /// 12 | /// Initializes a new instance of a LikeFilter. 13 | /// 14 | /// The left hand item. 15 | /// The right hand item. 16 | public LikeFilter(IFilterItem leftHand, IFilterItem rightHand) 17 | : base(leftHand, rightHand) 18 | { 19 | } 20 | 21 | /// 22 | /// Gets or sets whether to negate the comparison. 23 | /// 24 | public bool Not 25 | { 26 | get; 27 | set; 28 | } 29 | 30 | /// 31 | /// Provides information to the given visitor about the current builder. 32 | /// 33 | /// The visitor requesting information. 34 | protected override void OnAccept(BuilderVisitor visitor) 35 | { 36 | visitor.VisitLikeFilter(this); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/Literal.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Helps create literals. 8 | /// 9 | public abstract class Literal : IProjectionItem, IFilterItem, IGroupByItem 10 | { 11 | /// 12 | /// Initializes a new instance of a Literal. 13 | /// 14 | protected Literal() 15 | { 16 | } 17 | 18 | void IVisitableBuilder.Accept(BuilderVisitor visitor) 19 | { 20 | OnAccept(visitor); 21 | } 22 | 23 | /// 24 | /// Provides information to the given visitor about the current builder. 25 | /// 26 | /// The visitor requesting information. 27 | protected abstract void OnAccept(BuilderVisitor visitor); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/MatchCase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using SQLGeneration.Parsing; 5 | using SQLGeneration.Properties; 6 | 7 | namespace SQLGeneration.Builders 8 | { 9 | /// 10 | /// Represents a conditional statement where an item is matched with another. 11 | /// 12 | public class MatchCase : IProjectionItem, IFilterItem, IGroupByItem 13 | { 14 | private readonly List branches; 15 | 16 | /// 17 | /// Initializes a new instance of a MatchCase. 18 | /// 19 | /// The item that will be matched to the different values. 20 | public MatchCase(IProjectionItem item) 21 | { 22 | if (item == null) 23 | { 24 | throw new ArgumentNullException("item"); 25 | } 26 | Item = item; 27 | branches = new List(); 28 | } 29 | 30 | /// 31 | /// Gets the item that will be compared to the different branch options. 32 | /// 33 | public IProjectionItem Item 34 | { 35 | get; 36 | private set; 37 | } 38 | 39 | /// 40 | /// Gets the case branches. 41 | /// 42 | public IEnumerable Branches 43 | { 44 | get { return branches; } 45 | } 46 | 47 | /// 48 | /// Adds a branch with the given option and value to the case expression. 49 | /// 50 | /// The value that the case item must equal for given the result to be returned. 51 | /// The value to return when the item equals the option. 52 | public MatchCaseBranch AddBranch(IProjectionItem option, IProjectionItem value) 53 | { 54 | if (option == null) 55 | { 56 | throw new ArgumentNullException("option"); 57 | } 58 | if (value == null) 59 | { 60 | throw new ArgumentNullException("value"); 61 | } 62 | MatchCaseBranch branch = new MatchCaseBranch(); 63 | branch.Option = option; 64 | branch.Value = value; 65 | branches.Add(branch); 66 | return branch; 67 | } 68 | 69 | /// 70 | /// Removes the branch. 71 | /// 72 | /// The branch to be removed. 73 | /// True if the branch was found; otherwise, false. 74 | public bool RemoveBranch(MatchCaseBranch branch) 75 | { 76 | if (branch == null) 77 | { 78 | throw new ArgumentNullException("branch"); 79 | } 80 | return branches.Remove(branch); 81 | } 82 | 83 | /// 84 | /// Gets or sets the default value to return if no options match the item. 85 | /// 86 | public IProjectionItem Default 87 | { 88 | get; 89 | set; 90 | } 91 | 92 | void IVisitableBuilder.Accept(BuilderVisitor visitor) 93 | { 94 | visitor.VisitMatchCase(this); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/MatchCaseBranch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SQLGeneration.Builders 4 | { 5 | /// 6 | /// Represents a branch in a match case expression. 7 | /// 8 | public class MatchCaseBranch 9 | { 10 | /// 11 | /// The value that must match for the value to be chosen. 12 | /// 13 | public IProjectionItem Option { get; internal set; } 14 | 15 | /// 16 | /// The value that will be returned if the option matches. 17 | /// 18 | public IProjectionItem Value { get; internal set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/Minus.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Removes the items returned by the second query from the first query. 8 | /// 9 | public class Minus : SelectCombiner 10 | { 11 | /// 12 | /// Initializes a new instance of a Minus. 13 | /// 14 | /// The left hand SELECT command. 15 | /// The right hand SELECT command. 16 | public Minus(ISelectBuilder leftHand, ISelectBuilder rightHand) 17 | : base(leftHand, rightHand) 18 | { 19 | } 20 | 21 | /// 22 | /// Provides information to the given visitor about the current builder. 23 | /// 24 | /// The visitor requesting information. 25 | protected override void OnAccept(BuilderVisitor visitor) 26 | { 27 | visitor.VisitMinus(this); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/Modulus.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents the remainder after division in T-SQL systems. 8 | /// 9 | public class Modulus : ArithmeticExpression 10 | { 11 | /// 12 | /// Initializes a new instance of a Modulus. 13 | /// 14 | /// The left hand side of the expression. 15 | /// The right hand side of the expression. 16 | public Modulus(IProjectionItem leftHand, IProjectionItem rightHand) 17 | : base(leftHand, rightHand) 18 | { 19 | } 20 | 21 | /// 22 | /// Provides information to the given visitor about the current builder. 23 | /// 24 | /// The visitor requesting information. 25 | protected override void OnAccept(BuilderVisitor visitor) 26 | { 27 | visitor.VisitModulus(this); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/Multiplication.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents the multiplication of two items in a command. 8 | /// 9 | public class Multiplication : ArithmeticExpression 10 | { 11 | /// 12 | /// Initializes a new instance of a Multiplication. 13 | /// 14 | /// The left hand side of the expression. 15 | /// The right hand side of the expression. 16 | public Multiplication(IProjectionItem leftHand, IProjectionItem rightHand) 17 | : base(leftHand, rightHand) 18 | { 19 | } 20 | 21 | /// 22 | /// Provides information to the given visitor about the current builder. 23 | /// 24 | /// The visitor requesting information. 25 | protected override void OnAccept(BuilderVisitor visitor) 26 | { 27 | visitor.VisitMultiplication(this); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/Namespace.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using SQLGeneration.Parsing; 4 | using SQLGeneration.Properties; 5 | 6 | namespace SQLGeneration.Builders 7 | { 8 | /// 9 | /// Qualifies an object with one or more identifiers. 10 | /// 11 | public class Namespace 12 | { 13 | private readonly List qualifiers; 14 | 15 | /// 16 | /// Initializes a new instance of a Namespace. 17 | /// 18 | /// The qualifiers to include, in the order they will appear in the output. 19 | public Namespace(params string[] qualifiers) 20 | { 21 | if (qualifiers == null) 22 | { 23 | throw new ArgumentNullException("qualifiers"); 24 | } 25 | this.qualifiers = new List(); 26 | foreach (string qualifier in qualifiers) 27 | { 28 | AddQualifier(qualifier); 29 | } 30 | } 31 | 32 | /// 33 | /// Adds the given qualifier. 34 | /// 35 | /// The qualifier to add. 36 | public void AddQualifier(string qualifier) 37 | { 38 | if (String.IsNullOrWhiteSpace(qualifier)) 39 | { 40 | throw new ArgumentException(Resources.BlankSchemaName, "qualifier"); 41 | } 42 | qualifiers.Add(qualifier); 43 | } 44 | 45 | /// 46 | /// Gets the qualifiers making up the namespace. 47 | /// 48 | public IEnumerable Qualifiers 49 | { 50 | get { return qualifiers; } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/Negation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Negates an arithmetic expression. 8 | /// 9 | public class Negation : IProjectionItem, IFilterItem, IGroupByItem 10 | { 11 | /// 12 | /// Initializes a new instance of a Negation. 13 | /// 14 | /// The item to negate. 15 | public Negation(IProjectionItem item) 16 | { 17 | if (item == null) 18 | { 19 | throw new ArgumentNullException("item"); 20 | } 21 | Item = item; 22 | } 23 | 24 | /// 25 | /// Gets the item that will be negated. 26 | /// 27 | public IProjectionItem Item 28 | { 29 | get; 30 | private set; 31 | } 32 | 33 | void IVisitableBuilder.Accept(BuilderVisitor visitor) 34 | { 35 | visitor.VisitNegation(this); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/NotEqualToFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents a comparison between two items for inequality. 8 | /// 9 | public class NotEqualToFilter : OrderFilter 10 | { 11 | /// 12 | /// Initializes a new instance of a NotEqualToFilter. 13 | /// 14 | /// The left hand item. 15 | /// The right hand item. 16 | public NotEqualToFilter(IFilterItem leftHand, IFilterItem rightHand) 17 | : base(leftHand, rightHand) 18 | { 19 | } 20 | 21 | /// 22 | /// Provides information to the given visitor about the current builder. 23 | /// 24 | /// The visitor requesting information. 25 | protected override void OnAccept(BuilderVisitor visitor) 26 | { 27 | visitor.VisitNotEqualToFilter(this); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/NotEqualToQuantifierFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents a filter that see that a value is not equal to all or some of the values. 8 | /// 9 | public class NotEqualToQuantifierFilter : QuantifierFilter 10 | { 11 | /// 12 | /// Initializes a new insstance of an NotEqualToQuantifierFilter. 13 | /// 14 | /// The value being compared to the set of values. 15 | /// The quantifier to use to compare the value to the set of values. 16 | /// The source of values. 17 | public NotEqualToQuantifierFilter(IFilterItem leftHand, Quantifier quantifier, IValueProvider valueProvider) 18 | : base(leftHand, quantifier, valueProvider) 19 | { 20 | } 21 | 22 | /// 23 | /// Provides information to the given visitor about the current builder. 24 | /// 25 | /// The visitor requesting information. 26 | protected override void OnAccept(BuilderVisitor visitor) 27 | { 28 | visitor.VisitNotEqualToQuantifierFilter(this); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/NotFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Logically negates another filter. 8 | /// 9 | public class NotFilter : Filter 10 | { 11 | private readonly IFilter filter; 12 | 13 | /// 14 | /// Initializes a new instance of a NotFilter. 15 | /// 16 | /// The filter to negate. 17 | public NotFilter(IFilter filter) 18 | { 19 | if (filter == null) 20 | { 21 | throw new ArgumentNullException("filter"); 22 | } 23 | this.filter = filter; 24 | } 25 | 26 | /// 27 | /// Gets the filter that will be negated. 28 | /// 29 | public IFilter Filter 30 | { 31 | get { return filter; } 32 | } 33 | 34 | /// 35 | /// Provides information to the given visitor about the current builder. 36 | /// 37 | /// The visitor requesting information. 38 | protected override void OnAccept(BuilderVisitor visitor) 39 | { 40 | visitor.VisitNotFilter(this); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/NullFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents a comparison between a value and null. 8 | /// 9 | public class NullFilter : Filter 10 | { 11 | private readonly IFilterItem _item; 12 | 13 | /// 14 | /// Initializes a new instance of a NullFilter. 15 | /// 16 | /// The item to check whether or not is null. 17 | public NullFilter(IFilterItem item) 18 | { 19 | if (item == null) 20 | { 21 | throw new ArgumentNullException("item"); 22 | } 23 | _item = item; 24 | } 25 | 26 | /// 27 | /// Gets the item being compared to null. 28 | /// 29 | public IFilterItem LeftHand 30 | { 31 | get { return _item; } 32 | } 33 | 34 | /// 35 | /// Gets or sets whether to negate the comparison. 36 | /// 37 | public bool Not 38 | { 39 | get; 40 | set; 41 | } 42 | 43 | /// 44 | /// Provides information to the given visitor about the current builder. 45 | /// 46 | /// The visitor requesting information. 47 | protected override void OnAccept(BuilderVisitor visitor) 48 | { 49 | visitor.VisitNullFilter(this); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/NullLiteral.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents the literal NULL. 8 | /// 9 | public class NullLiteral : Literal 10 | { 11 | /// 12 | /// Initializes a new instance of a NullLiteral. 13 | /// 14 | public NullLiteral() 15 | { 16 | } 17 | 18 | /// 19 | /// Provides information to the given visitor about the current builder. 20 | /// 21 | /// The visitor requesting information. 22 | protected override void OnAccept(BuilderVisitor visitor) 23 | { 24 | visitor.VisitNullLiteral(this); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/NullPlacementConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | using SQLGeneration.Properties; 4 | 5 | namespace SQLGeneration.Builders 6 | { 7 | /// 8 | /// Specifies the position of NULLs in a result set. 9 | /// 10 | public enum NullPlacement 11 | { 12 | /// 13 | /// The null placement is determined by the database provider. 14 | /// 15 | Default, 16 | /// 17 | /// The null values appear before the remaining results. 18 | /// 19 | First, 20 | /// 21 | /// The null values appear after the remaining results. 22 | /// 23 | Last, 24 | } 25 | 26 | /// 27 | /// Converts null placements to their string representations. 28 | /// 29 | internal class NullPlacementConverter 30 | { 31 | /// 32 | /// Initializes a new instance of a NullPlacementConverter. 33 | /// 34 | public NullPlacementConverter() 35 | { 36 | } 37 | 38 | /// 39 | /// Gets a string representation of the given null placement. 40 | /// 41 | /// The null placement to convert to a string. 42 | /// The string representation. 43 | public string ToString(NullPlacement placement) 44 | { 45 | switch (placement) 46 | { 47 | case NullPlacement.First: 48 | return "NULLS FIRST"; 49 | case NullPlacement.Last: 50 | return "NULLS LAST"; 51 | default: 52 | throw new ArgumentException(Resources.UnknownNullPlacement, "placement"); 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/NumericLiteral.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using SQLGeneration.Parsing; 4 | 5 | namespace SQLGeneration.Builders 6 | { 7 | /// 8 | /// Represents a numeric literal. 9 | /// 10 | public class NumericLiteral : Literal 11 | { 12 | /// 13 | /// Initializes a new instance of a NumericLiteral. 14 | /// 15 | public NumericLiteral() 16 | { 17 | } 18 | 19 | /// 20 | /// Initializes a new instance of a NumericLiteral. 21 | /// 22 | /// The value to make the literal. 23 | public NumericLiteral(double value) 24 | { 25 | Value = value; 26 | } 27 | 28 | /// 29 | /// Gets or sets the numeric value of the literal. 30 | /// 31 | public double Value 32 | { 33 | get; 34 | set; 35 | } 36 | 37 | /// 38 | /// Gets or sets the format to represent the value with. 39 | /// 40 | public string Format 41 | { 42 | get; 43 | set; 44 | } 45 | 46 | /// 47 | /// Provides information to the given visitor about the current builder. 48 | /// 49 | /// The visitor requesting information. 50 | protected override void OnAccept(BuilderVisitor visitor) 51 | { 52 | visitor.VisitNumericLiteral(this); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/OrderBy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents an item in the order by clause of a select statement. 8 | /// 9 | public class OrderBy : IVisitableBuilder 10 | { 11 | /// 12 | /// Initializes a new instance of a OrderBy. 13 | /// 14 | /// The item to sort by. 15 | /// The order in which to sort the items. 16 | /// The placement of nulls in the results. 17 | public OrderBy( 18 | AliasedProjection projection, 19 | Order order = Order.Default, 20 | NullPlacement nullPlacement = NullPlacement.Default) 21 | { 22 | if (projection == null) 23 | { 24 | throw new ArgumentNullException("projection"); 25 | } 26 | Projection = projection; 27 | Order = order; 28 | NullPlacement = nullPlacement; 29 | } 30 | 31 | /// 32 | /// Initializes a new instance of a OrderBy. 33 | /// 34 | /// The item to sort by. 35 | /// The order in which to sort the items. 36 | /// The placement of nulls in the results. 37 | public OrderBy( 38 | IProjectionItem projection, 39 | Order order = Order.Default, 40 | NullPlacement nullPlacement = NullPlacement.Default) 41 | { 42 | if (projection == null) 43 | { 44 | throw new ArgumentNullException("projection"); 45 | } 46 | Projection = new AliasedProjection(projection, null); 47 | Order = order; 48 | NullPlacement = nullPlacement; 49 | } 50 | 51 | /// 52 | /// Gets the item to order by. 53 | /// 54 | public AliasedProjection Projection 55 | { 56 | get; 57 | private set; 58 | } 59 | 60 | /// 61 | /// Gets or sets the order to sort the results. 62 | /// 63 | public Order Order 64 | { 65 | get; 66 | set; 67 | } 68 | 69 | /// 70 | /// Specifies where null values appear in the results. 71 | /// 72 | public NullPlacement NullPlacement 73 | { 74 | get; 75 | set; 76 | } 77 | 78 | void IVisitableBuilder.Accept(BuilderVisitor visitor) 79 | { 80 | visitor.VisitOrderBy(this); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/OrderConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | using SQLGeneration.Properties; 4 | 5 | namespace SQLGeneration.Builders 6 | { 7 | /// 8 | /// Specifies the order that results are sorted. 9 | /// 10 | public enum Order 11 | { 12 | /// 13 | /// Sorts the result using the default ordering. 14 | /// 15 | Default, 16 | /// 17 | /// Sort the results in ascending order. 18 | /// 19 | Ascending, 20 | /// 21 | /// Sorts the results in descending order. 22 | /// 23 | Descending 24 | } 25 | 26 | /// 27 | /// Converts between representations of the Order enum. 28 | /// 29 | internal class OrderConverter 30 | { 31 | /// 32 | /// Initializes a new instance of a OrderConverter. 33 | /// 34 | public OrderConverter() 35 | { 36 | } 37 | 38 | /// 39 | /// Gets the string representation of an Order enum. 40 | /// 41 | /// The value of the enum. 42 | /// The string representation. 43 | public string ToString(Order order) 44 | { 45 | switch (order) 46 | { 47 | case Order.Ascending: 48 | return "ASC"; 49 | case Order.Descending: 50 | return "DESC"; 51 | default: 52 | throw new ArgumentException(Resources.UnknownOrder, "order"); 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/OrderFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents a filter that checks that a value is less than, greater than or equal to. 8 | /// 9 | public abstract class OrderFilter : Filter, IComparisonFilter 10 | { 11 | private readonly IFilterItem _leftHand; 12 | private readonly IFilterItem _rightHand; 13 | 14 | /// 15 | /// Initializes a new instance of a OrderFilter. 16 | /// 17 | /// The left hand side of the comparison. 18 | /// The right hand side of the comparison. 19 | protected OrderFilter(IFilterItem leftHand, IFilterItem rightHand) 20 | { 21 | if (leftHand == null) 22 | { 23 | throw new ArgumentNullException("leftHand"); 24 | } 25 | if (rightHand == null) 26 | { 27 | throw new ArgumentNullException("rightHand"); 28 | } 29 | _leftHand = leftHand; 30 | _rightHand = rightHand; 31 | } 32 | 33 | /// 34 | /// Gets the left hand operand of the filter. 35 | /// 36 | public IFilterItem LeftHand 37 | { 38 | get { return _leftHand; } 39 | } 40 | 41 | /// 42 | /// Gets the right hand operand of the comparison. 43 | /// 44 | public IFilterItem RightHand 45 | { 46 | get { return _rightHand; } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/Placeholder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Acts as a placeholder anywhere within the options of a SQL statement. 8 | /// 9 | public class Placeholder : IProjectionItem, IFilterItem, IGroupByItem 10 | { 11 | /// 12 | /// Initializes a new instance of a Placeholder. 13 | /// 14 | /// The value of the placeholder. 15 | public Placeholder(string value) 16 | { 17 | Value = value; 18 | } 19 | 20 | /// 21 | /// Gets the value of the placeholder. 22 | /// 23 | public string Value 24 | { 25 | get; 26 | private set; 27 | } 28 | 29 | void IVisitableBuilder.Accept(BuilderVisitor visitor) 30 | { 31 | visitor.VisitPlaceholder(this); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/PrecedingBoundFrame.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Describes a window frame that is limited to a specific number of rows preceding in one direction. 8 | /// 9 | public class PrecedingBoundFrame : BoundFrame, IPrecedingFrame 10 | { 11 | /// 12 | /// Initializes a new instance of a PrecedingBoundFrame. 13 | /// 14 | /// The limit to the number of rows to include in the frame. 15 | public PrecedingBoundFrame(int rowCount) 16 | : base(rowCount) 17 | { 18 | } 19 | 20 | /// 21 | /// Provides information to the given visitor about the current builder. 22 | /// 23 | /// The visitor requesting information. 24 | protected override void OnAccept(BuilderVisitor visitor) 25 | { 26 | visitor.VisitPrecedingBoundFrame(this); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/PrecedingOnlyWindowFrame.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Defines the limits of a function window whose frame ranges before the current row. 8 | /// 9 | public class PrecedingOnlyWindowFrame : WindowFrame 10 | { 11 | /// 12 | /// Initializes a new instance of a PrecedingOnlyWindowFrame. 13 | /// 14 | /// The object describing the preceding frame. 15 | public PrecedingOnlyWindowFrame(IPrecedingFrame precedingFrame) 16 | { 17 | if (precedingFrame == null) 18 | { 19 | throw new ArgumentNullException("precedingFrame"); 20 | } 21 | PrecedingFrame = precedingFrame; 22 | } 23 | 24 | /// 25 | /// Gets the preceding window frame. 26 | /// 27 | public IPrecedingFrame PrecedingFrame 28 | { 29 | get; 30 | private set; 31 | } 32 | 33 | /// 34 | /// Provides information to the given visitor about the current builder. 35 | /// 36 | /// The visitor requesting information. 37 | protected override void OnAccept(BuilderVisitor visitor) 38 | { 39 | visitor.VisitPrecedingOnlyWindowFrame(this); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/PrecedingUnboundFrame.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Describes a window frame that is unbounded in one direction. 8 | /// 9 | public class PrecedingUnboundFrame : UnboundFrame, IPrecedingFrame 10 | { 11 | /// 12 | /// Initializes a new instance of an PrecedingUnboundFrame. 13 | /// 14 | public PrecedingUnboundFrame() 15 | { 16 | } 17 | 18 | /// 19 | /// Provides information to the given visitor about the current builder. 20 | /// 21 | /// The visitor requesting information. 22 | protected override void OnAccept(BuilderVisitor visitor) 23 | { 24 | visitor.VisitPrecedingUnboundFrame(this); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/QuantifierConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | using SQLGeneration.Properties; 4 | 5 | namespace SQLGeneration.Builders 6 | { 7 | /// 8 | /// Represents how a value will be compared to a set of values. 9 | /// 10 | public enum Quantifier 11 | { 12 | /// 13 | /// Specifies that a predicate must be satisfied for all values in a set. 14 | /// 15 | All, 16 | /// 17 | /// Specifies that a predicate must be satisfied for at least one value in a set. 18 | /// 19 | Any, 20 | /// 21 | /// Specifies that a predicate must be satisfied for at least one value in a set. 22 | /// 23 | Some, 24 | } 25 | 26 | /// 27 | /// Converts between representation of quantifiers. 28 | /// 29 | internal sealed class QuantifierConverter 30 | { 31 | /// 32 | /// Initializes a new instance of a QuantifierConverter. 33 | /// 34 | public QuantifierConverter() 35 | { 36 | } 37 | 38 | /// 39 | /// Converts the given quantifier to its string equivalent. 40 | /// 41 | /// The valeu to convert to a string. 42 | /// The token representing the quantifier. 43 | public string ToString(Quantifier quantifier) 44 | { 45 | switch (quantifier) 46 | { 47 | case Quantifier.All: 48 | return "ALL"; 49 | case Quantifier.Any: 50 | return "ANY"; 51 | case Quantifier.Some: 52 | return "SOME"; 53 | default: 54 | throw new ArgumentException(Resources.UnknownQuantifier, "quantifier"); 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/QuantifierFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents a filter that performs a univeral or existential comparison. 8 | /// 9 | public abstract class QuantifierFilter : Filter 10 | { 11 | /// 12 | /// Initializes a new insstance of a QuantifierFilter. 13 | /// 14 | /// The value being compared to the set of values. 15 | /// The quantifier to use to compare the value to the set of values. 16 | /// The source of values. 17 | protected QuantifierFilter(IFilterItem leftHand, Quantifier quantifier, IValueProvider valueProvider) 18 | { 19 | if (leftHand == null) 20 | { 21 | throw new ArgumentNullException("leftHand"); 22 | } 23 | if (valueProvider == null) 24 | { 25 | throw new ArgumentNullException("valueProvider"); 26 | } 27 | LeftHand = leftHand; 28 | Quantifier = quantifier; 29 | ValueProvider = valueProvider; 30 | } 31 | 32 | /// 33 | /// Gets the value being compared to the set of values. 34 | /// 35 | public IFilterItem LeftHand 36 | { 37 | get; 38 | private set; 39 | } 40 | 41 | /// 42 | /// Gets the quantifier being used to compare the items. 43 | /// 44 | public Quantifier Quantifier 45 | { 46 | get; 47 | private set; 48 | } 49 | 50 | /// 51 | /// Gets the source of the values. 52 | /// 53 | public IValueProvider ValueProvider 54 | { 55 | get; 56 | private set; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/RightOuterJoin.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using SQLGeneration.Parsing; 4 | 5 | namespace SQLGeneration.Builders 6 | { 7 | /// 8 | /// Represents an right-outer join in a select statement. 9 | /// 10 | public class RightOuterJoin : FilteredJoin 11 | { 12 | /// 13 | /// Initializes a new instance of a RightOuterJoin. 14 | /// 15 | /// The left hand item in the join. 16 | /// The right hand table in the join. 17 | internal RightOuterJoin(Join leftHand, AliasedSource rightHand) 18 | : base(leftHand, rightHand) 19 | { 20 | } 21 | 22 | /// 23 | /// Provides information to the given visitor about the current builder. 24 | /// 25 | /// The visitor requesting information. 26 | protected override void OnAccept(BuilderVisitor visitor) 27 | { 28 | visitor.VisitRightOuterJoin(this); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/SelectCombiner.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using SQLGeneration.Parsing; 4 | 5 | namespace SQLGeneration.Builders 6 | { 7 | /// 8 | /// Performs a set operation on the results of two queries. 9 | /// 10 | public abstract class SelectCombiner : ISelectBuilder 11 | { 12 | private readonly ISelectBuilder leftHand; 13 | private readonly ISelectBuilder rightHand; 14 | private readonly List orderBy; 15 | 16 | /// 17 | /// Initializes a new instance of a SelectCombiner. 18 | /// 19 | protected SelectCombiner(ISelectBuilder leftHand, ISelectBuilder rightHand) 20 | { 21 | if (leftHand == null) 22 | { 23 | throw new ArgumentNullException("leftHand"); 24 | } 25 | if (rightHand == null) 26 | { 27 | throw new ArgumentNullException("rightHand"); 28 | } 29 | this.leftHand = leftHand; 30 | this.rightHand = rightHand; 31 | this.orderBy = new List(); 32 | } 33 | 34 | /// 35 | /// Gets the SELECT command on the left side. 36 | /// 37 | public ISelectBuilder LeftHand 38 | { 39 | get { return leftHand; } 40 | } 41 | 42 | /// 43 | /// Gets the SELECT comman on the right side. 44 | /// 45 | public ISelectBuilder RightHand 46 | { 47 | get { return rightHand; } 48 | } 49 | 50 | /// 51 | /// Gets the distinct qualifier for the combiner. 52 | /// 53 | public DistinctQualifier Distinct 54 | { 55 | get; 56 | set; 57 | } 58 | 59 | SourceCollection ISelectBuilder.Sources 60 | { 61 | get { return new SourceCollection(); } 62 | } 63 | 64 | List ISelectBuilder.OrderByList 65 | { 66 | get { return orderBy; } 67 | } 68 | 69 | /// 70 | /// Gets the items used to sort the results. 71 | /// 72 | public IEnumerable OrderBy 73 | { 74 | get { return orderBy; } 75 | } 76 | 77 | /// 78 | /// Adds a sort criteria to the query. 79 | /// 80 | /// The sort criteria to add. 81 | public void AddOrderBy(OrderBy item) 82 | { 83 | if (item == null) 84 | { 85 | throw new ArgumentNullException("item"); 86 | } 87 | orderBy.Add(item); 88 | } 89 | 90 | /// 91 | /// Removes the sort criteria from the query. 92 | /// 93 | /// The order by item to remove. 94 | /// True if the item was removed; otherwise, false. 95 | public bool RemoveOrderBy(OrderBy item) 96 | { 97 | if (item == null) 98 | { 99 | throw new ArgumentNullException("item"); 100 | } 101 | return orderBy.Remove(item); 102 | } 103 | 104 | string IRightJoinItem.GetSourceName() 105 | { 106 | return null; 107 | } 108 | 109 | bool IRightJoinItem.IsAliasRequired 110 | { 111 | get { return true; } 112 | } 113 | 114 | bool IValueProvider.IsValueList 115 | { 116 | get { return false; } 117 | } 118 | 119 | void IVisitableBuilder.Accept(BuilderVisitor visitor) 120 | { 121 | OnAccept(visitor); 122 | } 123 | 124 | /// 125 | /// Provides information to the given visitor about the current builder. 126 | /// 127 | /// The visitor requesting information. 128 | protected abstract void OnAccept(BuilderVisitor visitor); 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/Setter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Adds a column being set to a value to the command. 8 | /// 9 | public class Setter : IVisitableBuilder 10 | { 11 | private readonly Column _column; 12 | private readonly IProjectionItem _value; 13 | 14 | /// 15 | /// Initializes a new instance of a Setter. 16 | /// 17 | /// The name of the column to set. 18 | /// The value to set the column to. 19 | public Setter(Column column, IProjectionItem value) 20 | { 21 | if (column == null) 22 | { 23 | throw new ArgumentNullException("column"); 24 | } 25 | if (value == null) 26 | { 27 | throw new ArgumentNullException("value"); 28 | } 29 | _column = column; 30 | _value = value; 31 | } 32 | 33 | /// 34 | /// Gets the column being set. 35 | /// 36 | public Column Column 37 | { 38 | get { return _column; } 39 | } 40 | 41 | /// 42 | /// Gets the value that the column is being set to. 43 | /// 44 | public IProjectionItem Value 45 | { 46 | get { return _value; } 47 | } 48 | 49 | void IVisitableBuilder.Accept(BuilderVisitor visitor) 50 | { 51 | visitor.VisitSetter(this); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/SourceCollection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using SQLGeneration.Properties; 5 | 6 | namespace SQLGeneration.Builders 7 | { 8 | /// 9 | /// Holds all of the sources that occur within a SELECT statement. 10 | /// 11 | public class SourceCollection 12 | { 13 | private readonly Dictionary sourceLookup; 14 | 15 | /// 16 | /// Initializes a new instance of a SourceCollection. 17 | /// 18 | internal SourceCollection() 19 | { 20 | sourceLookup = new Dictionary(StringComparer.InvariantCultureIgnoreCase); 21 | } 22 | 23 | /// 24 | /// Initializes a new instance of a SourceCollection, copying the values 25 | /// from the given source collection. 26 | /// 27 | /// The source collection to copy the value from. 28 | internal SourceCollection(SourceCollection other) 29 | { 30 | sourceLookup = new Dictionary(other.sourceLookup, StringComparer.InvariantCultureIgnoreCase); 31 | } 32 | 33 | /// 34 | /// Adds the given source, associating it with the given source name. 35 | /// 36 | /// The name to associate with the source. 37 | /// The source to add. 38 | internal void AddSource(string sourceName, AliasedSource source) 39 | { 40 | if (sourceName == null) 41 | { 42 | return; 43 | } 44 | if (sourceLookup.ContainsKey(sourceName)) 45 | { 46 | string message = String.Format(CultureInfo.CurrentCulture, Resources.DuplicateSourceName, sourceName); 47 | throw new SQLGenerationException(message); 48 | } 49 | sourceLookup.Add(sourceName, source); 50 | } 51 | 52 | /// 53 | /// Adds all of the sources from the given collection to the current collection. 54 | /// 55 | /// The other source collection to add item from. 56 | internal void AddSources(SourceCollection other) 57 | { 58 | foreach (KeyValuePair pair in other.sourceLookup) 59 | { 60 | AddSource(pair.Key, pair.Value); 61 | } 62 | } 63 | 64 | /// 65 | /// Gets the source with the given name or alias. 66 | /// 67 | /// The name or alias of the source. 68 | /// The source with the given name or alias. 69 | public AliasedSource this[string sourceName] 70 | { 71 | get 72 | { 73 | AliasedSource source; 74 | if (!sourceLookup.TryGetValue(sourceName, out source)) 75 | { 76 | string message = String.Format(Resources.UnknownSource, sourceName); 77 | throw new SQLGenerationException(message); 78 | } 79 | return source; 80 | } 81 | } 82 | 83 | /// 84 | /// Gets the number of sources in the source collection. 85 | /// 86 | internal int Count 87 | { 88 | get { return sourceLookup.Count; } 89 | } 90 | 91 | /// 92 | /// Gets the aliased sources in the collection. 93 | /// 94 | internal IEnumerable Sources 95 | { 96 | get { return sourceLookup.Values; } 97 | } 98 | 99 | /// 100 | /// Gets whether a source exists with the given name. 101 | /// 102 | /// The name of the source. 103 | /// True if the source exists; otherwise, false. 104 | internal bool Exists(string sourceName) 105 | { 106 | return sourceLookup.ContainsKey(sourceName); 107 | } 108 | 109 | /// 110 | /// Removes the source with the given name. 111 | /// 112 | /// The name of the source to remove. 113 | /// True if the source is removed; otherwise, false. 114 | internal bool Remove(string sourceName) 115 | { 116 | return sourceLookup.Remove(sourceName); 117 | } 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/StringLiteral.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using SQLGeneration.Parsing; 4 | 5 | namespace SQLGeneration.Builders 6 | { 7 | /// 8 | /// Represents a literal string. 9 | /// 10 | public class StringLiteral : Literal 11 | { 12 | /// 13 | /// Initializes a new instance of a StringLiteral. 14 | /// 15 | public StringLiteral() 16 | { 17 | Value = String.Empty; 18 | } 19 | 20 | /// 21 | /// Initializes a new instance of a StringLiteral. 22 | /// 23 | /// The string value. 24 | public StringLiteral(string value) 25 | { 26 | Value = value; 27 | } 28 | 29 | /// 30 | /// Gets or sets the value of the string literal. 31 | /// 32 | public string Value 33 | { 34 | get; 35 | set; 36 | } 37 | 38 | /// 39 | /// Provides information to the given visitor about the current builder. 40 | /// 41 | /// The visitor requesting information. 42 | protected override void OnAccept(BuilderVisitor visitor) 43 | { 44 | visitor.VisitStringLiteral(this); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/Subtraction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Represents the substraction of two items in a command. 8 | /// 9 | public class Subtraction : ArithmeticExpression 10 | { 11 | /// 12 | /// Initializes a new instance of a Subtraction. 13 | /// 14 | /// The left hand side of the expression. 15 | /// The right hand side of the expression. 16 | public Subtraction(IProjectionItem leftHand, IProjectionItem rightHand) 17 | : base(leftHand, rightHand) 18 | { 19 | } 20 | 21 | /// 22 | /// Provides information to the given visitor about the current builder. 23 | /// 24 | /// The visitor requesting information. 25 | protected override void OnAccept(BuilderVisitor visitor) 26 | { 27 | visitor.VisitSubtraction(this); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/Table.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | using SQLGeneration.Properties; 4 | 5 | namespace SQLGeneration.Builders 6 | { 7 | /// 8 | /// Provides a table name. 9 | /// 10 | public class Table : IRightJoinItem 11 | { 12 | /// 13 | /// Initializes a new instance of a Table. 14 | /// 15 | /// The name of the table. 16 | public Table(string name) 17 | : this(null, name) 18 | { 19 | } 20 | 21 | /// 22 | /// Initializes a new instance of a Table. 23 | /// 24 | /// The schema the table belongs to. 25 | /// The name of the table. 26 | public Table(Namespace qualifier, string name) 27 | { 28 | if (String.IsNullOrWhiteSpace(name)) 29 | { 30 | throw new ArgumentException(Resources.BlankTableName, "name"); 31 | } 32 | Qualifier = qualifier; 33 | Name = name; 34 | } 35 | 36 | /// 37 | /// Gets or sets the schema the table belongs to. 38 | /// 39 | public Namespace Qualifier 40 | { 41 | get; 42 | private set; 43 | } 44 | 45 | /// 46 | /// Gets the name of the table. 47 | /// 48 | public string Name 49 | { 50 | get; 51 | private set; 52 | } 53 | 54 | string IRightJoinItem.GetSourceName() 55 | { 56 | return Name; 57 | } 58 | 59 | bool IRightJoinItem.IsAliasRequired 60 | { 61 | get { return false; } 62 | } 63 | 64 | void IVisitableBuilder.Accept(BuilderVisitor visitor) 65 | { 66 | visitor.VisitTable(this); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/Top.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Builds a TOP clause that is found in a SELECT statement. 8 | /// 9 | public class Top : IVisitableBuilder 10 | { 11 | private readonly IProjectionItem _expression; 12 | 13 | /// 14 | /// Initializes a new instance of a Top. 15 | /// 16 | /// The number or percent of items to return. 17 | public Top(IProjectionItem expression) 18 | { 19 | if (expression == null) 20 | { 21 | throw new ArgumentNullException("expression"); 22 | } 23 | _expression = expression; 24 | } 25 | 26 | /// 27 | /// Gets the expression representing the number or percent of rows to return. 28 | /// 29 | public IProjectionItem Expression 30 | { 31 | get 32 | { 33 | return _expression; 34 | } 35 | } 36 | 37 | /// 38 | /// Gets whether or not the expression represents a percent. 39 | /// 40 | public bool IsPercent 41 | { 42 | get; 43 | set; 44 | } 45 | 46 | /// 47 | /// Gets or sets whether records matching the last item according to the order by 48 | /// clause shall be returned. 49 | /// 50 | public bool WithTies 51 | { 52 | get; 53 | set; 54 | } 55 | 56 | void IVisitableBuilder.Accept(BuilderVisitor visitor) 57 | { 58 | visitor.VisitTop(this); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/UnboundFrame.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Describes a window frame that is unbounded in one direction. 8 | /// 9 | public abstract class UnboundFrame : IVisitableBuilder 10 | { 11 | /// 12 | /// Initializes a new instance of an UnboundFrame. 13 | /// 14 | protected UnboundFrame() 15 | { 16 | } 17 | 18 | void IVisitableBuilder.Accept(BuilderVisitor visitor) 19 | { 20 | OnAccept(visitor); 21 | } 22 | 23 | /// 24 | /// Provides information to the given visitor about the current builder. 25 | /// 26 | /// The visitor requesting information. 27 | protected abstract void OnAccept(BuilderVisitor visitor); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/Union.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Unions the items from the first query to the second. 8 | /// 9 | public class Union : SelectCombiner 10 | { 11 | /// 12 | /// Initializes a new instance of a Union. 13 | /// 14 | /// The left hand SELECT command. 15 | /// The right hand SELECT command. 16 | public Union(ISelectBuilder leftHand, ISelectBuilder rightHand) 17 | : base(leftHand, rightHand) 18 | { 19 | } 20 | 21 | /// 22 | /// Provides information to the given visitor about the current builder. 23 | /// 24 | /// The visitor requesting information. 25 | protected override void OnAccept(BuilderVisitor visitor) 26 | { 27 | visitor.VisitUnion(this); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/UpdateBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using SQLGeneration.Parsing; 4 | using SQLGeneration.Properties; 5 | 6 | namespace SQLGeneration.Builders 7 | { 8 | /// 9 | /// Builds a string of an update statement. 10 | /// 11 | public class UpdateBuilder : IFilteredCommand 12 | { 13 | private readonly AliasedSource _table; 14 | private readonly IList _setters; 15 | private readonly FilterGroup _where; 16 | 17 | /// 18 | /// Initializes a new instance of a UpdateBuilder. 19 | /// 20 | /// The table being updated. 21 | /// The alias to use to refer to the table. 22 | public UpdateBuilder(Table table, string alias = null) 23 | { 24 | if (table == null) 25 | { 26 | throw new ArgumentNullException("table"); 27 | } 28 | _table = new AliasedSource(table, alias); 29 | _setters = new List(); 30 | _where = new FilterGroup(); 31 | } 32 | 33 | /// 34 | /// Gets the table that is being updated. 35 | /// 36 | public AliasedSource Table 37 | { 38 | get { return _table; } 39 | } 40 | 41 | /// 42 | /// Gets the columns that are being set. 43 | /// 44 | public IEnumerable Setters 45 | { 46 | get { return _setters; } 47 | } 48 | 49 | /// 50 | /// Adds the setter to the update statement. 51 | /// 52 | /// The setter to add. 53 | public void AddSetter(Setter setter) 54 | { 55 | if (setter == null) 56 | { 57 | throw new ArgumentNullException("setter"); 58 | } 59 | _setters.Add(setter); 60 | } 61 | 62 | /// 63 | /// Removes the setter from the update statement. 64 | /// 65 | /// The setter to remove. 66 | /// True if the setter is removed; otherwise, false. 67 | public bool RemoveSetter(Setter setter) 68 | { 69 | if (setter == null) 70 | { 71 | throw new ArgumentNullException("setter"); 72 | } 73 | return _setters.Remove(setter); 74 | } 75 | 76 | /// 77 | /// Gets the filters in the where clause. 78 | /// 79 | public IEnumerable Where 80 | { 81 | get { return _where.Filters; } 82 | } 83 | 84 | /// 85 | /// Gets the filter group used to build the where clause. 86 | /// 87 | public FilterGroup WhereFilterGroup 88 | { 89 | get { return _where; } 90 | } 91 | 92 | /// 93 | /// Adds the filter to the where clause. 94 | /// 95 | /// The filter to add. 96 | public void AddWhere(IFilter filter) 97 | { 98 | _where.AddFilter(filter); 99 | } 100 | 101 | /// 102 | /// Removes the filter from the where clause. 103 | /// 104 | /// The filter to remove. 105 | /// True if the filter was removed; otherwise, false. 106 | public bool RemoveWhere(IFilter filter) 107 | { 108 | return _where.RemoveFilter(filter); 109 | } 110 | 111 | void IVisitableBuilder.Accept(BuilderVisitor visitor) 112 | { 113 | visitor.VisitUpdate(this); 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/ValueList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using SQLGeneration.Parsing; 5 | 6 | namespace SQLGeneration.Builders 7 | { 8 | /// 9 | /// Provides a list of values that can appear in an 'in' comparison. 10 | /// 11 | public class ValueList : IValueProvider 12 | { 13 | private readonly List _values; 14 | 15 | /// 16 | /// Initializes a new instance of a InList. 17 | /// 18 | public ValueList() 19 | { 20 | _values = new List(); 21 | } 22 | 23 | /// 24 | /// Initializes a new instance of a InList. 25 | /// 26 | /// The values to add to the list. 27 | public ValueList(params IProjectionItem[] values) 28 | { 29 | if (values == null) 30 | { 31 | throw new ArgumentNullException("values"); 32 | } 33 | _values = new List(); 34 | foreach (IProjectionItem value in values) 35 | { 36 | AddValue(value); 37 | } 38 | } 39 | 40 | /// 41 | /// Gets the values being provided. 42 | /// 43 | public IEnumerable Values 44 | { 45 | get { return _values; } 46 | } 47 | 48 | /// 49 | /// Adds the given projection item to the values list. 50 | /// 51 | /// The value to add. 52 | public void AddValue(IProjectionItem item) 53 | { 54 | if (item == null) 55 | { 56 | throw new ArgumentNullException("item"); 57 | } 58 | _values.Add(item); 59 | } 60 | 61 | /// 62 | /// Adds the given projection item from the values list. 63 | /// 64 | /// The item to remove. 65 | /// True if the item was removed; otherwise, false. 66 | public bool RemoveValue(IProjectionItem item) 67 | { 68 | if (item == null) 69 | { 70 | throw new ArgumentNullException("item"); 71 | } 72 | return _values.Remove(item); 73 | } 74 | 75 | bool IValueProvider.IsValueList 76 | { 77 | get { return true; } 78 | } 79 | 80 | void IVisitableBuilder.Accept(BuilderVisitor visitor) 81 | { 82 | visitor.VisitValueList(this); 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /SQLGeneration/Builders/WindowFrame.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Builders 5 | { 6 | /// 7 | /// Defines the limits of a function window. 8 | /// 9 | public abstract class WindowFrame : IVisitableBuilder 10 | { 11 | /// 12 | /// Initializes a new instance of a WindowFrame. 13 | /// 14 | protected WindowFrame() 15 | { 16 | } 17 | 18 | /// 19 | /// Gets or sets which keyword to use for the frame. 20 | /// 21 | public FrameType FrameType { get; set; } 22 | 23 | void IVisitableBuilder.Accept(BuilderVisitor visitor) 24 | { 25 | OnAccept(visitor); 26 | } 27 | 28 | /// 29 | /// Provides information to the given visitor about the current builder. 30 | /// 31 | /// The visitor requesting information. 32 | protected abstract void OnAccept(BuilderVisitor visitor); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /SQLGeneration/Generators/CommandBuilderOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SQLGeneration.Generators 4 | { 5 | /// 6 | /// Provides options for customizing the behavior of the command builder. 7 | /// 8 | public class CommandBuilderOptions 9 | { 10 | /// 11 | /// Specifies a prefix that indicates an identifier is a placeholder. 12 | /// 13 | public string PlaceholderPrefix { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /SQLGeneration/Generators/Formatter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Text; 4 | using SQLGeneration.Builders; 5 | using SQLGeneration.Parsing; 6 | 7 | namespace SQLGeneration.Generators 8 | { 9 | /// 10 | /// Generates simple SQL from a token source. 11 | /// 12 | public sealed class Formatter 13 | { 14 | /// 15 | /// Initializes a new instance of a Formatter. 16 | /// 17 | public Formatter() 18 | { 19 | } 20 | 21 | /// 22 | /// Gets the command text. 23 | /// 24 | /// The command text. 25 | public string GetCommandText(ICommand command, CommandOptions options = null) 26 | { 27 | if (options == null) 28 | { 29 | options = new CommandOptions(); 30 | } 31 | StringWriter writer = new StringWriter(); 32 | FormattingVisitor visitor = new FormattingVisitor(writer, options); 33 | visitor.Visit(command); 34 | return writer.ToString(); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /SQLGeneration/Generators/SqlGenerator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SQLGeneration.Parsing; 3 | 4 | namespace SQLGeneration.Generators 5 | { 6 | /// 7 | /// Provides the methods that must be overridden in order to properly process SQL expressions. 8 | /// 9 | public abstract class SqlGenerator 10 | { 11 | private readonly SqlGrammar grammar; 12 | 13 | /// 14 | /// Initializes a new instance of a SqlResponder. 15 | /// 16 | /// The grammar to use. 17 | protected SqlGenerator(SqlGrammar grammar) 18 | { 19 | if (grammar == null) 20 | { 21 | grammar = SqlGrammar.Default; 22 | } 23 | this.grammar = grammar; 24 | } 25 | 26 | /// 27 | /// Gets the grammar. 28 | /// 29 | protected SqlGrammar Grammar 30 | { 31 | get { return grammar; } 32 | } 33 | 34 | /// 35 | /// Extracts expressions from the token stream and calls the corresponding handler. 36 | /// 37 | /// The source of SQL tokens. 38 | /// The results of the parse. 39 | protected MatchResult GetResult(ITokenSource tokenSource) 40 | { 41 | Parser parser = new Parser(grammar); 42 | return parser.Parse(SqlGrammar.Start.Name, tokenSource); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /SQLGeneration/Parsing/Expression.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SQLGeneration.Parsing 4 | { 5 | /// 6 | /// Represents a sub-expression made up of tokens and sub-expressions. 7 | /// 8 | public sealed class Expression : IExpressionItem 9 | { 10 | private readonly ExpressionDefinition expression; 11 | 12 | /// 13 | /// Initializes a new instance of an Expression. 14 | /// 15 | /// The sequence of tokens and sub-expressions expected to appear. 16 | internal Expression(ExpressionDefinition expression) 17 | { 18 | this.expression = expression; 19 | } 20 | 21 | /// 22 | /// Attempts to match the expression item with the values returned by the parser. 23 | /// 24 | /// The parser currently iterating over the token source. 25 | /// The name of the item in the outer expression. 26 | /// The results of the match. 27 | public MatchResult Match(IParseAttempt attempt, string itemName) 28 | { 29 | MatchResult result = new MatchResult() { ItemName = itemName, IsMatch = true }; 30 | foreach (ExpressionItem detail in expression.Items) 31 | { 32 | IParseAttempt nextAttempt = attempt.Attempt(); 33 | MatchResult innerResult = detail.Item.Match(nextAttempt, detail.ItemName); 34 | if (innerResult.IsMatch) 35 | { 36 | attempt.Accept(nextAttempt); 37 | result.Matches.Add(innerResult); 38 | } 39 | else 40 | { 41 | nextAttempt.Reject(); 42 | if (detail.IsRequired) 43 | { 44 | result.IsMatch = false; 45 | return result; 46 | } 47 | } 48 | } 49 | return result; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /SQLGeneration/Parsing/ExpressionDefinition.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace SQLGeneration.Parsing 5 | { 6 | /// 7 | /// Represents a sequence of tokens and sub-expressions. 8 | /// 9 | public sealed class ExpressionDefinition 10 | { 11 | private readonly List items; 12 | 13 | /// 14 | /// Initializes a new instance of an ExpressionDefinition. 15 | /// 16 | /// An optional identifier for the expression's type. 17 | internal ExpressionDefinition(string expressionType) 18 | { 19 | ExpressionType = expressionType; 20 | items = new List(); 21 | } 22 | 23 | /// 24 | /// Gets the type of the expression. 25 | /// 26 | public string ExpressionType 27 | { 28 | get; 29 | private set; 30 | } 31 | 32 | /// 33 | /// Indicates that the given expression is expected next, giving it a 34 | /// name and specifying whether it is required. 35 | /// 36 | /// The name that the expression will be identified with in the outer expression. 37 | /// Indicates whether the expression is required in order for the outer expression to be a match. 38 | /// The expression to add to the outer expressions. 39 | /// The updated definition. 40 | public ExpressionDefinition Add(string name, bool isRequired, Expression expression) 41 | { 42 | if (expression == null) 43 | { 44 | throw new ArgumentNullException("expression"); 45 | } 46 | items.Add(new ExpressionItem(name, isRequired, expression)); 47 | return this; 48 | } 49 | 50 | /// 51 | /// Indicates that the given options list is the next expected, giving it a 52 | /// name and specifying whether it is required. 53 | /// 54 | /// Indicates whether at least one of the options is required in order for the outer expression to be a match. 55 | /// The options to add to the outer expression. 56 | /// The updated definition. 57 | public ExpressionDefinition Add(bool isRequired, Options options) 58 | { 59 | if (options == null) 60 | { 61 | throw new ArgumentNullException("options"); 62 | } 63 | items.Add(new ExpressionItem(String.Empty, isRequired, options)); 64 | return this; 65 | } 66 | 67 | /// 68 | /// Indicates that the given token is the next expected, giving it a 69 | /// name and specifying whether it is required. 70 | /// 71 | /// The name that the token will be identified with in the outer expression. 72 | /// Indicates whether the token is required in order for the outer expression to be a match. 73 | /// The token to add to the outer expression. 74 | /// The updated definition. 75 | public ExpressionDefinition Add(string itemName, bool isRequired, Token token) 76 | { 77 | if (token == null) 78 | { 79 | throw new ArgumentNullException("token"); 80 | } 81 | items.Add(new ExpressionItem(itemName, isRequired, token)); 82 | return this; 83 | } 84 | 85 | /// 86 | /// Indicates that the given sub-expression is the next expected, giving it a 87 | /// name and specifying whether it is required. 88 | /// 89 | /// The name that the sub-expression will be identified with in the outer expression. 90 | /// Indicates whether the sub-expression is required in order for the expression to match. 91 | /// The definition for the sub-expression. 92 | /// The updated definition. 93 | public ExpressionDefinition Add(string itemName, bool isRequired, ExpressionDefinition definition) 94 | { 95 | if (definition == null) 96 | { 97 | throw new ArgumentNullException("definition"); 98 | } 99 | IExpressionItem item = new Expression(definition); 100 | items.Add(new ExpressionItem(itemName, isRequired, item)); 101 | return this; 102 | } 103 | 104 | /// 105 | /// Gets the items making up the expression. 106 | /// 107 | internal IEnumerable Items 108 | { 109 | get { return items; } 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /SQLGeneration/Parsing/ExpressionItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SQLGeneration.Parsing 4 | { 5 | /// 6 | /// Holds information descibing an expression or token's role in an outer expression. 7 | /// 8 | internal sealed class ExpressionItem 9 | { 10 | /// 11 | /// Initializes a new instance of an ExpressionItem. 12 | /// 13 | /// The name of the item. 14 | /// Specifies whether the item missing results in the outer expression not matching. 15 | /// The actual item that is expected. 16 | public ExpressionItem(string itemName, bool isRequired, IExpressionItem item) 17 | { 18 | ItemName = itemName; 19 | IsRequired = isRequired; 20 | Item = item; 21 | } 22 | 23 | /// 24 | /// Gets the name that the outer expression refers to the item with. 25 | /// 26 | public string ItemName 27 | { 28 | get; 29 | private set; 30 | } 31 | 32 | /// 33 | /// Gets whether the item is required in order for the outer expression to match. 34 | /// 35 | public bool IsRequired 36 | { 37 | get; 38 | private set; 39 | } 40 | 41 | /// 42 | /// Gets the item. 43 | /// 44 | public IExpressionItem Item 45 | { 46 | get; 47 | private set; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /SQLGeneration/Parsing/Grammar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using SQLGeneration.Properties; 4 | 5 | namespace SQLGeneration.Parsing 6 | { 7 | /// 8 | /// Specifies the expressions making up a syntax. 9 | /// 10 | public class Grammar 11 | { 12 | private readonly TokenRegistry tokenRegistry; 13 | private readonly Dictionary expressionLookup; 14 | 15 | /// 16 | /// Initializes a new instance of a Grammar, initially empty. 17 | /// 18 | /// The token registry to use to verify referenced tokens types are defined. 19 | public Grammar(TokenRegistry tokenRegistry) 20 | { 21 | this.tokenRegistry = tokenRegistry; 22 | this.expressionLookup = new Dictionary(); 23 | } 24 | 25 | /// 26 | /// Gets the token registery being used. 27 | /// 28 | public TokenRegistry TokenRegistry 29 | { 30 | get { return tokenRegistry; } 31 | } 32 | 33 | /// 34 | /// Gets the definitions comprising the grammar. 35 | /// 36 | public IEnumerable Definitions 37 | { 38 | get { return expressionLookup.Values; } 39 | } 40 | 41 | /// 42 | /// Creates a sub-expression definition. 43 | /// 44 | /// The expression definition to allow for configuration. 45 | public ExpressionDefinition Define() 46 | { 47 | ExpressionDefinition definition = new ExpressionDefinition(null); 48 | return definition; 49 | } 50 | 51 | /// 52 | /// Creates or retrieves the expression definition associated with the given name. 53 | /// 54 | /// The identifier to use to refer to the expression type later. 55 | /// The expression definition to allow for configuration. 56 | public ExpressionDefinition Define(string type) 57 | { 58 | if (String.IsNullOrWhiteSpace(type)) 59 | { 60 | throw new ArgumentException(Resources.BlankExpressionType, "type"); 61 | } 62 | ExpressionDefinition definition; 63 | if (!expressionLookup.TryGetValue(type, out definition)) 64 | { 65 | definition = new ExpressionDefinition(type); 66 | expressionLookup.Add(type, definition); 67 | } 68 | return definition; 69 | } 70 | 71 | /// 72 | /// Gets a placeholder to indicate that a token is expected next in an expression. 73 | /// 74 | /// The type of the token that is expected. 75 | /// The token placeholder. 76 | public Token Token(string tokenName) 77 | { 78 | if (String.IsNullOrWhiteSpace(tokenName) || !tokenRegistry.IsRegistered(tokenName)) 79 | { 80 | throw new ArgumentException(Resources.UnknownTokenType, "tokenName"); 81 | } 82 | return new Token(tokenName); 83 | } 84 | 85 | /// 86 | /// Gets a placeholder to indicate that a token is expected next in an expression. 87 | /// 88 | /// The type of the token that is expected. 89 | /// The expected value of the token. 90 | /// The token placeholder. 91 | public Token Token(string tokenName, string expectedValue) 92 | { 93 | if (String.IsNullOrWhiteSpace(tokenName) || !tokenRegistry.IsRegistered(tokenName)) 94 | { 95 | throw new ArgumentException(Resources.UnknownTokenType, "tokenName"); 96 | } 97 | if (String.IsNullOrWhiteSpace(expectedValue)) 98 | { 99 | throw new ArgumentException(Resources.BlankTokenValue, "expectedValue"); 100 | } 101 | return new Token(tokenName, expectedValue); 102 | } 103 | 104 | /// 105 | /// Gets a placeholder to indicate that one of many expressions is next in an expression. 106 | /// 107 | /// The options placeholder. 108 | public Options Options() 109 | { 110 | return new Options(); 111 | } 112 | 113 | /// 114 | /// Gets a placeholder to indicate that one of many expressions is next in an expression. 115 | /// 116 | /// The type of the expression for future reference. 117 | /// The options placeholder. 118 | public Expression Expression(string type) 119 | { 120 | ExpressionDefinition definition = Define(type); 121 | return new Expression(definition); 122 | } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /SQLGeneration/Parsing/IExpressionItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SQLGeneration.Parsing 4 | { 5 | /// 6 | /// Represents an item in a grammar expression. 7 | /// 8 | public interface IExpressionItem 9 | { 10 | /// 11 | /// Attempts to match the expression item with the values returned by the parser. 12 | /// 13 | /// The parser currently iterating over the token source. 14 | /// The name of the item in the outer expression. 15 | /// The results of the match. 16 | MatchResult Match(IParseAttempt parser, string itemName); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /SQLGeneration/Parsing/IParseAttempt.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace SQLGeneration.Parsing 5 | { 6 | /// 7 | /// Represents an attempt to parse an expression. 8 | /// 9 | public interface IParseAttempt 10 | { 11 | /// 12 | /// Gets the tokens that were collected during the attempt. 13 | /// 14 | List Tokens { get; } 15 | 16 | /// 17 | /// Attempts to get a token of the given type. 18 | /// 19 | /// The result of the search. 20 | TokenResult GetToken(); 21 | 22 | /// 23 | /// Creates an attempt to parse a child expression. 24 | /// 25 | /// A new attempt object. 26 | IParseAttempt Attempt(); 27 | 28 | /// 29 | /// Accepts the attempt as a successful parse, joining the given attempt's tokens 30 | /// with the current attempt's. 31 | /// 32 | /// The child attempt to accept. 33 | void Accept(IParseAttempt attempt); 34 | 35 | /// 36 | /// Rejects the attempt as a failed parse, returning the attempt's token 37 | /// to the token stream. 38 | /// 39 | void Reject(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /SQLGeneration/Parsing/ITokenRegistry.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SQLGeneration.Parsing 4 | { 5 | /// 6 | /// Indicates whether a token has been registered. 7 | /// 8 | public interface ITokenRegistry 9 | { 10 | /// 11 | /// Gets whether a token with the given name has been registered. 12 | /// 13 | /// The name of the token to search for. 14 | /// True if the token has been registered; otherwise, false. 15 | bool IsRegistered(string tokenName); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /SQLGeneration/Parsing/ITokenSource.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SQLGeneration.Parsing 4 | { 5 | /// 6 | /// Retrieves tokens and provides the ability to return them if they can't be used. 7 | /// 8 | public interface ITokenSource 9 | { 10 | /// 11 | /// Attempts to retrieve a token matching the definition associated 12 | /// with the given name. 13 | /// 14 | /// 15 | /// A result object describing the token that was found -or- null if no more tokens are found. 16 | /// 17 | TokenResult GetToken(); 18 | 19 | /// 20 | /// Restores the given token to the front of the token stream. 21 | /// 22 | /// The token to restore. 23 | void PutBack(TokenResult result); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /SQLGeneration/Parsing/MatchResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SQLGeneration.Parsing 4 | { 5 | /// 6 | /// Holds the result of trying to match an expression item. 7 | /// 8 | public sealed class MatchResult 9 | { 10 | private readonly MatchResultCollection matches; 11 | 12 | /// 13 | /// Initializes a new instance of a MatchResult. 14 | /// 15 | internal MatchResult() 16 | { 17 | matches = new MatchResultCollection(); 18 | } 19 | 20 | /// 21 | /// Gets the name of the item as it will be referred to in the outer expression. 22 | /// 23 | public string ItemName 24 | { 25 | get; 26 | internal set; 27 | } 28 | 29 | /// 30 | /// Gets whether the expression item was matched against the parser. 31 | /// 32 | public bool IsMatch 33 | { 34 | get; 35 | internal set; 36 | } 37 | 38 | /// 39 | /// Gets any information to be passed along with the match results. 40 | /// 41 | public object Context 42 | { 43 | get; 44 | internal set; 45 | } 46 | 47 | /// 48 | /// Gets the match result for sub-expressions or tokens within the current expression. 49 | /// This collection will be empty for tokens. 50 | /// 51 | public MatchResultCollection Matches 52 | { 53 | get { return matches; } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /SQLGeneration/Parsing/MatchResultCollection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace SQLGeneration.Parsing 5 | { 6 | /// 7 | /// Holds the match results of the items found under an expression item. 8 | /// 9 | public sealed class MatchResultCollection 10 | { 11 | private readonly Dictionary resultLookup; 12 | 13 | /// 14 | /// Initializes a new instance of a MatchResultCollection. 15 | /// 16 | internal MatchResultCollection() 17 | { 18 | resultLookup = new Dictionary(); 19 | } 20 | 21 | /// 22 | /// Associates the given result to its name. 23 | /// 24 | /// The match result of an item. 25 | internal void Add(MatchResult result) 26 | { 27 | resultLookup.Add(result.ItemName, result); 28 | } 29 | 30 | /// 31 | /// Gets the match result for the item with the given name. 32 | /// 33 | /// The name of the item to get the results for. 34 | /// The match result for the item with the given name -or- an empty MatchResult. 35 | public MatchResult this[string itemName] 36 | { 37 | get 38 | { 39 | MatchResult result; 40 | if (!resultLookup.TryGetValue(itemName, out result)) 41 | { 42 | result = new MatchResult() { ItemName = itemName, IsMatch = false }; 43 | } 44 | return result; 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /SQLGeneration/Parsing/Options.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace SQLGeneration.Parsing 5 | { 6 | /// 7 | /// Represents a list of possible expressions or tokens that the parser should try. 8 | /// 9 | public sealed class Options : IExpressionItem 10 | { 11 | private readonly List options; 12 | 13 | /// 14 | /// Initializes a new instance of an Options. 15 | /// 16 | internal Options() 17 | { 18 | options = new List(); 19 | } 20 | 21 | /// 22 | /// Gets the option items. 23 | /// 24 | internal IEnumerable Items 25 | { 26 | get { return options; } 27 | } 28 | 29 | /// 30 | /// Indicates that the given item is the next expected, giving it a 31 | /// name and specifying whether it is required. 32 | /// 33 | /// The name that the token will be identified with in the outer expression. 34 | /// The expression item to add to the sequence. 35 | /// The updated expression. 36 | public Options Add(string itemName, IExpressionItem item) 37 | { 38 | if (item == null) 39 | { 40 | throw new ArgumentNullException("item"); 41 | } 42 | options.Add(new ExpressionItem(itemName, false, item)); 43 | return this; 44 | } 45 | 46 | /// 47 | /// Indicates that the given sub-expression is the next expected, giving it a 48 | /// name and specifying whether it is required. 49 | /// 50 | /// The name that the token will be identified with in the outer expression. 51 | /// The definition for the sub-expression. 52 | /// The updated expression. 53 | public Options Add(string itemName, ExpressionDefinition definition) 54 | { 55 | if (definition == null) 56 | { 57 | throw new ArgumentNullException("definition"); 58 | } 59 | IExpressionItem item = new Expression(definition); 60 | options.Add(new ExpressionItem(itemName, false, item)); 61 | return this; 62 | } 63 | 64 | /// 65 | /// Attempts to match the expression item with the values returned by the parser. 66 | /// 67 | /// The parser currently iterating over the token source. 68 | /// This value will be empty for an options list. 69 | /// The results of the match. 70 | public MatchResult Match(IParseAttempt attempt, string itemName) 71 | { 72 | foreach (ExpressionItem option in options) 73 | { 74 | IParseAttempt nextAttempt = attempt.Attempt(); 75 | MatchResult innerResult = option.Item.Match(nextAttempt, option.ItemName); 76 | if (innerResult.IsMatch) 77 | { 78 | attempt.Accept(nextAttempt); 79 | return innerResult; 80 | } 81 | nextAttempt.Reject(); 82 | } 83 | return new MatchResult() { IsMatch = false }; 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /SQLGeneration/Parsing/Parser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using SQLGeneration.Properties; 4 | 5 | namespace SQLGeneration.Parsing 6 | { 7 | /// 8 | /// Parses a sequence of tokens using a grammar, applying actions to matching sequences. 9 | /// 10 | public sealed class Parser 11 | { 12 | private readonly Grammar grammar; 13 | 14 | /// 15 | /// Initializes a new instance of a Parser. 16 | /// 17 | /// The grammar to use. 18 | public Parser(Grammar grammar) 19 | { 20 | if (grammar == null) 21 | { 22 | throw new ArgumentNullException("grammar"); 23 | } 24 | this.grammar = grammar; 25 | } 26 | 27 | /// 28 | /// Parses the given token source using the specified grammar, starting with 29 | /// expression with the given name. 30 | /// 31 | /// The type of the expression to start parsing. 32 | /// The source of tokens. 33 | public MatchResult Parse(string expressionType, ITokenSource tokenSource) 34 | { 35 | if (tokenSource == null) 36 | { 37 | throw new ArgumentNullException("tokenSource"); 38 | } 39 | 40 | Expression expression = grammar.Expression(expressionType); 41 | ParseAttempt attempt = new ParseAttempt(this, tokenSource); 42 | MatchResult result = expression.Match(attempt, String.Empty); 43 | 44 | // check that there are no trailing tokens 45 | if (result.IsMatch && attempt.GetToken() != null) 46 | { 47 | result.IsMatch = false; 48 | } 49 | 50 | return result; 51 | } 52 | 53 | private sealed class ParseAttempt : IParseAttempt 54 | { 55 | private readonly Parser parser; 56 | private readonly ITokenSource tokenSource; 57 | private readonly List tokens; 58 | 59 | /// 60 | /// Initializes a new instance of a ParseAttempt. 61 | /// 62 | /// The parser containing 63 | /// An object to retrieve the sequence of tokens from. 64 | public ParseAttempt(Parser parser, ITokenSource tokenSource) 65 | { 66 | this.parser = parser; 67 | this.tokenSource = tokenSource; 68 | this.tokens = new List(); 69 | } 70 | 71 | /// 72 | /// Gets the tokens collected during the attempt. 73 | /// 74 | public List Tokens 75 | { 76 | get { return tokens; } 77 | } 78 | 79 | /// 80 | /// Attempts to get a token of the given type. 81 | /// 82 | /// The result of the search. 83 | public TokenResult GetToken() 84 | { 85 | TokenResult result = tokenSource.GetToken(); 86 | if (result != null) 87 | { 88 | tokens.Add(result); 89 | } 90 | return result; 91 | } 92 | 93 | /// 94 | /// Creates an attempt to parse a child expression. 95 | /// 96 | /// A new attempt object. 97 | public IParseAttempt Attempt() 98 | { 99 | return new ParseAttempt(parser, tokenSource); 100 | } 101 | 102 | /// 103 | /// Accepts the attempt as a successful parse, joining the given attempt's tokens 104 | /// with the current attempt's. 105 | /// 106 | /// The child attempt to accept. 107 | public void Accept(IParseAttempt attempt) 108 | { 109 | tokens.AddRange(attempt.Tokens); 110 | } 111 | 112 | /// 113 | /// Rejects the attempt as a failed parse, returning the attempt's token 114 | /// to the token stream. 115 | /// 116 | public void Reject() 117 | { 118 | int index = tokens.Count; 119 | while (index != 0) 120 | { 121 | --index; 122 | tokenSource.PutBack(tokens[index]); 123 | } 124 | } 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /SQLGeneration/Parsing/Token.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SQLGeneration.Parsing 4 | { 5 | /// 6 | /// Represents a token within an expression. 7 | /// 8 | public sealed class Token : IExpressionItem 9 | { 10 | /// 11 | /// Initializes a new instance of a Token. 12 | /// 13 | /// The type of the token that is expected. 14 | internal Token(string tokenName) 15 | : this(tokenName, null) 16 | { 17 | } 18 | 19 | /// 20 | /// Initializes a new instance of a Token. 21 | /// 22 | /// The type of the token that is expected. 23 | /// The expected value of the token. 24 | internal Token(string tokenName, string expectedValue) 25 | { 26 | TokenType = tokenName; 27 | ExpectedValue = expectedValue; 28 | } 29 | 30 | /// 31 | /// Gets the type of the token that is expected. 32 | /// 33 | public string TokenType 34 | { 35 | get; 36 | private set; 37 | } 38 | 39 | /// 40 | /// Gets the expected value of the token. 41 | /// 42 | public string ExpectedValue 43 | { 44 | get; 45 | private set; 46 | } 47 | 48 | /// 49 | /// Attempts to match the expression item with the values returned by the parser. 50 | /// 51 | /// The parser currently iterating over the token source. 52 | /// The name of the token in the outer expression. 53 | /// The results of the match. 54 | public MatchResult Match(IParseAttempt attempt, string itemName) 55 | { 56 | TokenResult tokenResult = attempt.GetToken(); 57 | bool isMatch = tokenResult != null && tokenResult.Name == TokenType; 58 | MatchResult result = new MatchResult() 59 | { 60 | ItemName = itemName, 61 | IsMatch = isMatch, 62 | Context = tokenResult, 63 | }; 64 | return result; 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /SQLGeneration/Parsing/TokenResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SQLGeneration.Parsing 4 | { 5 | /// 6 | /// Holds the results of trying to extract a token from a token source. 7 | /// 8 | public sealed class TokenResult 9 | { 10 | /// 11 | /// Initializes a new instance of a TokenResult. 12 | /// 13 | internal TokenResult(string name, string value) 14 | { 15 | Name = name; 16 | Value = value; 17 | } 18 | 19 | /// 20 | /// Gets the name of the token type that was requested. 21 | /// 22 | public string Name 23 | { 24 | get; 25 | private set; 26 | } 27 | 28 | /// 29 | /// Gets the value that was found, whether it was the requested 30 | /// type or not -or- null if no more tokens were available from 31 | /// the token source. 32 | /// 33 | public string Value 34 | { 35 | get; 36 | private set; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /SQLGeneration/Parsing/TokenSource.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace SQLGeneration.Parsing 5 | { 6 | /// 7 | /// Retrieves tokens and provides the ability to return them if they can't be used. 8 | /// 9 | internal abstract class TokenSource : ITokenSource 10 | { 11 | private readonly Stack undo; 12 | 13 | /// 14 | /// Initializes a new instance of a TokenSource. 15 | /// 16 | protected TokenSource() 17 | { 18 | undo = new Stack(); 19 | } 20 | 21 | /// 22 | /// Attempts to retrieve a token matching the definition associated 23 | /// with the given name. 24 | /// 25 | /// 26 | /// A result object describing the token that was found -or- null if no more tokens are found. 27 | /// 28 | public TokenResult GetToken() 29 | { 30 | if (undo.Count == 0) 31 | { 32 | return GetNextToken(); 33 | } 34 | return undo.Pop(); 35 | } 36 | 37 | /// 38 | /// Retrieves the next token from the source if the undo buffer is empty. 39 | /// 40 | /// The next token -or- null if there are no more tokens. 41 | protected abstract TokenResult GetNextToken(); 42 | 43 | /// 44 | /// Restores the given token to the front of the token stream. 45 | /// 46 | /// The token to restore. 47 | public void PutBack(TokenResult result) 48 | { 49 | undo.Push(result); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /SQLGeneration/Parsing/TokenStream.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace SQLGeneration.Parsing 5 | { 6 | /// 7 | /// Provides convenience methods for building streams of tokens. 8 | /// 9 | public sealed class TokenStream 10 | { 11 | private List tokens; 12 | 13 | /// 14 | /// Initializes a new instance of a TokenStream. 15 | /// 16 | public TokenStream() 17 | { 18 | tokens = new List(); 19 | } 20 | 21 | /// 22 | /// Adds a token to the stream. 23 | /// 24 | /// The token result to add. 25 | /// The current token stream. 26 | public TokenStream Add(TokenResult result) 27 | { 28 | tokens.Add(result); 29 | return this; 30 | } 31 | 32 | /// 33 | /// Adds the given tokens to the stream. 34 | /// 35 | /// The tokens to add to the stream. 36 | /// The current token stream. 37 | public TokenStream AddRange(TokenStream stream) 38 | { 39 | tokens.AddRange(stream.tokens); 40 | return this; 41 | } 42 | 43 | /// 44 | /// Creates a token source from the stream. 45 | /// 46 | /// The token source. 47 | public ITokenSource CreateTokenSource() 48 | { 49 | return new StreamTokenSource(tokens); 50 | } 51 | 52 | private sealed class StreamTokenSource : TokenSource 53 | { 54 | private readonly List tokens; 55 | private int index; 56 | 57 | public StreamTokenSource(List tokens) 58 | { 59 | this.tokens = new List(tokens); 60 | } 61 | 62 | protected override TokenResult GetNextToken() 63 | { 64 | if (index >= tokens.Count) 65 | { 66 | return null; 67 | } 68 | TokenResult result = tokens[index]; 69 | ++index; 70 | return result; 71 | } 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /SQLGeneration/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Resources; 4 | using System.Runtime.InteropServices; 5 | 6 | // General Information about an assembly is controlled through the following 7 | // set of attributes. Change these attribute values to modify the information 8 | // associated with an assembly. 9 | [assembly: AssemblyTitle("SQLGeneration")] 10 | [assembly: AssemblyDescription("An object model for generating SQL at runtime.")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("Truncon")] 13 | [assembly: AssemblyProduct("SQLGeneration")] 14 | [assembly: AssemblyCopyright("Copyright © 2014")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | [assembly: CLSCompliant(true)] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [assembly: ComVisible(false)] 23 | 24 | // The following GUID is for the ID of the typelib if this project is exposed to COM 25 | [assembly: Guid("1e69a85b-72b7-4440-b39b-3388c75a2474")] 26 | 27 | [assembly: AssemblyVersion("2.5.2.0")] 28 | [assembly: AssemblyFileVersion("2.5.2.0")] 29 | [assembly: NeutralResourcesLanguageAttribute("en-US")] 30 | -------------------------------------------------------------------------------- /SQLGeneration/SQLGeneration.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $id$ 5 | $version$ 6 | $title$ 7 | $author$ 8 | $author$ 9 | http://github.com/jehugaleahsa/sqlgeneration 10 | false 11 | $description$ 12 | 13 | Copyright 2013 14 | SQL generation builder building command select insert update delete 15 | 16 | -------------------------------------------------------------------------------- /SQLGeneration/SQLGenerationException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.Serialization; 3 | 4 | namespace SQLGeneration 5 | { 6 | /// 7 | /// Represents an exception that is thrown when an error occurs within SQLGeneration. 8 | /// 9 | [Serializable] 10 | public class SQLGenerationException : Exception 11 | { 12 | /// 13 | /// Initializes a new instance of a SQLGenerationException. 14 | /// 15 | public SQLGenerationException() 16 | { 17 | } 18 | 19 | /// 20 | /// Initializes a new instance of a SQLGenerationException. 21 | /// 22 | /// A message describing the error. 23 | public SQLGenerationException(string message) 24 | : base(message) 25 | { 26 | } 27 | 28 | /// 29 | /// Initializes a new instance of a SQLGenerationException. 30 | /// 31 | /// A message describing the error. 32 | /// The exception that caused the exception. 33 | public SQLGenerationException(string message, Exception innerException) 34 | : base(message, innerException) 35 | { 36 | } 37 | 38 | /// 39 | /// Initializes a new instance of a SQLGenerationException. 40 | /// 41 | /// 42 | /// The System.Runtime.Serialization.SerializationInfo that holds the serialized object data about the exception being thrown. 43 | /// 44 | /// 45 | /// The System.Runtime.Serialization.StreamingContext that contains contextual information about the source or destination. 46 | /// 47 | protected SQLGenerationException(SerializationInfo info, StreamingContext context) 48 | : base(info, context) 49 | { 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /SQLGeneration/key.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jehugaleahsa/SQLGeneration/deadcb3a0beaa738bd678ae5ebe3052f5c313470/SQLGeneration/key.pfx -------------------------------------------------------------------------------- /UNLICENSE.txt: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | --------------------------------------------------------------------------------