• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

apache / iotdb / #9919

25 Aug 2023 07:08AM UTC coverage: 47.802% (+0.007%) from 47.795%
#9919

push

travis_ci

web-flow
Remove some useless configs (#10950)

80023 of 167404 relevant lines covered (47.8%)

0.48 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

27.72
/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/ASTVisitor.java
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one
3
 * or more contributor license agreements.  See the NOTICE file
4
 * distributed with this work for additional information
5
 * regarding copyright ownership.  The ASF licenses this file
6
 * to you under the Apache License, Version 2.0 (the
7
 * "License"); you may not use this file except in compliance
8
 * with the License.  You may obtain a copy of the License at
9
 *
10
 *     http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing,
13
 * software distributed under the License is distributed on an
14
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
 * KIND, either express or implied.  See the License for the
16
 * specific language governing permissions and limitations
17
 * under the License.
18
 */
19

20
package org.apache.iotdb.db.queryengine.plan.parser;
21

22
import org.apache.iotdb.common.rpc.thrift.TConsensusGroupType;
23
import org.apache.iotdb.common.rpc.thrift.TTimedQuota;
24
import org.apache.iotdb.common.rpc.thrift.ThrottleType;
25
import org.apache.iotdb.commons.auth.entity.PrivilegeType;
26
import org.apache.iotdb.commons.cluster.NodeStatus;
27
import org.apache.iotdb.commons.conf.IoTDBConstant;
28
import org.apache.iotdb.commons.cq.TimeoutPolicy;
29
import org.apache.iotdb.commons.path.PartialPath;
30
import org.apache.iotdb.commons.schema.filter.SchemaFilter;
31
import org.apache.iotdb.commons.schema.filter.SchemaFilterFactory;
32
import org.apache.iotdb.commons.utils.PathUtils;
33
import org.apache.iotdb.db.conf.IoTDBConfig;
34
import org.apache.iotdb.db.conf.IoTDBDescriptor;
35
import org.apache.iotdb.db.exception.sql.SemanticException;
36
import org.apache.iotdb.db.qp.sql.IoTDBSqlParser;
37
import org.apache.iotdb.db.qp.sql.IoTDBSqlParser.ConstantContext;
38
import org.apache.iotdb.db.qp.sql.IoTDBSqlParser.CountDatabasesContext;
39
import org.apache.iotdb.db.qp.sql.IoTDBSqlParser.CountDevicesContext;
40
import org.apache.iotdb.db.qp.sql.IoTDBSqlParser.CountNodesContext;
41
import org.apache.iotdb.db.qp.sql.IoTDBSqlParser.CountTimeseriesContext;
42
import org.apache.iotdb.db.qp.sql.IoTDBSqlParser.CreateFunctionContext;
43
import org.apache.iotdb.db.qp.sql.IoTDBSqlParser.DropFunctionContext;
44
import org.apache.iotdb.db.qp.sql.IoTDBSqlParser.ExpressionContext;
45
import org.apache.iotdb.db.qp.sql.IoTDBSqlParser.GroupByAttributeClauseContext;
46
import org.apache.iotdb.db.qp.sql.IoTDBSqlParser.IdentifierContext;
47
import org.apache.iotdb.db.qp.sql.IoTDBSqlParser.ShowFunctionsContext;
48
import org.apache.iotdb.db.qp.sql.IoTDBSqlParserBaseVisitor;
49
import org.apache.iotdb.db.queryengine.common.header.ColumnHeaderConstant;
50
import org.apache.iotdb.db.queryengine.execution.operator.window.WindowType;
51
import org.apache.iotdb.db.queryengine.plan.analyze.ExpressionAnalyzer;
52
import org.apache.iotdb.db.queryengine.plan.expression.Expression;
53
import org.apache.iotdb.db.queryengine.plan.expression.ExpressionType;
54
import org.apache.iotdb.db.queryengine.plan.expression.binary.AdditionExpression;
55
import org.apache.iotdb.db.queryengine.plan.expression.binary.CompareBinaryExpression;
56
import org.apache.iotdb.db.queryengine.plan.expression.binary.DivisionExpression;
57
import org.apache.iotdb.db.queryengine.plan.expression.binary.EqualToExpression;
58
import org.apache.iotdb.db.queryengine.plan.expression.binary.GreaterEqualExpression;
59
import org.apache.iotdb.db.queryengine.plan.expression.binary.GreaterThanExpression;
60
import org.apache.iotdb.db.queryengine.plan.expression.binary.LessEqualExpression;
61
import org.apache.iotdb.db.queryengine.plan.expression.binary.LessThanExpression;
62
import org.apache.iotdb.db.queryengine.plan.expression.binary.LogicAndExpression;
63
import org.apache.iotdb.db.queryengine.plan.expression.binary.LogicOrExpression;
64
import org.apache.iotdb.db.queryengine.plan.expression.binary.ModuloExpression;
65
import org.apache.iotdb.db.queryengine.plan.expression.binary.MultiplicationExpression;
66
import org.apache.iotdb.db.queryengine.plan.expression.binary.NonEqualExpression;
67
import org.apache.iotdb.db.queryengine.plan.expression.binary.SubtractionExpression;
68
import org.apache.iotdb.db.queryengine.plan.expression.binary.WhenThenExpression;
69
import org.apache.iotdb.db.queryengine.plan.expression.leaf.ConstantOperand;
70
import org.apache.iotdb.db.queryengine.plan.expression.leaf.NullOperand;
71
import org.apache.iotdb.db.queryengine.plan.expression.leaf.TimeSeriesOperand;
72
import org.apache.iotdb.db.queryengine.plan.expression.leaf.TimestampOperand;
73
import org.apache.iotdb.db.queryengine.plan.expression.multi.FunctionExpression;
74
import org.apache.iotdb.db.queryengine.plan.expression.multi.builtin.BuiltInScalarFunctionHelperFactory;
75
import org.apache.iotdb.db.queryengine.plan.expression.other.CaseWhenThenExpression;
76
import org.apache.iotdb.db.queryengine.plan.expression.ternary.BetweenExpression;
77
import org.apache.iotdb.db.queryengine.plan.expression.unary.InExpression;
78
import org.apache.iotdb.db.queryengine.plan.expression.unary.IsNullExpression;
79
import org.apache.iotdb.db.queryengine.plan.expression.unary.LikeExpression;
80
import org.apache.iotdb.db.queryengine.plan.expression.unary.LogicNotExpression;
81
import org.apache.iotdb.db.queryengine.plan.expression.unary.NegationExpression;
82
import org.apache.iotdb.db.queryengine.plan.expression.unary.RegularExpression;
83
import org.apache.iotdb.db.queryengine.plan.statement.AuthorType;
84
import org.apache.iotdb.db.queryengine.plan.statement.Statement;
85
import org.apache.iotdb.db.queryengine.plan.statement.StatementType;
86
import org.apache.iotdb.db.queryengine.plan.statement.component.FillComponent;
87
import org.apache.iotdb.db.queryengine.plan.statement.component.FillPolicy;
88
import org.apache.iotdb.db.queryengine.plan.statement.component.FromComponent;
89
import org.apache.iotdb.db.queryengine.plan.statement.component.GroupByComponent;
90
import org.apache.iotdb.db.queryengine.plan.statement.component.GroupByConditionComponent;
91
import org.apache.iotdb.db.queryengine.plan.statement.component.GroupByCountComponent;
92
import org.apache.iotdb.db.queryengine.plan.statement.component.GroupByLevelComponent;
93
import org.apache.iotdb.db.queryengine.plan.statement.component.GroupBySessionComponent;
94
import org.apache.iotdb.db.queryengine.plan.statement.component.GroupByTagComponent;
95
import org.apache.iotdb.db.queryengine.plan.statement.component.GroupByTimeComponent;
96
import org.apache.iotdb.db.queryengine.plan.statement.component.GroupByVariationComponent;
97
import org.apache.iotdb.db.queryengine.plan.statement.component.HavingCondition;
98
import org.apache.iotdb.db.queryengine.plan.statement.component.IntoComponent;
99
import org.apache.iotdb.db.queryengine.plan.statement.component.IntoItem;
100
import org.apache.iotdb.db.queryengine.plan.statement.component.NullOrdering;
101
import org.apache.iotdb.db.queryengine.plan.statement.component.OrderByComponent;
102
import org.apache.iotdb.db.queryengine.plan.statement.component.OrderByKey;
103
import org.apache.iotdb.db.queryengine.plan.statement.component.Ordering;
104
import org.apache.iotdb.db.queryengine.plan.statement.component.ResultColumn;
105
import org.apache.iotdb.db.queryengine.plan.statement.component.ResultSetFormat;
106
import org.apache.iotdb.db.queryengine.plan.statement.component.SelectComponent;
107
import org.apache.iotdb.db.queryengine.plan.statement.component.SortItem;
108
import org.apache.iotdb.db.queryengine.plan.statement.component.WhereCondition;
109
import org.apache.iotdb.db.queryengine.plan.statement.crud.DeleteDataStatement;
110
import org.apache.iotdb.db.queryengine.plan.statement.crud.InsertStatement;
111
import org.apache.iotdb.db.queryengine.plan.statement.crud.LoadTsFileStatement;
112
import org.apache.iotdb.db.queryengine.plan.statement.crud.QueryStatement;
113
import org.apache.iotdb.db.queryengine.plan.statement.literal.BooleanLiteral;
114
import org.apache.iotdb.db.queryengine.plan.statement.literal.DoubleLiteral;
115
import org.apache.iotdb.db.queryengine.plan.statement.literal.Literal;
116
import org.apache.iotdb.db.queryengine.plan.statement.literal.LongLiteral;
117
import org.apache.iotdb.db.queryengine.plan.statement.literal.StringLiteral;
118
import org.apache.iotdb.db.queryengine.plan.statement.metadata.AlterTimeSeriesStatement;
119
import org.apache.iotdb.db.queryengine.plan.statement.metadata.CountDatabaseStatement;
120
import org.apache.iotdb.db.queryengine.plan.statement.metadata.CountDevicesStatement;
121
import org.apache.iotdb.db.queryengine.plan.statement.metadata.CountLevelTimeSeriesStatement;
122
import org.apache.iotdb.db.queryengine.plan.statement.metadata.CountNodesStatement;
123
import org.apache.iotdb.db.queryengine.plan.statement.metadata.CountTimeSeriesStatement;
124
import org.apache.iotdb.db.queryengine.plan.statement.metadata.CountTimeSlotListStatement;
125
import org.apache.iotdb.db.queryengine.plan.statement.metadata.CreateAlignedTimeSeriesStatement;
126
import org.apache.iotdb.db.queryengine.plan.statement.metadata.CreateContinuousQueryStatement;
127
import org.apache.iotdb.db.queryengine.plan.statement.metadata.CreateFunctionStatement;
128
import org.apache.iotdb.db.queryengine.plan.statement.metadata.CreatePipePluginStatement;
129
import org.apache.iotdb.db.queryengine.plan.statement.metadata.CreateTimeSeriesStatement;
130
import org.apache.iotdb.db.queryengine.plan.statement.metadata.CreateTriggerStatement;
131
import org.apache.iotdb.db.queryengine.plan.statement.metadata.DatabaseSchemaStatement;
132
import org.apache.iotdb.db.queryengine.plan.statement.metadata.DeleteDatabaseStatement;
133
import org.apache.iotdb.db.queryengine.plan.statement.metadata.DeleteTimeSeriesStatement;
134
import org.apache.iotdb.db.queryengine.plan.statement.metadata.DropContinuousQueryStatement;
135
import org.apache.iotdb.db.queryengine.plan.statement.metadata.DropFunctionStatement;
136
import org.apache.iotdb.db.queryengine.plan.statement.metadata.DropPipePluginStatement;
137
import org.apache.iotdb.db.queryengine.plan.statement.metadata.DropTriggerStatement;
138
import org.apache.iotdb.db.queryengine.plan.statement.metadata.GetRegionIdStatement;
139
import org.apache.iotdb.db.queryengine.plan.statement.metadata.GetSeriesSlotListStatement;
140
import org.apache.iotdb.db.queryengine.plan.statement.metadata.GetTimeSlotListStatement;
141
import org.apache.iotdb.db.queryengine.plan.statement.metadata.MigrateRegionStatement;
142
import org.apache.iotdb.db.queryengine.plan.statement.metadata.SetTTLStatement;
143
import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowChildNodesStatement;
144
import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowChildPathsStatement;
145
import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowClusterStatement;
146
import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowConfigNodesStatement;
147
import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowContinuousQueriesStatement;
148
import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowDataNodesStatement;
149
import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowDatabaseStatement;
150
import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowDevicesStatement;
151
import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowFunctionsStatement;
152
import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowPipePluginsStatement;
153
import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowRegionStatement;
154
import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowTTLStatement;
155
import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowTimeSeriesStatement;
156
import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowTriggersStatement;
157
import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowVariablesStatement;
158
import org.apache.iotdb.db.queryengine.plan.statement.metadata.UnSetTTLStatement;
159
import org.apache.iotdb.db.queryengine.plan.statement.metadata.model.CreateModelStatement;
160
import org.apache.iotdb.db.queryengine.plan.statement.metadata.model.DropModelStatement;
161
import org.apache.iotdb.db.queryengine.plan.statement.metadata.model.ShowModelsStatement;
162
import org.apache.iotdb.db.queryengine.plan.statement.metadata.model.ShowTrailsStatement;
163
import org.apache.iotdb.db.queryengine.plan.statement.metadata.pipe.CreatePipeStatement;
164
import org.apache.iotdb.db.queryengine.plan.statement.metadata.pipe.DropPipeStatement;
165
import org.apache.iotdb.db.queryengine.plan.statement.metadata.pipe.ShowPipesStatement;
166
import org.apache.iotdb.db.queryengine.plan.statement.metadata.pipe.StartPipeStatement;
167
import org.apache.iotdb.db.queryengine.plan.statement.metadata.pipe.StopPipeStatement;
168
import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.ActivateTemplateStatement;
169
import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.AlterSchemaTemplateStatement;
170
import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.CreateSchemaTemplateStatement;
171
import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.DeactivateTemplateStatement;
172
import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.DropSchemaTemplateStatement;
173
import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.SetSchemaTemplateStatement;
174
import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.ShowNodesInSchemaTemplateStatement;
175
import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.ShowPathSetTemplateStatement;
176
import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.ShowPathsUsingTemplateStatement;
177
import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.ShowSchemaTemplateStatement;
178
import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.UnsetSchemaTemplateStatement;
179
import org.apache.iotdb.db.queryengine.plan.statement.metadata.view.AlterLogicalViewStatement;
180
import org.apache.iotdb.db.queryengine.plan.statement.metadata.view.CreateLogicalViewStatement;
181
import org.apache.iotdb.db.queryengine.plan.statement.metadata.view.DeleteLogicalViewStatement;
182
import org.apache.iotdb.db.queryengine.plan.statement.metadata.view.ShowLogicalViewStatement;
183
import org.apache.iotdb.db.queryengine.plan.statement.sys.AuthorStatement;
184
import org.apache.iotdb.db.queryengine.plan.statement.sys.ClearCacheStatement;
185
import org.apache.iotdb.db.queryengine.plan.statement.sys.ExplainStatement;
186
import org.apache.iotdb.db.queryengine.plan.statement.sys.FlushStatement;
187
import org.apache.iotdb.db.queryengine.plan.statement.sys.KillQueryStatement;
188
import org.apache.iotdb.db.queryengine.plan.statement.sys.LoadConfigurationStatement;
189
import org.apache.iotdb.db.queryengine.plan.statement.sys.MergeStatement;
190
import org.apache.iotdb.db.queryengine.plan.statement.sys.SetSystemStatusStatement;
191
import org.apache.iotdb.db.queryengine.plan.statement.sys.ShowQueriesStatement;
192
import org.apache.iotdb.db.queryengine.plan.statement.sys.ShowVersionStatement;
193
import org.apache.iotdb.db.queryengine.plan.statement.sys.quota.SetSpaceQuotaStatement;
194
import org.apache.iotdb.db.queryengine.plan.statement.sys.quota.SetThrottleQuotaStatement;
195
import org.apache.iotdb.db.queryengine.plan.statement.sys.quota.ShowSpaceQuotaStatement;
196
import org.apache.iotdb.db.queryengine.plan.statement.sys.quota.ShowThrottleQuotaStatement;
197
import org.apache.iotdb.db.schemaengine.template.TemplateAlterOperationType;
198
import org.apache.iotdb.db.utils.DateTimeUtils;
199
import org.apache.iotdb.db.utils.constant.SqlConstant;
200
import org.apache.iotdb.trigger.api.enums.TriggerEvent;
201
import org.apache.iotdb.trigger.api.enums.TriggerType;
202
import org.apache.iotdb.tsfile.common.conf.TSFileDescriptor;
203
import org.apache.iotdb.tsfile.common.constant.TsFileConstant;
204
import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
205
import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
206
import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
207
import org.apache.iotdb.tsfile.read.common.TimeRange;
208

209
import com.google.common.collect.ImmutableSet;
210
import org.antlr.v4.runtime.tree.TerminalNode;
211

212
import java.io.FileNotFoundException;
213
import java.net.URI;
214
import java.net.URISyntaxException;
215
import java.time.ZoneId;
216
import java.util.ArrayList;
217
import java.util.Arrays;
218
import java.util.HashMap;
219
import java.util.HashSet;
220
import java.util.LinkedHashSet;
221
import java.util.List;
222
import java.util.Map;
223
import java.util.Set;
224
import java.util.function.BiConsumer;
225
import java.util.function.Consumer;
226
import java.util.stream.Collectors;
227

228
import static org.apache.iotdb.db.queryengine.plan.optimization.LimitOffsetPushDown.canPushDownLimitOffsetToGroupByTime;
229
import static org.apache.iotdb.db.queryengine.plan.optimization.LimitOffsetPushDown.pushDownLimitOffsetToTimeParameter;
230
import static org.apache.iotdb.db.schemaengine.SchemaConstant.ALL_RESULT_NODES;
231
import static org.apache.iotdb.db.utils.constant.SqlConstant.CAST_FUNCTION;
232
import static org.apache.iotdb.db.utils.constant.SqlConstant.CAST_TYPE;
233
import static org.apache.iotdb.db.utils.constant.SqlConstant.REPLACE_FROM;
234
import static org.apache.iotdb.db.utils.constant.SqlConstant.REPLACE_FUNCTION;
235
import static org.apache.iotdb.db.utils.constant.SqlConstant.REPLACE_TO;
236
import static org.apache.iotdb.db.utils.constant.SqlConstant.ROUND_FUNCTION;
237
import static org.apache.iotdb.db.utils.constant.SqlConstant.ROUND_PLACES;
238
import static org.apache.iotdb.db.utils.constant.SqlConstant.SUBSTRING_FUNCTION;
239
import static org.apache.iotdb.db.utils.constant.SqlConstant.SUBSTRING_IS_STANDARD;
240
import static org.apache.iotdb.db.utils.constant.SqlConstant.SUBSTRING_LENGTH;
241
import static org.apache.iotdb.db.utils.constant.SqlConstant.SUBSTRING_START;
242

243
/** Parse AST to Statement. */
244
public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {
1✔
245

246
  private static final IoTDBConfig CONFIG = IoTDBDescriptor.getInstance().getConfig();
1✔
247

248
  private static final String DELETE_RANGE_ERROR_MSG =
249
      "For delete statement, where clause can only contain atomic expressions like : "
250
          + "time > XXX, time <= XXX, or two atomic expressions connected by 'AND'";
251
  private static final String DELETE_ONLY_SUPPORT_TIME_EXP_ERROR_MSG =
252
      "For delete statement, where clause can only contain time expressions, "
253
          + "value filter is not currently supported.";
254

255
  private static final String GROUP_BY_COMMON_ONLY_ONE_MSG =
256
      "Only one of group by time or group by variation/series/session can be supported at a time";
257

258
  private static final String NEGATIVE_TIMESTAMP_ERROR_MSG =
259
      "Please set the time >=0 or after 1970-01-01 00:00:00";
260
  private static final String LIMIT_CONFIGURATION_ENABLED_ERROR_MSG =
261
      "Limit configuration is not enabled, please enable it first.";
262

263
  private static final String IGNORENULL = "IgnoreNull";
264
  private ZoneId zoneId;
265

266
  private boolean useWildcard = false;
1✔
267

268
  private boolean lastLevelUseWildcard = false;
1✔
269

270
  public void setZoneId(ZoneId zoneId) {
271
    this.zoneId = zoneId;
1✔
272
  }
1✔
273

274
  /** Top Level Description. */
275
  @Override
276
  public Statement visitSingleStatement(IoTDBSqlParser.SingleStatementContext ctx) {
277
    Statement statement = visit(ctx.statement());
1✔
278
    if (ctx.DEBUG() != null) {
1✔
279
      statement.setDebug(true);
×
280
    }
281
    return statement;
1✔
282
  }
283

284
  /** Data Definition Language (DDL). */
285

286
  // Create Timeseries ========================================================================
287
  @Override
288
  public Statement visitCreateNonAlignedTimeseries(
289
      IoTDBSqlParser.CreateNonAlignedTimeseriesContext ctx) {
290
    CreateTimeSeriesStatement createTimeSeriesStatement = new CreateTimeSeriesStatement();
1✔
291
    createTimeSeriesStatement.setPath(parseFullPath(ctx.fullPath()));
1✔
292
    if (ctx.attributeClauses() != null) {
1✔
293
      parseAttributeClausesForCreateNonAlignedTimeSeries(
1✔
294
          ctx.attributeClauses(), createTimeSeriesStatement);
1✔
295
    }
296
    return createTimeSeriesStatement;
1✔
297
  }
298

299
  @Override
300
  public Statement visitCreateAlignedTimeseries(IoTDBSqlParser.CreateAlignedTimeseriesContext ctx) {
301
    CreateAlignedTimeSeriesStatement createAlignedTimeSeriesStatement =
1✔
302
        new CreateAlignedTimeSeriesStatement();
303
    createAlignedTimeSeriesStatement.setDevicePath(parseFullPath(ctx.fullPath()));
1✔
304
    parseAlignedMeasurements(ctx.alignedMeasurements(), createAlignedTimeSeriesStatement);
1✔
305
    return createAlignedTimeSeriesStatement;
1✔
306
  }
307

308
  public void parseAlignedMeasurements(
309
      IoTDBSqlParser.AlignedMeasurementsContext ctx,
310
      CreateAlignedTimeSeriesStatement createAlignedTimeSeriesStatement) {
311
    for (int i = 0; i < ctx.nodeNameWithoutWildcard().size(); i++) {
1✔
312
      createAlignedTimeSeriesStatement.addMeasurement(
1✔
313
          parseNodeNameWithoutWildCard(ctx.nodeNameWithoutWildcard(i)));
1✔
314
      parseAttributeClausesForCreateAlignedTimeSeries(
1✔
315
          ctx.attributeClauses(i), createAlignedTimeSeriesStatement);
1✔
316
    }
317
  }
1✔
318

319
  public void parseAttributeClausesForCreateNonAlignedTimeSeries(
320
      IoTDBSqlParser.AttributeClausesContext ctx,
321
      CreateTimeSeriesStatement createTimeSeriesStatement) {
322
    if (ctx.aliasNodeName() != null) {
1✔
323
      createTimeSeriesStatement.setAlias(parseNodeName(ctx.aliasNodeName().nodeName()));
×
324
    }
325

326
    Map<String, String> props = new HashMap<>();
1✔
327
    TSDataType dataType = parseDataTypeAttribute(ctx);
1✔
328
    if (dataType != null) {
1✔
329
      props.put(
1✔
330
          IoTDBConstant.COLUMN_TIMESERIES_DATATYPE.toLowerCase(),
1✔
331
          dataType.toString().toLowerCase());
1✔
332
    }
333
    List<IoTDBSqlParser.AttributePairContext> attributePairs = ctx.attributePair();
1✔
334
    if (ctx.attributePair(0) != null) {
1✔
335
      for (IoTDBSqlParser.AttributePairContext attributePair : attributePairs) {
×
336
        props.put(
×
337
            parseAttributeKey(attributePair.attributeKey()).toLowerCase(),
×
338
            parseAttributeValue(attributePair.attributeValue()).toLowerCase());
×
339
      }
×
340
    }
341

342
    createTimeSeriesStatement.setProps(props);
1✔
343
    checkPropsInCreateTimeSeries(createTimeSeriesStatement);
1✔
344

345
    if (ctx.tagClause() != null) {
1✔
346
      parseTagClause(ctx.tagClause(), createTimeSeriesStatement);
1✔
347
    }
348
    if (ctx.attributeClause() != null) {
1✔
349
      parseAttributeClauseForTimeSeries(ctx.attributeClause(), createTimeSeriesStatement);
1✔
350
    }
351
  }
1✔
352

353
  /**
354
   * Check and set datatype, encoding, compressor.
355
   *
356
   * @throws SemanticException if encoding or dataType meets error handling
357
   */
358
  private void checkPropsInCreateTimeSeries(CreateTimeSeriesStatement createTimeSeriesStatement) {
359
    Map<String, String> props = createTimeSeriesStatement.getProps();
1✔
360
    if (props != null
1✔
361
        && props.containsKey(IoTDBConstant.COLUMN_TIMESERIES_DATATYPE.toLowerCase())) {
1✔
362
      String datatypeString =
1✔
363
          props.get(IoTDBConstant.COLUMN_TIMESERIES_DATATYPE.toLowerCase()).toUpperCase();
1✔
364
      try {
365
        createTimeSeriesStatement.setDataType(TSDataType.valueOf(datatypeString));
1✔
366
        props.remove(IoTDBConstant.COLUMN_TIMESERIES_DATATYPE.toLowerCase());
1✔
367
      } catch (Exception e) {
×
368
        throw new SemanticException(String.format("Unsupported datatype: %s", datatypeString));
×
369
      }
1✔
370
    }
371
    if (createTimeSeriesStatement.getDataType() == null) {
1✔
372
      throw new SemanticException("datatype must be declared");
×
373
    }
374

375
    final IoTDBDescriptor ioTDBDescriptor = IoTDBDescriptor.getInstance();
1✔
376
    createTimeSeriesStatement.setEncoding(
1✔
377
        ioTDBDescriptor.getDefaultEncodingByType(createTimeSeriesStatement.getDataType()));
1✔
378
    if (props != null
1✔
379
        && props.containsKey(IoTDBConstant.COLUMN_TIMESERIES_ENCODING.toLowerCase())) {
1✔
380
      String encodingString =
×
381
          props.get(IoTDBConstant.COLUMN_TIMESERIES_ENCODING.toLowerCase()).toUpperCase();
×
382
      try {
383
        createTimeSeriesStatement.setEncoding(TSEncoding.valueOf(encodingString));
×
384
        props.remove(IoTDBConstant.COLUMN_TIMESERIES_ENCODING.toLowerCase());
×
385
      } catch (Exception e) {
×
386
        throw new SemanticException(String.format("Unsupported encoding: %s", encodingString));
×
387
      }
×
388
    }
389

390
    createTimeSeriesStatement.setCompressor(
1✔
391
        TSFileDescriptor.getInstance().getConfig().getCompressor());
1✔
392
    if (props != null
1✔
393
        && props.containsKey(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSION.toLowerCase())) {
1✔
394
      String compressionString =
×
395
          props.get(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSION.toLowerCase()).toUpperCase();
×
396
      try {
397
        createTimeSeriesStatement.setCompressor(CompressionType.valueOf(compressionString));
×
398
        props.remove(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSION.toLowerCase());
×
399
      } catch (Exception e) {
×
400
        throw new SemanticException(
×
401
            String.format("Unsupported compression: %s", compressionString));
×
402
      }
×
403
    } else if (props != null
1✔
404
        && props.containsKey(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSOR.toLowerCase())) {
1✔
405
      String compressorString =
×
406
          props.get(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSOR.toLowerCase()).toUpperCase();
×
407
      try {
408
        createTimeSeriesStatement.setCompressor(CompressionType.valueOf(compressorString));
×
409
        props.remove(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSOR.toLowerCase());
×
410
      } catch (Exception e) {
×
411
        throw new SemanticException(String.format("Unsupported compression: %s", compressorString));
×
412
      }
×
413
    }
414
    createTimeSeriesStatement.setProps(props);
1✔
415
  }
1✔
416

417
  public void parseAttributeClausesForCreateAlignedTimeSeries(
418
      IoTDBSqlParser.AttributeClausesContext ctx,
419
      CreateAlignedTimeSeriesStatement createAlignedTimeSeriesStatement) {
420
    if (ctx.aliasNodeName() != null) {
1✔
421
      createAlignedTimeSeriesStatement.addAliasList(parseNodeName(ctx.aliasNodeName().nodeName()));
×
422
    } else {
423
      createAlignedTimeSeriesStatement.addAliasList(null);
1✔
424
    }
425

426
    TSDataType dataType = parseDataTypeAttribute(ctx);
1✔
427
    createAlignedTimeSeriesStatement.addDataType(dataType);
1✔
428

429
    Map<String, String> props = new HashMap<>();
1✔
430
    if (ctx.attributePair() != null) {
1✔
431
      for (int i = 0; i < ctx.attributePair().size(); i++) {
1✔
432
        props.put(
×
433
            parseAttributeKey(ctx.attributePair(i).attributeKey()).toLowerCase(),
×
434
            parseAttributeValue(ctx.attributePair(i).attributeValue()));
×
435
      }
436
    }
437

438
    TSEncoding encoding = IoTDBDescriptor.getInstance().getDefaultEncodingByType(dataType);
1✔
439
    if (props.containsKey(IoTDBConstant.COLUMN_TIMESERIES_ENCODING.toLowerCase())) {
1✔
440
      String encodingString =
×
441
          props.get(IoTDBConstant.COLUMN_TIMESERIES_ENCODING.toLowerCase()).toUpperCase();
×
442
      try {
443
        encoding = TSEncoding.valueOf(encodingString);
×
444
        createAlignedTimeSeriesStatement.addEncoding(encoding);
×
445
        props.remove(IoTDBConstant.COLUMN_TIMESERIES_ENCODING.toLowerCase());
×
446
      } catch (Exception e) {
×
447
        throw new SemanticException(String.format("unsupported encoding: %s", encodingString));
×
448
      }
×
449
    } else {
×
450
      createAlignedTimeSeriesStatement.addEncoding(encoding);
1✔
451
    }
452

453
    CompressionType compressor = TSFileDescriptor.getInstance().getConfig().getCompressor();
1✔
454
    if (props.containsKey(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSOR.toLowerCase())) {
1✔
455
      String compressorString =
×
456
          props.get(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSOR.toLowerCase()).toUpperCase();
×
457
      try {
458
        compressor = CompressionType.valueOf(compressorString);
×
459
        createAlignedTimeSeriesStatement.addCompressor(compressor);
×
460
        props.remove(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSOR.toLowerCase());
×
461
      } catch (Exception e) {
×
462
        throw new SemanticException(String.format("unsupported compressor: %s", compressorString));
×
463
      }
×
464
    } else if (props.containsKey(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSION.toLowerCase())) {
1✔
465
      String compressionString =
×
466
          props.get(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSION.toLowerCase()).toUpperCase();
×
467
      try {
468
        compressor = CompressionType.valueOf(compressionString);
×
469
        createAlignedTimeSeriesStatement.addCompressor(compressor);
×
470
        props.remove(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSION.toLowerCase());
×
471
      } catch (Exception e) {
×
472
        throw new SemanticException(
×
473
            String.format("unsupported compression: %s", compressionString));
×
474
      }
×
475
    } else {
×
476
      createAlignedTimeSeriesStatement.addCompressor(compressor);
1✔
477
    }
478

479
    if (props.size() > 0) {
1✔
480
      throw new SemanticException("create aligned timeseries: property is not supported yet.");
×
481
    }
482

483
    if (ctx.tagClause() != null) {
1✔
484
      parseTagClause(ctx.tagClause(), createAlignedTimeSeriesStatement);
×
485
    } else {
486
      createAlignedTimeSeriesStatement.addTagsList(null);
1✔
487
    }
488

489
    if (ctx.attributeClause() != null) {
1✔
490
      parseAttributeClauseForTimeSeries(ctx.attributeClause(), createAlignedTimeSeriesStatement);
×
491
    } else {
492
      createAlignedTimeSeriesStatement.addAttributesList(null);
1✔
493
    }
494
  }
1✔
495

496
  // Tag & Property & Attribute
497

498
  public void parseTagClause(IoTDBSqlParser.TagClauseContext ctx, Statement statement) {
499
    Map<String, String> tags = extractMap(ctx.attributePair(), ctx.attributePair(0));
1✔
500
    if (statement instanceof CreateTimeSeriesStatement) {
1✔
501
      ((CreateTimeSeriesStatement) statement).setTags(tags);
1✔
502
    } else if (statement instanceof CreateAlignedTimeSeriesStatement) {
×
503
      ((CreateAlignedTimeSeriesStatement) statement).addTagsList(tags);
×
504
    } else if (statement instanceof AlterTimeSeriesStatement) {
×
505
      ((AlterTimeSeriesStatement) statement).setTagsMap(tags);
×
506
    }
507
  }
1✔
508

509
  public void parseAttributeClauseForTimeSeries(
510
      IoTDBSqlParser.AttributeClauseContext ctx, Statement statement) {
511
    Map<String, String> attributes = extractMap(ctx.attributePair(), ctx.attributePair(0));
1✔
512
    if (statement instanceof CreateTimeSeriesStatement) {
1✔
513
      ((CreateTimeSeriesStatement) statement).setAttributes(attributes);
1✔
514
    } else if (statement instanceof CreateAlignedTimeSeriesStatement) {
×
515
      ((CreateAlignedTimeSeriesStatement) statement).addAttributesList(attributes);
×
516
    } else if (statement instanceof AlterTimeSeriesStatement) {
×
517
      ((AlterTimeSeriesStatement) statement).setAttributesMap(attributes);
×
518
    }
519
  }
1✔
520

521
  // Alter Timeseries ========================================================================
522

523
  @Override
524
  public Statement visitAlterTimeseries(IoTDBSqlParser.AlterTimeseriesContext ctx) {
525
    AlterTimeSeriesStatement alterTimeSeriesStatement = new AlterTimeSeriesStatement();
×
526
    alterTimeSeriesStatement.setPath(parseFullPath(ctx.fullPath()));
×
527
    parseAlterClause(ctx.alterClause(), alterTimeSeriesStatement);
×
528
    return alterTimeSeriesStatement;
×
529
  }
530

531
  private void parseAlterClause(
532
      IoTDBSqlParser.AlterClauseContext ctx, AlterTimeSeriesStatement alterTimeSeriesStatement) {
533
    Map<String, String> alterMap = new HashMap<>();
×
534
    // Rename
535
    if (ctx.RENAME() != null) {
×
536
      alterTimeSeriesStatement.setAlterType(AlterTimeSeriesStatement.AlterType.RENAME);
×
537
      alterMap.put(parseAttributeKey(ctx.beforeName), parseAttributeKey(ctx.currentName));
×
538
    } else if (ctx.SET() != null) {
×
539
      // Set
540
      alterTimeSeriesStatement.setAlterType(AlterTimeSeriesStatement.AlterType.SET);
×
541
      setMap(ctx, alterMap);
×
542
    } else if (ctx.DROP() != null) {
×
543
      // Drop
544
      alterTimeSeriesStatement.setAlterType(AlterTimeSeriesStatement.AlterType.DROP);
×
545
      for (int i = 0; i < ctx.attributeKey().size(); i++) {
×
546
        alterMap.put(parseAttributeKey(ctx.attributeKey().get(i)), null);
×
547
      }
548
    } else if (ctx.TAGS() != null) {
×
549
      // Add tag
550
      alterTimeSeriesStatement.setAlterType((AlterTimeSeriesStatement.AlterType.ADD_TAGS));
×
551
      setMap(ctx, alterMap);
×
552
    } else if (ctx.ATTRIBUTES() != null) {
×
553
      // Add attribute
554
      alterTimeSeriesStatement.setAlterType(AlterTimeSeriesStatement.AlterType.ADD_ATTRIBUTES);
×
555
      setMap(ctx, alterMap);
×
556
    } else {
557
      // Upsert
558
      alterTimeSeriesStatement.setAlterType(AlterTimeSeriesStatement.AlterType.UPSERT);
×
559
      if (ctx.aliasClause() != null) {
×
560
        parseAliasClause(ctx.aliasClause(), alterTimeSeriesStatement);
×
561
      }
562
      if (ctx.tagClause() != null) {
×
563
        parseTagClause(ctx.tagClause(), alterTimeSeriesStatement);
×
564
      }
565
      if (ctx.attributeClause() != null) {
×
566
        parseAttributeClauseForTimeSeries(ctx.attributeClause(), alterTimeSeriesStatement);
×
567
      }
568
    }
569
    alterTimeSeriesStatement.setAlterMap(alterMap);
×
570
  }
×
571

572
  public void parseAliasClause(
573
      IoTDBSqlParser.AliasClauseContext ctx, AlterTimeSeriesStatement alterTimeSeriesStatement) {
574
    if (alterTimeSeriesStatement != null && ctx.ALIAS() != null) {
×
575
      alterTimeSeriesStatement.setAlias(parseAliasNode(ctx.alias()));
×
576
    }
577
  }
×
578

579
  // Drop Timeseries ======================================================================
580

581
  @Override
582
  public Statement visitDropTimeseries(IoTDBSqlParser.DropTimeseriesContext ctx) {
583
    DeleteTimeSeriesStatement deleteTimeSeriesStatement = new DeleteTimeSeriesStatement();
×
584
    List<PartialPath> partialPaths = new ArrayList<>();
×
585
    for (IoTDBSqlParser.PrefixPathContext prefixPathContext : ctx.prefixPath()) {
×
586
      partialPaths.add(parsePrefixPath(prefixPathContext));
×
587
    }
×
588
    deleteTimeSeriesStatement.setPathPatternList(partialPaths);
×
589
    return deleteTimeSeriesStatement;
×
590
  }
591

592
  // Show Timeseries ========================================================================
593

594
  @Override
595
  public Statement visitShowTimeseries(IoTDBSqlParser.ShowTimeseriesContext ctx) {
596
    boolean orderByHeat = ctx.LATEST() != null;
×
597
    ShowTimeSeriesStatement showTimeSeriesStatement;
598
    if (ctx.prefixPath() != null) {
×
599
      showTimeSeriesStatement =
×
600
          new ShowTimeSeriesStatement(parsePrefixPath(ctx.prefixPath()), orderByHeat);
×
601
    } else {
602
      showTimeSeriesStatement =
×
603
          new ShowTimeSeriesStatement(
604
              new PartialPath(SqlConstant.getSingleRootArray()), orderByHeat);
×
605
    }
606
    if (ctx.timeseriesWhereClause() != null) {
×
607
      SchemaFilter schemaFilter = parseTimeseriesWhereClause(ctx.timeseriesWhereClause());
×
608
      showTimeSeriesStatement.setSchemaFilter(schemaFilter);
×
609
    }
610
    if (ctx.rowPaginationClause() != null) {
×
611
      if (ctx.rowPaginationClause().limitClause() != null) {
×
612
        showTimeSeriesStatement.setLimit(parseLimitClause(ctx.rowPaginationClause().limitClause()));
×
613
      }
614
      if (ctx.rowPaginationClause().offsetClause() != null) {
×
615
        showTimeSeriesStatement.setOffset(
×
616
            parseOffsetClause(ctx.rowPaginationClause().offsetClause()));
×
617
      }
618
    }
619
    return showTimeSeriesStatement;
×
620
  }
621

622
  private SchemaFilter parseTimeseriesWhereClause(IoTDBSqlParser.TimeseriesWhereClauseContext ctx) {
623
    if (ctx.timeseriesContainsExpression() != null) {
×
624
      // path contains filter
625
      return SchemaFilterFactory.createPathContainsFilter(
×
626
          parseStringLiteral(ctx.timeseriesContainsExpression().value.getText()));
×
627
    } else if (ctx.columnEqualsExpression() != null) {
×
628
      return parseColumnEqualsExpressionContext(ctx.columnEqualsExpression());
×
629
    } else {
630
      // tag filter
631
      if (ctx.tagContainsExpression() != null) {
×
632
        return SchemaFilterFactory.createTagFilter(
×
633
            parseAttributeKey(ctx.tagContainsExpression().attributeKey()),
×
634
            parseStringLiteral(ctx.tagContainsExpression().value.getText()),
×
635
            true);
636
      } else {
637
        return SchemaFilterFactory.createTagFilter(
×
638
            parseAttributeKey(ctx.tagEqualsExpression().attributeKey()),
×
639
            parseAttributeValue(ctx.tagEqualsExpression().attributeValue()),
×
640
            false);
641
      }
642
    }
643
  }
644

645
  private SchemaFilter parseColumnEqualsExpressionContext(
646
      IoTDBSqlParser.ColumnEqualsExpressionContext ctx) {
647
    String column = parseAttributeKey(ctx.attributeKey());
×
648
    String value = parseAttributeValue(ctx.attributeValue());
×
649
    if (column.equalsIgnoreCase(IoTDBConstant.COLUMN_TIMESERIES_DATATYPE)) {
×
650
      try {
651
        TSDataType dataType = TSDataType.valueOf(value.toUpperCase());
×
652
        return SchemaFilterFactory.createDataTypeFilter(dataType);
×
653
      } catch (Exception e) {
×
654
        throw new SemanticException(String.format("unsupported datatype: %s", value));
×
655
      }
656
    } else {
657
      throw new SemanticException("unexpected filter key");
×
658
    }
659
  }
660

661
  // SHOW DATABASES
662

663
  @Override
664
  public Statement visitShowDatabases(IoTDBSqlParser.ShowDatabasesContext ctx) {
665
    ShowDatabaseStatement showDatabaseStatement;
666

667
    // Parse prefixPath
668
    if (ctx.prefixPath() != null) {
×
669
      showDatabaseStatement = new ShowDatabaseStatement(parsePrefixPath(ctx.prefixPath()));
×
670
    } else {
671
      showDatabaseStatement =
×
672
          new ShowDatabaseStatement(new PartialPath(SqlConstant.getSingleRootArray()));
×
673
    }
674

675
    // Is detailed
676
    showDatabaseStatement.setDetailed(ctx.DETAILS() != null);
×
677

678
    return showDatabaseStatement;
×
679
  }
680

681
  // Show Devices ========================================================================
682

683
  @Override
684
  public Statement visitShowDevices(IoTDBSqlParser.ShowDevicesContext ctx) {
685
    ShowDevicesStatement showDevicesStatement;
686
    if (ctx.prefixPath() != null) {
×
687
      showDevicesStatement = new ShowDevicesStatement(parsePrefixPath(ctx.prefixPath()));
×
688
    } else {
689
      showDevicesStatement =
×
690
          new ShowDevicesStatement(new PartialPath(SqlConstant.getSingleRootArray()));
×
691
    }
692
    if (ctx.devicesWhereClause() != null) {
×
693
      showDevicesStatement.setSchemaFilter(parseDevicesWhereClause(ctx.devicesWhereClause()));
×
694
    }
695

696
    if (ctx.rowPaginationClause() != null) {
×
697
      if (ctx.rowPaginationClause().limitClause() != null) {
×
698
        showDevicesStatement.setLimit(parseLimitClause(ctx.rowPaginationClause().limitClause()));
×
699
      }
700
      if (ctx.rowPaginationClause().offsetClause() != null) {
×
701
        showDevicesStatement.setOffset(parseOffsetClause(ctx.rowPaginationClause().offsetClause()));
×
702
      }
703
    }
704
    // show devices with database
705
    if (ctx.WITH() != null) {
×
706
      showDevicesStatement.setSgCol(true);
×
707
    }
708
    return showDevicesStatement;
×
709
  }
710

711
  private SchemaFilter parseDevicesWhereClause(IoTDBSqlParser.DevicesWhereClauseContext ctx) {
712
    // path contains filter
713
    return SchemaFilterFactory.createPathContainsFilter(
×
714
        parseStringLiteral(ctx.deviceContainsExpression().value.getText()));
×
715
  }
716

717
  // Count Devices ========================================================================
718

719
  @Override
720
  public Statement visitCountDevices(CountDevicesContext ctx) {
721
    PartialPath path;
722
    if (ctx.prefixPath() != null) {
×
723
      path = parsePrefixPath(ctx.prefixPath());
×
724
    } else {
725
      path = new PartialPath(SqlConstant.getSingleRootArray());
×
726
    }
727
    return new CountDevicesStatement(path);
×
728
  }
729

730
  // Count TimeSeries ========================================================================
731
  @Override
732
  public Statement visitCountTimeseries(CountTimeseriesContext ctx) {
733
    Statement statement;
734
    PartialPath path;
735
    if (ctx.prefixPath() != null) {
×
736
      path = parsePrefixPath(ctx.prefixPath());
×
737
    } else {
738
      path = new PartialPath(SqlConstant.getSingleRootArray());
×
739
    }
740
    if (ctx.INTEGER_LITERAL() != null) {
×
741
      int level = Integer.parseInt(ctx.INTEGER_LITERAL().getText());
×
742
      statement = new CountLevelTimeSeriesStatement(path, level);
×
743
    } else {
×
744
      statement = new CountTimeSeriesStatement(path);
×
745
    }
746
    if (ctx.timeseriesWhereClause() != null) {
×
747
      SchemaFilter schemaFilter = parseTimeseriesWhereClause(ctx.timeseriesWhereClause());
×
748
      if (statement instanceof CountTimeSeriesStatement) {
×
749
        ((CountTimeSeriesStatement) statement).setSchemaFilter(schemaFilter);
×
750
      } else if (statement instanceof CountLevelTimeSeriesStatement) {
×
751
        ((CountLevelTimeSeriesStatement) statement).setSchemaFilter(schemaFilter);
×
752
      }
753
    }
754
    return statement;
×
755
  }
756

757
  // Count Nodes ========================================================================
758
  @Override
759
  public Statement visitCountNodes(CountNodesContext ctx) {
760
    PartialPath path;
761
    if (ctx.prefixPath() != null) {
×
762
      path = parsePrefixPath(ctx.prefixPath());
×
763
    } else {
764
      path = new PartialPath(SqlConstant.getSingleRootArray());
×
765
    }
766
    int level = Integer.parseInt(ctx.INTEGER_LITERAL().getText());
×
767
    return new CountNodesStatement(path, level);
×
768
  }
769

770
  // Count StorageGroup ========================================================================
771
  @Override
772
  public Statement visitCountDatabases(CountDatabasesContext ctx) {
773
    PartialPath path;
774
    if (ctx.prefixPath() != null) {
×
775
      path = parsePrefixPath(ctx.prefixPath());
×
776
    } else {
777
      path = new PartialPath(SqlConstant.getSingleRootArray());
×
778
    }
779
    return new CountDatabaseStatement(path);
×
780
  }
781

782
  // Show version
783
  @Override
784
  public Statement visitShowVersion(IoTDBSqlParser.ShowVersionContext ctx) {
785
    return new ShowVersionStatement();
×
786
  }
787

788
  // Create Function
789
  @Override
790
  public Statement visitCreateFunction(CreateFunctionContext ctx) {
791
    if (ctx.uriClause() == null) {
×
792
      return new CreateFunctionStatement(
×
793
          parseIdentifier(ctx.udfName.getText()),
×
794
          parseStringLiteral(ctx.className.getText()),
×
795
          false);
796
    } else {
797
      String uriString = parseAndValidateURI(ctx.uriClause());
×
798
      return new CreateFunctionStatement(
×
799
          parseIdentifier(ctx.udfName.getText()),
×
800
          parseStringLiteral(ctx.className.getText()),
×
801
          true,
802
          uriString);
803
    }
804
  }
805

806
  private String parseAndValidateURI(IoTDBSqlParser.UriClauseContext ctx) {
807
    String uriString = parseStringLiteral(ctx.uri().getText());
×
808
    try {
809
      new URI(uriString);
×
810
    } catch (URISyntaxException e) {
×
811
      throw new SemanticException(String.format("Invalid URI: %s", uriString));
×
812
    }
×
813
    return uriString;
×
814
  }
815

816
  // Drop Function
817
  @Override
818
  public Statement visitDropFunction(DropFunctionContext ctx) {
819
    return new DropFunctionStatement(parseIdentifier(ctx.udfName.getText()));
×
820
  }
821

822
  // Show Functions
823
  @Override
824
  public Statement visitShowFunctions(ShowFunctionsContext ctx) {
825
    return new ShowFunctionsStatement();
×
826
  }
827

828
  // Create Trigger =====================================================================
829
  @Override
830
  public Statement visitCreateTrigger(IoTDBSqlParser.CreateTriggerContext ctx) {
831
    if (ctx.triggerEventClause().DELETE() != null) {
×
832
      throw new SemanticException("Trigger does not support DELETE as TRIGGER_EVENT for now.");
×
833
    }
834
    if (ctx.triggerType() == null) {
×
835
      throw new SemanticException("Please specify trigger type: STATELESS or STATEFUL.");
×
836
    }
837
    Map<String, String> attributes = new HashMap<>();
×
838
    if (ctx.triggerAttributeClause() != null) {
×
839
      for (IoTDBSqlParser.TriggerAttributeContext triggerAttributeContext :
840
          ctx.triggerAttributeClause().triggerAttribute()) {
×
841
        attributes.put(
×
842
            parseAttributeKey(triggerAttributeContext.key),
×
843
            parseAttributeValue(triggerAttributeContext.value));
×
844
      }
×
845
    }
846
    if (ctx.uriClause() == null) {
×
847
      return new CreateTriggerStatement(
×
848
          parseIdentifier(ctx.triggerName.getText()),
×
849
          parseStringLiteral(ctx.className.getText()),
×
850
          "",
851
          false,
852
          ctx.triggerEventClause().BEFORE() != null
×
853
              ? TriggerEvent.BEFORE_INSERT
×
854
              : TriggerEvent.AFTER_INSERT,
×
855
          ctx.triggerType().STATELESS() != null ? TriggerType.STATELESS : TriggerType.STATEFUL,
×
856
          parsePrefixPath(ctx.prefixPath()),
×
857
          attributes);
858
    } else {
859
      String uriString = parseAndValidateURI(ctx.uriClause());
×
860
      return new CreateTriggerStatement(
×
861
          parseIdentifier(ctx.triggerName.getText()),
×
862
          parseStringLiteral(ctx.className.getText()),
×
863
          uriString,
864
          true,
865
          ctx.triggerEventClause().BEFORE() != null
×
866
              ? TriggerEvent.BEFORE_INSERT
×
867
              : TriggerEvent.AFTER_INSERT,
×
868
          ctx.triggerType().STATELESS() != null ? TriggerType.STATELESS : TriggerType.STATEFUL,
×
869
          parsePrefixPath(ctx.prefixPath()),
×
870
          attributes);
871
    }
872
  }
873

874
  // Drop Trigger =====================================================================
875
  @Override
876
  public Statement visitDropTrigger(IoTDBSqlParser.DropTriggerContext ctx) {
877
    return new DropTriggerStatement(parseIdentifier(ctx.triggerName.getText()));
×
878
  }
879

880
  // Show Trigger =====================================================================
881
  @Override
882
  public Statement visitShowTriggers(IoTDBSqlParser.ShowTriggersContext ctx) {
883
    return new ShowTriggersStatement();
×
884
  }
885

886
  // Create PipePlugin =====================================================================
887
  @Override
888
  public Statement visitCreatePipePlugin(IoTDBSqlParser.CreatePipePluginContext ctx) {
889
    return new CreatePipePluginStatement(
×
890
        ctx.pluginName.getText(),
×
891
        parseStringLiteral(ctx.className.getText()),
×
892
        parseAndValidateURI(ctx.uriClause()));
×
893
  }
894

895
  // Drop PipePlugin =====================================================================
896
  @Override
897
  public Statement visitDropPipePlugin(IoTDBSqlParser.DropPipePluginContext ctx) {
898
    return new DropPipePluginStatement(ctx.pluginName.getText());
×
899
  }
900

901
  // Show PipePlugins =====================================================================
902
  @Override
903
  public Statement visitShowPipePlugins(IoTDBSqlParser.ShowPipePluginsContext ctx) {
904
    return new ShowPipePluginsStatement();
×
905
  }
906

907
  // Show Child Paths =====================================================================
908
  @Override
909
  public Statement visitShowChildPaths(IoTDBSqlParser.ShowChildPathsContext ctx) {
910
    if (ctx.prefixPath() != null) {
×
911
      return new ShowChildPathsStatement(parsePrefixPath(ctx.prefixPath()));
×
912
    } else {
913
      return new ShowChildPathsStatement(new PartialPath(SqlConstant.getSingleRootArray()));
×
914
    }
915
  }
916

917
  // Show Child Nodes =====================================================================
918
  @Override
919
  public Statement visitShowChildNodes(IoTDBSqlParser.ShowChildNodesContext ctx) {
920
    if (ctx.prefixPath() != null) {
×
921
      return new ShowChildNodesStatement(parsePrefixPath(ctx.prefixPath()));
×
922
    } else {
923
      return new ShowChildNodesStatement(new PartialPath(SqlConstant.getSingleRootArray()));
×
924
    }
925
  }
926

927
  // Create CQ =====================================================================
928
  @Override
929
  public Statement visitCreateContinuousQuery(IoTDBSqlParser.CreateContinuousQueryContext ctx) {
930
    CreateContinuousQueryStatement statement = new CreateContinuousQueryStatement();
×
931

932
    statement.setCqId(parseIdentifier(ctx.cqId.getText()));
×
933

934
    QueryStatement queryBodyStatement =
×
935
        (QueryStatement) visitSelectStatement(ctx.selectStatement());
×
936
    queryBodyStatement.setCqQueryBody(true);
×
937
    statement.setQueryBodyStatement(queryBodyStatement);
×
938

939
    if (ctx.resampleClause() != null) {
×
940
      parseResampleClause(ctx.resampleClause(), statement);
×
941
    } else {
942
      QueryStatement queryStatement = statement.getQueryBodyStatement();
×
943
      if (!queryStatement.isGroupByTime()) {
×
944
        throw new SemanticException(
×
945
            "CQ: At least one of the parameters `every_interval` and `group_by_interval` needs to be specified.");
946
      }
947

948
      long interval = queryStatement.getGroupByTimeComponent().getInterval();
×
949
      statement.setEveryInterval(interval);
×
950
      statement.setStartTimeOffset(interval);
×
951
    }
952

953
    if (ctx.timeoutPolicyClause() != null) {
×
954
      parseTimeoutPolicyClause(ctx.timeoutPolicyClause(), statement);
×
955
    }
956

957
    return statement;
×
958
  }
959

960
  private void parseResampleClause(
961
      IoTDBSqlParser.ResampleClauseContext ctx, CreateContinuousQueryStatement statement) {
962
    if (ctx.EVERY() != null) {
×
963
      statement.setEveryInterval(
×
964
          DateTimeUtils.convertDurationStrToLong(ctx.everyInterval.getText()));
×
965
    } else {
966
      QueryStatement queryStatement = statement.getQueryBodyStatement();
×
967
      if (!queryStatement.isGroupByTime()) {
×
968
        throw new SemanticException(
×
969
            "CQ: At least one of the parameters `every_interval` and `group_by_interval` needs to be specified.");
970
      }
971
      statement.setEveryInterval(queryStatement.getGroupByTimeComponent().getInterval());
×
972
    }
973

974
    if (ctx.BOUNDARY() != null) {
×
975
      statement.setBoundaryTime(parseTimeValue(ctx.boundaryTime, DateTimeUtils.currentTime()));
×
976
    }
977

978
    if (ctx.RANGE() != null) {
×
979
      statement.setStartTimeOffset(
×
980
          DateTimeUtils.convertDurationStrToLong(ctx.startTimeOffset.getText()));
×
981
      if (ctx.endTimeOffset != null) {
×
982
        statement.setEndTimeOffset(
×
983
            DateTimeUtils.convertDurationStrToLong(ctx.endTimeOffset.getText()));
×
984
      }
985
    } else {
986
      statement.setStartTimeOffset(statement.getEveryInterval());
×
987
    }
988
  }
×
989

990
  private void parseTimeoutPolicyClause(
991
      IoTDBSqlParser.TimeoutPolicyClauseContext ctx, CreateContinuousQueryStatement statement) {
992
    if (ctx.DISCARD() != null) {
×
993
      statement.setTimeoutPolicy(TimeoutPolicy.DISCARD);
×
994
    }
995
  }
×
996

997
  // Drop CQ =====================================================================
998
  @Override
999
  public Statement visitDropContinuousQuery(IoTDBSqlParser.DropContinuousQueryContext ctx) {
1000
    return new DropContinuousQueryStatement(parseIdentifier(ctx.cqId.getText()));
×
1001
  }
1002

1003
  // Show CQs =====================================================================
1004
  @Override
1005
  public Statement visitShowContinuousQueries(IoTDBSqlParser.ShowContinuousQueriesContext ctx) {
1006
    return new ShowContinuousQueriesStatement();
×
1007
  }
1008

1009
  // Create Logical View
1010
  @Override
1011
  public Statement visitCreateLogicalView(IoTDBSqlParser.CreateLogicalViewContext ctx) {
1012
    CreateLogicalViewStatement createLogicalViewStatement = new CreateLogicalViewStatement();
×
1013
    // parse target
1014
    parseViewTargetPaths(
×
1015
        ctx.viewTargetPaths(),
×
1016
        createLogicalViewStatement::setTargetFullPaths,
×
1017
        createLogicalViewStatement::setTargetPathsGroup,
×
1018
        createLogicalViewStatement::setTargetIntoItem);
×
1019
    // parse source
1020
    parseViewSourcePaths(
×
1021
        ctx.viewSourcePaths(),
×
1022
        createLogicalViewStatement::setSourceFullPaths,
×
1023
        createLogicalViewStatement::setSourcePathsGroup,
×
1024
        createLogicalViewStatement::setSourceQueryStatement);
×
1025

1026
    return createLogicalViewStatement;
×
1027
  }
1028

1029
  @Override
1030
  public Statement visitDropLogicalView(IoTDBSqlParser.DropLogicalViewContext ctx) {
1031
    DeleteLogicalViewStatement deleteLogicalViewStatement = new DeleteLogicalViewStatement();
×
1032
    List<PartialPath> partialPaths = new ArrayList<>();
×
1033
    for (IoTDBSqlParser.PrefixPathContext prefixPathContext : ctx.prefixPath()) {
×
1034
      partialPaths.add(parsePrefixPath(prefixPathContext));
×
1035
    }
×
1036
    deleteLogicalViewStatement.setPathPatternList(partialPaths);
×
1037
    return deleteLogicalViewStatement;
×
1038
  }
1039

1040
  @Override
1041
  public Statement visitShowLogicalView(IoTDBSqlParser.ShowLogicalViewContext ctx) {
1042
    ShowLogicalViewStatement showLogicalViewStatement;
1043
    if (ctx.prefixPath() != null) {
×
1044
      showLogicalViewStatement = new ShowLogicalViewStatement(parsePrefixPath(ctx.prefixPath()));
×
1045
    } else {
1046
      showLogicalViewStatement =
×
1047
          new ShowLogicalViewStatement(new PartialPath(SqlConstant.getSingleRootArray()));
×
1048
    }
1049
    if (ctx.timeseriesWhereClause() != null) {
×
1050
      SchemaFilter schemaFilter = parseTimeseriesWhereClause(ctx.timeseriesWhereClause());
×
1051
      showLogicalViewStatement.setSchemaFilter(schemaFilter);
×
1052
    }
1053
    if (ctx.rowPaginationClause() != null) {
×
1054
      if (ctx.rowPaginationClause().limitClause() != null) {
×
1055
        showLogicalViewStatement.setLimit(
×
1056
            parseLimitClause(ctx.rowPaginationClause().limitClause()));
×
1057
      }
1058
      if (ctx.rowPaginationClause().offsetClause() != null) {
×
1059
        showLogicalViewStatement.setOffset(
×
1060
            parseOffsetClause(ctx.rowPaginationClause().offsetClause()));
×
1061
      }
1062
    }
1063
    return showLogicalViewStatement;
×
1064
  }
1065

1066
  @Override
1067
  public Statement visitRenameLogicalView(IoTDBSqlParser.RenameLogicalViewContext ctx) {
1068
    throw new SemanticException("Renaming view is not supported.");
×
1069
  }
1070

1071
  @Override
1072
  public Statement visitAlterLogicalView(IoTDBSqlParser.AlterLogicalViewContext ctx) {
1073
    if (ctx.alterClause() == null) {
×
1074
      AlterLogicalViewStatement alterLogicalViewStatement = new AlterLogicalViewStatement();
×
1075
      // parse target
1076
      parseViewTargetPaths(
×
1077
          ctx.viewTargetPaths(),
×
1078
          alterLogicalViewStatement::setTargetFullPaths,
×
1079
          alterLogicalViewStatement::setTargetPathsGroup,
×
1080
          intoItem -> {
1081
            if (intoItem != null) {
×
1082
              throw new SemanticException(
×
1083
                  "Can not use char '$' or into item in alter view statement.");
1084
            }
1085
          });
×
1086
      // parse source
1087
      parseViewSourcePaths(
×
1088
          ctx.viewSourcePaths(),
×
1089
          alterLogicalViewStatement::setSourceFullPaths,
×
1090
          alterLogicalViewStatement::setSourcePathsGroup,
×
1091
          alterLogicalViewStatement::setSourceQueryStatement);
×
1092

1093
      return alterLogicalViewStatement;
×
1094
    } else {
1095
      AlterTimeSeriesStatement alterTimeSeriesStatement = new AlterTimeSeriesStatement(true);
×
1096
      alterTimeSeriesStatement.setPath(parseFullPath(ctx.fullPath()));
×
1097
      parseAlterClause(ctx.alterClause(), alterTimeSeriesStatement);
×
1098
      if (alterTimeSeriesStatement.getAlias() != null) {
×
1099
        throw new SemanticException("View doesn't support alias.");
×
1100
      }
1101
      return alterTimeSeriesStatement;
×
1102
    }
1103
  }
1104

1105
  // parse suffix paths in logical view with into item
1106
  private PartialPath parseViewPrefixPathWithInto(IoTDBSqlParser.PrefixPathContext ctx) {
1107
    List<IoTDBSqlParser.NodeNameContext> nodeNames = ctx.nodeName();
×
1108
    String[] path = new String[nodeNames.size() + 1];
×
1109
    path[0] = ctx.ROOT().getText();
×
1110
    for (int i = 0; i < nodeNames.size(); i++) {
×
1111
      path[i + 1] = parseNodeStringInIntoPath(nodeNames.get(i).getText());
×
1112
    }
1113
    return new PartialPath(path);
×
1114
  }
1115

1116
  private PartialPath parseViewSuffixPatWithInto(IoTDBSqlParser.ViewSuffixPathsContext ctx) {
1117
    List<IoTDBSqlParser.NodeNameWithoutWildcardContext> nodeNamesWithoutStar =
×
1118
        ctx.nodeNameWithoutWildcard();
×
1119
    String[] nodeList = new String[nodeNamesWithoutStar.size()];
×
1120
    for (int i = 0; i < nodeNamesWithoutStar.size(); i++) {
×
1121
      nodeList[i] = parseNodeStringInIntoPath(nodeNamesWithoutStar.get(i).getText());
×
1122
    }
1123
    return new PartialPath(nodeList);
×
1124
  }
1125

1126
  private PartialPath parseViewSuffixPath(IoTDBSqlParser.ViewSuffixPathsContext ctx) {
1127
    List<IoTDBSqlParser.NodeNameWithoutWildcardContext> nodeNamesWithoutStar =
×
1128
        ctx.nodeNameWithoutWildcard();
×
1129
    String[] nodeList = new String[nodeNamesWithoutStar.size()];
×
1130
    for (int i = 0; i < nodeNamesWithoutStar.size(); i++) {
×
1131
      nodeList[i] = parseNodeNameWithoutWildCard(nodeNamesWithoutStar.get(i));
×
1132
    }
1133
    return new PartialPath(nodeList);
×
1134
  }
1135

1136
  // parse target paths in CreateLogicalView statement
1137
  private void parseViewTargetPaths(
1138
      IoTDBSqlParser.ViewTargetPathsContext ctx,
1139
      Consumer<List<PartialPath>> setTargetFullPaths,
1140
      BiConsumer<PartialPath, List<PartialPath>> setTargetPathsGroup,
1141
      Consumer<IntoItem> setTargetIntoItem) {
1142
    // full paths
1143
    if (ctx.fullPath() != null && !ctx.fullPath().isEmpty()) {
×
1144
      List<IoTDBSqlParser.FullPathContext> fullPathContextList = ctx.fullPath();
×
1145
      List<PartialPath> pathList = new ArrayList<>();
×
1146
      for (IoTDBSqlParser.FullPathContext pathContext : fullPathContextList) {
×
1147
        pathList.add(parseFullPath(pathContext));
×
1148
      }
×
1149
      setTargetFullPaths.accept(pathList);
×
1150
    }
1151
    // prefix path and suffix paths
1152
    if (ctx.prefixPath() != null
×
1153
        && ctx.viewSuffixPaths() != null
×
1154
        && !ctx.viewSuffixPaths().isEmpty()) {
×
1155
      IoTDBSqlParser.PrefixPathContext prefixPathContext = ctx.prefixPath();
×
1156
      List<IoTDBSqlParser.ViewSuffixPathsContext> suffixPathContextList = ctx.viewSuffixPaths();
×
1157
      List<PartialPath> suffixPathList = new ArrayList<>();
×
1158
      PartialPath prefixPath = null;
×
1159
      boolean isMultipleCreating = false;
×
1160
      try {
1161
        prefixPath = parsePrefixPath(prefixPathContext);
×
1162
        for (IoTDBSqlParser.ViewSuffixPathsContext suffixPathContext : suffixPathContextList) {
×
1163
          suffixPathList.add(parseViewSuffixPath(suffixPathContext));
×
1164
        }
×
1165
      } catch (SemanticException e) {
×
1166
        // there is '$', '{', '}' in this statement
1167
        isMultipleCreating = true;
×
1168
        suffixPathList.clear();
×
1169
      }
×
1170
      if (!isMultipleCreating) {
×
1171
        setTargetPathsGroup.accept(prefixPath, suffixPathList);
×
1172
      } else {
1173
        prefixPath = parseViewPrefixPathWithInto(prefixPathContext);
×
1174
        for (IoTDBSqlParser.ViewSuffixPathsContext suffixPathContext : suffixPathContextList) {
×
1175
          suffixPathList.add(parseViewSuffixPatWithInto(suffixPathContext));
×
1176
        }
×
1177
        List<String> intoMeasurementList = new ArrayList<>();
×
1178
        for (PartialPath path : suffixPathList) {
×
1179
          intoMeasurementList.add(path.toString());
×
1180
        }
×
1181
        IntoItem intoItem = new IntoItem(prefixPath, intoMeasurementList, false);
×
1182
        setTargetIntoItem.accept(intoItem);
×
1183
      }
1184
    }
1185
  }
×
1186

1187
  // parse source paths in CreateLogicalView statement
1188
  private void parseViewSourcePaths(
1189
      IoTDBSqlParser.ViewSourcePathsContext ctx,
1190
      Consumer<List<PartialPath>> setSourceFullPaths,
1191
      BiConsumer<PartialPath, List<PartialPath>> setSourcePathsGroup,
1192
      Consumer<QueryStatement> setSourceQueryStatement) {
1193
    // full paths
1194
    if (ctx.fullPath() != null && !ctx.fullPath().isEmpty()) {
×
1195
      List<IoTDBSqlParser.FullPathContext> fullPathContextList = ctx.fullPath();
×
1196
      List<PartialPath> pathList = new ArrayList<>();
×
1197
      for (IoTDBSqlParser.FullPathContext pathContext : fullPathContextList) {
×
1198
        pathList.add(parseFullPath(pathContext));
×
1199
      }
×
1200
      setSourceFullPaths.accept(pathList);
×
1201
    }
1202
    // prefix path and suffix paths
1203
    if (ctx.prefixPath() != null
×
1204
        && ctx.viewSuffixPaths() != null
×
1205
        && !ctx.viewSuffixPaths().isEmpty()) {
×
1206
      IoTDBSqlParser.PrefixPathContext prefixPathContext = ctx.prefixPath();
×
1207
      PartialPath prefixPath = parsePrefixPath(prefixPathContext);
×
1208
      List<IoTDBSqlParser.ViewSuffixPathsContext> suffixPathContextList = ctx.viewSuffixPaths();
×
1209
      List<PartialPath> suffixPathList = new ArrayList<>();
×
1210
      for (IoTDBSqlParser.ViewSuffixPathsContext suffixPathContext : suffixPathContextList) {
×
1211
        suffixPathList.add(parseViewSuffixPath(suffixPathContext));
×
1212
      }
×
1213
      setSourcePathsGroup.accept(prefixPath, suffixPathList);
×
1214
    }
1215
    if (ctx.selectClause() != null && ctx.fromClause() != null) {
×
1216
      QueryStatement queryStatement = new QueryStatement();
×
1217
      queryStatement.setSelectComponent(parseSelectClause(ctx.selectClause(), queryStatement));
×
1218
      queryStatement.setFromComponent(parseFromClause(ctx.fromClause()));
×
1219
      setSourceQueryStatement.accept(queryStatement);
×
1220
    }
1221
  }
×
1222

1223
  // Create Model =====================================================================
1224
  @Override
1225
  public Statement visitCreateModel(IoTDBSqlParser.CreateModelContext ctx) {
1226
    CreateModelStatement createModelStatement = new CreateModelStatement();
×
1227
    createModelStatement.setModelId(parseIdentifier(ctx.modelId.getText()));
×
1228
    createModelStatement.setAuto(ctx.AUTO() != null);
×
1229

1230
    Map<String, String> attributes = new HashMap<>();
×
1231
    for (IoTDBSqlParser.AttributePairContext attribute : ctx.attributePair()) {
×
1232
      attributes.put(
×
1233
          parseAttributeKey(attribute.key).toLowerCase(), parseAttributeValue(attribute.value));
×
1234
    }
×
1235
    createModelStatement.setAttributes(attributes);
×
1236

1237
    createModelStatement.setQueryStatement(
×
1238
        (QueryStatement) visitSelectStatement(ctx.selectStatement()));
×
1239
    return createModelStatement;
×
1240
  }
1241

1242
  // Drop Model =====================================================================
1243
  @Override
1244
  public Statement visitDropModel(IoTDBSqlParser.DropModelContext ctx) {
1245
    return new DropModelStatement(parseIdentifier(ctx.modelId.getText()));
×
1246
  }
1247

1248
  // Show Models =====================================================================
1249
  @Override
1250
  public Statement visitShowModels(IoTDBSqlParser.ShowModelsContext ctx) {
1251
    return new ShowModelsStatement();
×
1252
  }
1253

1254
  // Show Trails =====================================================================
1255
  @Override
1256
  public Statement visitShowTrails(IoTDBSqlParser.ShowTrailsContext ctx) {
1257
    return new ShowTrailsStatement(parseIdentifier(ctx.modelId.getText()));
×
1258
  }
1259

1260
  /** Data Manipulation Language (DML). */
1261

1262
  // Select Statement ========================================================================
1263
  @Override
1264
  public Statement visitSelectStatement(IoTDBSqlParser.SelectStatementContext ctx) {
1265
    QueryStatement queryStatement = new QueryStatement();
1✔
1266

1267
    // parse SELECT & FROM
1268
    queryStatement.setSelectComponent(parseSelectClause(ctx.selectClause(), queryStatement));
1✔
1269
    queryStatement.setFromComponent(parseFromClause(ctx.fromClause()));
1✔
1270

1271
    // parse INTO
1272
    if (ctx.intoClause() != null) {
1✔
1273
      queryStatement.setIntoComponent(parseIntoClause(ctx.intoClause()));
1✔
1274
    }
1275

1276
    // parse WHERE
1277
    if (ctx.whereClause() != null) {
1✔
1278
      queryStatement.setWhereCondition(parseWhereClause(ctx.whereClause()));
1✔
1279
    }
1280

1281
    // parse GROUP BY
1282
    if (ctx.groupByClause() != null) {
1✔
1283
      Set<String> groupByKeys = new HashSet<>();
1✔
1284
      List<IoTDBSqlParser.GroupByAttributeClauseContext> groupByAttributes =
1✔
1285
          ctx.groupByClause().groupByAttributeClause();
1✔
1286
      for (IoTDBSqlParser.GroupByAttributeClauseContext groupByAttribute : groupByAttributes) {
1✔
1287
        if (groupByAttribute.TIME() != null || groupByAttribute.interval != null) {
1✔
1288
          if (groupByKeys.contains("COMMON")) {
1✔
1289
            throw new SemanticException(GROUP_BY_COMMON_ONLY_ONE_MSG);
×
1290
          }
1291

1292
          groupByKeys.add("COMMON");
1✔
1293
          queryStatement.setGroupByTimeComponent(parseGroupByTimeClause(groupByAttribute));
1✔
1294
        } else if (groupByAttribute.LEVEL() != null) {
1✔
1295
          if (groupByKeys.contains("LEVEL")) {
1✔
1296
            throw new SemanticException("duplicated group by key: LEVEL");
×
1297
          }
1298

1299
          groupByKeys.add("LEVEL");
1✔
1300
          queryStatement.setGroupByLevelComponent(parseGroupByLevelClause(groupByAttribute));
1✔
1301
        } else if (groupByAttribute.TAGS() != null) {
1✔
1302
          if (groupByKeys.contains("TAGS")) {
1✔
1303
            throw new SemanticException("duplicated group by key: TAGS");
×
1304
          }
1305

1306
          groupByKeys.add("TAGS");
1✔
1307
          queryStatement.setGroupByTagComponent(parseGroupByTagClause(groupByAttribute));
1✔
1308
        } else if (groupByAttribute.VARIATION() != null) {
1✔
1309
          if (groupByKeys.contains("COMMON")) {
1✔
1310
            throw new SemanticException(GROUP_BY_COMMON_ONLY_ONE_MSG);
×
1311
          }
1312

1313
          groupByKeys.add("COMMON");
1✔
1314
          queryStatement.setGroupByComponent(
1✔
1315
              parseGroupByClause(groupByAttribute, WindowType.VARIATION_WINDOW));
1✔
1316
        } else if (groupByAttribute.CONDITION() != null) {
×
1317
          if (groupByKeys.contains("COMMON")) {
×
1318
            throw new SemanticException(GROUP_BY_COMMON_ONLY_ONE_MSG);
×
1319
          }
1320

1321
          groupByKeys.add("COMMON");
×
1322
          queryStatement.setGroupByComponent(
×
1323
              parseGroupByClause(groupByAttribute, WindowType.CONDITION_WINDOW));
×
1324
        } else if (groupByAttribute.SESSION() != null) {
×
1325
          if (groupByKeys.contains("COMMON")) {
×
1326
            throw new SemanticException(GROUP_BY_COMMON_ONLY_ONE_MSG);
×
1327
          }
1328

1329
          groupByKeys.add("COMMON");
×
1330
          queryStatement.setGroupByComponent(
×
1331
              parseGroupByClause(groupByAttribute, WindowType.SESSION_WINDOW));
×
1332
        } else if (groupByAttribute.COUNT() != null) {
×
1333
          if (groupByKeys.contains("COMMON")) {
×
1334
            throw new SemanticException(GROUP_BY_COMMON_ONLY_ONE_MSG);
×
1335
          }
1336

1337
          groupByKeys.add("COMMON");
×
1338
          queryStatement.setGroupByComponent(
×
1339
              parseGroupByClause(groupByAttribute, WindowType.COUNT_WINDOW));
×
1340

1341
        } else {
1342
          throw new SemanticException("Unknown GROUP BY type.");
×
1343
        }
1344
      }
1✔
1345
    }
1346

1347
    // parse HAVING
1348
    if (ctx.havingClause() != null) {
1✔
1349
      queryStatement.setHavingCondition(parseHavingClause(ctx.havingClause()));
1✔
1350
    }
1351

1352
    // parse ORDER BY
1353
    if (ctx.orderByClause() != null) {
1✔
1354
      queryStatement.setOrderByComponent(
1✔
1355
          parseOrderByClause(
1✔
1356
              ctx.orderByClause(),
1✔
1357
              ImmutableSet.of(OrderByKey.TIME, OrderByKey.DEVICE, OrderByKey.TIMESERIES)));
1✔
1358
    }
1359

1360
    // parse FILL
1361
    if (ctx.fillClause() != null) {
1✔
1362
      queryStatement.setFillComponent(parseFillClause(ctx.fillClause()));
1✔
1363
    }
1364

1365
    // parse ALIGN BY
1366
    if (ctx.alignByClause() != null) {
1✔
1367
      queryStatement.setResultSetFormat(parseAlignBy(ctx.alignByClause()));
1✔
1368
    }
1369

1370
    if (ctx.paginationClause() != null) {
1✔
1371
      // parse SLIMIT & SOFFSET
1372
      if (ctx.paginationClause().seriesPaginationClause() != null) {
1✔
1373
        if (ctx.paginationClause().seriesPaginationClause().slimitClause() != null) {
1✔
1374
          queryStatement.setSeriesLimit(
1✔
1375
              parseSLimitClause(ctx.paginationClause().seriesPaginationClause().slimitClause()));
1✔
1376
        }
1377
        if (ctx.paginationClause().seriesPaginationClause().soffsetClause() != null) {
1✔
1378
          queryStatement.setSeriesOffset(
1✔
1379
              parseSOffsetClause(ctx.paginationClause().seriesPaginationClause().soffsetClause()));
1✔
1380
        }
1381
      }
1382

1383
      // parse LIMIT & OFFSET
1384
      if (ctx.paginationClause().rowPaginationClause() != null) {
1✔
1385
        if (ctx.paginationClause().rowPaginationClause().limitClause() != null) {
1✔
1386
          queryStatement.setRowLimit(
1✔
1387
              parseLimitClause(ctx.paginationClause().rowPaginationClause().limitClause()));
1✔
1388
        }
1389
        if (ctx.paginationClause().rowPaginationClause().offsetClause() != null) {
1✔
1390
          queryStatement.setRowOffset(
1✔
1391
              parseOffsetClause(ctx.paginationClause().rowPaginationClause().offsetClause()));
1✔
1392
        }
1393
        if (canPushDownLimitOffsetToGroupByTime(queryStatement)) {
1✔
1394
          pushDownLimitOffsetToTimeParameter(queryStatement);
1✔
1395
        }
1396
      }
1397
    }
1398

1399
    queryStatement.setUseWildcard(useWildcard);
1✔
1400
    queryStatement.setLastLevelUseWildcard(lastLevelUseWildcard);
1✔
1401
    return queryStatement;
1✔
1402
  }
1403

1404
  // ---- Select Clause
1405
  private SelectComponent parseSelectClause(
1406
      IoTDBSqlParser.SelectClauseContext ctx, QueryStatement queryStatement) {
1407
    SelectComponent selectComponent = new SelectComponent(zoneId);
1✔
1408

1409
    // parse LAST
1410
    if (ctx.LAST() != null) {
1✔
1411
      selectComponent.setHasLast(true);
1✔
1412
    }
1413

1414
    // parse resultColumn
1415
    Map<String, Expression> aliasToColumnMap = new HashMap<>();
1✔
1416
    for (IoTDBSqlParser.ResultColumnContext resultColumnContext : ctx.resultColumn()) {
1✔
1417
      ResultColumn resultColumn = parseResultColumn(resultColumnContext);
1✔
1418
      // __endTime shouldn't be included in resultColumns
1419
      if (resultColumn.getExpression().getExpressionString().equals(ColumnHeaderConstant.ENDTIME)) {
1✔
1420
        queryStatement.setOutputEndTime(true);
×
1421
        continue;
×
1422
      }
1423
      if (resultColumn.hasAlias()) {
1✔
1424
        String alias = resultColumn.getAlias();
1✔
1425
        if (aliasToColumnMap.containsKey(alias)) {
1✔
1426
          throw new SemanticException("duplicate alias in select clause");
×
1427
        }
1428
        aliasToColumnMap.put(alias, resultColumn.getExpression());
1✔
1429
      }
1430
      selectComponent.addResultColumn(resultColumn);
1✔
1431
    }
1✔
1432
    selectComponent.setAliasToColumnMap(aliasToColumnMap);
1✔
1433

1434
    return selectComponent;
1✔
1435
  }
1436

1437
  private ResultColumn parseResultColumn(IoTDBSqlParser.ResultColumnContext resultColumnContext) {
1438
    Expression expression = parseExpression(resultColumnContext.expression(), false);
1✔
1439
    if (expression.isConstantOperand()) {
1✔
1440
      throw new SemanticException("Constant operand is not allowed: " + expression);
×
1441
    }
1442
    String alias = null;
1✔
1443
    if (resultColumnContext.AS() != null) {
1✔
1444
      alias = parseAlias(resultColumnContext.alias());
1✔
1445
    }
1446
    ResultColumn.ColumnType columnType =
1✔
1447
        ExpressionAnalyzer.identifyOutputColumnType(expression, true);
1✔
1448
    return new ResultColumn(expression, alias, columnType);
1✔
1449
  }
1450

1451
  // ---- From Clause
1452
  private FromComponent parseFromClause(IoTDBSqlParser.FromClauseContext ctx) {
1453
    FromComponent fromComponent = new FromComponent();
1✔
1454
    List<IoTDBSqlParser.PrefixPathContext> prefixFromPaths = ctx.prefixPath();
1✔
1455
    for (IoTDBSqlParser.PrefixPathContext prefixFromPath : prefixFromPaths) {
1✔
1456
      PartialPath path = parsePrefixPath(prefixFromPath);
1✔
1457
      fromComponent.addPrefixPath(path);
1✔
1458
    }
1✔
1459
    return fromComponent;
1✔
1460
  }
1461

1462
  // ---- Into Clause
1463
  private IntoComponent parseIntoClause(IoTDBSqlParser.IntoClauseContext ctx) {
1464
    List<IntoItem> intoItems = new ArrayList<>();
1✔
1465
    for (IoTDBSqlParser.IntoItemContext intoItemContext : ctx.intoItem()) {
1✔
1466
      intoItems.add(parseIntoItem(intoItemContext));
1✔
1467
    }
1✔
1468
    return new IntoComponent(intoItems);
1✔
1469
  }
1470

1471
  private IntoItem parseIntoItem(IoTDBSqlParser.IntoItemContext intoItemContext) {
1472
    boolean isAligned = intoItemContext.ALIGNED() != null;
1✔
1473
    PartialPath intoDevice = parseIntoPath(intoItemContext.intoPath());
1✔
1474
    List<String> intoMeasurements =
1✔
1475
        intoItemContext.nodeNameInIntoPath().stream()
1✔
1476
            .map(this::parseNodeNameInIntoPath)
1✔
1477
            .collect(Collectors.toList());
1✔
1478
    return new IntoItem(intoDevice, intoMeasurements, isAligned);
1✔
1479
  }
1480

1481
  private PartialPath parseIntoPath(IoTDBSqlParser.IntoPathContext intoPathContext) {
1482
    if (intoPathContext instanceof IoTDBSqlParser.FullPathInIntoPathContext) {
1✔
1483
      return parseFullPathInIntoPath((IoTDBSqlParser.FullPathInIntoPathContext) intoPathContext);
1✔
1484
    } else {
1485
      List<IoTDBSqlParser.NodeNameInIntoPathContext> nodeNames =
1✔
1486
          ((IoTDBSqlParser.SuffixPathInIntoPathContext) intoPathContext).nodeNameInIntoPath();
1✔
1487
      String[] path = new String[nodeNames.size()];
1✔
1488
      for (int i = 0; i < nodeNames.size(); i++) {
1✔
1489
        path[i] = parseNodeNameInIntoPath(nodeNames.get(i));
1✔
1490
      }
1491
      return new PartialPath(path);
1✔
1492
    }
1493
  }
1494

1495
  // ---- Where Clause
1496
  private WhereCondition parseWhereClause(IoTDBSqlParser.WhereClauseContext ctx) {
1497
    Expression predicate = parseExpression(ctx.expression(), true);
1✔
1498
    return new WhereCondition(predicate);
1✔
1499
  }
1500

1501
  // ---- Group By Clause
1502
  private GroupByTimeComponent parseGroupByTimeClause(
1503
      IoTDBSqlParser.GroupByAttributeClauseContext ctx) {
1504
    GroupByTimeComponent groupByTimeComponent = new GroupByTimeComponent();
1✔
1505

1506
    // Parse time range
1507
    if (ctx.timeRange() != null) {
1✔
1508
      parseTimeRangeForGroupByTime(ctx.timeRange(), groupByTimeComponent);
1✔
1509
      groupByTimeComponent.setLeftCRightO(ctx.timeRange().LS_BRACKET() != null);
1✔
1510
    }
1511

1512
    // Parse time interval
1513
    groupByTimeComponent.setInterval(
1✔
1514
        parseTimeIntervalOrSlidingStep(ctx.interval.getText(), true, groupByTimeComponent));
1✔
1515
    if (groupByTimeComponent.getInterval() <= 0) {
1✔
1516
      throw new SemanticException(
×
1517
          "The second parameter time interval should be a positive integer.");
1518
    }
1519

1520
    // parse sliding step
1521
    if (ctx.step != null) {
1✔
1522
      groupByTimeComponent.setSlidingStep(
1✔
1523
          parseTimeIntervalOrSlidingStep(ctx.step.getText(), false, groupByTimeComponent));
1✔
1524
    } else {
1525
      groupByTimeComponent.setSlidingStep(groupByTimeComponent.getInterval());
1✔
1526
      groupByTimeComponent.setSlidingStepByMonth(groupByTimeComponent.isIntervalByMonth());
1✔
1527
    }
1528

1529
    return groupByTimeComponent;
1✔
1530
  }
1531

1532
  /**
1533
   * Parse time range (startTime and endTime) in group by time.
1534
   *
1535
   * @throws SemanticException if startTime is larger or equals to endTime in timeRange
1536
   */
1537
  private void parseTimeRangeForGroupByTime(
1538
      IoTDBSqlParser.TimeRangeContext timeRange, GroupByTimeComponent groupByClauseComponent) {
1539
    long currentTime = DateTimeUtils.currentTime();
1✔
1540
    long startTime = parseTimeValue(timeRange.timeValue(0), currentTime);
1✔
1541
    long endTime = parseTimeValue(timeRange.timeValue(1), currentTime);
1✔
1542
    groupByClauseComponent.setStartTime(startTime);
1✔
1543
    groupByClauseComponent.setEndTime(endTime);
1✔
1544
    if (startTime >= endTime) {
1✔
1545
      throw new SemanticException("Start time should be smaller than endTime in GroupBy");
×
1546
    }
1547
  }
1✔
1548

1549
  /**
1550
   * parse time interval or sliding step in group by query.
1551
   *
1552
   * @param duration represent duration string like: 12d8m9ns, 1y1d, etc.
1553
   * @return time in milliseconds, microseconds, or nanoseconds depending on the profile
1554
   */
1555
  private long parseTimeIntervalOrSlidingStep(
1556
      String duration, boolean isParsingTimeInterval, GroupByTimeComponent groupByTimeComponent) {
1557
    if (duration.toLowerCase().contains("mo")) {
1✔
1558
      if (isParsingTimeInterval) {
×
1559
        groupByTimeComponent.setIntervalByMonth(true);
×
1560
      } else {
1561
        groupByTimeComponent.setSlidingStepByMonth(true);
×
1562
      }
1563
    }
1564
    return DateTimeUtils.convertDurationStrToLong(duration);
1✔
1565
  }
1566

1567
  private GroupByComponent parseGroupByClause(
1568
      GroupByAttributeClauseContext ctx, WindowType windowType) {
1569

1570
    boolean ignoringNull = true;
1✔
1571
    if (ctx.attributePair() != null
1✔
1572
        && !ctx.attributePair().isEmpty()
×
1573
        && ctx.attributePair().key.getText().equalsIgnoreCase(IGNORENULL)) {
×
1574
      ignoringNull = Boolean.parseBoolean(ctx.attributePair().value.getText());
×
1575
    }
1576
    List<ExpressionContext> expressions = ctx.expression();
1✔
1577
    if (windowType == WindowType.VARIATION_WINDOW) {
1✔
1578
      ExpressionContext expressionContext = expressions.get(0);
1✔
1579
      GroupByVariationComponent groupByVariationComponent = new GroupByVariationComponent();
1✔
1580
      groupByVariationComponent.setControlColumnExpression(
1✔
1581
          parseExpression(expressionContext, true));
1✔
1582
      groupByVariationComponent.setDelta(
1✔
1583
          ctx.delta == null ? 0 : Double.parseDouble(ctx.delta.getText()));
1✔
1584
      groupByVariationComponent.setIgnoringNull(ignoringNull);
1✔
1585
      return groupByVariationComponent;
1✔
1586
    } else if (windowType == WindowType.CONDITION_WINDOW) {
×
1587
      ExpressionContext conditionExpressionContext = expressions.get(0);
×
1588
      GroupByConditionComponent groupByConditionComponent = new GroupByConditionComponent();
×
1589
      groupByConditionComponent.setControlColumnExpression(
×
1590
          parseExpression(conditionExpressionContext, true));
×
1591
      if (expressions.size() == 2) {
×
1592
        groupByConditionComponent.setKeepExpression(parseExpression(expressions.get(1), true));
×
1593
      }
1594
      groupByConditionComponent.setIgnoringNull(ignoringNull);
×
1595
      return groupByConditionComponent;
×
1596
    } else if (windowType == WindowType.SESSION_WINDOW) {
×
1597
      long interval = DateTimeUtils.convertDurationStrToLong(ctx.timeInterval.getText());
×
1598
      return new GroupBySessionComponent(interval);
×
1599
    } else if (windowType == WindowType.COUNT_WINDOW) {
×
1600
      ExpressionContext countExpressionContext = expressions.get(0);
×
1601
      long countNumber = Long.parseLong(ctx.countNumber.getText());
×
1602
      GroupByCountComponent groupByCountComponent = new GroupByCountComponent(countNumber);
×
1603
      groupByCountComponent.setControlColumnExpression(
×
1604
          parseExpression(countExpressionContext, true));
×
1605
      groupByCountComponent.setIgnoringNull(ignoringNull);
×
1606
      return groupByCountComponent;
×
1607
    } else {
1608
      throw new SemanticException("Unsupported window type");
×
1609
    }
1610
  }
1611

1612
  private GroupByLevelComponent parseGroupByLevelClause(
1613
      IoTDBSqlParser.GroupByAttributeClauseContext ctx) {
1614
    GroupByLevelComponent groupByLevelComponent = new GroupByLevelComponent();
1✔
1615
    int[] levels = new int[ctx.INTEGER_LITERAL().size()];
1✔
1616
    for (int i = 0; i < ctx.INTEGER_LITERAL().size(); i++) {
1✔
1617
      levels[i] = Integer.parseInt(ctx.INTEGER_LITERAL().get(i).getText());
1✔
1618
    }
1619
    groupByLevelComponent.setLevels(levels);
1✔
1620
    return groupByLevelComponent;
1✔
1621
  }
1622

1623
  private GroupByTagComponent parseGroupByTagClause(
1624
      IoTDBSqlParser.GroupByAttributeClauseContext ctx) {
1625
    Set<String> tagKeys = new LinkedHashSet<>();
1✔
1626
    for (IdentifierContext identifierContext : ctx.identifier()) {
1✔
1627
      String key = parseIdentifier(identifierContext.getText());
1✔
1628
      if (tagKeys.contains(key)) {
1✔
1629
        throw new SemanticException("duplicated key in GROUP BY TAGS: " + key);
1✔
1630
      }
1631
      tagKeys.add(key);
1✔
1632
    }
1✔
1633
    return new GroupByTagComponent(new ArrayList<>(tagKeys));
1✔
1634
  }
1635

1636
  // ---- Having Clause
1637
  private HavingCondition parseHavingClause(IoTDBSqlParser.HavingClauseContext ctx) {
1638
    Expression predicate = parseExpression(ctx.expression(), true);
1✔
1639
    return new HavingCondition(predicate);
1✔
1640
  }
1641

1642
  // ---- Order By Clause
1643
  // all SortKeys should be contained by limitSet
1644
  private OrderByComponent parseOrderByClause(
1645
      IoTDBSqlParser.OrderByClauseContext ctx, ImmutableSet<String> limitSet) {
1646
    OrderByComponent orderByComponent = new OrderByComponent();
1✔
1647
    Set<String> sortKeySet = new HashSet<>();
1✔
1648
    for (IoTDBSqlParser.OrderByAttributeClauseContext orderByAttributeClauseContext :
1649
        ctx.orderByAttributeClause()) {
1✔
1650
      // if the order by clause is unique, then the following sort keys will be ignored
1651
      if (orderByComponent.isUnique()) {
1✔
1652
        break;
×
1653
      }
1654
      SortItem sortItem = parseOrderByAttributeClause(orderByAttributeClauseContext, limitSet);
1✔
1655

1656
      String sortKey = sortItem.getSortKey();
1✔
1657
      if (sortKeySet.contains(sortKey)) {
1✔
1658
        continue;
×
1659
      } else {
1660
        sortKeySet.add(sortKey);
1✔
1661
      }
1662

1663
      if (sortItem.isExpression()) {
1✔
1664
        orderByComponent.addExpressionSortItem(sortItem);
1✔
1665
      } else {
1666
        orderByComponent.addSortItem(sortItem);
1✔
1667
      }
1668
    }
1✔
1669
    return orderByComponent;
1✔
1670
  }
1671

1672
  private SortItem parseOrderByAttributeClause(
1673
      IoTDBSqlParser.OrderByAttributeClauseContext ctx, ImmutableSet<String> limitSet) {
1674
    if (ctx.sortKey() != null) {
1✔
1675
      String sortKey = ctx.sortKey().getText().toUpperCase();
1✔
1676
      if (!limitSet.contains(sortKey)) {
1✔
1677
        throw new SemanticException(
×
1678
            String.format("ORDER BY: sort key[%s] is not contained in '%s'", sortKey, limitSet));
×
1679
      }
1680
      return new SortItem(sortKey, ctx.DESC() != null ? Ordering.DESC : Ordering.ASC);
1✔
1681
    } else {
1682
      Expression sortExpression = parseExpression(ctx.expression(), true);
1✔
1683
      return new SortItem(
1✔
1684
          sortExpression,
1685
          ctx.DESC() != null ? Ordering.DESC : Ordering.ASC,
1✔
1686
          ctx.FIRST() != null ? NullOrdering.FIRST : NullOrdering.LAST);
1✔
1687
    }
1688
  }
1689

1690
  // ---- Fill Clause
1691
  public FillComponent parseFillClause(IoTDBSqlParser.FillClauseContext ctx) {
1692
    FillComponent fillComponent = new FillComponent();
1✔
1693
    if (ctx.LINEAR() != null) {
1✔
1694
      fillComponent.setFillPolicy(FillPolicy.LINEAR);
1✔
1695
    } else if (ctx.PREVIOUS() != null) {
1✔
1696
      fillComponent.setFillPolicy(FillPolicy.PREVIOUS);
1✔
1697
    } else if (ctx.constant() != null) {
1✔
1698
      fillComponent.setFillPolicy(FillPolicy.VALUE);
1✔
1699
      Literal fillValue = parseLiteral(ctx.constant());
1✔
1700
      fillComponent.setFillValue(fillValue);
1✔
1701
    } else {
1✔
1702
      throw new SemanticException("Unknown FILL type.");
×
1703
    }
1704
    return fillComponent;
1✔
1705
  }
1706

1707
  private Literal parseLiteral(ConstantContext constantContext) {
1708
    String text = constantContext.getText();
1✔
1709
    if (constantContext.boolean_literal() != null) {
1✔
1710
      return new BooleanLiteral(text);
×
1711
    } else if (constantContext.STRING_LITERAL() != null) {
1✔
1712
      return new StringLiteral(parseStringLiteral(text));
×
1713
    } else if (constantContext.INTEGER_LITERAL() != null) {
1✔
1714
      return new LongLiteral(text);
1✔
1715
    } else if (constantContext.realLiteral() != null) {
×
1716
      return new DoubleLiteral(text);
×
1717
    } else if (constantContext.dateExpression() != null) {
×
1718
      return new LongLiteral(parseDateExpression(constantContext.dateExpression()));
×
1719
    } else {
1720
      throw new SemanticException("Unsupported constant value in FILL: " + text);
×
1721
    }
1722
  }
1723

1724
  // parse LIMIT & OFFSET
1725
  private long parseLimitClause(IoTDBSqlParser.LimitClauseContext ctx) {
1726
    long limit;
1727
    try {
1728
      limit = Long.parseLong(ctx.INTEGER_LITERAL().getText());
1✔
1729
    } catch (NumberFormatException e) {
×
1730
      throw new SemanticException("Out of range. LIMIT <N>: N should be Int64.");
×
1731
    }
1✔
1732
    if (limit <= 0) {
1✔
1733
      throw new SemanticException("LIMIT <N>: N should be greater than 0.");
×
1734
    }
1735
    return limit;
1✔
1736
  }
1737

1738
  private long parseOffsetClause(IoTDBSqlParser.OffsetClauseContext ctx) {
1739
    long offset;
1740
    try {
1741
      offset = Long.parseLong(ctx.INTEGER_LITERAL().getText());
1✔
1742
    } catch (NumberFormatException e) {
×
1743
      throw new SemanticException(
×
1744
          "Out of range. OFFSET <OFFSETValue>: OFFSETValue should be Int64.");
1745
    }
1✔
1746
    if (offset < 0) {
1✔
1747
      throw new SemanticException("OFFSET <OFFSETValue>: OFFSETValue should >= 0.");
×
1748
    }
1749
    return offset;
1✔
1750
  }
1751

1752
  // parse SLIMIT & SOFFSET
1753
  private int parseSLimitClause(IoTDBSqlParser.SlimitClauseContext ctx) {
1754
    int slimit;
1755
    try {
1756
      slimit = Integer.parseInt(ctx.INTEGER_LITERAL().getText());
1✔
1757
    } catch (NumberFormatException e) {
×
1758
      throw new SemanticException("Out of range. SLIMIT <SN>: SN should be Int32.");
×
1759
    }
1✔
1760
    if (slimit <= 0) {
1✔
1761
      throw new SemanticException("SLIMIT <SN>: SN should be greater than 0.");
×
1762
    }
1763
    return slimit;
1✔
1764
  }
1765

1766
  // parse SOFFSET
1767
  public int parseSOffsetClause(IoTDBSqlParser.SoffsetClauseContext ctx) {
1768
    int soffset;
1769
    try {
1770
      soffset = Integer.parseInt(ctx.INTEGER_LITERAL().getText());
1✔
1771
    } catch (NumberFormatException e) {
×
1772
      throw new SemanticException(
×
1773
          "Out of range. SOFFSET <SOFFSETValue>: SOFFSETValue should be Int32.");
1774
    }
1✔
1775
    if (soffset < 0) {
1✔
1776
      throw new SemanticException("SOFFSET <SOFFSETValue>: SOFFSETValue should >= 0.");
×
1777
    }
1778
    return soffset;
1✔
1779
  }
1780

1781
  // ---- Align By Clause
1782
  private ResultSetFormat parseAlignBy(IoTDBSqlParser.AlignByClauseContext ctx) {
1783
    if (ctx.DEVICE() != null) {
1✔
1784
      return ResultSetFormat.ALIGN_BY_DEVICE;
1✔
1785
    } else {
1786
      return ResultSetFormat.ALIGN_BY_TIME;
×
1787
    }
1788
  }
1789

1790
  // Insert Statement ========================================================================
1791

1792
  @Override
1793
  public Statement visitInsertStatement(IoTDBSqlParser.InsertStatementContext ctx) {
1794
    InsertStatement insertStatement = new InsertStatement();
1✔
1795
    insertStatement.setDevice(parsePrefixPath(ctx.prefixPath()));
1✔
1796
    boolean isTimeDefault = parseInsertColumnSpec(ctx.insertColumnsSpec(), insertStatement);
1✔
1797
    parseInsertValuesSpec(ctx.insertValuesSpec(), insertStatement, isTimeDefault);
1✔
1798
    insertStatement.setAligned(ctx.ALIGNED() != null);
1✔
1799
    return insertStatement;
1✔
1800
  }
1801

1802
  private boolean parseInsertColumnSpec(
1803
      IoTDBSqlParser.InsertColumnsSpecContext ctx, InsertStatement insertStatement) {
1804
    List<String> measurementList = new ArrayList<>();
1✔
1805
    for (IoTDBSqlParser.NodeNameWithoutWildcardContext measurementName :
1806
        ctx.nodeNameWithoutWildcard()) {
1✔
1807
      measurementList.add(parseNodeNameWithoutWildCard(measurementName));
1✔
1808
    }
1✔
1809
    insertStatement.setMeasurementList(measurementList.toArray(new String[0]));
1✔
1810
    return (ctx.TIME() == null && ctx.TIMESTAMP() == null);
1✔
1811
  }
1812

1813
  private void parseInsertValuesSpec(
1814
      IoTDBSqlParser.InsertValuesSpecContext ctx,
1815
      InsertStatement insertStatement,
1816
      boolean isTimeDefault) {
1817
    List<IoTDBSqlParser.InsertMultiValueContext> insertMultiValues = ctx.insertMultiValue();
1✔
1818
    List<String[]> valuesList = new ArrayList<>();
1✔
1819
    long[] timeArray = new long[insertMultiValues.size()];
1✔
1820
    for (int i = 0; i < insertMultiValues.size(); i++) {
1✔
1821
      // parse timestamp
1822
      long timestamp;
1823
      List<String> valueList = new ArrayList<>();
1✔
1824

1825
      if (insertMultiValues.get(i).timeValue() != null) {
1✔
1826
        if (isTimeDefault) {
1✔
1827
          if (insertMultiValues.size() != 1) {
×
1828
            throw new SemanticException("need timestamps when insert multi rows");
×
1829
          }
1830
          valueList.add(insertMultiValues.get(i).timeValue().getText());
×
1831
          timestamp = DateTimeUtils.currentTime();
×
1832
        } else {
1833
          timestamp =
1✔
1834
              parseTimeValue(insertMultiValues.get(i).timeValue(), DateTimeUtils.currentTime());
1✔
1835
        }
1836
      } else {
1837
        if (!isTimeDefault) {
×
1838
          throw new SemanticException(
×
1839
              "the measurementList's size is not consistent with the valueList's size");
1840
        }
1841
        if (insertMultiValues.size() != 1) {
×
1842
          throw new SemanticException("need timestamps when insert multi rows");
×
1843
        }
1844
        timestamp = parseDateFormat(SqlConstant.NOW_FUNC);
×
1845
      }
1846
      timeArray[i] = timestamp;
1✔
1847

1848
      // parse values
1849
      List<IoTDBSqlParser.MeasurementValueContext> values =
1✔
1850
          insertMultiValues.get(i).measurementValue();
1✔
1851
      for (IoTDBSqlParser.MeasurementValueContext value : values) {
1✔
1852
        for (IoTDBSqlParser.ConstantContext constant : value.constant()) {
1✔
1853
          if (constant.STRING_LITERAL() != null) {
1✔
1854
            valueList.add(parseStringLiteralInInsertValue(constant.getText()));
×
1855
          } else {
1856
            valueList.add(constant.getText());
1✔
1857
          }
1858
        }
1✔
1859
      }
1✔
1860
      valuesList.add(valueList.toArray(new String[0]));
1✔
1861
    }
1862
    insertStatement.setTimes(timeArray);
1✔
1863
    insertStatement.setValuesList(valuesList);
1✔
1864
  }
1✔
1865

1866
  // Load File
1867

1868
  @Override
1869
  public Statement visitLoadFile(IoTDBSqlParser.LoadFileContext ctx) {
1870
    try {
1871
      LoadTsFileStatement loadTsFileStatement =
×
1872
          new LoadTsFileStatement(parseStringLiteral(ctx.fileName.getText()));
×
1873
      if (ctx.loadFileAttributeClauses() != null) {
×
1874
        for (IoTDBSqlParser.LoadFileAttributeClauseContext attributeContext :
1875
            ctx.loadFileAttributeClauses().loadFileAttributeClause()) {
×
1876
          parseLoadFileAttributeClause(loadTsFileStatement, attributeContext);
×
1877
        }
×
1878
      }
1879
      return loadTsFileStatement;
×
1880
    } catch (FileNotFoundException e) {
×
1881
      throw new SemanticException(e.getMessage());
×
1882
    }
1883
  }
1884

1885
  /**
1886
   * Used for parsing load tsfile, context will be one of "SCHEMA, LEVEL, METADATA", and maybe
1887
   * followed by a recursion property statement.
1888
   *
1889
   * @param loadTsFileStatement the result statement, setting by clause context
1890
   * @param ctx context of property statement
1891
   * @throws SemanticException if AUTOREGISTER | SGLEVEL | VERIFY are not specified
1892
   */
1893
  private void parseLoadFileAttributeClause(
1894
      LoadTsFileStatement loadTsFileStatement, IoTDBSqlParser.LoadFileAttributeClauseContext ctx) {
1895
    if (ctx.ONSUCCESS() != null) {
×
1896
      loadTsFileStatement.setDeleteAfterLoad(ctx.DELETE() != null);
×
1897
    } else if (ctx.SGLEVEL() != null) {
×
1898
      loadTsFileStatement.setDatabaseLevel(Integer.parseInt(ctx.INTEGER_LITERAL().getText()));
×
1899
    } else if (ctx.VERIFY() != null) {
×
1900
      loadTsFileStatement.setVerifySchema(Boolean.parseBoolean(ctx.boolean_literal().getText()));
×
1901
    } else {
1902
      throw new SemanticException(
×
1903
          String.format(
×
1904
              "Load tsfile format %s error, please input AUTOREGISTER | SGLEVEL | VERIFY.",
1905
              ctx.getText()));
×
1906
    }
1907
  }
×
1908

1909
  /** Common Parsers. */
1910

1911
  // IoTDB Objects ========================================================================
1912
  private PartialPath parseFullPath(IoTDBSqlParser.FullPathContext ctx) {
1913
    List<IoTDBSqlParser.NodeNameWithoutWildcardContext> nodeNamesWithoutStar =
1✔
1914
        ctx.nodeNameWithoutWildcard();
1✔
1915
    String[] path = new String[nodeNamesWithoutStar.size() + 1];
1✔
1916
    int i = 0;
1✔
1917
    if (ctx.ROOT() != null) {
1✔
1918
      path[0] = ctx.ROOT().getText();
1✔
1919
    }
1920
    for (IoTDBSqlParser.NodeNameWithoutWildcardContext nodeNameWithoutStar : nodeNamesWithoutStar) {
1✔
1921
      i++;
1✔
1922
      path[i] = parseNodeNameWithoutWildCard(nodeNameWithoutStar);
1✔
1923
    }
1✔
1924
    return new PartialPath(path);
1✔
1925
  }
1926

1927
  private PartialPath parseFullPathInExpression(
1928
      IoTDBSqlParser.FullPathInExpressionContext ctx, boolean canUseFullPath) {
1929
    List<IoTDBSqlParser.NodeNameContext> nodeNames = ctx.nodeName();
1✔
1930
    int size = nodeNames.size();
1✔
1931
    if (ctx.ROOT() != null) {
1✔
1932
      if (!canUseFullPath) {
1✔
1933
        // now full path cannot occur in SELECT only
1934
        throw new SemanticException("Path can not start with root in select clause.");
×
1935
      }
1936
      size++;
1✔
1937
    }
1938
    String[] path = new String[size];
1✔
1939
    if (ctx.ROOT() != null) {
1✔
1940
      path[0] = ctx.ROOT().getText();
1✔
1941
      for (int i = 0; i < nodeNames.size(); i++) {
1✔
1942
        path[i + 1] = parseNodeName(nodeNames.get(i));
1✔
1943
      }
1944
    } else {
1945
      for (int i = 0; i < nodeNames.size(); i++) {
1✔
1946
        path[i] = parseNodeName(nodeNames.get(i));
1✔
1947
      }
1948
    }
1949
    if (!lastLevelUseWildcard
1✔
1950
        && !nodeNames.isEmpty()
1✔
1951
        && !nodeNames.get(nodeNames.size() - 1).wildcard().isEmpty()) {
1✔
1952
      lastLevelUseWildcard = true;
1✔
1953
    }
1954
    return new PartialPath(path);
1✔
1955
  }
1956

1957
  private PartialPath parseFullPathInIntoPath(IoTDBSqlParser.FullPathInIntoPathContext ctx) {
1958
    List<IoTDBSqlParser.NodeNameInIntoPathContext> nodeNames = ctx.nodeNameInIntoPath();
1✔
1959
    String[] path = new String[nodeNames.size() + 1];
1✔
1960
    int i = 0;
1✔
1961
    if (ctx.ROOT() != null) {
1✔
1962
      path[0] = ctx.ROOT().getText();
1✔
1963
    }
1964
    for (IoTDBSqlParser.NodeNameInIntoPathContext nodeName : nodeNames) {
1✔
1965
      i++;
1✔
1966
      path[i] = parseNodeNameInIntoPath(nodeName);
1✔
1967
    }
1✔
1968
    return new PartialPath(path);
1✔
1969
  }
1970

1971
  private PartialPath parsePrefixPath(IoTDBSqlParser.PrefixPathContext ctx) {
1972
    List<IoTDBSqlParser.NodeNameContext> nodeNames = ctx.nodeName();
1✔
1973
    String[] path = new String[nodeNames.size() + 1];
1✔
1974
    path[0] = ctx.ROOT().getText();
1✔
1975
    for (int i = 0; i < nodeNames.size(); i++) {
1✔
1976
      path[i + 1] = parseNodeName(nodeNames.get(i));
1✔
1977
    }
1978
    return new PartialPath(path);
1✔
1979
  }
1980

1981
  private String parseNodeName(IoTDBSqlParser.NodeNameContext ctx) {
1982
    if (!useWildcard && !ctx.wildcard().isEmpty()) {
1✔
1983
      useWildcard = true;
1✔
1984
    }
1985
    return parseNodeString(ctx.getText());
1✔
1986
  }
1987

1988
  private String parseNodeNameWithoutWildCard(IoTDBSqlParser.NodeNameWithoutWildcardContext ctx) {
1989
    return parseNodeString(ctx.getText());
1✔
1990
  }
1991

1992
  private String parseNodeNameInIntoPath(IoTDBSqlParser.NodeNameInIntoPathContext ctx) {
1993
    return parseNodeStringInIntoPath(ctx.getText());
1✔
1994
  }
1995

1996
  private String parseNodeString(String nodeName) {
1997
    if (nodeName.equals(IoTDBConstant.ONE_LEVEL_PATH_WILDCARD)
1✔
1998
        || nodeName.equals(IoTDBConstant.MULTI_LEVEL_PATH_WILDCARD)) {
1✔
1999
      return nodeName;
1✔
2000
    }
2001
    if (nodeName.startsWith(TsFileConstant.BACK_QUOTE_STRING)
1✔
2002
        && nodeName.endsWith(TsFileConstant.BACK_QUOTE_STRING)) {
×
2003
      return PathUtils.removeBackQuotesIfNecessary(nodeName);
×
2004
    }
2005
    checkNodeName(nodeName);
1✔
2006
    return nodeName;
1✔
2007
  }
2008

2009
  private String parseNodeStringInIntoPath(String nodeName) {
2010
    if (nodeName.equals(IoTDBConstant.DOUBLE_COLONS)) {
1✔
2011
      return nodeName;
1✔
2012
    }
2013
    if (nodeName.startsWith(TsFileConstant.BACK_QUOTE_STRING)
1✔
2014
        && nodeName.endsWith(TsFileConstant.BACK_QUOTE_STRING)) {
×
2015
      return PathUtils.removeBackQuotesIfNecessary(nodeName);
×
2016
    }
2017
    checkNodeNameInIntoPath(nodeName);
1✔
2018
    return nodeName;
1✔
2019
  }
2020

2021
  private void checkNodeName(String src) {
2022
    // node name could start with * and end with *
2023
    if (!TsFileConstant.NODE_NAME_PATTERN.matcher(src).matches()) {
1✔
2024
      throw new SemanticException(
×
2025
          String.format(
×
2026
              "%s is illegal, unquoted node name can only consist of digits, characters and underscore, or start or end with wildcard",
2027
              src));
2028
    }
2029
  }
1✔
2030

2031
  private void checkNodeNameInIntoPath(String src) {
2032
    // ${} are allowed
2033
    if (!TsFileConstant.NODE_NAME_IN_INTO_PATH_PATTERN.matcher(src).matches()) {
1✔
2034
      throw new SemanticException(
×
2035
          String.format(
×
2036
              "%s is illegal, unquoted node name in select into clause can only consist of digits, characters, $, { and }",
2037
              src));
2038
    }
2039
  }
1✔
2040

2041
  private static void checkIdentifier(String src) {
2042
    if (!TsFileConstant.IDENTIFIER_PATTERN.matcher(src).matches() || PathUtils.isRealNumber(src)) {
1✔
2043
      throw new SemanticException(
×
2044
          String.format(
×
2045
              "%s is illegal, identifier not enclosed with backticks can only consist of digits, characters and underscore.",
2046
              src));
2047
    }
2048
  }
1✔
2049

2050
  // Literals ========================================================================
2051

2052
  public long parseDateFormat(String timestampStr) {
2053
    if (timestampStr == null || "".equals(timestampStr.trim())) {
1✔
2054
      throw new SemanticException("input timestamp cannot be empty");
1✔
2055
    }
2056
    if (timestampStr.equalsIgnoreCase(SqlConstant.NOW_FUNC)) {
1✔
2057
      return DateTimeUtils.currentTime();
1✔
2058
    }
2059
    try {
2060
      return DateTimeUtils.convertDatetimeStrToLong(timestampStr, zoneId);
×
2061
    } catch (Exception e) {
×
2062
      throw new SemanticException(
×
2063
          String.format(
×
2064
              "Input time format %s error. "
2065
                  + "Input like yyyy-MM-dd HH:mm:ss, yyyy-MM-ddTHH:mm:ss or "
2066
                  + "refer to user document for more info.",
2067
              timestampStr));
2068
    }
2069
  }
2070

2071
  public long parseDateFormat(String timestampStr, long currentTime) {
2072
    if (timestampStr == null || "".equals(timestampStr.trim())) {
1✔
2073
      throw new SemanticException("input timestamp cannot be empty");
×
2074
    }
2075
    if (timestampStr.equalsIgnoreCase(SqlConstant.NOW_FUNC)) {
1✔
2076
      return currentTime;
×
2077
    }
2078
    try {
2079
      return DateTimeUtils.convertDatetimeStrToLong(timestampStr, zoneId);
1✔
2080
    } catch (Exception e) {
×
2081
      throw new SemanticException(
×
2082
          String.format(
×
2083
              "Input time format %s error. "
2084
                  + "Input like yyyy-MM-dd HH:mm:ss, yyyy-MM-ddTHH:mm:ss or "
2085
                  + "refer to user document for more info.",
2086
              timestampStr));
2087
    }
2088
  }
2089

2090
  private String parseStringLiteral(String src) {
2091
    if (2 <= src.length()) {
1✔
2092
      // do not unescape string
2093
      String unWrappedString = src.substring(1, src.length() - 1);
1✔
2094
      if (src.charAt(0) == '\"' && src.charAt(src.length() - 1) == '\"') {
1✔
2095
        // replace "" with "
2096
        String replaced = unWrappedString.replace("\"\"", "\"");
×
2097
        return replaced.length() == 0 ? "" : replaced;
×
2098
      }
2099
      if ((src.charAt(0) == '\'' && src.charAt(src.length() - 1) == '\'')) {
1✔
2100
        // replace '' with '
2101
        String replaced = unWrappedString.replace("''", "'");
1✔
2102
        return replaced.length() == 0 ? "" : replaced;
1✔
2103
      }
2104
    }
2105
    return src;
×
2106
  }
2107

2108
  private String parseStringLiteralInInsertValue(String src) {
2109
    if (2 <= src.length()
×
2110
        && ((src.charAt(0) == '\"' && src.charAt(src.length() - 1) == '\"')
×
2111
            || (src.charAt(0) == '\'' && src.charAt(src.length() - 1) == '\''))) {
×
2112
      return "'" + parseStringLiteral(src) + "'";
×
2113
    }
2114
    return src;
×
2115
  }
2116

2117
  public static String parseIdentifier(String src) {
2118
    if (src.startsWith(TsFileConstant.BACK_QUOTE_STRING)
1✔
2119
        && src.endsWith(TsFileConstant.BACK_QUOTE_STRING)) {
×
2120
      return src.substring(1, src.length() - 1)
×
2121
          .replace(TsFileConstant.DOUBLE_BACK_QUOTE_STRING, TsFileConstant.BACK_QUOTE_STRING);
×
2122
    }
2123
    checkIdentifier(src);
1✔
2124
    return src;
1✔
2125
  }
2126

2127
  // Alias
2128

2129
  /** Function for parsing Alias of ResultColumn. */
2130
  private String parseAlias(IoTDBSqlParser.AliasContext ctx) {
2131
    String alias;
2132
    if (ctx.constant() != null) {
1✔
2133
      alias = parseConstant(ctx.constant());
×
2134
    } else {
2135
      alias = parseIdentifier(ctx.identifier().getText());
1✔
2136
    }
2137
    return alias;
1✔
2138
  }
2139

2140
  /**
2141
   * Function for parsing AliasNode.
2142
   *
2143
   * @throws SemanticException if the alias pattern is not supported
2144
   */
2145
  private String parseAliasNode(IoTDBSqlParser.AliasContext ctx) {
2146
    String alias;
2147
    if (ctx.constant() != null) {
×
2148
      alias = parseConstant(ctx.constant());
×
2149
      if (PathUtils.isRealNumber(alias)
×
2150
          || !TsFileConstant.IDENTIFIER_PATTERN.matcher(alias).matches()) {
×
2151
        throw new SemanticException("Not support for this alias, Please enclose in back quotes.");
×
2152
      }
2153
    } else {
2154
      alias = parseNodeString(ctx.identifier().getText());
×
2155
    }
2156
    return alias;
×
2157
  }
2158

2159
  /** Data Control Language (DCL). */
2160

2161
  // Create User
2162
  @Override
2163
  public Statement visitCreateUser(IoTDBSqlParser.CreateUserContext ctx) {
2164
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.CREATE_USER);
×
2165
    authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
×
2166
    authorStatement.setPassWord(parseStringLiteral(ctx.password.getText()));
×
2167
    return authorStatement;
×
2168
  }
2169

2170
  // Create Role
2171

2172
  @Override
2173
  public Statement visitCreateRole(IoTDBSqlParser.CreateRoleContext ctx) {
2174
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.CREATE_ROLE);
×
2175
    authorStatement.setRoleName(parseIdentifier(ctx.roleName.getText()));
×
2176
    return authorStatement;
×
2177
  }
