1 /*
2  * Copyright 2015-2018 HuntLabs.cn
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 module hunt.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock;
17 
18 
19 import hunt.collection;
20 
21 import hunt.sql.ast.SQLExpr;
22 import hunt.sql.ast.SQLOrderBy;
23 import hunt.sql.ast.statement.SQLSelectQueryBlock;
24 import hunt.sql.dialect.postgresql.ast.PGSQLObject;
25 import hunt.sql.dialect.postgresql.ast.PGSQLObjectImpl;
26 import hunt.sql.dialect.postgresql.visitor.PGASTVisitor;
27 import hunt.sql.visitor.SQLASTVisitor;
28 import hunt.sql.util.DBType;
29 import hunt.sql.ast.SQLObject;
30 import hunt.sql.ast.statement.SQLSelectItem;
31 
32 public class PGSelectQueryBlock : SQLSelectQueryBlock , PGSQLObject{
33 
34     private List!(SQLExpr) distinctOn;
35     private WindowClause  window;
36 
37     private SQLOrderBy    orderBy;
38     private FetchClause   fetch;
39     private ForClause     forClause;
40     private IntoOption    intoOption;
41 
42     override public PGSelectQueryBlock clone() {
43         PGSelectQueryBlock x = new PGSelectQueryBlock();
44         cloneTo(x);
45 
46         if (orderBy !is null) {
47             x.setOrderBy(orderBy.clone());
48         }
49         x.window = window;
50         x.fetch = fetch;
51 
52         x.forClause = forClause;
53         x.intoOption = intoOption;
54       
55         if (distinctOn !is null) {
56             foreach(SQLExpr arg ; distinctOn) {
57                 SQLExpr arg_cloned = arg.clone();
58                 arg_cloned.setParent(this);
59                 x.distinctOn.add(arg_cloned);
60             }
61         }
62 
63         return x;
64     }
65 
66     public static struct IntoOption {
67         enum IntoOption TEMPORARY = IntoOption("TEMPORARY");
68         enum IntoOption TEMP = IntoOption("TEMP");
69         enum IntoOption UNLOGGED = IntoOption("UNLOGGED");
70 
71         private string _name;
72 
73         this(string name)
74         {
75             _name = name;
76         }
77 
78         @property name()
79         {
80             return _name;
81         }
82 
83         bool opEquals(const IntoOption h) nothrow {
84         return _name == h._name ;
85         } 
86 
87         bool opEquals(ref const IntoOption h) nothrow {
88             return _name == h._name ;
89         } 
90     }
91 
92     public this() {
93         distinctOn = new ArrayList!(SQLExpr)(2);
94         dbType = DBType.POSTGRESQL.name;
95     }
96 
97     public IntoOption getIntoOption() {
98         return intoOption;
99     }
100 
101     public void setIntoOption(IntoOption intoOption) {
102         this.intoOption = intoOption;
103     }
104 
105     
106     override  protected void accept0(SQLASTVisitor visitor) {
107         if (cast(PGASTVisitor)(visitor) !is null) {
108             accept0(cast(PGASTVisitor) visitor);
109         } else {
110             super.accept0(visitor);
111         }
112     }
113 
114     override
115     public void accept0(PGASTVisitor visitor) {
116         if (visitor.visit(this)) {
117             acceptChild!SQLExpr(visitor, this.distinctOn);
118             acceptChild!SQLSelectItem(visitor, this.selectList);
119             acceptChild(visitor, this.into);
120             acceptChild(visitor, this.from);
121             acceptChild(visitor, this.where);
122             acceptChild(visitor, this.groupBy);
123             acceptChild(visitor, this.window);
124             acceptChild(visitor, this.orderBy);
125             acceptChild(visitor, this._limit);
126             acceptChild(visitor, this.fetch);
127             acceptChild(visitor, this.forClause);
128         }
129         visitor.endVisit(this);
130     }
131 
132     public FetchClause getFetch() {
133         return fetch;
134     }
135 
136     public void setFetch(FetchClause fetch) {
137         this.fetch = fetch;
138     }
139 
140     public ForClause getForClause() {
141         return forClause;
142     }
143 
144     public void setForClause(ForClause forClause) {
145         this.forClause = forClause;
146     }
147 
148     public WindowClause getWindow() {
149         return window;
150     }
151 
152     public void setWindow(WindowClause window) {
153         this.window = window;
154     }
155 
156     override public SQLOrderBy getOrderBy() {
157         return orderBy;
158     }
159 
160     override public void setOrderBy(SQLOrderBy orderBy) {
161         this.orderBy = orderBy;
162     }
163 
164     public List!(SQLExpr) getDistinctOn() {
165         return distinctOn;
166     }
167 
168     public void setDistinctOn(List!(SQLExpr) distinctOn) {
169         this.distinctOn = distinctOn;
170     }
171 
172     public static class WindowClause : PGSQLObjectImpl {
173         alias accept0 = PGSQLObjectImpl.accept0;
174         private SQLExpr       name;
175         private List!(SQLExpr) definition;
176 
177         this()
178         {
179             definition = new ArrayList!(SQLExpr)(2);
180         }
181 
182         public SQLExpr getName() {
183             return name;
184         }
185 
186         public void setName(SQLExpr name) {
187             this.name = name;
188         }
189 
190         public List!(SQLExpr) getDefinition() {
191             return definition;
192         }
193 
194         public void setDefinition(List!(SQLExpr) definition) {
195             this.definition = definition;
196         }
197 
198         override
199         public void accept0(PGASTVisitor visitor) {
200             if (visitor.visit(this)) {
201                 acceptChild(visitor, name);
202                 acceptChild!SQLExpr(visitor, definition);
203             }
204             visitor.endVisit(this);
205         }
206     }
207 
208     public static class FetchClause : PGSQLObjectImpl {
209         alias accept0 = PGSQLObjectImpl.accept0;
210         public static enum Option {
211             FIRST, NEXT
212         }
213 
214         private Option  option;
215         private SQLExpr count;
216 
217         public Option getOption() {
218             return option;
219         }
220 
221         public void setOption(Option option) {
222             this.option = option;
223         }
224 
225         public SQLExpr getCount() {
226             return count;
227         }
228 
229         public void setCount(SQLExpr count) {
230             this.count = count;
231         }
232 
233         override
234         public void accept0(PGASTVisitor visitor) {
235             if (visitor.visit(this)) {
236                 acceptChild(visitor, count);
237             }
238             visitor.endVisit(this);
239         }
240 
241     }
242 
243     public static class ForClause : PGSQLObjectImpl {
244         alias accept0 = PGSQLObjectImpl.accept0;
245         public static enum Option {
246             UPDATE, SHARE
247         }
248 
249         private List!(SQLExpr) of;
250         private bool       noWait;
251         private Option        option;
252 
253         this()
254         {
255             of = new ArrayList!(SQLExpr)(2);
256         }
257 
258         public Option getOption() {
259             return option;
260         }
261 
262         public void setOption(Option option) {
263             this.option = option;
264         }
265 
266         public List!(SQLExpr) getOf() {
267             return of;
268         }
269 
270         public void setOf(List!(SQLExpr) of) {
271             this.of = of;
272         }
273 
274         public bool isNoWait() {
275             return noWait;
276         }
277 
278         public void setNoWait(bool noWait) {
279             this.noWait = noWait;
280         }
281 
282         override
283         public void accept0(PGASTVisitor visitor) {
284             if (visitor.visit(this)) {
285                 acceptChild!SQLExpr(visitor, of);
286             }
287             visitor.endVisit(this);
288         }
289     }
290 }