View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.shardingsphere.sql.parser.sqlserver.visitor.statement.type;
19  
20  import org.apache.shardingsphere.infra.database.core.type.DatabaseType;
21  import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
22  import org.apache.shardingsphere.sql.parser.api.ASTNode;
23  import org.apache.shardingsphere.sql.parser.api.visitor.statement.type.DCLStatementVisitor;
24  import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.AlterLoginContext;
25  import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.AlterRoleContext;
26  import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.AlterUserContext;
27  import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.ClassPrivilegesContext;
28  import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.ColumnNamesContext;
29  import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.CreateLoginContext;
30  import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.CreateRoleContext;
31  import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.CreateUserContext;
32  import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.CreateUserLoginWindowsPrincipalClauseContext;
33  import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.CreateUserWindowsPrincipalClauseContext;
34  import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.DenyContext;
35  import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.DropLoginContext;
36  import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.DropRoleContext;
37  import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.DropUserContext;
38  import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.GrantContext;
39  import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.IgnoredNameIdentifierContext;
40  import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.OnClassClauseContext;
41  import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.OnClassTypeClauseContext;
42  import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.OwnerContext;
43  import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.RevertContext;
44  import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.RevokeContext;
45  import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.SecurableContext;
46  import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.SetUserContext;
47  import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.UserNameContext;
48  import org.apache.shardingsphere.sql.parser.sqlserver.visitor.statement.SQLServerStatementVisitor;
49  import org.apache.shardingsphere.sql.parser.statement.core.segment.dcl.LoginSegment;
50  import org.apache.shardingsphere.sql.parser.statement.core.segment.dcl.UserSegment;
51  import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.column.ColumnSegment;
52  import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.OwnerSegment;
53  import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.SimpleTableSegment;
54  import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.TableNameSegment;
55  import org.apache.shardingsphere.sql.parser.statement.core.statement.type.dcl.role.AlterRoleStatement;
56  import org.apache.shardingsphere.sql.parser.statement.core.statement.type.dcl.role.CreateRoleStatement;
57  import org.apache.shardingsphere.sql.parser.statement.core.statement.type.dcl.role.DropRoleStatement;
58  import org.apache.shardingsphere.sql.parser.statement.core.statement.type.dcl.user.AlterUserStatement;
59  import org.apache.shardingsphere.sql.parser.statement.core.statement.type.dcl.user.CreateUserStatement;
60  import org.apache.shardingsphere.sql.parser.statement.core.statement.type.dcl.user.DropUserStatement;
61  import org.apache.shardingsphere.sql.parser.statement.core.value.collection.CollectionValue;
62  import org.apache.shardingsphere.sql.parser.statement.core.value.identifier.IdentifierValue;
63  import org.apache.shardingsphere.sql.parser.statement.core.value.literal.impl.StringLiteralValue;
64  import org.apache.shardingsphere.sql.parser.statement.sqlserver.dcl.SQLServerGrantStatement;
65  import org.apache.shardingsphere.sql.parser.statement.sqlserver.dcl.SQLServerRevertStatement;
66  import org.apache.shardingsphere.sql.parser.statement.sqlserver.dcl.SQLServerRevokeStatement;
67  import org.apache.shardingsphere.sql.parser.statement.sqlserver.dcl.login.SQLServerAlterLoginStatement;
68  import org.apache.shardingsphere.sql.parser.statement.sqlserver.dcl.login.SQLServerCreateLoginStatement;
69  import org.apache.shardingsphere.sql.parser.statement.sqlserver.dcl.login.SQLServerDropLoginStatement;
70  import org.apache.shardingsphere.sql.parser.statement.sqlserver.dcl.user.SQLServerDenyUserStatement;
71  import org.apache.shardingsphere.sql.parser.statement.sqlserver.dcl.user.SQLServerSetUserStatement;
72  
73  import java.util.Collections;
74  import java.util.Optional;
75  
76  /**
77   * DCL statement visitor for SQLServer.
78   */
79  public final class SQLServerDCLStatementVisitor extends SQLServerStatementVisitor implements DCLStatementVisitor {
80      
81      private final DatabaseType databaseType = TypedSPILoader.getService(DatabaseType.class, "SQLServer");
82      
83      @Override
84      public ASTNode visitGrant(final GrantContext ctx) {
85          SQLServerGrantStatement result = new SQLServerGrantStatement(databaseType);
86          if (null != ctx.grantClassPrivilegesClause()) {
87              findTableSegment(ctx.grantClassPrivilegesClause().onClassClause(), ctx.grantClassPrivilegesClause().classPrivileges()).ifPresent(optional -> result.getTables().add(optional));
88              if (null != ctx.grantClassPrivilegesClause().classPrivileges().columnNames()) {
89                  for (ColumnNamesContext each : ctx.grantClassPrivilegesClause().classPrivileges().columnNames()) {
90                      result.getColumns().addAll(((CollectionValue<ColumnSegment>) visit(each)).getValue());
91                  }
92              }
93          }
94          if (null != ctx.grantClassTypePrivilegesClause()) {
95              findTableSegment(ctx.grantClassTypePrivilegesClause().onClassTypeClause()).ifPresent(optional -> result.getTables().add(optional));
96          }
97          return result;
98      }
99      
100     @Override
101     public ASTNode visitRevoke(final RevokeContext ctx) {
102         SQLServerRevokeStatement result = new SQLServerRevokeStatement(databaseType);
103         if (null != ctx.revokeClassPrivilegesClause()) {
104             findTableSegment(ctx.revokeClassPrivilegesClause().onClassClause(), ctx.revokeClassPrivilegesClause().classPrivileges()).ifPresent(optional -> result.getTables().add(optional));
105             if (null != ctx.revokeClassPrivilegesClause().classPrivileges().columnNames()) {
106                 for (ColumnNamesContext each : ctx.revokeClassPrivilegesClause().classPrivileges().columnNames()) {
107                     result.getColumns().addAll(((CollectionValue<ColumnSegment>) visit(each)).getValue());
108                 }
109             }
110         }
111         if (null != ctx.revokeClassTypePrivilegesClause()) {
112             findTableSegment(ctx.revokeClassTypePrivilegesClause().onClassTypeClause()).ifPresent(optional -> result.getTables().add(optional));
113         }
114         return result;
115     }
116     
117     @Override
118     public ASTNode visitSecurable(final SecurableContext ctx) {
119         SimpleTableSegment result = new SimpleTableSegment(new TableNameSegment(ctx.name().getStart().getStartIndex(), ctx.name().getStop().getStopIndex(), (IdentifierValue) visit(ctx.name())));
120         OwnerContext owner = ctx.owner();
121         if (null != owner) {
122             result.setOwner(new OwnerSegment(owner.getStart().getStartIndex(), owner.getStop().getStopIndex(), (IdentifierValue) visit(owner.identifier())));
123         }
124         return result;
125     }
126     
127     @Override
128     public ASTNode visitCreateUser(final CreateUserContext ctx) {
129         CreateUserStatement result = new CreateUserStatement(databaseType);
130         if (null != ctx.createUserLoginClause()) {
131             result.getUsers().add((UserSegment) visit(ctx.createUserLoginClause().userName()));
132         } else if (null != ctx.createUserWindowsPrincipalClause()) {
133             result.getUsers().add((UserSegment) visit(ctx.createUserWindowsPrincipalClause()));
134         } else if (null != ctx.createUserLoginWindowsPrincipalClause()) {
135             result.getUsers().add((UserSegment) visit(ctx.createUserLoginWindowsPrincipalClause()));
136         } else if (null != ctx.createUserWithoutLoginClause()) {
137             result.getUsers().add((UserSegment) visit(ctx.createUserWithoutLoginClause().userName()));
138         } else if (null != ctx.createUserFromExternalProviderClause()) {
139             result.getUsers().add((UserSegment) visit(ctx.createUserFromExternalProviderClause().userName()));
140         } else if (null != ctx.createUserWithDefaultSchema()) {
141             result.getUsers().add((UserSegment) visit(ctx.createUserWithDefaultSchema().userName()));
142         } else if (null != ctx.createUserWithAzureActiveDirectoryPrincipalClause()) {
143             result.getUsers().add((UserSegment) visit(ctx.createUserWithAzureActiveDirectoryPrincipalClause().azureActiveDirectoryPrincipal().userName()));
144         } else {
145             result.getUsers().add((UserSegment) visit(ctx.userName()));
146         }
147         return result;
148     }
149     
150     @Override
151     public ASTNode visitUserName(final UserNameContext ctx) {
152         UserSegment result = new UserSegment();
153         String user = ((IdentifierValue) visit(ctx.ignoredNameIdentifier())).getValue();
154         result.setUser(user);
155         return result;
156     }
157     
158     @Override
159     public ASTNode visitIgnoredNameIdentifier(final IgnoredNameIdentifierContext ctx) {
160         int identifierCount = ctx.identifier().size();
161         return 1 == identifierCount ? (IdentifierValue) visit(ctx.identifier(0)) : new IdentifierValue(ctx.getText());
162     }
163     
164     @Override
165     public ASTNode visitCreateUserWindowsPrincipalClause(final CreateUserWindowsPrincipalClauseContext ctx) {
166         if (null != ctx.windowsPrincipal()) {
167             return visit(ctx.windowsPrincipal().userName());
168         }
169         if (null != ctx.azureActiveDirectoryPrincipal()) {
170             return visit(ctx.azureActiveDirectoryPrincipal().userName());
171         }
172         return visit(ctx.userName());
173     }
174     
175     @Override
176     public ASTNode visitCreateUserLoginWindowsPrincipalClause(final CreateUserLoginWindowsPrincipalClauseContext ctx) {
177         return null == ctx.userName() ? (UserSegment) visit(ctx.windowsPrincipal(0)) : (UserSegment) visit(ctx.userName());
178     }
179     
180     @Override
181     public ASTNode visitAlterUser(final AlterUserContext ctx) {
182         return new AlterUserStatement(databaseType, (UserSegment) visit(ctx.userName()));
183     }
184     
185     @Override
186     public ASTNode visitDeny(final DenyContext ctx) {
187         SQLServerDenyUserStatement result = new SQLServerDenyUserStatement(databaseType);
188         if (null != ctx.denyClassPrivilegesClause()) {
189             findTableSegment(ctx.denyClassPrivilegesClause().onClassClause(), ctx.denyClassPrivilegesClause().classPrivileges()).ifPresent(result::setTable);
190             if (null != ctx.denyClassPrivilegesClause().classPrivileges().columnNames()) {
191                 for (ColumnNamesContext each : ctx.denyClassPrivilegesClause().classPrivileges().columnNames()) {
192                     result.getColumns().addAll(((CollectionValue<ColumnSegment>) visit(each)).getValue());
193                 }
194             }
195         }
196         if (null != ctx.denyClassTypePrivilegesClause()) {
197             findTableSegment(ctx.denyClassTypePrivilegesClause().onClassTypeClause()).ifPresent(result::setTable);
198         }
199         return result;
200     }
201     
202     private Optional<SimpleTableSegment> findTableSegment(final OnClassClauseContext onClassClauseCtx, final ClassPrivilegesContext classPrivilegesCtx) {
203         if (null == onClassClauseCtx) {
204             return Optional.empty();
205         }
206         if (null != onClassClauseCtx.classItem() && null != onClassClauseCtx.classItem().OBJECT()
207                 || null != classPrivilegesCtx.privilegeType().get(0).objectPermission() || null != classPrivilegesCtx.privilegeType().get(0).PRIVILEGES()) {
208             return Optional.of((SimpleTableSegment) visit(onClassClauseCtx.securable()));
209         }
210         return Optional.empty();
211     }
212     
213     private Optional<SimpleTableSegment> findTableSegment(final OnClassTypeClauseContext ctx) {
214         return null == ctx || null == ctx.classType() || null == ctx.classType().OBJECT() ? Optional.empty() : Optional.of((SimpleTableSegment) visit(ctx.securable()));
215     }
216     
217     @Override
218     public ASTNode visitDropUser(final DropUserContext ctx) {
219         return new DropUserStatement(databaseType, Collections.singleton(((UserSegment) visit(ctx.userName())).getUser()));
220     }
221     
222     @Override
223     public ASTNode visitCreateRole(final CreateRoleContext ctx) {
224         return new CreateRoleStatement(databaseType);
225     }
226     
227     @Override
228     public ASTNode visitAlterRole(final AlterRoleContext ctx) {
229         return new AlterRoleStatement(databaseType);
230     }
231     
232     @Override
233     public ASTNode visitDropRole(final DropRoleContext ctx) {
234         return new DropRoleStatement(databaseType);
235     }
236     
237     @Override
238     public ASTNode visitCreateLogin(final CreateLoginContext ctx) {
239         return new SQLServerCreateLoginStatement(databaseType,
240                 null == ctx.ignoredNameIdentifier()
241                         ? null
242                         : new LoginSegment(
243                                 ctx.ignoredNameIdentifier().getStart().getStartIndex(), ctx.ignoredNameIdentifier().getStop().getStopIndex(), (IdentifierValue) visit(ctx.ignoredNameIdentifier())));
244     }
245     
246     @Override
247     public ASTNode visitAlterLogin(final AlterLoginContext ctx) {
248         return new SQLServerAlterLoginStatement(databaseType, null == ctx.ignoredNameIdentifier()
249                 ? null
250                 : new LoginSegment(
251                         ctx.ignoredNameIdentifier().getStart().getStartIndex(), ctx.ignoredNameIdentifier().getStop().getStopIndex(), (IdentifierValue) visit(ctx.ignoredNameIdentifier())));
252     }
253     
254     @Override
255     public ASTNode visitDropLogin(final DropLoginContext ctx) {
256         return new SQLServerDropLoginStatement(databaseType, new LoginSegment(
257                 ctx.ignoredNameIdentifier().getStart().getStartIndex(), ctx.ignoredNameIdentifier().getStop().getStopIndex(), (IdentifierValue) visit(ctx.ignoredNameIdentifier())));
258     }
259     
260     @Override
261     public ASTNode visitSetUser(final SetUserContext ctx) {
262         return new SQLServerSetUserStatement(databaseType, null == ctx.stringLiterals() ? null : getUserSegment(ctx));
263     }
264     
265     private UserSegment getUserSegment(final SetUserContext ctx) {
266         UserSegment result = new UserSegment();
267         result.setUser(((StringLiteralValue) visit(ctx.stringLiterals())).getValue());
268         result.setStartIndex(ctx.stringLiterals().start.getStartIndex());
269         result.setStopIndex(ctx.stringLiterals().stop.getStopIndex());
270         return result;
271     }
272     
273     @Override
274     public ASTNode visitRevert(final RevertContext ctx) {
275         return new SQLServerRevertStatement(databaseType);
276     }
277 }