2178

2179
  // Alter Password
2180

2181
  @Override
2182
  public Statement visitAlterUser(IoTDBSqlParser.AlterUserContext ctx) {
2183
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.UPDATE_USER);
×
2184
    authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
×
2185
    authorStatement.setNewPassword(parseStringLiteral(ctx.password.getText()));
×
2186
    return authorStatement;
×
2187
  }
2188

2189
  // Grant User Privileges
2190

2191
  @Override
2192
  public Statement visitGrantUser(IoTDBSqlParser.GrantUserContext ctx) {
2193
    String[] privileges = parsePrivilege(ctx.privileges());
×
2194
    List<PartialPath> nodeNameList =
×
2195
        ctx.prefixPath().stream()
×
2196
            .map(this::parsePrefixPath)
×
2197
            .distinct()
×
2198
            .collect(Collectors.toList());
×
2199
    checkGrantRevokePrivileges(privileges, nodeNameList);
×
2200

2201
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.GRANT_USER);
×
2202
    authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
×
2203
    authorStatement.setPrivilegeList(privileges);
×
2204
    authorStatement.setNodeNameList(nodeNameList);
×
2205
    return authorStatement;
×
2206
  }
2207

2208
  // Grant Role Privileges
2209

2210
  @Override
2211
  public Statement visitGrantRole(IoTDBSqlParser.GrantRoleContext ctx) {
2212
    String[] privileges = parsePrivilege(ctx.privileges());
×
2213
    List<PartialPath> nodeNameList =
×
2214
        ctx.prefixPath().stream()
×
2215
            .map(this::parsePrefixPath)
×
2216
            .distinct()
×
2217
            .collect(Collectors.toList());
×
2218
    checkGrantRevokePrivileges(privileges, nodeNameList);
×
2219

2220
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.GRANT_ROLE);
×
2221
    authorStatement.setRoleName(parseIdentifier(ctx.roleName.getText()));
×
2222
    authorStatement.setPrivilegeList(privileges);
×
2223
    authorStatement.setNodeNameList(nodeNameList);
×
2224
    return authorStatement;
×
2225
  }
2226

2227
  // Grant User Role
2228

2229
  @Override
2230
  public Statement visitGrantRoleToUser(IoTDBSqlParser.GrantRoleToUserContext ctx) {
2231
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.GRANT_USER_ROLE);
×
2232
    authorStatement.setRoleName(parseIdentifier(ctx.roleName.getText()));
×
2233
    authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
×
2234
    return authorStatement;
×
2235
  }
2236

2237
  // Revoke User Privileges
2238

2239
  @Override
2240
  public Statement visitRevokeUser(IoTDBSqlParser.RevokeUserContext ctx) {
2241
    String[] privileges = parsePrivilege(ctx.privileges());
×
2242
    List<PartialPath> nodeNameList =
×
2243
        ctx.prefixPath().stream()
×
2244
            .map(this::parsePrefixPath)
×
2245
            .distinct()
×
2246
            .collect(Collectors.toList());
×
2247
    checkGrantRevokePrivileges(privileges, nodeNameList);
×
2248

2249
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.REVOKE_USER);
×
2250
    authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
×
2251
    authorStatement.setPrivilegeList(privileges);
×
2252
    authorStatement.setNodeNameList(nodeNameList);
×
2253
    return authorStatement;
×
2254
  }
2255

2256
  // Revoke Role Privileges
2257

2258
  @Override
2259
  public Statement visitRevokeRole(IoTDBSqlParser.RevokeRoleContext ctx) {
2260
    String[] privileges = parsePrivilege(ctx.privileges());
×
2261
    List<PartialPath> nodeNameList =
×
2262
        ctx.prefixPath().stream()
×
2263
            .map(this::parsePrefixPath)
×
2264
            .distinct()
×
2265
            .collect(Collectors.toList());
×
2266
    checkGrantRevokePrivileges(privileges, nodeNameList);
×
2267

2268
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.REVOKE_ROLE);
×
2269
    authorStatement.setRoleName(parseIdentifier(ctx.roleName.getText()));
×
2270
    authorStatement.setPrivilegeList(privileges);
×
2271
    authorStatement.setNodeNameList(nodeNameList);
×
2272
    return authorStatement;
×
2273
  }
2274

2275
  private void checkGrantRevokePrivileges(String[] privileges, List<PartialPath> nodeNameList) {
2276
    if (nodeNameList.isEmpty()) {
×
2277
      nodeNameList.add(new PartialPath(ALL_RESULT_NODES));
×
2278
      return;
×
2279
    }
2280
    boolean pathRelevant = true;
×
2281
    String errorPrivilegeName = "";
×
2282
    for (String privilege : privileges) {
×
2283
      if ("SET_STORAGE_GROUP".equalsIgnoreCase(privilege)) {
×
2284
        privilege = PrivilegeType.CREATE_DATABASE.name();
×
2285
      }
2286
      if ("DELETE_STORAGE_GROUP".equalsIgnoreCase(privilege)) {
×
2287
        privilege = PrivilegeType.DELETE_DATABASE.name();
×
2288
      }
2289
      if (!PrivilegeType.valueOf(privilege.toUpperCase()).isPathRelevant()) {
×
2290
        pathRelevant = false;
×
2291
        errorPrivilegeName = privilege.toUpperCase();
×
2292
        break;
×
2293
      }
2294
    }
2295
    if (!(pathRelevant
×
2296
        || (nodeNameList.size() == 1
×
2297
            && nodeNameList.contains(new PartialPath(ALL_RESULT_NODES))))) {
×
2298
      throw new SemanticException(
×
2299
          String.format(
×
2300
              "path independent privilege: [%s] can only be set on path: root.**",
2301
              errorPrivilegeName));
2302
    }
2303
  }
×
2304

2305
  // Revoke Role From User
2306

2307
  @Override
2308
  public Statement visitRevokeRoleFromUser(IoTDBSqlParser.RevokeRoleFromUserContext ctx) {
2309
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.REVOKE_USER_ROLE);
×
2310
    authorStatement.setRoleName(parseIdentifier(ctx.roleName.getText()));
×
2311
    authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
×
2312
    return authorStatement;
×
2313
  }
2314

2315
  // Drop User
2316

2317
  @Override
2318
  public Statement visitDropUser(IoTDBSqlParser.DropUserContext ctx) {
2319
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.DROP_USER);
×
2320
    authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
×
2321
    return authorStatement;
×
2322
  }
2323

2324
  // Drop Role
2325

2326
  @Override
2327
  public Statement visitDropRole(IoTDBSqlParser.DropRoleContext ctx) {
2328
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.DROP_ROLE);
×
2329
    authorStatement.setRoleName(parseIdentifier(ctx.roleName.getText()));
×
2330
    return authorStatement;
×
2331
  }
2332

2333
  // List Users
2334

2335
  @Override
2336
  public Statement visitListUser(IoTDBSqlParser.ListUserContext ctx) {
2337
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.LIST_USER);
×
2338
    if (ctx.roleName != null) {
×
2339
      authorStatement.setRoleName(parseIdentifier(ctx.roleName.getText()));
×
2340
    }
2341
    return authorStatement;
×
2342
  }
2343

2344
  // List Roles
2345

2346
  @Override
2347
  public Statement visitListRole(IoTDBSqlParser.ListRoleContext ctx) {
2348
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.LIST_ROLE);
×
2349
    if (ctx.userName != null) {
×
2350
      authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
×
2351
    }
2352
    return authorStatement;
×
2353
  }
2354

2355
  // List Privileges
2356

2357
  @Override
2358
  public Statement visitListPrivilegesUser(IoTDBSqlParser.ListPrivilegesUserContext ctx) {
2359
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.LIST_USER_PRIVILEGE);
×
2360
    authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
×
2361
    List<PartialPath> nodeNameList =
×
2362
        ctx.prefixPath().stream().map(this::parsePrefixPath).collect(Collectors.toList());
×
2363
    authorStatement.setNodeNameList(nodeNameList);
×
2364
    return authorStatement;
×
2365
  }
2366

2367
  // List Privileges of Roles On Specific Path
2368

2369
  @Override
2370
  public Statement visitListPrivilegesRole(IoTDBSqlParser.ListPrivilegesRoleContext ctx) {
2371
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.LIST_ROLE_PRIVILEGE);
×
2372
    authorStatement.setRoleName(parseIdentifier(ctx.roleName.getText()));
×
2373
    List<PartialPath> nodeNameList =
×
2374
        ctx.prefixPath().stream().map(this::parsePrefixPath).collect(Collectors.toList());
×
2375
    authorStatement.setNodeNameList(nodeNameList);
×
2376
    return authorStatement;
×
2377
  }
2378

2379
  private String[] parsePrivilege(IoTDBSqlParser.PrivilegesContext ctx) {
2380
    List<IoTDBSqlParser.PrivilegeValueContext> privilegeList = ctx.privilegeValue();
×
2381
    List<String> privileges = new ArrayList<>();
×
2382
    for (IoTDBSqlParser.PrivilegeValueContext privilegeValue : privilegeList) {
×
2383
      privileges.add(privilegeValue.getText());
×
2384
    }
×
2385
    return privileges.toArray(new String[0]);
×
2386
  }
2387

2388
  // Create database
2389
  @Override
2390
  public Statement visitCreateDatabase(IoTDBSqlParser.CreateDatabaseContext ctx) {
2391
    DatabaseSchemaStatement databaseSchemaStatement =
×
2392
        new DatabaseSchemaStatement(DatabaseSchemaStatement.DatabaseSchemaStatementType.CREATE);
2393
    PartialPath path = parsePrefixPath(ctx.prefixPath());
×
2394
    databaseSchemaStatement.setDatabasePath(path);
×
2395
    if (ctx.databaseAttributesClause() != null) {
×
2396
      parseDatabaseAttributesClause(databaseSchemaStatement, ctx.databaseAttributesClause());
×
2397
    }
2398
    return databaseSchemaStatement;
×
2399
  }
2400

2401
  @Override
2402
  public Statement visitAlterDatabase(IoTDBSqlParser.AlterDatabaseContext ctx) {
2403
    DatabaseSchemaStatement databaseSchemaStatement =
×
2404
        new DatabaseSchemaStatement(DatabaseSchemaStatement.DatabaseSchemaStatementType.ALTER);
2405
    PartialPath path = parsePrefixPath(ctx.prefixPath());
×
2406
    databaseSchemaStatement.setDatabasePath(path);
×
2407
    parseDatabaseAttributesClause(databaseSchemaStatement, ctx.databaseAttributesClause());
×
2408
    return databaseSchemaStatement;
×
2409
  }
2410

2411
  private void parseDatabaseAttributesClause(
2412
      DatabaseSchemaStatement databaseSchemaStatement,
2413
      IoTDBSqlParser.DatabaseAttributesClauseContext ctx) {
2414
    for (IoTDBSqlParser.DatabaseAttributeClauseContext attribute : ctx.databaseAttributeClause()) {
×
2415
      IoTDBSqlParser.DatabaseAttributeKeyContext attributeKey = attribute.databaseAttributeKey();
×
2416
      if (attributeKey.TTL() != null) {
×
2417
        long ttl = Long.parseLong(attribute.INTEGER_LITERAL().getText());
×
2418
        databaseSchemaStatement.setTtl(ttl);
×
2419
      } else if (attributeKey.SCHEMA_REPLICATION_FACTOR() != null) {
×
2420
        int schemaReplicationFactor = Integer.parseInt(attribute.INTEGER_LITERAL().getText());
×
2421
        databaseSchemaStatement.setSchemaReplicationFactor(schemaReplicationFactor);
×
2422
      } else if (attributeKey.DATA_REPLICATION_FACTOR() != null) {
×
2423
        int dataReplicationFactor = Integer.parseInt(attribute.INTEGER_LITERAL().getText());
×
2424
        databaseSchemaStatement.setDataReplicationFactor(dataReplicationFactor);
×
2425
      } else if (attributeKey.TIME_PARTITION_INTERVAL() != null) {
×
2426
        long timePartitionInterval = Long.parseLong(attribute.INTEGER_LITERAL().getText());
×
2427
        databaseSchemaStatement.setTimePartitionInterval(timePartitionInterval);
×
2428
      } else if (attributeKey.SCHEMA_REGION_GROUP_NUM() != null) {
×
2429
        int schemaRegionGroupNum = Integer.parseInt(attribute.INTEGER_LITERAL().getText());
×
2430
        databaseSchemaStatement.setSchemaRegionGroupNum(schemaRegionGroupNum);
×
2431
      } else if (attributeKey.DATA_REGION_GROUP_NUM() != null) {
×
2432
        int dataRegionGroupNum = Integer.parseInt(attribute.INTEGER_LITERAL().getText());
×
2433
        databaseSchemaStatement.setDataRegionGroupNum(dataRegionGroupNum);
×
2434
      }
2435
    }
×
2436
  }
×
2437

2438
  @Override
2439
  public Statement visitSetTTL(IoTDBSqlParser.SetTTLContext ctx) {
2440
    SetTTLStatement setTTLStatement = new SetTTLStatement();
1✔
2441
    PartialPath path = parsePrefixPath(ctx.prefixPath());
1✔
2442
    long ttl = Long.parseLong(ctx.INTEGER_LITERAL().getText());
1✔
2443
    setTTLStatement.setDatabasePath(path);
1✔
2444
    setTTLStatement.setTTL(ttl);
1✔
2445
    return setTTLStatement;
1✔
2446
  }
2447

2448
  @Override
2449
  public Statement visitUnsetTTL(IoTDBSqlParser.UnsetTTLContext ctx) {
2450
    UnSetTTLStatement unSetTTLStatement = new UnSetTTLStatement();
1✔
2451
    PartialPath partialPath = parsePrefixPath(ctx.prefixPath());
1✔
2452
    unSetTTLStatement.setDatabasePath(partialPath);
1✔
2453
    return unSetTTLStatement;
1✔
2454
  }
2455

2456
  @Override
2457
  public Statement visitShowTTL(IoTDBSqlParser.ShowTTLContext ctx) {
2458
    ShowTTLStatement showTTLStatement = new ShowTTLStatement();
1✔
2459
    for (IoTDBSqlParser.PrefixPathContext prefixPathContext : ctx.prefixPath()) {
1✔
2460
      PartialPath partialPath = parsePrefixPath(prefixPathContext);
1✔
2461
      showTTLStatement.addPathPatterns(partialPath);
1✔
2462
    }
1✔
2463
    return showTTLStatement;
1✔
2464
  }
2465

2466
  @Override
2467
  public Statement visitShowAllTTL(IoTDBSqlParser.ShowAllTTLContext ctx) {
2468
    ShowTTLStatement showTTLStatement = new ShowTTLStatement();
1✔
2469
    showTTLStatement.setAll(true);
1✔
2470
    return showTTLStatement;
1✔
2471
  }
2472

2473
  @Override
2474
  public Statement visitShowVariables(IoTDBSqlParser.ShowVariablesContext ctx) {
2475
    return new ShowVariablesStatement();
×
2476
  }
2477

2478
  @Override
2479
  public Statement visitShowCluster(IoTDBSqlParser.ShowClusterContext ctx) {
2480
    ShowClusterStatement showClusterStatement = new ShowClusterStatement();
×
2481
    if (ctx.DETAILS() != null) {
×
2482
      showClusterStatement.setDetails(true);
×
2483
    }
2484
    return showClusterStatement;
×
2485
  }
2486

2487
  @Override
2488
  public Statement visitDropDatabase(IoTDBSqlParser.DropDatabaseContext ctx) {
2489
    DeleteDatabaseStatement dropDatabaseStatement = new DeleteDatabaseStatement();
×
2490
    List<IoTDBSqlParser.PrefixPathContext> prefixPathContexts = ctx.prefixPath();
×
2491
    List<String> paths = new ArrayList<>();
×
2492
    for (IoTDBSqlParser.PrefixPathContext prefixPathContext : prefixPathContexts) {
×
2493
      paths.add(parsePrefixPath(prefixPathContext).getFullPath());
×
2494
    }
×
2495
    dropDatabaseStatement.setPrefixPath(paths);
×
2496
    return dropDatabaseStatement;
×
2497
  }
2498

2499
  // Explain ========================================================================
2500
  @Override
2501
  public Statement visitExplain(IoTDBSqlParser.ExplainContext ctx) {
2502
    QueryStatement queryStatement = (QueryStatement) visitSelectStatement(ctx.selectStatement());
×
2503
    return new ExplainStatement(queryStatement);
×
2504
  }
2505

2506
  @Override
2507
  public Statement visitDeleteStatement(IoTDBSqlParser.DeleteStatementContext ctx) {
2508
    DeleteDataStatement statement = new DeleteDataStatement();
×
2509
    List<IoTDBSqlParser.PrefixPathContext> prefixPaths = ctx.prefixPath();
×
2510
    List<PartialPath> pathList = new ArrayList<>();
×
2511
    for (IoTDBSqlParser.PrefixPathContext prefixPath : prefixPaths) {
×
2512
      pathList.add(parsePrefixPath(prefixPath));
×
2513
    }
×
2514
    statement.setPathList(pathList);
×
2515
    if (ctx.whereClause() != null) {
×
2516
      WhereCondition whereCondition = parseWhereClause(ctx.whereClause());
×
2517
      TimeRange timeRange = parseDeleteTimeRange(whereCondition.getPredicate());
×
2518
      statement.setTimeRange(timeRange);
×
2519
    } else {
×
2520
      statement.setTimeRange(new TimeRange(Long.MIN_VALUE, Long.MAX_VALUE));
×
2521
    }
2522
    return statement;
×
2523
  }
2524

2525
  private TimeRange parseDeleteTimeRange(Expression predicate) {
2526
    if (predicate instanceof LogicAndExpression) {
×
2527
      TimeRange leftTimeRange =
×
2528
          parseDeleteTimeRange(((LogicAndExpression) predicate).getLeftExpression());
×
2529
      TimeRange rightTimeRange =
×
2530
          parseDeleteTimeRange(((LogicAndExpression) predicate).getRightExpression());
×
2531
      return new TimeRange(
×
2532
          Math.max(leftTimeRange.getMin(), rightTimeRange.getMin()),
×
2533
          Math.min(leftTimeRange.getMax(), rightTimeRange.getMax()));
×
2534
    } else if (predicate instanceof CompareBinaryExpression) {
×
2535
      if (((CompareBinaryExpression) predicate).getLeftExpression() instanceof TimestampOperand) {
×
2536
        return parseTimeRangeForDeleteTimeRange(
×
2537
            predicate.getExpressionType(),
×
2538
            ((CompareBinaryExpression) predicate).getLeftExpression(),
×
2539
            ((CompareBinaryExpression) predicate).getRightExpression());
×
2540
      } else {
2541
        return parseTimeRangeForDeleteTimeRange(
×
2542
            predicate.getExpressionType(),
×
2543
            ((CompareBinaryExpression) predicate).getRightExpression(),
×
2544
            ((CompareBinaryExpression) predicate).getLeftExpression());
×
2545
      }
2546
    } else {
2547
      throw new SemanticException(DELETE_RANGE_ERROR_MSG);
×
2548
    }
2549
  }
2550

2551
  private TimeRange parseTimeRangeForDeleteTimeRange(
2552
      ExpressionType expressionType, Expression timeExpression, Expression valueExpression) {
2553
    if (!(timeExpression instanceof TimestampOperand)
×
2554
        || !(valueExpression instanceof ConstantOperand)) {
2555
      throw new SemanticException(DELETE_ONLY_SUPPORT_TIME_EXP_ERROR_MSG);
×
2556
    }
2557

2558
    if (((ConstantOperand) valueExpression).getDataType() != TSDataType.INT64) {
×
2559
      throw new SemanticException("The datatype of timestamp should be LONG.");
×
2560
    }
2561

2562
    long time = Long.parseLong(((ConstantOperand) valueExpression).getValueString());
×
2563
    switch (expressionType) {
×
2564
      case LESS_THAN:
2565
        return new TimeRange(Long.MIN_VALUE, time - 1);
×
2566
      case LESS_EQUAL:
2567
        return new TimeRange(Long.MIN_VALUE, time);
×
2568
      case GREATER_THAN:
2569
        return new TimeRange(time + 1, Long.MAX_VALUE);
×
2570
      case GREATER_EQUAL:
2571
        return new TimeRange(time, Long.MAX_VALUE);
×
2572
      case EQUAL_TO:
2573
        return new TimeRange(time, time);
×
2574
      default:
2575
        throw new SemanticException(DELETE_RANGE_ERROR_MSG);
×
2576
    }
2577
  }
2578

2579
  /** function for parsing file path used by LOAD statement. */
2580
  public String parseFilePath(String src) {
2581
    return src.substring(1, src.length() - 1);
×
2582
  }
2583

2584
  // Expression & Predicate ========================================================================
2585

2586
  private Expression parseExpression(
2587
      IoTDBSqlParser.ExpressionContext context, boolean canUseFullPath) {
2588
    if (context.unaryInBracket != null) {
1✔
2589
      return parseExpression(context.unaryInBracket, canUseFullPath);
1✔
2590
    }
2591

2592
    if (context.expressionAfterUnaryOperator != null) {
1✔
2593
      if (context.MINUS() != null) {
×
2594
        return new NegationExpression(
×
2595
            parseExpression(context.expressionAfterUnaryOperator, canUseFullPath));
×
2596
      }
2597
      if (context.operator_not() != null) {
×
2598
        return new LogicNotExpression(
×
2599
            parseExpression(context.expressionAfterUnaryOperator, canUseFullPath));
×
2600
      }
2601
      return parseExpression(context.expressionAfterUnaryOperator, canUseFullPath);
×
2602
    }
2603

2604
    if (context.leftExpression != null && context.rightExpression != null) {
1✔
2605
      Expression leftExpression = parseExpression(context.leftExpression, canUseFullPath);
1✔
2606
      Expression rightExpression = parseExpression(context.rightExpression, canUseFullPath);
1✔
2607
      if (context.STAR() != null) {
1✔
2608
        return new MultiplicationExpression(leftExpression, rightExpression);
1✔
2609
      }
2610
      if (context.DIV() != null) {
1✔
2611
        return new DivisionExpression(leftExpression, rightExpression);
1✔
2612
      }
2613
      if (context.MOD() != null) {
1✔
2614
        return new ModuloExpression(leftExpression, rightExpression);
1✔
2615
      }
2616
      if (context.PLUS() != null) {
1✔
2617
        return new AdditionExpression(leftExpression, rightExpression);
1✔
2618
      }
2619
      if (context.MINUS() != null) {
1✔
2620
        return new SubtractionExpression(leftExpression, rightExpression);
1✔
2621
      }
2622
      if (context.OPERATOR_GT() != null) {
1✔
2623
        return new GreaterThanExpression(leftExpression, rightExpression);
1✔
2624
      }
2625
      if (context.OPERATOR_GTE() != null) {
1✔
2626
        return new GreaterEqualExpression(leftExpression, rightExpression);
1✔
2627
      }
2628
      if (context.OPERATOR_LT() != null) {
1✔
2629
        return new LessThanExpression(leftExpression, rightExpression);
1✔
2630
      }
2631
      if (context.OPERATOR_LTE() != null) {
1✔
2632
        return new LessEqualExpression(leftExpression, rightExpression);
1✔
2633
      }
2634
      if (context.OPERATOR_DEQ() != null || context.OPERATOR_SEQ() != null) {
1✔
2635
        return new EqualToExpression(leftExpression, rightExpression);
1✔
2636
      }
2637
      if (context.OPERATOR_NEQ() != null) {
1✔
2638
        return new NonEqualExpression(leftExpression, rightExpression);
1✔
2639
      }
2640
      if (context.operator_and() != null) {
1✔
2641
        return new LogicAndExpression(leftExpression, rightExpression);
1✔
2642
      }
2643
      if (context.operator_or() != null) {
1✔
2644
        return new LogicOrExpression(leftExpression, rightExpression);
1✔
2645
      }
2646
      throw new UnsupportedOperationException();
×
2647
    }
2648

2649
    if (context.unaryBeforeRegularOrLikeExpression != null) {
1✔
2650
      if (context.REGEXP() != null) {
×
2651
        return parseRegularExpression(context, canUseFullPath);
×
2652
      }
2653
      if (context.LIKE() != null) {
×
2654
        return parseLikeExpression(context, canUseFullPath);
×
2655
      }
2656
      throw new UnsupportedOperationException();
×
2657
    }
2658

2659
    if (context.unaryBeforeIsNullExpression != null) {
1✔
2660
      return parseIsNullExpression(context, canUseFullPath);
×
2661
    }
2662

2663
    if (context.firstExpression != null
1✔
2664
        && context.secondExpression != null
2665
        && context.thirdExpression != null) {
2666
      Expression firstExpression = parseExpression(context.firstExpression, canUseFullPath);
×
2667
      Expression secondExpression = parseExpression(context.secondExpression, canUseFullPath);
×
2668
      Expression thirdExpression = parseExpression(context.thirdExpression, canUseFullPath);
×
2669

2670
      if (context.operator_between() != null) {
×
2671
        return new BetweenExpression(
×
2672
            firstExpression, secondExpression, thirdExpression, context.operator_not() != null);
×
2673
      }
2674
      throw new UnsupportedOperationException();
×
2675
    }
2676

2677
    if (context.unaryBeforeInExpression != null) {
1✔
2678
      return parseInExpression(context, canUseFullPath);
×
2679
    }
2680

2681
    if (context.scalarFunctionExpression() != null) {
1✔
2682
      return parseScalarFunctionExpression(context.scalarFunctionExpression(), canUseFullPath);
×
2683
    }
2684

2685
    if (context.functionName() != null) {
1✔
2686
      return parseFunctionExpression(context, canUseFullPath);
1✔
2687
    }
2688

2689
    if (context.fullPathInExpression() != null) {
1✔
2690
      return new TimeSeriesOperand(
1✔
2691
          parseFullPathInExpression(context.fullPathInExpression(), canUseFullPath));
1✔
2692
    }
2693

2694
    if (context.time != null) {
1✔
2695
      return new TimestampOperand();
1✔
2696
    }
2697

2698
    if (context.constant() != null && !context.constant().isEmpty()) {
1✔
2699
      return parseConstantOperand(context.constant(0));
1✔
2700
    }
2701

2702
    if (context.caseWhenThenExpression() != null) {
×
2703
      return parseCaseWhenThenExpression(context.caseWhenThenExpression(), canUseFullPath);
×
2704
    }
2705

2706
    throw new UnsupportedOperationException();
×
2707
  }
2708

2709
  private Expression parseScalarFunctionExpression(
2710
      IoTDBSqlParser.ScalarFunctionExpressionContext context, boolean canUseFullPath) {
2711
    if (context.CAST() != null) {
×
2712
      return parseCastFunction(context, canUseFullPath);
×
2713
    } else if (context.REPLACE() != null) {
×
2714
      return parseReplaceFunction(context, canUseFullPath);
×
2715
    } else if (context.ROUND() != null) {
×
2716
      return parseRoundFunction(context, canUseFullPath);
×
2717
    } else if (context.SUBSTRING() != null) {
×
2718
      return parseSubStrFunction(context, canUseFullPath);
×
2719
    }
2720
    throw new UnsupportedOperationException();
×
2721
  }
2722

2723
  private Expression parseCastFunction(
2724
      IoTDBSqlParser.ScalarFunctionExpressionContext castClause, boolean canUseFullPath) {
2725
    FunctionExpression functionExpression = new FunctionExpression(CAST_FUNCTION);
×
2726
    functionExpression.addExpression(parseExpression(castClause.castInput, canUseFullPath));
×
2727
    functionExpression.addAttribute(CAST_TYPE, parseAttributeValue(castClause.attributeValue()));
×
2728
    return functionExpression;
×
2729
  }
2730

2731
  private Expression parseReplaceFunction(
2732
      IoTDBSqlParser.ScalarFunctionExpressionContext replaceClause, boolean canUseFullPath) {
2733
    FunctionExpression functionExpression = new FunctionExpression(REPLACE_FUNCTION);
×
2734
    functionExpression.addExpression(parseExpression(replaceClause.text, canUseFullPath));
×
2735
    functionExpression.addAttribute(REPLACE_FROM, parseStringLiteral(replaceClause.from.getText()));
×
2736
    functionExpression.addAttribute(REPLACE_TO, parseStringLiteral(replaceClause.to.getText()));
×
2737
    return functionExpression;
×
2738
  }
2739

2740
  private Expression parseSubStrFunction(
2741
      IoTDBSqlParser.ScalarFunctionExpressionContext subStrClause, boolean canUseFullPath) {
2742
    FunctionExpression functionExpression = new FunctionExpression(SUBSTRING_FUNCTION);
×
2743
    IoTDBSqlParser.SubStringExpressionContext subStringExpression =
×
2744
        subStrClause.subStringExpression();
×
2745
    functionExpression.addExpression(parseExpression(subStringExpression.input, canUseFullPath));
×
2746
    if (subStringExpression.startPosition != null) {
×
2747
      functionExpression.addAttribute(SUBSTRING_START, subStringExpression.startPosition.getText());
×
2748
      if (subStringExpression.length != null) {
×
2749
        functionExpression.addAttribute(SUBSTRING_LENGTH, subStringExpression.length.getText());
×
2750
      }
2751
    }
2752
    if (subStringExpression.from != null) {
×
2753
      functionExpression.addAttribute(SUBSTRING_IS_STANDARD, "0");
×
2754
      functionExpression.addAttribute(
×
2755
          SUBSTRING_START, parseStringLiteral(subStringExpression.from.getText()));
×
2756
      if (subStringExpression.forLength != null) {
×
2757
        functionExpression.addAttribute(SUBSTRING_LENGTH, subStringExpression.forLength.getText());
×
2758
      }
2759
    }
2760
    return functionExpression;
×
2761
  }
2762

2763
  private Expression parseRoundFunction(
2764
      IoTDBSqlParser.ScalarFunctionExpressionContext roundClause, boolean canUseFullPath) {
2765
    FunctionExpression functionExpression = new FunctionExpression(ROUND_FUNCTION);
×
2766
    functionExpression.addExpression(parseExpression(roundClause.input, canUseFullPath));
×
2767
    if (roundClause.places != null) {
×
2768
      functionExpression.addAttribute(ROUND_PLACES, parseConstant(roundClause.constant()));
×
2769
    }
2770
    return functionExpression;
×
2771
  }
2772

2773
  private CaseWhenThenExpression parseCaseWhenThenExpression(
2774
      IoTDBSqlParser.CaseWhenThenExpressionContext context, boolean canUseFullPath) {
2775
    // handle CASE
2776
    Expression caseExpression = null;
×
2777
    boolean simpleCase = false;
×
2778
    if (context.caseExpression != null) {
×
2779
      caseExpression = parseExpression(context.caseExpression, canUseFullPath);
×
2780
      simpleCase = true;
×
2781
    }
2782
    // handle WHEN-THEN
2783
    List<WhenThenExpression> whenThenList = new ArrayList<>();
×
2784
    if (simpleCase) {
×
2785
      for (IoTDBSqlParser.WhenThenExpressionContext whenThenExpressionContext :
2786
          context.whenThenExpression()) {
×
2787
        Expression when = parseExpression(whenThenExpressionContext.whenExpression, canUseFullPath);
×
2788
        Expression then = parseExpression(whenThenExpressionContext.thenExpression, canUseFullPath);
×
2789
        Expression comparison = new EqualToExpression(caseExpression, when);
×
2790
        whenThenList.add(new WhenThenExpression(comparison, then));
×
2791
      }
×
2792
    } else {
2793
      for (IoTDBSqlParser.WhenThenExpressionContext whenThenExpressionContext :
2794
          context.whenThenExpression()) {
×
2795
        whenThenList.add(
×
2796
            new WhenThenExpression(
2797
                parseExpression(whenThenExpressionContext.whenExpression, canUseFullPath),
×
2798
                parseExpression(whenThenExpressionContext.thenExpression, canUseFullPath)));
×
2799
      }
×
2800
    }
2801
    // handle ELSE
2802
    Expression elseExpression = new NullOperand();
×
2803
    if (context.elseExpression != null) {
×
2804
      elseExpression = parseExpression(context.elseExpression, canUseFullPath);
×
2805
    }
2806
    return new CaseWhenThenExpression(whenThenList, elseExpression);
×
2807
  }
2808

2809
  private Expression parseFunctionExpression(
2810
      IoTDBSqlParser.ExpressionContext functionClause, boolean canUseFullPath) {
2811
    FunctionExpression functionExpression =
1✔
2812
        new FunctionExpression(parseIdentifier(functionClause.functionName().getText()));
1✔
2813

2814
    // expressions
2815
    boolean hasNonPureConstantSubExpression = false;
1✔
2816
    for (IoTDBSqlParser.ExpressionContext expression : functionClause.expression()) {
1✔
2817
      Expression subexpression = parseExpression(expression, canUseFullPath);
1✔
2818
      if (!subexpression.isConstantOperand()) {
1✔
2819
        hasNonPureConstantSubExpression = true;
1✔
2820
      }
2821
      if (subexpression instanceof EqualToExpression) {
1✔
2822
        Expression subLeftExpression = ((EqualToExpression) subexpression).getLeftExpression();
1✔
2823
        Expression subRightExpression = ((EqualToExpression) subexpression).getRightExpression();
1✔
2824
        if (subLeftExpression.isConstantOperand()
1✔
2825
            && (!(subRightExpression.isConstantOperand()
1✔
2826
                && ((ConstantOperand) subRightExpression).getDataType().equals(TSDataType.TEXT)))) {
1✔
2827
          throw new SemanticException("Attributes of functions should be quoted with '' or \"\"");
×
2828
        }
2829
        if (subLeftExpression.isConstantOperand() && subRightExpression.isConstantOperand()) {
1✔
2830
          // parse attribute
2831
          functionExpression.addAttribute(
1✔
2832
              ((ConstantOperand) subLeftExpression).getValueString(),
1✔
2833
              ((ConstantOperand) subRightExpression).getValueString());
1✔
2834
        } else {
2835
          functionExpression.addExpression(subexpression);
×
2836
        }
2837
      } else {
1✔
2838
        functionExpression.addExpression(subexpression);
1✔
2839
      }
2840
    }
1✔
2841

2842
    // It is not allowed to have function expressions like F(1, 1.0). There should be at least one
2843
    // non-pure-constant sub-expression, otherwise the timestamp of the row cannot be inferred.
2844
    if (!hasNonPureConstantSubExpression) {
1✔
2845
      throw new SemanticException(
×
2846
          "Invalid function expression, all the arguments are constant operands: "
2847
              + functionClause.getText());
×
2848
    }
2849

2850
    // check size of input expressions
2851
    // type check of input expressions is put in ExpressionTypeAnalyzer
2852
    if (functionExpression.isBuiltInAggregationFunctionExpression()) {
1✔
2853
      checkAggregationFunctionInput(functionExpression);
1✔
2854
    } else if (functionExpression.isBuiltInScalarFunction()) {
1✔
2855
      checkBuiltInScalarFunctionInput(functionExpression);
1✔
2856
    }
2857
    return functionExpression;
1✔
2858
  }
2859

2860
  private void checkAggregationFunctionInput(FunctionExpression functionExpression) {
2861
    final String functionName = functionExpression.getFunctionName().toLowerCase();
1✔
2862
    switch (functionName) {
1✔
2863
      case SqlConstant.MIN_TIME:
2864
      case SqlConstant.MAX_TIME:
2865
      case SqlConstant.COUNT:
2866
      case SqlConstant.COUNT_TIME:
2867
      case SqlConstant.MIN_VALUE:
2868
      case SqlConstant.LAST_VALUE:
2869
      case SqlConstant.FIRST_VALUE:
2870
      case SqlConstant.MAX_VALUE:
2871
      case SqlConstant.EXTREME:
2872
      case SqlConstant.AVG:
2873
      case SqlConstant.SUM:
2874
      case SqlConstant.TIME_DURATION:
2875
      case SqlConstant.MODE:
2876
        checkFunctionExpressionInputSize(
1✔
2877
            functionExpression.getExpressionString(),
1✔
2878
            functionExpression.getExpressions().size(),
1✔
2879
            1);
2880
        return;
1✔
2881
      case SqlConstant.COUNT_IF:
2882
        checkFunctionExpressionInputSize(
×
2883
            functionExpression.getExpressionString(),
×
2884
            functionExpression.getExpressions().size(),
×
2885
            2);
2886
        return;
×
2887
      default:
2888
        throw new IllegalArgumentException(
×
2889
            "Invalid Aggregation function: " + functionExpression.getFunctionName());
×
2890
    }
2891
  }
2892

2893
  private void checkBuiltInScalarFunctionInput(FunctionExpression functionExpression) {
2894
    BuiltInScalarFunctionHelperFactory.createHelper(functionExpression.getFunctionName())
1✔
2895
        .checkBuiltInScalarFunctionInputSize(functionExpression);
1✔
2896
  }
1✔
2897

2898
  public static void checkFunctionExpressionInputSize(
2899
      String expressionString, int actual, int... expected) {
2900
    for (int expect : expected) {
1✔
2901
      if (expect == actual) {
1✔
2902
        return;
1✔
2903
      }
2904
    }
2905
    throw new SemanticException(
×
2906
        String.format(
×
2907
            "Error size of input expressions. expression: %s, actual size: %s, expected size: %s.",
2908
            expressionString, actual, Arrays.toString(expected)));
×
2909
  }
2910

2911
  private Expression parseRegularExpression(ExpressionContext context, boolean canUseFullPath) {
2912
    return new RegularExpression(
×
2913
        parseExpression(context.unaryBeforeRegularOrLikeExpression, canUseFullPath),
×
2914
        parseStringLiteral(context.STRING_LITERAL().getText()));
×
2915
  }
2916

2917
  private Expression parseLikeExpression(ExpressionContext context, boolean canUseFullPath) {
2918
    return new LikeExpression(
×
2919
        parseExpression(context.unaryBeforeRegularOrLikeExpression, canUseFullPath),
×
2920
        parseStringLiteral(context.STRING_LITERAL().getText()));
×
2921
  }
2922

2923
  private Expression parseIsNullExpression(ExpressionContext context, boolean canUseFullPath) {
2924
    return new IsNullExpression(
×
2925
        parseExpression(context.unaryBeforeIsNullExpression, canUseFullPath),
×
2926
        context.operator_not() != null);
×
2927
  }
2928

2929
  private Expression parseInExpression(ExpressionContext context, boolean canUseFullPath) {
2930
    Expression childExpression = parseExpression(context.unaryBeforeInExpression, canUseFullPath);
×
2931
    LinkedHashSet<String> values = new LinkedHashSet<>();
×
2932
    for (ConstantContext constantContext : context.constant()) {
×
2933
      values.add(parseConstant(constantContext));
×
2934
    }
×
2935
    return new InExpression(childExpression, context.operator_not() != null, values);
×
2936
  }
2937

2938
  private String parseConstant(ConstantContext constantContext) {
2939
    String text = constantContext.getText();
×
2940
    if (constantContext.boolean_literal() != null
×
2941
        || constantContext.INTEGER_LITERAL() != null
×
2942
        || constantContext.realLiteral() != null) {
×
2943
      return text;
×
2944
    } else if (constantContext.STRING_LITERAL() != null) {
×
2945
      return parseStringLiteral(text);
×
2946
    } else if (constantContext.dateExpression() != null) {
×
2947
      return String.valueOf(parseDateExpression(constantContext.dateExpression()));
×
2948
    } else {
2949
      throw new IllegalArgumentException("Unsupported constant value: " + text);
×
2950
    }
2951
  }
2952

2953
  private Expression parseConstantOperand(ConstantContext constantContext) {
2954
    String text = constantContext.getText();
1✔
2955
    if (constantContext.boolean_literal() != null) {
1✔
2956
      return new ConstantOperand(TSDataType.BOOLEAN, text);
×
2957
    } else if (constantContext.STRING_LITERAL() != null) {
1✔
2958
      return new ConstantOperand(TSDataType.TEXT, parseStringLiteral(text));
1✔
2959
    } else if (constantContext.INTEGER_LITERAL() != null) {
1✔
2960
      return new ConstantOperand(TSDataType.INT64, text);
1✔
2961
    } else if (constantContext.realLiteral() != null) {
×
2962
      return parseRealLiteral(text);
×
2963
    } else if (constantContext.dateExpression() != null) {
×
2964
      return new ConstantOperand(
×
2965
          TSDataType.INT64, String.valueOf(parseDateExpression(constantContext.dateExpression())));
×
2966
    } else {
2967
      throw new SemanticException("Unsupported constant operand: " + text);
×
2968
    }
2969
  }
2970

2971
  private Expression parseRealLiteral(String value) {
2972
    // 3.33 is float by default
2973
    return new ConstantOperand(
×
2974
        CONFIG.getFloatingStringInferType().equals(TSDataType.DOUBLE)
×
2975
            ? TSDataType.DOUBLE
×
2976
            : TSDataType.FLOAT,
×
2977
        value);
2978
  }
2979

2980
  /**
2981
   * parse time expression, which is addition and subtraction expression of duration time, now() or
2982
   * DataTimeFormat time.
2983
   *
2984
   * <p>eg. now() + 1d - 2h
2985
   */
2986
  private Long parseDateExpression(IoTDBSqlParser.DateExpressionContext ctx) {
2987
    long time;
2988
    time = parseDateFormat(ctx.getChild(0).getText());
×
2989
    for (int i = 1; i < ctx.getChildCount(); i = i + 2) {
×
2990
      if ("+".equals(ctx.getChild(i).getText())) {
×
2991
        time += DateTimeUtils.convertDurationStrToLong(time, ctx.getChild(i + 1).getText());
×
2992
      } else {
2993
        time -= DateTimeUtils.convertDurationStrToLong(time, ctx.getChild(i + 1).getText());
×
2994
      }
2995
    }
2996
    return time;
×
2997
  }
2998

2999
  private Long parseDateExpression(IoTDBSqlParser.DateExpressionContext ctx, long currentTime) {
3000
    long time;
3001
    time = parseDateFormat(ctx.getChild(0).getText(), currentTime);
×
3002
    for (int i = 1; i < ctx.getChildCount(); i = i + 2) {
×
3003
      if ("+".equals(ctx.getChild(i).getText())) {
×
3004
        time += DateTimeUtils.convertDurationStrToLong(time, ctx.getChild(i + 1).getText());
×
3005
      } else {
3006
        time -= DateTimeUtils.convertDurationStrToLong(time, ctx.getChild(i + 1).getText());
×
3007
      }
3008
    }
3009
    return time;
×
3010
  }
3011

3012
  private long parseTimeValue(IoTDBSqlParser.TimeValueContext ctx, long currentTime) {
3013
    if (ctx.INTEGER_LITERAL() != null) {
1✔
3014
      try {
3015
        if (ctx.MINUS() != null) {
1✔
3016
          return -Long.parseLong(ctx.INTEGER_LITERAL().getText());
×
3017
        }
3018
        return Long.parseLong(ctx.INTEGER_LITERAL().getText());
1✔
3019
      } catch (NumberFormatException e) {
×
3020
        throw new SemanticException(
×
3021
            String.format("Can not parse %s to long value", ctx.INTEGER_LITERAL().getText()));
×
3022
      }
3023
    } else if (ctx.dateExpression() != null) {
1✔
3024
      return parseDateExpression(ctx.dateExpression(), currentTime);
×
3025
    } else {
3026
      return parseDateFormat(ctx.datetimeLiteral().getText(), currentTime);
1✔
3027
    }
3028
  }
3029

3030
  /** Utils. */
3031
  private void setMap(IoTDBSqlParser.AlterClauseContext ctx, Map<String, String> alterMap) {
3032
    List<IoTDBSqlParser.AttributePairContext> tagsList = ctx.attributePair();
×
3033
    String key;
3034
    if (ctx.attributePair(0) != null) {
×
3035
      for (IoTDBSqlParser.AttributePairContext attributePair : tagsList) {
×
3036
        key = parseAttributeKey(attributePair.attributeKey());
×
3037
        alterMap.computeIfPresent(
×
3038
            key,
3039
            (k, v) -> {
3040
              throw new SemanticException(
×
3041
                  String.format("There's duplicate [%s] in tag or attribute clause.", k));
×
3042
            });
3043
        alterMap.put(key, parseAttributeValue(attributePair.attributeValue()));
×
3044
      }
×
3045
    }
3046
  }
×
3047

3048
  private Map<String, String> extractMap(
3049
      List<IoTDBSqlParser.AttributePairContext> attributePair2,
3050
      IoTDBSqlParser.AttributePairContext attributePair3) {
3051
    Map<String, String> tags = new HashMap<>(attributePair2.size());
1✔
3052
    if (attributePair3 != null) {
1✔
3053
      String key;
3054
      for (IoTDBSqlParser.AttributePairContext attributePair : attributePair2) {
1✔
3055
        key = parseAttributeKey(attributePair.attributeKey());
1✔
3056
        tags.computeIfPresent(
1✔
3057
            key,
3058
            (k, v) -> {
3059
              throw new SemanticException(
×
3060
                  String.format("There's duplicate [%s] in tag or attribute clause.", k));
×
3061
            });
3062
        tags.put(key, parseAttributeValue(attributePair.attributeValue()));
1✔
3063
      }
1✔
3064
    }
3065
    return tags;
1✔
3066
  }
3067

3068
  private String parseAttributeKey(IoTDBSqlParser.AttributeKeyContext ctx) {
3069
    if (ctx.constant() != null) {
1✔
3070
      return parseStringLiteral(ctx.getText());
1✔
3071
    }
3072
    return parseIdentifier(ctx.getText());
×
3073
  }
3074

3075
  private String parseAttributeValue(IoTDBSqlParser.AttributeValueContext ctx) {
3076
    if (ctx.constant() != null) {
1✔
3077
      return parseStringLiteral(ctx.getText());
1✔
3078
    }
3079
    return parseIdentifier(ctx.getText());
×
3080
  }
3081

3082
  // Merge
3083
  @Override
3084
  public Statement visitMerge(IoTDBSqlParser.MergeContext ctx) {
3085
    MergeStatement mergeStatement = new MergeStatement(StatementType.MERGE);
×
3086
    if (ctx.CLUSTER() != null && !IoTDBDescriptor.getInstance().getConfig().isClusterMode()) {
×
3087
      throw new SemanticException("MERGE ON CLUSTER is not supported in standalone mode");
×
3088
    }
3089
    mergeStatement.setOnCluster(ctx.LOCAL() == null);
×
3090
    return mergeStatement;
×
3091
  }
3092

3093
  @Override
3094
  public Statement visitFullMerge(IoTDBSqlParser.FullMergeContext ctx) {
3095
    MergeStatement mergeStatement = new MergeStatement(StatementType.FULL_MERGE);
×
3096
    if (ctx.CLUSTER() != null && !IoTDBDescriptor.getInstance().getConfig().isClusterMode()) {
×
3097
      throw new SemanticException("FULL MERGE ON CLUSTER is not supported in standalone mode");
×
3098
    }
3099
    mergeStatement.setOnCluster(ctx.LOCAL() == null);
×
3100
    return mergeStatement;
×
3101
  }
3102

3103
  // Flush
3104

3105
  @Override
3106
  public Statement visitFlush(IoTDBSqlParser.FlushContext ctx) {
3107
    FlushStatement flushStatement = new FlushStatement(StatementType.FLUSH);
×
3108
    List<PartialPath> storageGroups = null;
×
3109
    if (ctx.boolean_literal() != null) {
×
3110
      flushStatement.setSeq(Boolean.parseBoolean(ctx.boolean_literal().getText()));
×
3111
    }
3112
    if (ctx.CLUSTER() != null && !IoTDBDescriptor.getInstance().getConfig().isClusterMode()) {
×
3113
      throw new SemanticException("FLUSH ON CLUSTER is not supported in standalone mode");
×
3114
    }
3115
    flushStatement.setOnCluster(ctx.LOCAL() == null);
×
3116
    if (ctx.prefixPath(0) != null) {
×
3117
      storageGroups = new ArrayList<>();
×
3118
      for (IoTDBSqlParser.PrefixPathContext prefixPathContext : ctx.prefixPath()) {
×
3119
        storageGroups.add(parsePrefixPath(prefixPathContext));
×
3120
      }
×
3121
    }
3122
    flushStatement.setStorageGroups(storageGroups);
×
3123
    return flushStatement;
×
3124
  }
3125

3126
  // Clear Cache
3127

3128
  @Override
3129
  public Statement visitClearCache(IoTDBSqlParser.ClearCacheContext ctx) {
3130
    ClearCacheStatement clearCacheStatement = new ClearCacheStatement(StatementType.CLEAR_CACHE);
×
3131
    if (ctx.CLUSTER() != null && !IoTDBDescriptor.getInstance().getConfig().isClusterMode()) {
×
3132
      throw new SemanticException("CLEAR CACHE ON CLUSTER is not supported in standalone mode");
×
3133
    }
3134
    clearCacheStatement.setOnCluster(ctx.LOCAL() == null);
×
3135
    return clearCacheStatement;
×
3136
  }
3137

3138
  // Load Configuration
3139

3140
  @Override
3141
  public Statement visitLoadConfiguration(IoTDBSqlParser.LoadConfigurationContext ctx) {
3142
    LoadConfigurationStatement loadConfigurationStatement =
×
3143
        new LoadConfigurationStatement(StatementType.LOAD_CONFIGURATION);
3144
    if (ctx.CLUSTER() != null && !IoTDBDescriptor.getInstance().getConfig().isClusterMode()) {
×
3145
      throw new SemanticException(
×
3146
          "LOAD CONFIGURATION ON CLUSTER is not supported in standalone mode");
3147
    }
3148
    loadConfigurationStatement.setOnCluster(ctx.LOCAL() == null);
×
3149
    return loadConfigurationStatement;
×
3150
  }
3151

3152
  // Set System Status
3153

3154
  @Override
3155
  public Statement visitSetSystemStatus(IoTDBSqlParser.SetSystemStatusContext ctx) {
3156
    SetSystemStatusStatement setSystemStatusStatement = new SetSystemStatusStatement();
×
3157
    if (ctx.CLUSTER() != null && !IoTDBDescriptor.getInstance().getConfig().isClusterMode()) {
×
3158
      throw new SemanticException(
×
3159
          "SET SYSTEM STATUS ON CLUSTER is not supported in standalone mode");
3160
    }
3161
    setSystemStatusStatement.setOnCluster(ctx.LOCAL() == null);
×
3162
    if (ctx.RUNNING() != null) {
×
3163
      setSystemStatusStatement.setStatus(NodeStatus.Running);
×
3164
    } else if (ctx.READONLY() != null) {
×
3165
      setSystemStatusStatement.setStatus(NodeStatus.ReadOnly);
×
3166
    } else {
3167
      throw new SemanticException("Unknown system status in set system command.");
×
3168
    }
3169
    return setSystemStatusStatement;
×
3170
  }
3171

3172
  // Kill Query
3173
  @Override
3174
  public Statement visitKillQuery(IoTDBSqlParser.KillQueryContext ctx) {
3175
    if (ctx.queryId != null) {
×
3176
      return new KillQueryStatement(parseStringLiteral(ctx.queryId.getText()));
×
3177
    }
3178
    return new KillQueryStatement();
×
3179
  }
3180

3181
  // show query processlist
3182

3183
  @Override
3184
  public Statement visitShowQueries(IoTDBSqlParser.ShowQueriesContext ctx) {
3185
    ShowQueriesStatement showQueriesStatement = new ShowQueriesStatement();
×
3186
    // parse WHERE
3187
    if (ctx.whereClause() != null) {
×
3188
      showQueriesStatement.setWhereCondition(parseWhereClause(ctx.whereClause()));
×
3189
    }
3190

3191
    // parse ORDER BY
3192
    if (ctx.orderByClause() != null) {
×
3193
      showQueriesStatement.setOrderByComponent(
×
3194
          parseOrderByClause(
×
3195
              ctx.orderByClause(),
×
3196
              ImmutableSet.of(
×
3197
                  OrderByKey.TIME,
3198
                  OrderByKey.QUERYID,
3199
                  OrderByKey.DATANODEID,
3200
                  OrderByKey.ELAPSEDTIME,
3201
                  OrderByKey.STATEMENT)));
3202
    }
3203

3204
    // parse LIMIT & OFFSET
3205
    if (ctx.rowPaginationClause() != null) {
×
3206
      if (ctx.rowPaginationClause().limitClause() != null) {
×
3207
        showQueriesStatement.setRowLimit(parseLimitClause(ctx.rowPaginationClause().limitClause()));
×
3208
      }
3209
      if (ctx.rowPaginationClause().offsetClause() != null) {
×
3210
        showQueriesStatement.setRowOffset(
×
3211
            parseOffsetClause(ctx.rowPaginationClause().offsetClause()));
×
3212
      }
3213
    }
3214

3215
    showQueriesStatement.setZoneId(zoneId);
×
3216
    return showQueriesStatement;
×
3217
  }
3218

3219
  // show region
3220

3221
  @Override
3222
  public Statement visitShowRegions(IoTDBSqlParser.ShowRegionsContext ctx) {
3223
    ShowRegionStatement showRegionStatement = new ShowRegionStatement();
×
3224
    // TODO: Maybe add a show ConfigNode region in the future
3225
    if (ctx.DATA() != null) {
×
3226
      showRegionStatement.setRegionType(TConsensusGroupType.DataRegion);
×
3227
    } else if (ctx.SCHEMA() != null) {
×
3228
      showRegionStatement.setRegionType(TConsensusGroupType.SchemaRegion);
×
3229
    } else {
3230
      showRegionStatement.setRegionType(null);
×
3231
    }
3232

3233
    if (ctx.OF() != null) {
×
3234
      List<PartialPath> storageGroups = null;
×
3235
      if (ctx.prefixPath(0) != null) {
×
3236
        storageGroups = new ArrayList<>();
×
3237
        for (IoTDBSqlParser.PrefixPathContext prefixPathContext : ctx.prefixPath()) {
×
3238
          storageGroups.add(parsePrefixPath(prefixPathContext));
×
3239
        }
×
3240
      }
3241
      showRegionStatement.setStorageGroups(storageGroups);
×
3242
    } else {
×
3243
      showRegionStatement.setStorageGroups(null);
×
3244
    }
3245

3246
    if (ctx.ON() != null) {
×
3247
      List<Integer> nodeIds = new ArrayList<>();
×
3248
      for (TerminalNode nodeid : ctx.INTEGER_LITERAL()) {
×
3249
        nodeIds.add(Integer.parseInt(nodeid.getText()));
×
3250
      }
×
3251
      showRegionStatement.setNodeIds(nodeIds);
×
3252
    } else {
×
3253
      showRegionStatement.setNodeIds(null);
×
3254
    }
3255
    return showRegionStatement;
×
3256
  }
3257

3258
  // show datanodes
3259

3260
  @Override
3261
  public Statement visitShowDataNodes(IoTDBSqlParser.ShowDataNodesContext ctx) {
3262
    return new ShowDataNodesStatement();
×
3263
  }
3264

3265
  // show confignodes
3266

3267
  @Override
3268
  public Statement visitShowConfigNodes(IoTDBSqlParser.ShowConfigNodesContext ctx) {
3269
    return new ShowConfigNodesStatement();
×
3270
  }
3271

3272
  // schema template
3273

3274
  @Override
3275
  public Statement visitCreateSchemaTemplate(IoTDBSqlParser.CreateSchemaTemplateContext ctx) {
3276
    String name = parseIdentifier(ctx.templateName.getText());
×
3277
    List<List<String>> measurementsList = new ArrayList<>();
×
3278
    List<List<TSDataType>> dataTypesList = new ArrayList<>();
×
3279
    List<List<TSEncoding>> encodingsList = new ArrayList<>();
×
3280
    List<List<CompressionType>> compressorsList = new ArrayList<>();
×
3281

3282
    if (ctx.ALIGNED() != null) {
×
3283
      // aligned
3284
      List<String> measurements = new ArrayList<>();
×
3285
      List<TSDataType> dataTypes = new ArrayList<>();
×
3286
      List<TSEncoding> encodings = new ArrayList<>();
×
3287
      List<CompressionType> compressors = new ArrayList<>();
×
3288
      for (IoTDBSqlParser.TemplateMeasurementClauseContext templateClauseContext :
3289
          ctx.templateMeasurementClause()) {
×
3290
        measurements.add(
×
3291
            parseNodeNameWithoutWildCard(templateClauseContext.nodeNameWithoutWildcard()));
×
3292
        parseAttributeClauseForSchemaTemplate(
×
3293
            templateClauseContext.attributeClauses(), dataTypes, encodings, compressors);
×
3294
      }
×
3295
      measurementsList.add(measurements);
×
3296
      dataTypesList.add(dataTypes);
×
3297
      encodingsList.add(encodings);
×
3298
      compressorsList.add(compressors);
×
3299
    } else {
×
3300
      // non-aligned
3301
      for (IoTDBSqlParser.TemplateMeasurementClauseContext templateClauseContext :
3302
          ctx.templateMeasurementClause()) {
×
3303
        List<String> measurements = new ArrayList<>();
×
3304
        List<TSDataType> dataTypes = new ArrayList<>();
×
3305
        List<TSEncoding> encodings = new ArrayList<>();
×
3306
        List<CompressionType> compressors = new ArrayList<>();
×
3307
        measurements.add(
×
3308
            parseNodeNameWithoutWildCard(templateClauseContext.nodeNameWithoutWildcard()));
×
3309
        parseAttributeClauseForSchemaTemplate(
×
3310
            templateClauseContext.attributeClauses(), dataTypes, encodings, compressors);
×
3311
        measurementsList.add(measurements);
×
3312
        dataTypesList.add(dataTypes);
×
3313
        encodingsList.add(encodings);
×
3314
        compressorsList.add(compressors);
×
3315
      }
×
3316
    }
3317

3318
    return new CreateSchemaTemplateStatement(
×
3319
        name,
3320
        measurementsList,
3321
        dataTypesList,
3322
        encodingsList,
3323
        compressorsList,
3324
        ctx.ALIGNED() != null);
×
3325
  }
3326

3327
  @Override
3328
  public Statement visitAlterSchemaTemplate(IoTDBSqlParser.AlterSchemaTemplateContext ctx) {
3329
    String name = parseIdentifier(ctx.templateName.getText());
×
3330
    List<String> measurements = new ArrayList<>();
×
3331
    List<TSDataType> dataTypes = new ArrayList<>();
×
3332
    List<TSEncoding> encodings = new ArrayList<>();
×
3333
    List<CompressionType> compressors = new ArrayList<>();
×
3334

3335
    for (IoTDBSqlParser.TemplateMeasurementClauseContext templateClauseContext :
3336
        ctx.templateMeasurementClause()) {
×
3337
      measurements.add(
×
3338
          parseNodeNameWithoutWildCard(templateClauseContext.nodeNameWithoutWildcard()));
×
3339
      parseAttributeClauseForSchemaTemplate(
×
3340
          templateClauseContext.attributeClauses(), dataTypes, encodings, compressors);
×
3341
    }
×
3342

3343
    return new AlterSchemaTemplateStatement(
×
3344
        name,
3345
        measurements,
3346
        dataTypes,
3347
        encodings,
3348
        compressors,
3349
        TemplateAlterOperationType.EXTEND_TEMPLATE);
3350
  }
3351

3352
  void parseAttributeClauseForSchemaTemplate(
3353
      IoTDBSqlParser.AttributeClausesContext ctx,
3354
      List<TSDataType> dataTypes,
3355
      List<TSEncoding> encodings,
3356
      List<CompressionType> compressors) {
3357
    if (ctx.aliasNodeName() != null) {
×
3358
      throw new SemanticException("Schema template: alias is not supported yet.");
×
3359
    }
3360

3361
    TSDataType dataType = parseDataTypeAttribute(ctx);
×
3362
    dataTypes.add(dataType);
×
3363

3364
    Map<String, String> props = new HashMap<>();
×
3365
    if (ctx.attributePair() != null) {
×
3366
      for (int i = 0; i < ctx.attributePair().size(); i++) {
×
3367
        props.put(
×
3368
            parseAttributeKey(ctx.attributePair(i).attributeKey()).toLowerCase(),
×
3369
            parseAttributeValue(ctx.attributePair(i).attributeValue()));
×
3370
      }
3371
    }
3372

3373
    TSEncoding encoding = IoTDBDescriptor.getInstance().getDefaultEncodingByType(dataType);
×
3374
    if (props.containsKey(IoTDBConstant.COLUMN_TIMESERIES_ENCODING.toLowerCase())) {
×
3375
      String encodingString =
×
3376
          props.get(IoTDBConstant.COLUMN_TIMESERIES_ENCODING.toLowerCase()).toUpperCase();
×
3377
      try {
3378
        encoding = TSEncoding.valueOf(encodingString);
×
3379
        encodings.add(encoding);
×
3380
        props.remove(IoTDBConstant.COLUMN_TIMESERIES_ENCODING.toLowerCase());
×
3381
      } catch (Exception e) {
×
3382
        throw new SemanticException(String.format("Unsupported encoding: %s", encodingString));
×
3383
      }
×
3384
    } else {
×
3385
      encodings.add(encoding);
×
3386
    }
3387

3388
    CompressionType compressor = TSFileDescriptor.getInstance().getConfig().getCompressor();
×
3389
    if (props.containsKey(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSOR.toLowerCase())) {
×
3390
      String compressorString =
×
3391
          props.get(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSOR.toLowerCase()).toUpperCase();
×
3392
      try {
3393
        compressor = CompressionType.valueOf(compressorString);
×
3394
        compressors.add(compressor);
×
3395
        props.remove(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSOR.toLowerCase());
×
3396
      } catch (Exception e) {
×
3397
        throw new SemanticException(String.format("Unsupported compressor: %s", compressorString));
×
3398
      }
×
3399
    } else if (props.containsKey(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSION.toLowerCase())) {
×
3400
      String compressionString =
×
3401
          props.get(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSION.toLowerCase()).toUpperCase();
×
3402
      try {
3403
        compressor = CompressionType.valueOf(compressionString);
×
3404
        compressors.add(compressor);
×
3405
        props.remove(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSION.toLowerCase());
×
3406
      } catch (Exception e) {
×
3407
        throw new SemanticException(
×
3408
            String.format("Unsupported compression: %s", compressionString));
×
3409
      }
×
3410
    } else {
×
3411
      compressors.add(compressor);
×
3412
    }
3413

3414
    if (props.size() > 0) {
×
3415
      throw new SemanticException("Schema template: property is not supported yet.");
×
3416
    }
3417

3418
    if (ctx.tagClause() != null) {
×
3419
      throw new SemanticException("Schema template: tag is not supported yet.");
×
3420
    }
3421

3422
    if (ctx.attributeClause() != null) {
×
3423
      throw new SemanticException("Schema template: attribute is not supported yet.");
×
3424
    }
3425
  }
×
3426

3427
  private TSDataType parseDataTypeAttribute(IoTDBSqlParser.AttributeClausesContext ctx) {
3428
    TSDataType dataType = null;
1✔
3429
    if (ctx.dataType != null) {
1✔
3430
      if (ctx.attributeKey() != null
1✔
3431
          && !parseAttributeKey(ctx.attributeKey())
×
3432
              .equalsIgnoreCase(IoTDBConstant.COLUMN_TIMESERIES_DATATYPE)) {
×
3433
        throw new SemanticException("Expecting datatype");
×
3434
      }
3435
      String dataTypeString = ctx.dataType.getText().toUpperCase();
1✔
3436
      try {
3437
        dataType = TSDataType.valueOf(dataTypeString);
1✔
3438
      } catch (Exception e) {
×
3439
        throw new SemanticException(String.format("Unsupported datatype: %s", dataTypeString));
×
3440
      }
1✔
3441
    }
3442
    return dataType;
1✔
3443
  }
3444

3445
  @Override
3446
  public Statement visitShowSchemaTemplates(IoTDBSqlParser.ShowSchemaTemplatesContext ctx) {
3447
    return new ShowSchemaTemplateStatement();
×
3448
  }
3449

3450
  @Override
3451
  public Statement visitShowNodesInSchemaTemplate(
3452
      IoTDBSqlParser.ShowNodesInSchemaTemplateContext ctx) {
3453
    String templateName = parseIdentifier(ctx.templateName.getText());
×
3454
    return new ShowNodesInSchemaTemplateStatement(templateName);
×
3455
  }
3456

3457
  @Override
3458
  public Statement visitSetSchemaTemplate(IoTDBSqlParser.SetSchemaTemplateContext ctx) {
3459
    String templateName = parseIdentifier(ctx.templateName.getText());
×
3460
    return new SetSchemaTemplateStatement(templateName, parsePrefixPath(ctx.prefixPath()));
×
3461
  }
3462

3463
  @Override
3464
  public Statement visitShowPathsSetSchemaTemplate(
3465
      IoTDBSqlParser.ShowPathsSetSchemaTemplateContext ctx) {
3466
    String templateName = parseIdentifier(ctx.templateName.getText());
×
3467
    return new ShowPathSetTemplateStatement(templateName);
×
3468
  }
3469

3470
  @Override
3471
  public Statement visitCreateTimeseriesUsingSchemaTemplate(
3472
      IoTDBSqlParser.CreateTimeseriesUsingSchemaTemplateContext ctx) {
3473
    ActivateTemplateStatement statement = new ActivateTemplateStatement();
×
3474
    statement.setPath(parsePrefixPath(ctx.prefixPath()));
×
3475
    return statement;
×
3476
  }
3477

3478
  @Override
3479
  public Statement visitShowPathsUsingSchemaTemplate(
3480
      IoTDBSqlParser.ShowPathsUsingSchemaTemplateContext ctx) {
3481
    PartialPath pathPattern;
3482
    if (ctx.prefixPath() == null) {
×
3483
      pathPattern = new PartialPath(SqlConstant.getSingleRootArray());
×
3484
    } else {
3485
      pathPattern = parsePrefixPath(ctx.prefixPath());
×
3486
    }
3487
    return new ShowPathsUsingTemplateStatement(
×
3488
        pathPattern, parseIdentifier(ctx.templateName.getText()));
×
3489
  }
3490

3491
  @Override
3492
  public Statement visitDropTimeseriesOfSchemaTemplate(
3493
      IoTDBSqlParser.DropTimeseriesOfSchemaTemplateContext ctx) {
3494
    DeactivateTemplateStatement statement = new DeactivateTemplateStatement();
×
3495
    if (ctx.templateName != null) {
×
3496
      statement.setTemplateName(parseIdentifier(ctx.templateName.getText()));
×
3497
    }
3498
    List<PartialPath> pathPatternList = new ArrayList<>();
×
3499
    for (IoTDBSqlParser.PrefixPathContext prefixPathContext : ctx.prefixPath()) {
×
3500
      pathPatternList.add(parsePrefixPath(prefixPathContext));
×
3501
    }
×
3502
    statement.setPathPatternList(pathPatternList);
×
3503
    return statement;
×
3504
  }
3505

3506
  @Override
3507
  public Statement visitUnsetSchemaTemplate(IoTDBSqlParser.UnsetSchemaTemplateContext ctx) {
3508
    String templateName = parseIdentifier(ctx.templateName.getText());
×
3509
    PartialPath path = parsePrefixPath(ctx.prefixPath());
×
3510
    return new UnsetSchemaTemplateStatement(templateName, path);
×
3511
  }
3512

3513
  @Override
3514
  public Statement visitDropSchemaTemplate(IoTDBSqlParser.DropSchemaTemplateContext ctx) {
3515
    return new DropSchemaTemplateStatement(parseIdentifier(ctx.templateName.getText()));
×
3516
  }
3517

3518
  public Map<String, String> parseSyncAttributeClauses(
3519
      IoTDBSqlParser.SyncAttributeClausesContext ctx) {
3520

3521
    Map<String, String> attributes = new HashMap<>();
×
3522

3523
    List<IoTDBSqlParser.AttributePairContext> attributePairs = ctx.attributePair();
×
3524
    if (ctx.attributePair(0) != null) {
×
3525
      for (IoTDBSqlParser.AttributePairContext attributePair : attributePairs) {
×
3526
        attributes.put(
×
3527
            parseAttributeKey(attributePair.attributeKey()).toLowerCase(),
×
3528
            parseAttributeValue(attributePair.attributeValue()).toLowerCase());
×
3529
      }
×
3530
    }
3531

3532
    return attributes;
×
3533
  }
3534

3535
  // PIPE
3536

3537
  @Override
3538
  public Statement visitCreatePipe(IoTDBSqlParser.CreatePipeContext ctx) {
3539
    final CreatePipeStatement createPipeStatement =
×
3540
        new CreatePipeStatement(StatementType.CREATE_PIPE);
3541

3542
    if (ctx.pipeName != null) {
×
3543
      createPipeStatement.setPipeName(ctx.pipeName.getText());
×
3544
    } else {
3545
      throw new SemanticException(
×
3546
          "Not support for this sql in CREATEPIPE, please enter pipe name.");
3547
    }
3548
    if (ctx.extractorAttributesClause() != null) {
×
3549
      createPipeStatement.setExtractorAttributes(
×
3550
          parseExtractorAttributesClause(ctx.extractorAttributesClause()));
×
3551
    } else {
3552
      createPipeStatement.setExtractorAttributes(new HashMap<>());
×
3553
    }
3554
    if (ctx.processorAttributesClause() != null) {
×
3555
      createPipeStatement.setProcessorAttributes(
×
3556
          parseProcessorAttributesClause(ctx.processorAttributesClause()));
×
3557
    } else {
3558
      createPipeStatement.setProcessorAttributes(new HashMap<>());
×
3559
    }
3560
    createPipeStatement.setConnectorAttributes(
×
3561
        parseConnectorAttributesClause(ctx.connectorAttributesClause()));
×
3562
    return createPipeStatement;
×
3563
  }
3564

3565
  private Map<String, String> parseExtractorAttributesClause(
3566
      IoTDBSqlParser.ExtractorAttributesClauseContext ctx) {
3567
    final Map<String, String> collectorMap = new HashMap<>();
×
3568
    for (IoTDBSqlParser.ExtractorAttributeClauseContext singleCtx :
3569
        ctx.extractorAttributeClause()) {
×
3570
      collectorMap.put(
×
3571
          parseStringLiteral(singleCtx.extractorKey.getText()),
×
3572
          parseStringLiteral(singleCtx.extractorValue.getText()));
×
3573
    }
×
3574
    return collectorMap;
×
3575
  }
3576

3577
  private Map<String, String> parseProcessorAttributesClause(
3578
      IoTDBSqlParser.ProcessorAttributesClauseContext ctx) {
3579
    final Map<String, String> processorMap = new HashMap<>();
×
3580
    for (IoTDBSqlParser.ProcessorAttributeClauseContext singleCtx :
3581
        ctx.processorAttributeClause()) {
×
3582
      processorMap.put(
×
3583
          parseStringLiteral(singleCtx.processorKey.getText()),
×
3584
          parseStringLiteral(singleCtx.processorValue.getText()));
×
3585
    }
×
3586
    return processorMap;
×
3587
  }
3588

3589
  private Map<String, String> parseConnectorAttributesClause(
3590
      IoTDBSqlParser.ConnectorAttributesClauseContext ctx) {
3591
    final Map<String, String> connectorMap = new HashMap<>();
×
3592
    for (IoTDBSqlParser.ConnectorAttributeClauseContext singleCtx :
3593
        ctx.connectorAttributeClause()) {
×
3594
      connectorMap.put(
×
3595
          parseStringLiteral(singleCtx.connectorKey.getText()),
×
3596
          parseStringLiteral(singleCtx.connectorValue.getText()));
×
3597
    }
×
3598
    return connectorMap;
×
3599
  }
3600

3601
  @Override
3602
  public Statement visitDropPipe(IoTDBSqlParser.DropPipeContext ctx) {
3603
    final DropPipeStatement dropPipeStatement = new DropPipeStatement(StatementType.DROP_PIPE);
×
3604

3605
    if (ctx.pipeName != null) {
×
3606
      dropPipeStatement.setPipeName(ctx.pipeName.getText());
×
3607
    } else {
3608
      throw new SemanticException("Not support for this sql in DROP PIPE, please enter pipename.");
×
3609
    }
3610

3611
    return dropPipeStatement;
×
3612
  }
3613

3614
  @Override
3615
  public Statement visitStartPipe(IoTDBSqlParser.StartPipeContext ctx) {
3616
    final StartPipeStatement startPipeStatement = new StartPipeStatement(StatementType.START_PIPE);
×
3617

3618
    if (ctx.pipeName != null) {
×
3619
      startPipeStatement.setPipeName(ctx.pipeName.getText());
×
3620
    } else {
3621
      throw new SemanticException("Not support for this sql in START PIPE, please enter pipename.");
×
3622
    }
3623

3624
    return startPipeStatement;
×
3625
  }
3626

3627
  @Override
3628
  public Statement visitStopPipe(IoTDBSqlParser.StopPipeContext ctx) {
3629
    final StopPipeStatement stopPipeStatement = new StopPipeStatement(StatementType.STOP_PIPE);
×
3630

3631
    if (ctx.pipeName != null) {
×
3632
      stopPipeStatement.setPipeName(ctx.pipeName.getText());
×
3633
    } else {
3634
      throw new SemanticException("Not support for this sql in STOP PIPE, please enter pipename.");
×
3635
    }
3636

3637
    return stopPipeStatement;
×
3638
  }
3639

3640
  @Override
3641
  public Statement visitShowPipes(IoTDBSqlParser.ShowPipesContext ctx) {
3642
    final ShowPipesStatement showPipesStatement = new ShowPipesStatement();
×
3643

3644
    if (ctx.pipeName != null) {
×
3645
      showPipesStatement.setPipeName(parseIdentifier(ctx.pipeName.getText()));
×
3646
    }
3647
    showPipesStatement.setWhereClause(ctx.CONNECTOR() != null);
×
3648

3649
    return showPipesStatement;
×
3650
  }
3651

3652
  @Override
3653
  public Statement visitGetRegionId(IoTDBSqlParser.GetRegionIdContext ctx) {
3654
    TConsensusGroupType type =
3655
        ctx.DATA() == null ? TConsensusGroupType.SchemaRegion : TConsensusGroupType.DataRegion;
×
3656
    GetRegionIdStatement getRegionIdStatement = new GetRegionIdStatement(type);
×
3657
    if (ctx.database != null) {
×
3658
      getRegionIdStatement.setDatabase(ctx.database.getText());
×
3659
    } else {
3660
      getRegionIdStatement.setDevice(ctx.device.getText());
×
3661
    }
3662
    if (ctx.time != null) {
×
3663
      long timestamp = parseTimeValue(ctx.time, DateTimeUtils.currentTime());
×
3664
      if (timestamp < 0) {
×
3665
        throw new SemanticException(NEGATIVE_TIMESTAMP_ERROR_MSG);
×
3666
      } else {
3667
        getRegionIdStatement.setTimeStamp(timestamp);
×
3668
      }
3669
    }
3670
    return getRegionIdStatement;
×
3671
  }
3672

3673
  @Override
3674
  public Statement visitGetSeriesSlotList(IoTDBSqlParser.GetSeriesSlotListContext ctx) {
3675
    TConsensusGroupType type =
3676
        ctx.DATA() == null ? TConsensusGroupType.SchemaRegion : TConsensusGroupType.DataRegion;
×
3677
    return new GetSeriesSlotListStatement(ctx.database.getText(), type);
×
3678
  }
3679

3680
  @Override
3681
  public Statement visitGetTimeSlotList(IoTDBSqlParser.GetTimeSlotListContext ctx) {
3682
    GetTimeSlotListStatement getTimeSlotListStatement = new GetTimeSlotListStatement();
×
3683
    if (ctx.database != null) {
×
3684
      getTimeSlotListStatement.setDatabase(ctx.database.getText());
×
3685
    } else if (ctx.device != null) {
×
3686
      getTimeSlotListStatement.setDevice(ctx.device.getText());
×
3687
    } else if (ctx.regionId != null) {
×
3688
      getTimeSlotListStatement.setRegionId(Integer.parseInt(ctx.regionId.getText()));
×
3689
    }
3690
    if (ctx.startTime != null) {
×
3691
      long timestamp = parseTimeValue(ctx.startTime, DateTimeUtils.currentTime());
×
3692
      if (timestamp < 0) {
×
3693
        throw new SemanticException(NEGATIVE_TIMESTAMP_ERROR_MSG);
×
3694
      } else {
3695
        getTimeSlotListStatement.setStartTime(timestamp);
×
3696
      }
3697
    }
3698
    if (ctx.endTime != null) {
×
3699
      long timestamp = parseTimeValue(ctx.endTime, DateTimeUtils.currentTime());
×
3700
      if (timestamp < 0) {
×
3701
        throw new SemanticException(NEGATIVE_TIMESTAMP_ERROR_MSG);
×
3702
      } else {
3703
        getTimeSlotListStatement.setEndTime(timestamp);
×
3704
      }
3705
    }
3706
    return getTimeSlotListStatement;
×
3707
  }
3708

3709
  @Override
3710
  public Statement visitCountTimeSlotList(IoTDBSqlParser.CountTimeSlotListContext ctx) {
3711
    CountTimeSlotListStatement countTimeSlotListStatement = new CountTimeSlotListStatement();
×
3712
    if (ctx.database != null) {
×
3713
      countTimeSlotListStatement.setDatabase(ctx.database.getText());
×
3714
    } else if (ctx.device != null) {
×
3715
      countTimeSlotListStatement.setDevice(ctx.device.getText());
×
3716
    } else if (ctx.regionId != null) {
×
3717
      countTimeSlotListStatement.setRegionId(Integer.parseInt(ctx.regionId.getText()));
×
3718
    }
3719
    if (ctx.startTime != null) {
×
3720
      countTimeSlotListStatement.setStartTime(Long.parseLong(ctx.startTime.getText()));
×
3721
    }
3722
    if (ctx.endTime != null) {
×
3723
      countTimeSlotListStatement.setEndTime(Long.parseLong(ctx.endTime.getText()));
×
3724
    }
3725
    return countTimeSlotListStatement;
×
3726
  }
3727

3728
  @Override
3729
  public Statement visitMigrateRegion(IoTDBSqlParser.MigrateRegionContext ctx) {
3730
    return new MigrateRegionStatement(
×
3731
        Integer.parseInt(ctx.regionId.getText()),
×
3732
        Integer.parseInt(ctx.fromId.getText()),
×
3733
        Integer.parseInt(ctx.toId.getText()));
×
3734
  }
3735

3736
  // Quota
3737
  @Override
3738
  public Statement visitSetSpaceQuota(IoTDBSqlParser.SetSpaceQuotaContext ctx) {
3739
    if (!IoTDBDescriptor.getInstance().getConfig().isQuotaEnable()) {
×
3740
      throw new SemanticException(LIMIT_CONFIGURATION_ENABLED_ERROR_MSG);
×
3741
    }
3742
    SetSpaceQuotaStatement setSpaceQuotaStatement = new SetSpaceQuotaStatement();
×
3743
    List<IoTDBSqlParser.PrefixPathContext> prefixPathContexts = ctx.prefixPath();
×
3744
    List<String> paths = new ArrayList<>();
×
3745
    for (IoTDBSqlParser.PrefixPathContext prefixPathContext : prefixPathContexts) {
×
3746
      paths.add(parsePrefixPath(prefixPathContext).getFullPath());
×
3747
    }
×
3748
    setSpaceQuotaStatement.setPrefixPathList(paths);
×
3749

3750
    Map<String, String> quotas = new HashMap<>();
×
3751
    for (IoTDBSqlParser.AttributePairContext attributePair : ctx.attributePair()) {
×
3752
      quotas.put(
×
3753
          parseAttributeKey(attributePair.attributeKey()),
×
3754
          parseAttributeValue(attributePair.attributeValue()));
×
3755
    }
×
3756

3757
    quotas
×
3758
        .keySet()
×
3759
        .forEach(
×
3760
            quotaType -> {
3761
              switch (quotaType) {
×
3762
                case IoTDBConstant.COLUMN_DEVICES:
3763
                  break;
×
3764
                case IoTDBConstant.COLUMN_TIMESERIES:
3765
                  break;
×
3766
                case IoTDBConstant.SPACE_QUOTA_DISK:
3767
                  break;
×
3768
                default:
3769
                  throw new SemanticException("Wrong space quota type: " + quotaType);
×
3770
              }
3771
            });
×
3772

3773
    if (quotas.containsKey(IoTDBConstant.COLUMN_DEVICES)) {
×
3774
      if (quotas.get(IoTDBConstant.COLUMN_DEVICES).equals(IoTDBConstant.QUOTA_UNLIMITED)) {
×
3775
        setSpaceQuotaStatement.setDeviceNum(IoTDBConstant.UNLIMITED_VALUE);
×
3776
      } else if (Long.parseLong(quotas.get(IoTDBConstant.COLUMN_DEVICES)) <= 0) {
×
3777
        throw new SemanticException("Please set the number of devices greater than 0");
×
3778
      } else {
3779
        setSpaceQuotaStatement.setDeviceNum(
×
3780
            Long.parseLong(quotas.get(IoTDBConstant.COLUMN_DEVICES)));
×
3781
      }
3782
    }
3783
    if (quotas.containsKey(IoTDBConstant.COLUMN_TIMESERIES)) {
×
3784
      if (quotas.get(IoTDBConstant.COLUMN_TIMESERIES).equals(IoTDBConstant.QUOTA_UNLIMITED)) {
×
3785
        setSpaceQuotaStatement.setTimeSeriesNum(IoTDBConstant.UNLIMITED_VALUE);
×
3786
      } else if (Long.parseLong(quotas.get(IoTDBConstant.COLUMN_TIMESERIES)) <= 0) {
×
3787
        throw new SemanticException("Please set the number of timeseries greater than 0");
×
3788
      } else {
3789
        setSpaceQuotaStatement.setTimeSeriesNum(
×
3790
            Long.parseLong(quotas.get(IoTDBConstant.COLUMN_TIMESERIES)));
×
3791
      }
3792
    }
3793
    if (quotas.containsKey(IoTDBConstant.SPACE_QUOTA_DISK)) {
×
3794
      if (quotas.get(IoTDBConstant.SPACE_QUOTA_DISK).equals(IoTDBConstant.QUOTA_UNLIMITED)) {
×
3795
        setSpaceQuotaStatement.setDiskSize(IoTDBConstant.UNLIMITED_VALUE);
×
3796
      } else {
3797
        setSpaceQuotaStatement.setDiskSize(
×
3798
            parseSpaceQuotaSizeUnit(quotas.get(IoTDBConstant.SPACE_QUOTA_DISK)));
×
3799
      }
3800
    }
3801
    return setSpaceQuotaStatement;
×
3802
  }
3803

3804
  @Override
3805
  public Statement visitSetThrottleQuota(IoTDBSqlParser.SetThrottleQuotaContext ctx) {
3806
    if (!IoTDBDescriptor.getInstance().getConfig().isQuotaEnable()) {
×
3807
      throw new SemanticException(LIMIT_CONFIGURATION_ENABLED_ERROR_MSG);
×
3808
    }
3809
    if (parseIdentifier(ctx.userName.getText()).equals(IoTDBConstant.PATH_ROOT)) {
×
3810
      throw new SemanticException("Cannot set throttle quota for user root.");
×
3811
    }
3812
    SetThrottleQuotaStatement setThrottleQuotaStatement = new SetThrottleQuotaStatement();
×
3813
    setThrottleQuotaStatement.setUserName(parseIdentifier(ctx.userName.getText()));
×
3814
    Map<String, String> quotas = new HashMap<>();
×
3815
    Map<ThrottleType, TTimedQuota> throttleLimit = new HashMap<>();
×
3816
    for (IoTDBSqlParser.AttributePairContext attributePair : ctx.attributePair()) {
×
3817
      quotas.put(
×
3818
          parseAttributeKey(attributePair.attributeKey()),
×
3819
          parseAttributeValue(attributePair.attributeValue()));
×
3820
    }
×
3821
    if (quotas.containsKey(IoTDBConstant.REQUEST_NUM_PER_UNIT_TIME)) {
×
3822
      TTimedQuota timedQuota;
3823
      String request = quotas.get(IoTDBConstant.REQUEST_NUM_PER_UNIT_TIME);
×
3824
      if (request.equals(IoTDBConstant.QUOTA_UNLIMITED)) {
×
3825
        timedQuota = new TTimedQuota(IoTDBConstant.SEC, Long.MAX_VALUE);
×
3826
      } else {
3827
        String[] split = request.toLowerCase().split(IoTDBConstant.REQ_SPLIT_UNIT);
×
3828
        if (Long.parseLong(split[0]) < 0) {
×
3829
          throw new SemanticException("Please set the number of requests greater than 0");
×
3830
        }
3831
        timedQuota =
×
3832
            new TTimedQuota(parseThrottleQuotaTimeUnit(split[1]), Long.parseLong(split[0]));
×
3833
      }
3834
      if (quotas.get(IoTDBConstant.REQUEST_TYPE) == null) {
×
3835
        throttleLimit.put(ThrottleType.REQUEST_NUMBER, timedQuota);
×
3836
      } else {
3837
        switch (quotas.get(IoTDBConstant.REQUEST_TYPE)) {
×
3838
          case IoTDBConstant.REQUEST_TYPE_READ:
3839
            throttleLimit.put(ThrottleType.READ_NUMBER, timedQuota);
×
3840
            break;
×
3841
          case IoTDBConstant.REQUEST_TYPE_WRITE:
3842
            throttleLimit.put(ThrottleType.WRITE_NUMBER, timedQuota);
×
3843
            break;
×
3844
          default:
3845
            throw new SemanticException(
×
3846
                "Please set the correct request type: " + quotas.get(IoTDBConstant.REQUEST_TYPE));
×
3847
        }
3848
      }
3849
    }
3850

3851
    if (quotas.containsKey(IoTDBConstant.REQUEST_SIZE_PER_UNIT_TIME)) {
×
3852
      TTimedQuota timedQuota;
3853
      String size = quotas.get(IoTDBConstant.REQUEST_SIZE_PER_UNIT_TIME);
×
3854
      if (size.equals(IoTDBConstant.QUOTA_UNLIMITED)) {
×
3855
        timedQuota = new TTimedQuota(IoTDBConstant.SEC, Long.MAX_VALUE);
×
3856
      } else {
3857
        String[] split = size.toLowerCase().split("/");
×
3858
        timedQuota =
×
3859
            new TTimedQuota(
3860
                parseThrottleQuotaTimeUnit(split[1]), parseThrottleQuotaSizeUnit(split[0]));
×
3861
      }
3862
      if (quotas.get(IoTDBConstant.REQUEST_TYPE) == null) {
×
3863
        throttleLimit.put(ThrottleType.REQUEST_SIZE, timedQuota);
×
3864
      } else {
3865
        switch (quotas.get(IoTDBConstant.REQUEST_TYPE)) {
×
3866
          case IoTDBConstant.REQUEST_TYPE_READ:
3867
            throttleLimit.put(ThrottleType.READ_SIZE, timedQuota);
×
3868
            break;
×
3869
          case IoTDBConstant.REQUEST_TYPE_WRITE:
3870
            throttleLimit.put(ThrottleType.WRITE_SIZE, timedQuota);
×
3871
            break;
×
3872
          default:
3873
            throw new SemanticException(
×
3874
                "Please set the correct request type: " + quotas.get(IoTDBConstant.REQUEST_TYPE));
×
3875
        }
3876
      }
3877
    }
3878

3879
    if (quotas.containsKey(IoTDBConstant.MEMORY_SIZE_PER_READ)) {
×
3880
      String mem = quotas.get(IoTDBConstant.MEMORY_SIZE_PER_READ);
×
3881
      if (mem.equals(IoTDBConstant.QUOTA_UNLIMITED)) {
×
3882
        setThrottleQuotaStatement.setMemLimit(IoTDBConstant.UNLIMITED_VALUE);
×
3883
      } else {
3884
        setThrottleQuotaStatement.setMemLimit(parseThrottleQuotaSizeUnit(mem));
×
3885
      }
3886
    }
3887

3888
    if (quotas.containsKey(IoTDBConstant.CPU_NUMBER_PER_READ)) {
×
3889
      String cpuLimit = quotas.get(IoTDBConstant.CPU_NUMBER_PER_READ);
×
3890
      if (cpuLimit.contains(IoTDBConstant.QUOTA_UNLIMITED)) {
×
3891
        setThrottleQuotaStatement.setCpuLimit(IoTDBConstant.UNLIMITED_VALUE);
×
3892
      } else {
3893
        int cpuNum = Integer.parseInt(cpuLimit);
×
3894
        if (cpuNum <= 0) {
×
3895
          throw new SemanticException("Please set the number of cpu greater than 0");
×
3896
        }
3897
        setThrottleQuotaStatement.setCpuLimit(cpuNum);
×
3898
      }
3899
    }
3900
    setThrottleQuotaStatement.setThrottleLimit(throttleLimit);
×
3901
    return setThrottleQuotaStatement;
×
3902
  }
3903

3904
  @Override
3905
  public Statement visitShowThrottleQuota(IoTDBSqlParser.ShowThrottleQuotaContext ctx) {
3906
    if (!IoTDBDescriptor.getInstance().getConfig().isQuotaEnable()) {
×
3907
      throw new SemanticException(LIMIT_CONFIGURATION_ENABLED_ERROR_MSG);
×
3908
    }
3909
    ShowThrottleQuotaStatement showThrottleQuotaStatement = new ShowThrottleQuotaStatement();
×
3910
    if (ctx.userName != null) {
×
3911
      showThrottleQuotaStatement.setUserName(parseIdentifier(ctx.userName.getText()));
×
3912
    }
3913
    return showThrottleQuotaStatement;
×
3914
  }
3915

3916
  private long parseThrottleQuotaTimeUnit(String timeUnit) {
3917
    switch (timeUnit.toLowerCase()) {
×
3918
      case IoTDBConstant.SEC_UNIT:
3919
        return IoTDBConstant.SEC;
×
3920
      case IoTDBConstant.MIN_UNIT:
3921
        return IoTDBConstant.MIN;
×
3922
      case IoTDBConstant.HOUR_UNIT:
3923
        return IoTDBConstant.HOUR;
×
3924
      case IoTDBConstant.DAY_UNIT:
3925
        return IoTDBConstant.DAY;
×
3926
      default:
3927
        throw new SemanticException(
×
3928
            "When setting the request, the unit is incorrect. Please use 'sec', 'min', 'hour', 'day' as the unit");
3929
    }
3930
  }
3931

3932
  private long parseThrottleQuotaSizeUnit(String data) {
3933
    String unit = data.substring(data.length() - 1);
×
3934
    long size = Long.parseLong(data.substring(0, data.length() - 1));
×
3935
    if (size <= 0) {
×
3936
      throw new SemanticException("Please set the size greater than 0");
×
3937
    }
3938
    switch (unit.toUpperCase()) {
×
3939
      case IoTDBConstant.B_UNIT:
3940
        return size;
×
3941
      case IoTDBConstant.KB_UNIT:
3942
        return size * IoTDBConstant.KB;
×
3943
      case IoTDBConstant.MB_UNIT:
3944
        return size * IoTDBConstant.MB;
×
3945
      case IoTDBConstant.GB_UNIT:
3946
        return size * IoTDBConstant.GB;
×
3947
      case IoTDBConstant.TB_UNIT:
3948
        return size * IoTDBConstant.TB;
×
3949
      case IoTDBConstant.PB_UNIT:
3950
        return size * IoTDBConstant.PB;
×
3951
      default:
3952
        throw new SemanticException(
×
3953
            "When setting the size/time, the unit is incorrect. Please use 'B', 'K', 'M', 'G', 'P', 'T' as the unit");
3954
    }
3955
  }
3956

3957
  private long parseSpaceQuotaSizeUnit(String data) {
3958
    String unit = data.substring(data.length() - 1);
×
3959
    long disk = Long.parseLong(data.substring(0, data.length() - 1));
×
3960
    if (disk <= 0) {
×
3961
      throw new SemanticException("Please set the disk size greater than 0");
×
3962
    }
3963
    switch (unit.toUpperCase()) {
×
3964
      case IoTDBConstant.MB_UNIT:
3965
        return disk;
×
3966
      case IoTDBConstant.GB_UNIT:
3967
        return disk * IoTDBConstant.KB;
×
3968
      case IoTDBConstant.TB_UNIT:
3969
        return disk * IoTDBConstant.MB;
×
3970
      case IoTDBConstant.PB_UNIT:
3971
        return disk * IoTDBConstant.GB;
×
3972
      default:
3973
        throw new SemanticException(
×
3974
            "When setting the disk size, the unit is incorrect. Please use 'M', 'G', 'P', 'T' as the unit");
3975
    }
3976
  }
3977

3978
  @Override
3979
  public Statement visitShowSpaceQuota(IoTDBSqlParser.ShowSpaceQuotaContext ctx) {
3980
    if (!IoTDBDescriptor.getInstance().getConfig().isQuotaEnable()) {
×
3981
      throw new SemanticException(LIMIT_CONFIGURATION_ENABLED_ERROR_MSG);
×
3982
    }
3983
    ShowSpaceQuotaStatement showSpaceQuotaStatement = new ShowSpaceQuotaStatement();
×
3984
    if (ctx.prefixPath() != null) {
×
3985
      List<PartialPath> databases = new ArrayList<>();
×
3986
      for (IoTDBSqlParser.PrefixPathContext prefixPathContext : ctx.prefixPath()) {
×
3987
        databases.add(parsePrefixPath(prefixPathContext));
×
3988
      }
×
3989
      showSpaceQuotaStatement.setDatabases(databases);
×
3990
    } else {
×
3991
      showSpaceQuotaStatement.setDatabases(null);
×
3992
    }
3993
    return showSpaceQuotaStatement;
×
3994
  }
3995
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc