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

apache / iotdb / #9805

pending completion
#9805

push

travis_ci

web-flow
[IOTDB-6105] Load: NPE when analyzing tsfile (#10821) (#10833)

(cherry picked from commit 2e6d9527c)

271 of 271 new or added lines in 5 files covered. (100.0%)

79671 of 165738 relevant lines covered (48.07%)

0.48 hits per line

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

27.43
/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.template.ActivateTemplateStatement;
164
import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.AlterSchemaTemplateStatement;
165
import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.CreateSchemaTemplateStatement;
166
import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.DeactivateTemplateStatement;
167
import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.DropSchemaTemplateStatement;
168
import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.SetSchemaTemplateStatement;
169
import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.ShowNodesInSchemaTemplateStatement;
170
import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.ShowPathSetTemplateStatement;
171
import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.ShowPathsUsingTemplateStatement;
172
import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.ShowSchemaTemplateStatement;
173
import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.UnsetSchemaTemplateStatement;
174
import org.apache.iotdb.db.queryengine.plan.statement.metadata.view.AlterLogicalViewStatement;
175
import org.apache.iotdb.db.queryengine.plan.statement.metadata.view.CreateLogicalViewStatement;
176
import org.apache.iotdb.db.queryengine.plan.statement.metadata.view.DeleteLogicalViewStatement;
177
import org.apache.iotdb.db.queryengine.plan.statement.metadata.view.ShowLogicalViewStatement;
178
import org.apache.iotdb.db.queryengine.plan.statement.sys.AuthorStatement;
179
import org.apache.iotdb.db.queryengine.plan.statement.sys.ClearCacheStatement;
180
import org.apache.iotdb.db.queryengine.plan.statement.sys.ExplainStatement;
181
import org.apache.iotdb.db.queryengine.plan.statement.sys.FlushStatement;
182
import org.apache.iotdb.db.queryengine.plan.statement.sys.KillQueryStatement;
183
import org.apache.iotdb.db.queryengine.plan.statement.sys.LoadConfigurationStatement;
184
import org.apache.iotdb.db.queryengine.plan.statement.sys.MergeStatement;
185
import org.apache.iotdb.db.queryengine.plan.statement.sys.SetSystemStatusStatement;
186
import org.apache.iotdb.db.queryengine.plan.statement.sys.ShowQueriesStatement;
187
import org.apache.iotdb.db.queryengine.plan.statement.sys.ShowVersionStatement;
188
import org.apache.iotdb.db.queryengine.plan.statement.sys.pipe.CreatePipeStatement;
189
import org.apache.iotdb.db.queryengine.plan.statement.sys.pipe.DropPipeStatement;
190
import org.apache.iotdb.db.queryengine.plan.statement.sys.pipe.ShowPipesStatement;
191
import org.apache.iotdb.db.queryengine.plan.statement.sys.pipe.StartPipeStatement;
192
import org.apache.iotdb.db.queryengine.plan.statement.sys.pipe.StopPipeStatement;
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.schemaengine.SchemaConstant.ALL_RESULT_NODES;
229
import static org.apache.iotdb.db.utils.constant.SqlConstant.CAST_FUNCTION;
230
import static org.apache.iotdb.db.utils.constant.SqlConstant.CAST_TYPE;
231
import static org.apache.iotdb.db.utils.constant.SqlConstant.REPLACE_FROM;
232
import static org.apache.iotdb.db.utils.constant.SqlConstant.REPLACE_FUNCTION;
233
import static org.apache.iotdb.db.utils.constant.SqlConstant.REPLACE_TO;
234
import static org.apache.iotdb.db.utils.constant.SqlConstant.ROUND_FUNCTION;
235
import static org.apache.iotdb.db.utils.constant.SqlConstant.ROUND_PLACES;
236
import static org.apache.iotdb.db.utils.constant.SqlConstant.SUBSTRING_FUNCTION;
237
import static org.apache.iotdb.db.utils.constant.SqlConstant.SUBSTRING_IS_STANDARD;
238
import static org.apache.iotdb.db.utils.constant.SqlConstant.SUBSTRING_LENGTH;
239
import static org.apache.iotdb.db.utils.constant.SqlConstant.SUBSTRING_START;
240

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

244
  private static final IoTDBConfig CONFIG = IoTDBDescriptor.getInstance().getConfig();
1✔
245

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

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

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

261
  private static final String IGNORENULL = "IgnoreNull";
262
  private ZoneId zoneId;
263

264
  private boolean useWildcard = false;
1✔
265

266
  public void setZoneId(ZoneId zoneId) {
267
    this.zoneId = zoneId;
1✔
268
  }
1✔
269

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

280
  /** Data Definition Language (DDL). */
281

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

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

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

315
  public void parseAttributeClausesForCreateNonAlignedTimeSeries(
316
      IoTDBSqlParser.AttributeClausesContext ctx,
317
      CreateTimeSeriesStatement createTimeSeriesStatement) {
318
    if (ctx.aliasNodeName() != null) {
1✔
319
      createTimeSeriesStatement.setAlias(parseNodeName(ctx.aliasNodeName().nodeName()));
×
320
    }
321

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

338
    createTimeSeriesStatement.setProps(props);
1✔
339
    checkPropsInCreateTimeSeries(createTimeSeriesStatement);
1✔
340

341
    if (ctx.tagClause() != null) {
1✔
342
      parseTagClause(ctx.tagClause(), createTimeSeriesStatement);
1✔
343
    }
344
    if (ctx.attributeClause() != null) {
1✔
345
      parseAttributeClauseForTimeSeries(ctx.attributeClause(), createTimeSeriesStatement);
1✔
346
    }
347
  }
1✔
348

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

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

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

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

422
    TSDataType dataType = parseDataTypeAttribute(ctx);
1✔
423
    createAlignedTimeSeriesStatement.addDataType(dataType);
1✔
424

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

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

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

475
    if (props.size() > 0) {
1✔
476
      throw new SemanticException("create aligned timeseries: property is not supported yet.");
×
477
    }
478

479
    if (ctx.tagClause() != null) {
1✔
480
      parseTagClause(ctx.tagClause(), createAlignedTimeSeriesStatement);
×
481
    } else {
482
      createAlignedTimeSeriesStatement.addTagsList(null);
1✔
483
    }
484

485
    if (ctx.attributeClause() != null) {
1✔
486
      parseAttributeClauseForTimeSeries(ctx.attributeClause(), createAlignedTimeSeriesStatement);
×
487
    } else {
488
      createAlignedTimeSeriesStatement.addAttributesList(null);
1✔
489
    }
490
  }
1✔
491

492
  // Tag & Property & Attribute
493

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

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

517
  // Alter Timeseries ========================================================================
518

519
  @Override
520
  public Statement visitAlterTimeseries(IoTDBSqlParser.AlterTimeseriesContext ctx) {
521
    AlterTimeSeriesStatement alterTimeSeriesStatement = new AlterTimeSeriesStatement();
×
522
    alterTimeSeriesStatement.setPath(parseFullPath(ctx.fullPath()));
×
523
    parseAlterClause(ctx.alterClause(), alterTimeSeriesStatement);
×
524
    return alterTimeSeriesStatement;
×
525
  }
526

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

568
  public void parseAliasClause(
569
      IoTDBSqlParser.AliasClauseContext ctx, AlterTimeSeriesStatement alterTimeSeriesStatement) {
570
    if (alterTimeSeriesStatement != null && ctx.ALIAS() != null) {
×
571
      alterTimeSeriesStatement.setAlias(parseAliasNode(ctx.alias()));
×
572
    }
573
  }
×
574

575
  // Drop Timeseries ======================================================================
576

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

588
  // Show Timeseries ========================================================================
589

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

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

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

657
  // SHOW DATABASES
658

659
  @Override
660
  public Statement visitShowDatabases(IoTDBSqlParser.ShowDatabasesContext ctx) {
661
    ShowDatabaseStatement showDatabaseStatement;
662

663
    // Parse prefixPath
664
    if (ctx.prefixPath() != null) {
×
665
      showDatabaseStatement = new ShowDatabaseStatement(parsePrefixPath(ctx.prefixPath()));
×
666
    } else {
667
      showDatabaseStatement =
×
668
          new ShowDatabaseStatement(new PartialPath(SqlConstant.getSingleRootArray()));
×
669
    }
670

671
    // Is detailed
672
    showDatabaseStatement.setDetailed(ctx.DETAILS() != null);
×
673

674
    return showDatabaseStatement;
×
675
  }
676

677
  // Show Devices ========================================================================
678

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

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

707
  private SchemaFilter parseDevicesWhereClause(IoTDBSqlParser.DevicesWhereClauseContext ctx) {
708
    // path contains filter
709
    return SchemaFilterFactory.createPathContainsFilter(
×
710
        parseStringLiteral(ctx.deviceContainsExpression().value.getText()));
×
711
  }
712

713
  // Count Devices ========================================================================
714

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

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

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

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

778
  // Show version
779
  @Override
780
  public Statement visitShowVersion(IoTDBSqlParser.ShowVersionContext ctx) {
781
    return new ShowVersionStatement();
×
782
  }
783

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

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

812
  // Drop Function
813
  @Override
814
  public Statement visitDropFunction(DropFunctionContext ctx) {
815
    return new DropFunctionStatement(parseIdentifier(ctx.udfName.getText()));
×
816
  }
817

818
  // Show Functions
819
  @Override
820
  public Statement visitShowFunctions(ShowFunctionsContext ctx) {
821
    return new ShowFunctionsStatement();
×
822
  }
823

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

870
  // Drop Trigger =====================================================================
871
  @Override
872
  public Statement visitDropTrigger(IoTDBSqlParser.DropTriggerContext ctx) {
873
    return new DropTriggerStatement(parseIdentifier(ctx.triggerName.getText()));
×
874
  }
875

876
  // Show Trigger =====================================================================
877
  @Override
878
  public Statement visitShowTriggers(IoTDBSqlParser.ShowTriggersContext ctx) {
879
    return new ShowTriggersStatement();
×
880
  }
881

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

891
  // Drop PipePlugin =====================================================================
892
  @Override
893
  public Statement visitDropPipePlugin(IoTDBSqlParser.DropPipePluginContext ctx) {
894
    return new DropPipePluginStatement(ctx.pluginName.getText());
×
895
  }
896

897
  // Show PipePlugins =====================================================================
898
  @Override
899
  public Statement visitShowPipePlugins(IoTDBSqlParser.ShowPipePluginsContext ctx) {
900
    return new ShowPipePluginsStatement();
×
901
  }
902

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

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

923
  // Create CQ =====================================================================
924
  @Override
925
  public Statement visitCreateContinuousQuery(IoTDBSqlParser.CreateContinuousQueryContext ctx) {
926
    CreateContinuousQueryStatement statement = new CreateContinuousQueryStatement();
×
927

928
    statement.setCqId(parseIdentifier(ctx.cqId.getText()));
×
929

930
    QueryStatement queryBodyStatement =
×
931
        (QueryStatement) visitSelectStatement(ctx.selectStatement());
×
932
    queryBodyStatement.setCqQueryBody(true);
×
933
    statement.setQueryBodyStatement(queryBodyStatement);
×
934

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

944
      long interval = queryStatement.getGroupByTimeComponent().getInterval();
×
945
      statement.setEveryInterval(interval);
×
946
      statement.setStartTimeOffset(interval);
×
947
    }
948

949
    if (ctx.timeoutPolicyClause() != null) {
×
950
      parseTimeoutPolicyClause(ctx.timeoutPolicyClause(), statement);
×
951
    }
952

953
    return statement;
×
954
  }
955

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

970
    if (ctx.BOUNDARY() != null) {
×
971
      statement.setBoundaryTime(parseTimeValue(ctx.boundaryTime, DateTimeUtils.currentTime()));
×
972
    }
973

974
    if (ctx.RANGE() != null) {
×
975
      statement.setStartTimeOffset(
×
976
          DateTimeUtils.convertDurationStrToLong(ctx.startTimeOffset.getText()));
×
977
      if (ctx.endTimeOffset != null) {
×
978
        statement.setEndTimeOffset(
×
979
            DateTimeUtils.convertDurationStrToLong(ctx.endTimeOffset.getText()));
×
980
      }
981
    } else {
982
      statement.setStartTimeOffset(statement.getEveryInterval());
×
983
    }
984
  }
×
985

986
  private void parseTimeoutPolicyClause(
987
      IoTDBSqlParser.TimeoutPolicyClauseContext ctx, CreateContinuousQueryStatement statement) {
988
    if (ctx.DISCARD() != null) {
×
989
      statement.setTimeoutPolicy(TimeoutPolicy.DISCARD);
×
990
    }
991
  }
×
992

993
  // Drop CQ =====================================================================
994
  @Override
995
  public Statement visitDropContinuousQuery(IoTDBSqlParser.DropContinuousQueryContext ctx) {
996
    return new DropContinuousQueryStatement(parseIdentifier(ctx.cqId.getText()));
×
997
  }
998

999
  // Show CQs =====================================================================
1000
  @Override
1001
  public Statement visitShowContinuousQueries(IoTDBSqlParser.ShowContinuousQueriesContext ctx) {
1002
    return new ShowContinuousQueriesStatement();
×
1003
  }
1004

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

1022
    return createLogicalViewStatement;
×
1023
  }
1024

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

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

1062
  @Override
1063
  public Statement visitRenameLogicalView(IoTDBSqlParser.RenameLogicalViewContext ctx) {
1064
    throw new SemanticException("Renaming view is not supported.");
×
1065
  }
1066

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

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

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

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

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

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

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

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

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

1233
    createModelStatement.setQueryStatement(
×
1234
        (QueryStatement) visitSelectStatement(ctx.selectStatement()));
×
1235
    return createModelStatement;
×
1236
  }
1237

1238
  // Drop Model =====================================================================
1239
  @Override
1240
  public Statement visitDropModel(IoTDBSqlParser.DropModelContext ctx) {
1241
    return new DropModelStatement(parseIdentifier(ctx.modelId.getText()));
×
1242
  }
1243

1244
  // Show Models =====================================================================
1245
  @Override
1246
  public Statement visitShowModels(IoTDBSqlParser.ShowModelsContext ctx) {
1247
    return new ShowModelsStatement();
×
1248
  }
1249

1250
  // Show Trails =====================================================================
1251
  @Override
1252
  public Statement visitShowTrails(IoTDBSqlParser.ShowTrailsContext ctx) {
1253
    return new ShowTrailsStatement(parseIdentifier(ctx.modelId.getText()));
×
1254
  }
1255

1256
  /** Data Manipulation Language (DML). */
1257

1258
  // Select Statement ========================================================================
1259
  @Override
1260
  public Statement visitSelectStatement(IoTDBSqlParser.SelectStatementContext ctx) {
1261
    QueryStatement queryStatement = new QueryStatement();
1✔
1262

1263
    // parse SELECT & FROM
1264
    queryStatement.setSelectComponent(parseSelectClause(ctx.selectClause(), queryStatement));
1✔
1265
    queryStatement.setFromComponent(parseFromClause(ctx.fromClause()));
1✔
1266

1267
    // parse INTO
1268
    if (ctx.intoClause() != null) {
1✔
1269
      queryStatement.setIntoComponent(parseIntoClause(ctx.intoClause()));
1✔
1270
    }
1271

1272
    // parse WHERE
1273
    if (ctx.whereClause() != null) {
1✔
1274
      queryStatement.setWhereCondition(parseWhereClause(ctx.whereClause()));
1✔
1275
    }
1276

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

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

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

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

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

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

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

1333
          groupByKeys.add("COMMON");
×
1334
          queryStatement.setGroupByComponent(
×
1335
              parseGroupByClause(groupByAttribute, WindowType.COUNT_WINDOW));
×
1336

1337
        } else {
1338
          throw new SemanticException("Unknown GROUP BY type.");
×
1339
        }
1340
      }
1✔
1341
    }
1342

1343
    // parse HAVING
1344
    if (ctx.havingClause() != null) {
1✔
1345
      queryStatement.setHavingCondition(parseHavingClause(ctx.havingClause()));
1✔
1346
    }
1347

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

1356
    // parse FILL
1357
    if (ctx.fillClause() != null) {
1✔
1358
      queryStatement.setFillComponent(parseFillClause(ctx.fillClause()));
1✔
1359
    }
1360

1361
    if (ctx.paginationClause() != null) {
1✔
1362
      // parse SLIMIT & SOFFSET
1363
      if (ctx.paginationClause().seriesPaginationClause() != null) {
1✔
1364
        if (ctx.paginationClause().seriesPaginationClause().slimitClause() != null) {
1✔
1365
          queryStatement.setSeriesLimit(
1✔
1366
              parseSLimitClause(ctx.paginationClause().seriesPaginationClause().slimitClause()));
1✔
1367
        }
1368
        if (ctx.paginationClause().seriesPaginationClause().soffsetClause() != null) {
1✔
1369
          queryStatement.setSeriesOffset(
1✔
1370
              parseSOffsetClause(ctx.paginationClause().seriesPaginationClause().soffsetClause()));
1✔
1371
        }
1372
      }
1373

1374
      // parse LIMIT & OFFSET
1375
      if (ctx.paginationClause().rowPaginationClause() != null) {
1✔
1376
        if (ctx.paginationClause().rowPaginationClause().limitClause() != null) {
1✔
1377
          queryStatement.setRowLimit(
1✔
1378
              parseLimitClause(ctx.paginationClause().rowPaginationClause().limitClause()));
1✔
1379
        }
1380
        if (ctx.paginationClause().rowPaginationClause().offsetClause() != null) {
1✔
1381
          queryStatement.setRowOffset(
1✔
1382
              parseOffsetClause(ctx.paginationClause().rowPaginationClause().offsetClause()));
1✔
1383
        }
1384
      }
1385
    }
1386

1387
    // parse ALIGN BY
1388
    if (ctx.alignByClause() != null) {
1✔
1389
      queryStatement.setResultSetFormat(parseAlignBy(ctx.alignByClause()));
1✔
1390
    }
1391

1392
    queryStatement.setUseWildcard(useWildcard);
1✔
1393
    return queryStatement;
1✔
1394
  }
1395

1396
  // ---- Select Clause
1397
  private SelectComponent parseSelectClause(
1398
      IoTDBSqlParser.SelectClauseContext ctx, QueryStatement queryStatement) {
1399
    SelectComponent selectComponent = new SelectComponent(zoneId);
1✔
1400

1401
    // parse LAST
1402
    if (ctx.LAST() != null) {
1✔
1403
      selectComponent.setHasLast(true);
1✔
1404
    }
1405

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

1426
    return selectComponent;
1✔
1427
  }
1428

1429
  private ResultColumn parseResultColumn(IoTDBSqlParser.ResultColumnContext resultColumnContext) {
1430
    Expression expression = parseExpression(resultColumnContext.expression(), false);
1✔
1431
    if (expression.isConstantOperand()) {
1✔
1432
      throw new SemanticException("Constant operand is not allowed: " + expression);
×
1433
    }
1434
    String alias = null;
1✔
1435
    if (resultColumnContext.AS() != null) {
1✔
1436
      alias = parseAlias(resultColumnContext.alias());
1✔
1437
    }
1438
    ResultColumn.ColumnType columnType =
1✔
1439
        ExpressionAnalyzer.identifyOutputColumnType(expression, true);
1✔
1440
    return new ResultColumn(expression, alias, columnType);
1✔
1441
  }
1442

1443
  // ---- From Clause
1444
  private FromComponent parseFromClause(IoTDBSqlParser.FromClauseContext ctx) {
1445
    FromComponent fromComponent = new FromComponent();
1✔
1446
    List<IoTDBSqlParser.PrefixPathContext> prefixFromPaths = ctx.prefixPath();
1✔
1447
    for (IoTDBSqlParser.PrefixPathContext prefixFromPath : prefixFromPaths) {
1✔
1448
      PartialPath path = parsePrefixPath(prefixFromPath);
1✔
1449
      fromComponent.addPrefixPath(path);
1✔
1450
    }
1✔
1451
    return fromComponent;
1✔
1452
  }
1453

1454
  // ---- Into Clause
1455
  private IntoComponent parseIntoClause(IoTDBSqlParser.IntoClauseContext ctx) {
1456
    List<IntoItem> intoItems = new ArrayList<>();
1✔
1457
    for (IoTDBSqlParser.IntoItemContext intoItemContext : ctx.intoItem()) {
1✔
1458
      intoItems.add(parseIntoItem(intoItemContext));
1✔
1459
    }
1✔
1460
    return new IntoComponent(intoItems);
1✔
1461
  }
1462

1463
  private IntoItem parseIntoItem(IoTDBSqlParser.IntoItemContext intoItemContext) {
1464
    boolean isAligned = intoItemContext.ALIGNED() != null;
1✔
1465
    PartialPath intoDevice = parseIntoPath(intoItemContext.intoPath());
1✔
1466
    List<String> intoMeasurements =
1✔
1467
        intoItemContext.nodeNameInIntoPath().stream()
1✔
1468
            .map(this::parseNodeNameInIntoPath)
1✔
1469
            .collect(Collectors.toList());
1✔
1470
    return new IntoItem(intoDevice, intoMeasurements, isAligned);
1✔
1471
  }
1472

1473
  private PartialPath parseIntoPath(IoTDBSqlParser.IntoPathContext intoPathContext) {
1474
    if (intoPathContext instanceof IoTDBSqlParser.FullPathInIntoPathContext) {
1✔
1475
      return parseFullPathInIntoPath((IoTDBSqlParser.FullPathInIntoPathContext) intoPathContext);
1✔
1476
    } else {
1477
      List<IoTDBSqlParser.NodeNameInIntoPathContext> nodeNames =
1✔
1478
          ((IoTDBSqlParser.SuffixPathInIntoPathContext) intoPathContext).nodeNameInIntoPath();
1✔
1479
      String[] path = new String[nodeNames.size()];
1✔
1480
      for (int i = 0; i < nodeNames.size(); i++) {
1✔
1481
        path[i] = parseNodeNameInIntoPath(nodeNames.get(i));
1✔
1482
      }
1483
      return new PartialPath(path);
1✔
1484
    }
1485
  }
1486

1487
  // ---- Where Clause
1488
  private WhereCondition parseWhereClause(IoTDBSqlParser.WhereClauseContext ctx) {
1489
    Expression predicate = parseExpression(ctx.expression(), true);
1✔
1490
    return new WhereCondition(predicate);
1✔
1491
  }
1492

1493
  // ---- Group By Clause
1494
  private GroupByTimeComponent parseGroupByTimeClause(
1495
      IoTDBSqlParser.GroupByAttributeClauseContext ctx) {
1496
    GroupByTimeComponent groupByTimeComponent = new GroupByTimeComponent();
1✔
1497

1498
    // Parse time range
1499
    if (ctx.timeRange() != null) {
1✔
1500
      parseTimeRangeForGroupByTime(ctx.timeRange(), groupByTimeComponent);
1✔
1501
      groupByTimeComponent.setLeftCRightO(ctx.timeRange().LS_BRACKET() != null);
1✔
1502
    }
1503

1504
    // Parse time interval
1505
    groupByTimeComponent.setInterval(
1✔
1506
        parseTimeIntervalOrSlidingStep(ctx.interval.getText(), true, groupByTimeComponent));
1✔
1507
    if (groupByTimeComponent.getInterval() <= 0) {
1✔
1508
      throw new SemanticException(
×
1509
          "The second parameter time interval should be a positive integer.");
1510
    }
1511

1512
    // parse sliding step
1513
    if (ctx.step != null) {
1✔
1514
      groupByTimeComponent.setSlidingStep(
1✔
1515
          parseTimeIntervalOrSlidingStep(ctx.step.getText(), false, groupByTimeComponent));
1✔
1516
    } else {
1517
      groupByTimeComponent.setSlidingStep(groupByTimeComponent.getInterval());
1✔
1518
      groupByTimeComponent.setSlidingStepByMonth(groupByTimeComponent.isIntervalByMonth());
1✔
1519
    }
1520

1521
    return groupByTimeComponent;
1✔
1522
  }
1523

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

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

1559
  private GroupByComponent parseGroupByClause(
1560
      GroupByAttributeClauseContext ctx, WindowType windowType) {
1561

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

1604
  private GroupByLevelComponent parseGroupByLevelClause(
1605
      IoTDBSqlParser.GroupByAttributeClauseContext ctx) {
1606
    GroupByLevelComponent groupByLevelComponent = new GroupByLevelComponent();
1✔
1607
    int[] levels = new int[ctx.INTEGER_LITERAL().size()];
1✔
1608
    for (int i = 0; i < ctx.INTEGER_LITERAL().size(); i++) {
1✔
1609
      levels[i] = Integer.parseInt(ctx.INTEGER_LITERAL().get(i).getText());
1✔
1610
    }
1611
    groupByLevelComponent.setLevels(levels);
1✔
1612
    return groupByLevelComponent;
1✔
1613
  }
1614

1615
  private GroupByTagComponent parseGroupByTagClause(
1616
      IoTDBSqlParser.GroupByAttributeClauseContext ctx) {
1617
    Set<String> tagKeys = new LinkedHashSet<>();
1✔
1618
    for (IdentifierContext identifierContext : ctx.identifier()) {
1✔
1619
      String key = parseIdentifier(identifierContext.getText());
1✔
1620
      if (tagKeys.contains(key)) {
1✔
1621
        throw new SemanticException("duplicated key in GROUP BY TAGS: " + key);
1✔
1622
      }
1623
      tagKeys.add(key);
1✔
1624
    }
1✔
1625
    return new GroupByTagComponent(new ArrayList<>(tagKeys));
1✔
1626
  }
1627

1628
  // ---- Having Clause
1629
  private HavingCondition parseHavingClause(IoTDBSqlParser.HavingClauseContext ctx) {
1630
    Expression predicate = parseExpression(ctx.expression(), true);
1✔
1631
    return new HavingCondition(predicate);
1✔
1632
  }
1633

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

1648
      String sortKey = sortItem.getSortKey();
1✔
1649
      if (sortKeySet.contains(sortKey)) {
1✔
1650
        continue;
×
1651
      } else {
1652
        sortKeySet.add(sortKey);
1✔
1653
      }
1654

1655
      if (sortItem.isExpression()) {
1✔
1656
        orderByComponent.addExpressionSortItem(sortItem);
1✔
1657
      } else {
1658
        orderByComponent.addSortItem(sortItem);
1✔
1659
      }
1660
    }
1✔
1661
    return orderByComponent;
1✔
1662
  }
1663

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

1682
  // ---- Fill Clause
1683
  public FillComponent parseFillClause(IoTDBSqlParser.FillClauseContext ctx) {
1684
    FillComponent fillComponent = new FillComponent();
1✔
1685
    if (ctx.LINEAR() != null) {
1✔
1686
      fillComponent.setFillPolicy(FillPolicy.LINEAR);
1✔
1687
    } else if (ctx.PREVIOUS() != null) {
1✔
1688
      fillComponent.setFillPolicy(FillPolicy.PREVIOUS);
1✔
1689
    } else if (ctx.constant() != null) {
1✔
1690
      fillComponent.setFillPolicy(FillPolicy.VALUE);
1✔
1691
      Literal fillValue = parseLiteral(ctx.constant());
1✔
1692
      fillComponent.setFillValue(fillValue);
1✔
1693
    } else {
1✔
1694
      throw new SemanticException("Unknown FILL type.");
×
1695
    }
1696
    return fillComponent;
1✔
1697
  }
1698

1699
  private Literal parseLiteral(ConstantContext constantContext) {
1700
    String text = constantContext.getText();
1✔
1701
    if (constantContext.boolean_literal() != null) {
1✔
1702
      return new BooleanLiteral(text);
×
1703
    } else if (constantContext.STRING_LITERAL() != null) {
1✔
1704
      return new StringLiteral(parseStringLiteral(text));
×
1705
    } else if (constantContext.INTEGER_LITERAL() != null) {
1✔
1706
      return new LongLiteral(text);
1✔
1707
    } else if (constantContext.realLiteral() != null) {
×
1708
      return new DoubleLiteral(text);
×
1709
    } else if (constantContext.dateExpression() != null) {
×
1710
      return new LongLiteral(parseDateExpression(constantContext.dateExpression()));
×
1711
    } else {
1712
      throw new SemanticException("Unsupported constant value in FILL: " + text);
×
1713
    }
1714
  }
1715

1716
  // parse LIMIT & OFFSET
1717
  private long parseLimitClause(IoTDBSqlParser.LimitClauseContext ctx) {
1718
    long limit;
1719
    try {
1720
      limit = Long.parseLong(ctx.INTEGER_LITERAL().getText());
1✔
1721
    } catch (NumberFormatException e) {
×
1722
      throw new SemanticException("Out of range. LIMIT <N>: N should be Int64.");
×
1723
    }
1✔
1724
    if (limit <= 0) {
1✔
1725
      throw new SemanticException("LIMIT <N>: N should be greater than 0.");
×
1726
    }
1727
    return limit;
1✔
1728
  }
1729

1730
  private long parseOffsetClause(IoTDBSqlParser.OffsetClauseContext ctx) {
1731
    long offset;
1732
    try {
1733
      offset = Long.parseLong(ctx.INTEGER_LITERAL().getText());
1✔
1734
    } catch (NumberFormatException e) {
×
1735
      throw new SemanticException(
×
1736
          "Out of range. OFFSET <OFFSETValue>: OFFSETValue should be Int64.");
1737
    }
1✔
1738
    if (offset < 0) {
1✔
1739
      throw new SemanticException("OFFSET <OFFSETValue>: OFFSETValue should >= 0.");
×
1740
    }
1741
    return offset;
1✔
1742
  }
1743

1744
  // parse SLIMIT & SOFFSET
1745
  private int parseSLimitClause(IoTDBSqlParser.SlimitClauseContext ctx) {
1746
    int slimit;
1747
    try {
1748
      slimit = Integer.parseInt(ctx.INTEGER_LITERAL().getText());
1✔
1749
    } catch (NumberFormatException e) {
×
1750
      throw new SemanticException("Out of range. SLIMIT <SN>: SN should be Int32.");
×
1751
    }
1✔
1752
    if (slimit <= 0) {
1✔
1753
      throw new SemanticException("SLIMIT <SN>: SN should be greater than 0.");
×
1754
    }
1755
    return slimit;
1✔
1756
  }
1757

1758
  // parse SOFFSET
1759
  public int parseSOffsetClause(IoTDBSqlParser.SoffsetClauseContext ctx) {
1760
    int soffset;
1761
    try {
1762
      soffset = Integer.parseInt(ctx.INTEGER_LITERAL().getText());
1✔
1763
    } catch (NumberFormatException e) {
×
1764
      throw new SemanticException(
×
1765
          "Out of range. SOFFSET <SOFFSETValue>: SOFFSETValue should be Int32.");
1766
    }
1✔
1767
    if (soffset < 0) {
1✔
1768
      throw new SemanticException("SOFFSET <SOFFSETValue>: SOFFSETValue should >= 0.");
×
1769
    }
1770
    return soffset;
1✔
1771
  }
1772

1773
  // ---- Align By Clause
1774
  private ResultSetFormat parseAlignBy(IoTDBSqlParser.AlignByClauseContext ctx) {
1775
    if (ctx.DEVICE() != null) {
1✔
1776
      return ResultSetFormat.ALIGN_BY_DEVICE;
1✔
1777
    } else {
1778
      return ResultSetFormat.ALIGN_BY_TIME;
×
1779
    }
1780
  }
1781

1782
  // Insert Statement ========================================================================
1783

1784
  @Override
1785
  public Statement visitInsertStatement(IoTDBSqlParser.InsertStatementContext ctx) {
1786
    InsertStatement insertStatement = new InsertStatement();
1✔
1787
    insertStatement.setDevice(parsePrefixPath(ctx.prefixPath()));
1✔
1788
    boolean isTimeDefault = parseInsertColumnSpec(ctx.insertColumnsSpec(), insertStatement);
1✔
1789
    parseInsertValuesSpec(ctx.insertValuesSpec(), insertStatement, isTimeDefault);
1✔
1790
    insertStatement.setAligned(ctx.ALIGNED() != null);
1✔
1791
    return insertStatement;
1✔
1792
  }
1793

1794
  private boolean parseInsertColumnSpec(
1795
      IoTDBSqlParser.InsertColumnsSpecContext ctx, InsertStatement insertStatement) {
1796
    List<String> measurementList = new ArrayList<>();
1✔
1797
    for (IoTDBSqlParser.NodeNameWithoutWildcardContext measurementName :
1798
        ctx.nodeNameWithoutWildcard()) {
1✔
1799
      measurementList.add(parseNodeNameWithoutWildCard(measurementName));
1✔
1800
    }
1✔
1801
    insertStatement.setMeasurementList(measurementList.toArray(new String[0]));
1✔
1802
    return (ctx.TIME() == null && ctx.TIMESTAMP() == null);
1✔
1803
  }
1804

1805
  private void parseInsertValuesSpec(
1806
      IoTDBSqlParser.InsertValuesSpecContext ctx,
1807
      InsertStatement insertStatement,
1808
      boolean isTimeDefault) {
1809
    List<IoTDBSqlParser.InsertMultiValueContext> insertMultiValues = ctx.insertMultiValue();
1✔
1810
    List<String[]> valuesList = new ArrayList<>();
1✔
1811
    long[] timeArray = new long[insertMultiValues.size()];
1✔
1812
    for (int i = 0; i < insertMultiValues.size(); i++) {
1✔
1813
      // parse timestamp
1814
      long timestamp;
1815
      List<String> valueList = new ArrayList<>();
1✔
1816

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

1840
      // parse values
1841
      List<IoTDBSqlParser.MeasurementValueContext> values =
1✔
1842
          insertMultiValues.get(i).measurementValue();
1✔
1843
      for (IoTDBSqlParser.MeasurementValueContext value : values) {
1✔
1844
        for (IoTDBSqlParser.ConstantContext constant : value.constant()) {
1✔
1845
          if (constant.STRING_LITERAL() != null) {
1✔
1846
            valueList.add(parseStringLiteralInInsertValue(constant.getText()));
×
1847
          } else {
1848
            valueList.add(constant.getText());
1✔
1849
          }
1850
        }
1✔
1851
      }
1✔
1852
      valuesList.add(valueList.toArray(new String[0]));
1✔
1853
    }
1854
    insertStatement.setTimes(timeArray);
1✔
1855
    insertStatement.setValuesList(valuesList);
1✔
1856
  }
1✔
1857

1858
  // Load File
1859

1860
  @Override
1861
  public Statement visitLoadFile(IoTDBSqlParser.LoadFileContext ctx) {
1862
    try {
1863
      LoadTsFileStatement loadTsFileStatement =
×
1864
          new LoadTsFileStatement(parseStringLiteral(ctx.fileName.getText()));
×
1865
      if (ctx.loadFileAttributeClauses() != null) {
×
1866
        for (IoTDBSqlParser.LoadFileAttributeClauseContext attributeContext :
1867
            ctx.loadFileAttributeClauses().loadFileAttributeClause()) {
×
1868
          parseLoadFileAttributeClause(loadTsFileStatement, attributeContext);
×
1869
        }
×
1870
      }
1871
      return loadTsFileStatement;
×
1872
    } catch (FileNotFoundException e) {
×
1873
      throw new SemanticException(e.getMessage());
×
1874
    }
1875
  }
1876

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

1901
  /** Common Parsers. */
1902

1903
  // IoTDB Objects ========================================================================
1904
  private PartialPath parseFullPath(IoTDBSqlParser.FullPathContext ctx) {
1905
    List<IoTDBSqlParser.NodeNameWithoutWildcardContext> nodeNamesWithoutStar =
1✔
1906
        ctx.nodeNameWithoutWildcard();
1✔
1907
    String[] path = new String[nodeNamesWithoutStar.size() + 1];
1✔
1908
    int i = 0;
1✔
1909
    if (ctx.ROOT() != null) {
1✔
1910
      path[0] = ctx.ROOT().getText();
1✔
1911
    }
1912
    for (IoTDBSqlParser.NodeNameWithoutWildcardContext nodeNameWithoutStar : nodeNamesWithoutStar) {
1✔
1913
      i++;
1✔
1914
      path[i] = parseNodeNameWithoutWildCard(nodeNameWithoutStar);
1✔
1915
    }
1✔
1916
    return new PartialPath(path);
1✔
1917
  }
1918

1919
  private PartialPath parseFullPathInExpression(
1920
      IoTDBSqlParser.FullPathInExpressionContext ctx, boolean canUseFullPath) {
1921
    List<IoTDBSqlParser.NodeNameContext> nodeNames = ctx.nodeName();
1✔
1922
    int size = nodeNames.size();
1✔
1923
    if (ctx.ROOT() != null) {
1✔
1924
      if (!canUseFullPath) {
1✔
1925
        // now full path cannot occur in SELECT only
1926
        throw new SemanticException("Path can not start with root in select clause.");
×
1927
      }
1928
      size++;
1✔
1929
    }
1930
    String[] path = new String[size];
1✔
1931
    if (ctx.ROOT() != null) {
1✔
1932
      path[0] = ctx.ROOT().getText();
1✔
1933
      for (int i = 0; i < nodeNames.size(); i++) {
1✔
1934
        path[i + 1] = parseNodeName(nodeNames.get(i));
1✔
1935
      }
1936
    } else {
1937
      for (int i = 0; i < nodeNames.size(); i++) {
1✔
1938
        path[i] = parseNodeName(nodeNames.get(i));
1✔
1939
      }
1940
    }
1941
    return new PartialPath(path);
1✔
1942
  }
1943

1944
  private PartialPath parseFullPathInIntoPath(IoTDBSqlParser.FullPathInIntoPathContext ctx) {
1945
    List<IoTDBSqlParser.NodeNameInIntoPathContext> nodeNames = ctx.nodeNameInIntoPath();
1✔
1946
    String[] path = new String[nodeNames.size() + 1];
1✔
1947
    int i = 0;
1✔
1948
    if (ctx.ROOT() != null) {
1✔
1949
      path[0] = ctx.ROOT().getText();
1✔
1950
    }
1951
    for (IoTDBSqlParser.NodeNameInIntoPathContext nodeName : nodeNames) {
1✔
1952
      i++;
1✔
1953
      path[i] = parseNodeNameInIntoPath(nodeName);
1✔
1954
    }
1✔
1955
    return new PartialPath(path);
1✔
1956
  }
1957

1958
  private PartialPath parsePrefixPath(IoTDBSqlParser.PrefixPathContext ctx) {
1959
    List<IoTDBSqlParser.NodeNameContext> nodeNames = ctx.nodeName();
1✔
1960
    String[] path = new String[nodeNames.size() + 1];
1✔
1961
    path[0] = ctx.ROOT().getText();
1✔
1962
    for (int i = 0; i < nodeNames.size(); i++) {
1✔
1963
      path[i + 1] = parseNodeName(nodeNames.get(i));
1✔
1964
    }
1965
    return new PartialPath(path);
1✔
1966
  }
1967

1968
  private String parseNodeName(IoTDBSqlParser.NodeNameContext ctx) {
1969
    if (!useWildcard && !ctx.wildcard().isEmpty()) {
1✔
1970
      useWildcard = true;
1✔
1971
    }
1972
    return parseNodeString(ctx.getText());
1✔
1973
  }
1974

1975
  private String parseNodeNameWithoutWildCard(IoTDBSqlParser.NodeNameWithoutWildcardContext ctx) {
1976
    return parseNodeString(ctx.getText());
1✔
1977
  }
1978

1979
  private String parseNodeNameInIntoPath(IoTDBSqlParser.NodeNameInIntoPathContext ctx) {
1980
    return parseNodeStringInIntoPath(ctx.getText());
1✔
1981
  }
1982

1983
  private String parseNodeString(String nodeName) {
1984
    if (nodeName.equals(IoTDBConstant.ONE_LEVEL_PATH_WILDCARD)
1✔
1985
        || nodeName.equals(IoTDBConstant.MULTI_LEVEL_PATH_WILDCARD)) {
1✔
1986
      return nodeName;
1✔
1987
    }
1988
    if (nodeName.startsWith(TsFileConstant.BACK_QUOTE_STRING)
1✔
1989
        && nodeName.endsWith(TsFileConstant.BACK_QUOTE_STRING)) {
×
1990
      return PathUtils.removeBackQuotesIfNecessary(nodeName);
×
1991
    }
1992
    checkNodeName(nodeName);
1✔
1993
    return nodeName;
1✔
1994
  }
1995

1996
  private String parseNodeStringInIntoPath(String nodeName) {
1997
    if (nodeName.equals(IoTDBConstant.DOUBLE_COLONS)) {
1✔
1998
      return nodeName;
1✔
1999
    }
2000
    if (nodeName.startsWith(TsFileConstant.BACK_QUOTE_STRING)
1✔
2001
        && nodeName.endsWith(TsFileConstant.BACK_QUOTE_STRING)) {
×
2002
      return PathUtils.removeBackQuotesIfNecessary(nodeName);
×
2003
    }
2004
    checkNodeNameInIntoPath(nodeName);
1✔
2005
    return nodeName;
1✔
2006
  }
2007

2008
  private void checkNodeName(String src) {
2009
    // node name could start with * and end with *
2010
    if (!TsFileConstant.NODE_NAME_PATTERN.matcher(src).matches()) {
1✔
2011
      throw new SemanticException(
×
2012
          String.format(
×
2013
              "%s is illegal, unquoted node name can only consist of digits, characters and underscore, or start or end with wildcard",
2014
              src));
2015
    }
2016
  }
1✔
2017

2018
  private void checkNodeNameInIntoPath(String src) {
2019
    // ${} are allowed
2020
    if (!TsFileConstant.NODE_NAME_IN_INTO_PATH_PATTERN.matcher(src).matches()) {
1✔
2021
      throw new SemanticException(
×
2022
          String.format(
×
2023
              "%s is illegal, unquoted node name in select into clause can only consist of digits, characters, $, { and }",
2024
              src));
2025
    }
2026
  }
1✔
2027

2028
  private static void checkIdentifier(String src) {
2029
    if (!TsFileConstant.IDENTIFIER_PATTERN.matcher(src).matches() || PathUtils.isRealNumber(src)) {
1✔
2030
      throw new SemanticException(
×
2031
          String.format(
×
2032
              "%s is illegal, identifier not enclosed with backticks can only consist of digits, characters and underscore.",
2033
              src));
2034
    }
2035
  }
1✔
2036

2037
  // Literals ========================================================================
2038

2039
  public long parseDateFormat(String timestampStr) {
2040
    if (timestampStr == null || "".equals(timestampStr.trim())) {
1✔
2041
      throw new SemanticException("input timestamp cannot be empty");
1✔
2042
    }
2043
    if (timestampStr.equalsIgnoreCase(SqlConstant.NOW_FUNC)) {
1✔
2044
      return DateTimeUtils.currentTime();
1✔
2045
    }
2046
    try {
2047
      return DateTimeUtils.convertDatetimeStrToLong(timestampStr, zoneId);
×
2048
    } catch (Exception e) {
×
2049
      throw new SemanticException(
×
2050
          String.format(
×
2051
              "Input time format %s error. "
2052
                  + "Input like yyyy-MM-dd HH:mm:ss, yyyy-MM-ddTHH:mm:ss or "
2053
                  + "refer to user document for more info.",
2054
              timestampStr));
2055
    }
2056
  }
2057

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

2077
  private String parseStringLiteral(String src) {
2078
    if (2 <= src.length()) {
1✔
2079
      // do not unescape string
2080
      String unWrappedString = src.substring(1, src.length() - 1);
1✔
2081
      if (src.charAt(0) == '\"' && src.charAt(src.length() - 1) == '\"') {
1✔
2082
        // replace "" with "
2083
        String replaced = unWrappedString.replace("\"\"", "\"");
×
2084
        return replaced.length() == 0 ? "" : replaced;
×
2085
      }
2086
      if ((src.charAt(0) == '\'' && src.charAt(src.length() - 1) == '\'')) {
1✔
2087
        // replace '' with '
2088
        String replaced = unWrappedString.replace("''", "'");
1✔
2089
        return replaced.length() == 0 ? "" : replaced;
1✔
2090
      }
2091
    }
2092
    return src;
×
2093
  }
2094

2095
  private String parseStringLiteralInInsertValue(String src) {
2096
    if (2 <= src.length()
×
2097
        && ((src.charAt(0) == '\"' && src.charAt(src.length() - 1) == '\"')
×
2098
            || (src.charAt(0) == '\'' && src.charAt(src.length() - 1) == '\''))) {
×
2099
      return "'" + parseStringLiteral(src) + "'";
×
2100
    }
2101
    return src;
×
2102
  }
2103

2104
  public static String parseIdentifier(String src) {
2105
    if (src.startsWith(TsFileConstant.BACK_QUOTE_STRING)
1✔
2106
        && src.endsWith(TsFileConstant.BACK_QUOTE_STRING)) {
×
2107
      return src.substring(1, src.length() - 1)
×
2108
          .replace(TsFileConstant.DOUBLE_BACK_QUOTE_STRING, TsFileConstant.BACK_QUOTE_STRING);
×
2109
    }
2110
    checkIdentifier(src);
1✔
2111
    return src;
1✔
2112
  }
2113

2114
  // Alias
2115

2116
  /** Function for parsing Alias of ResultColumn. */
2117
  private String parseAlias(IoTDBSqlParser.AliasContext ctx) {
2118
    String alias;
2119
    if (ctx.constant() != null) {
1✔
2120
      alias = parseConstant(ctx.constant());
×
2121
    } else {
2122
      alias = parseIdentifier(ctx.identifier().getText());
1✔
2123
    }
2124
    return alias;
1✔
2125
  }
2126

2127
  /**
2128
   * Function for parsing AliasNode.
2129
   *
2130
   * @throws SemanticException if the alias pattern is not supported
2131
   */
2132
  private String parseAliasNode(IoTDBSqlParser.AliasContext ctx) {
2133
    String alias;
2134
    if (ctx.constant() != null) {
×
2135
      alias = parseConstant(ctx.constant());
×
2136
      if (PathUtils.isRealNumber(alias)
×
2137
          || !TsFileConstant.IDENTIFIER_PATTERN.matcher(alias).matches()) {
×
2138
        throw new SemanticException("Not support for this alias, Please enclose in back quotes.");
×
2139
      }
2140
    } else {
2141
      alias = parseNodeString(ctx.identifier().getText());
×
2142
    }
2143
    return alias;
×
2144
  }
2145

2146
  /** Data Control Language (DCL). */
2147

2148
  // Create User
2149
  @Override
2150
  public Statement visitCreateUser(IoTDBSqlParser.CreateUserContext ctx) {
2151
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.CREATE_USER);
×
2152
    authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
×
2153
    authorStatement.setPassWord(parseStringLiteral(ctx.password.getText()));
×
2154
    return authorStatement;
×
2155
  }
2156

2157
  // Create Role
2158

2159
  @Override
2160
  public Statement visitCreateRole(IoTDBSqlParser.CreateRoleContext ctx) {
2161
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.CREATE_ROLE);
×
2162
    authorStatement.setRoleName(parseIdentifier(ctx.roleName.getText()));
×
2163
    return authorStatement;
×
2164
  }
2165

2166
  // Alter Password
2167

2168
  @Override
2169
  public Statement visitAlterUser(IoTDBSqlParser.AlterUserContext ctx) {
2170
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.UPDATE_USER);
×
2171
    authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
×
2172
    authorStatement.setNewPassword(parseStringLiteral(ctx.password.getText()));
×
2173
    return authorStatement;
×
2174
  }
2175

2176
  // Grant User Privileges
2177

2178
  @Override
2179
  public Statement visitGrantUser(IoTDBSqlParser.GrantUserContext ctx) {
2180
    String[] privileges = parsePrivilege(ctx.privileges());
×
2181
    List<PartialPath> nodeNameList =
×
2182
        ctx.prefixPath().stream()
×
2183
            .map(this::parsePrefixPath)
×
2184
            .distinct()
×
2185
            .collect(Collectors.toList());
×
2186
    checkGrantRevokePrivileges(privileges, nodeNameList);
×
2187

2188
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.GRANT_USER);
×
2189
    authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
×
2190
    authorStatement.setPrivilegeList(privileges);
×
2191
    authorStatement.setNodeNameList(nodeNameList);
×
2192
    return authorStatement;
×
2193
  }
2194

2195
  // Grant Role Privileges
2196

2197
  @Override
2198
  public Statement visitGrantRole(IoTDBSqlParser.GrantRoleContext ctx) {
2199
    String[] privileges = parsePrivilege(ctx.privileges());
×
2200
    List<PartialPath> nodeNameList =
×
2201
        ctx.prefixPath().stream()
×
2202
            .map(this::parsePrefixPath)
×
2203
            .distinct()
×
2204
            .collect(Collectors.toList());
×
2205
    checkGrantRevokePrivileges(privileges, nodeNameList);
×
2206

2207
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.GRANT_ROLE);
×
2208
    authorStatement.setRoleName(parseIdentifier(ctx.roleName.getText()));
×
2209
    authorStatement.setPrivilegeList(privileges);
×
2210
    authorStatement.setNodeNameList(nodeNameList);
×
2211
    return authorStatement;
×
2212
  }
2213

2214
  // Grant User Role
2215

2216
  @Override
2217
  public Statement visitGrantRoleToUser(IoTDBSqlParser.GrantRoleToUserContext ctx) {
2218
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.GRANT_USER_ROLE);
×
2219
    authorStatement.setRoleName(parseIdentifier(ctx.roleName.getText()));
×
2220
    authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
×
2221
    return authorStatement;
×
2222
  }
2223

2224
  // Revoke User Privileges
2225

2226
  @Override
2227
  public Statement visitRevokeUser(IoTDBSqlParser.RevokeUserContext ctx) {
2228
    String[] privileges = parsePrivilege(ctx.privileges());
×
2229
    List<PartialPath> nodeNameList =
×
2230
        ctx.prefixPath().stream()
×
2231
            .map(this::parsePrefixPath)
×
2232
            .distinct()
×
2233
            .collect(Collectors.toList());
×
2234
    checkGrantRevokePrivileges(privileges, nodeNameList);
×
2235

2236
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.REVOKE_USER);
×
2237
    authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
×
2238
    authorStatement.setPrivilegeList(privileges);
×
2239
    authorStatement.setNodeNameList(nodeNameList);
×
2240
    return authorStatement;
×
2241
  }
2242

2243
  // Revoke Role Privileges
2244

2245
  @Override
2246
  public Statement visitRevokeRole(IoTDBSqlParser.RevokeRoleContext ctx) {
2247
    String[] privileges = parsePrivilege(ctx.privileges());
×
2248
    List<PartialPath> nodeNameList =
×
2249
        ctx.prefixPath().stream()
×
2250
            .map(this::parsePrefixPath)
×
2251
            .distinct()
×
2252
            .collect(Collectors.toList());
×
2253
    checkGrantRevokePrivileges(privileges, nodeNameList);
×
2254

2255
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.REVOKE_ROLE);
×
2256
    authorStatement.setRoleName(parseIdentifier(ctx.roleName.getText()));
×
2257
    authorStatement.setPrivilegeList(privileges);
×
2258
    authorStatement.setNodeNameList(nodeNameList);
×
2259
    return authorStatement;
×
2260
  }
2261

2262
  private void checkGrantRevokePrivileges(String[] privileges, List<PartialPath> nodeNameList) {
2263
    if (nodeNameList.isEmpty()) {
×
2264
      nodeNameList.add(new PartialPath(ALL_RESULT_NODES));
×
2265
      return;
×
2266
    }
2267
    boolean pathRelevant = true;
×
2268
    String errorPrivilegeName = "";
×
2269
    for (String privilege : privileges) {
×
2270
      if ("SET_STORAGE_GROUP".equalsIgnoreCase(privilege)) {
×
2271
        privilege = PrivilegeType.CREATE_DATABASE.name();
×
2272
      }
2273
      if ("DELETE_STORAGE_GROUP".equalsIgnoreCase(privilege)) {
×
2274
        privilege = PrivilegeType.DELETE_DATABASE.name();
×
2275
      }
2276
      if (!PrivilegeType.valueOf(privilege.toUpperCase()).isPathRelevant()) {
×
2277
        pathRelevant = false;
×
2278
        errorPrivilegeName = privilege.toUpperCase();
×
2279
        break;
×
2280
      }
2281
    }
2282
    if (!(pathRelevant
×
2283
        || (nodeNameList.size() == 1
×
2284
            && nodeNameList.contains(new PartialPath(ALL_RESULT_NODES))))) {
×
2285
      throw new SemanticException(
×
2286
          String.format(
×
2287
              "path independent privilege: [%s] can only be set on path: root.**",
2288
              errorPrivilegeName));
2289
    }
2290
  }
×
2291

2292
  // Revoke Role From User
2293

2294
  @Override
2295
  public Statement visitRevokeRoleFromUser(IoTDBSqlParser.RevokeRoleFromUserContext ctx) {
2296
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.REVOKE_USER_ROLE);
×
2297
    authorStatement.setRoleName(parseIdentifier(ctx.roleName.getText()));
×
2298
    authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
×
2299
    return authorStatement;
×
2300
  }
2301

2302
  // Drop User
2303

2304
  @Override
2305
  public Statement visitDropUser(IoTDBSqlParser.DropUserContext ctx) {
2306
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.DROP_USER);
×
2307
    authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
×
2308
    return authorStatement;
×
2309
  }
2310

2311
  // Drop Role
2312

2313
  @Override
2314
  public Statement visitDropRole(IoTDBSqlParser.DropRoleContext ctx) {
2315
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.DROP_ROLE);
×
2316
    authorStatement.setRoleName(parseIdentifier(ctx.roleName.getText()));
×
2317
    return authorStatement;
×
2318
  }
2319

2320
  // List Users
2321

2322
  @Override
2323
  public Statement visitListUser(IoTDBSqlParser.ListUserContext ctx) {
2324
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.LIST_USER);
×
2325
    if (ctx.roleName != null) {
×
2326
      authorStatement.setRoleName(parseIdentifier(ctx.roleName.getText()));
×
2327
    }
2328
    return authorStatement;
×
2329
  }
2330

2331
  // List Roles
2332

2333
  @Override
2334
  public Statement visitListRole(IoTDBSqlParser.ListRoleContext ctx) {
2335
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.LIST_ROLE);
×
2336
    if (ctx.userName != null) {
×
2337
      authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
×
2338
    }
2339
    return authorStatement;
×
2340
  }
2341

2342
  // List Privileges
2343

2344
  @Override
2345
  public Statement visitListPrivilegesUser(IoTDBSqlParser.ListPrivilegesUserContext ctx) {
2346
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.LIST_USER_PRIVILEGE);
×
2347
    authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
×
2348
    List<PartialPath> nodeNameList =
×
2349
        ctx.prefixPath().stream().map(this::parsePrefixPath).collect(Collectors.toList());
×
2350
    authorStatement.setNodeNameList(nodeNameList);
×
2351
    return authorStatement;
×
2352
  }
2353

2354
  // List Privileges of Roles On Specific Path
2355

2356
  @Override
2357
  public Statement visitListPrivilegesRole(IoTDBSqlParser.ListPrivilegesRoleContext ctx) {
2358
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.LIST_ROLE_PRIVILEGE);
×
2359
    authorStatement.setRoleName(parseIdentifier(ctx.roleName.getText()));
×
2360
    List<PartialPath> nodeNameList =
×
2361
        ctx.prefixPath().stream().map(this::parsePrefixPath).collect(Collectors.toList());
×
2362
    authorStatement.setNodeNameList(nodeNameList);
×
2363
    return authorStatement;
×
2364
  }
2365

2366
  private String[] parsePrivilege(IoTDBSqlParser.PrivilegesContext ctx) {
2367
    List<IoTDBSqlParser.PrivilegeValueContext> privilegeList = ctx.privilegeValue();
×
2368
    List<String> privileges = new ArrayList<>();
×
2369
    for (IoTDBSqlParser.PrivilegeValueContext privilegeValue : privilegeList) {
×
2370
      privileges.add(privilegeValue.getText());
×
2371
    }
×
2372
    return privileges.toArray(new String[0]);
×
2373
  }
2374

2375
  // Create database
2376
  @Override
2377
  public Statement visitCreateDatabase(IoTDBSqlParser.CreateDatabaseContext ctx) {
2378
    DatabaseSchemaStatement databaseSchemaStatement =
×
2379
        new DatabaseSchemaStatement(DatabaseSchemaStatement.DatabaseSchemaStatementType.CREATE);
2380
    PartialPath path = parsePrefixPath(ctx.prefixPath());
×
2381
    databaseSchemaStatement.setDatabasePath(path);
×
2382
    if (ctx.databaseAttributesClause() != null) {
×
2383
      parseDatabaseAttributesClause(databaseSchemaStatement, ctx.databaseAttributesClause());
×
2384
    }
2385
    return databaseSchemaStatement;
×
2386
  }
2387

2388
  @Override
2389
  public Statement visitAlterDatabase(IoTDBSqlParser.AlterDatabaseContext ctx) {
2390
    DatabaseSchemaStatement databaseSchemaStatement =
×
2391
        new DatabaseSchemaStatement(DatabaseSchemaStatement.DatabaseSchemaStatementType.ALTER);
2392
    PartialPath path = parsePrefixPath(ctx.prefixPath());
×
2393
    databaseSchemaStatement.setDatabasePath(path);
×
2394
    parseDatabaseAttributesClause(databaseSchemaStatement, ctx.databaseAttributesClause());
×
2395
    return databaseSchemaStatement;
×
2396
  }
2397

2398
  private void parseDatabaseAttributesClause(
2399
      DatabaseSchemaStatement databaseSchemaStatement,
2400
      IoTDBSqlParser.DatabaseAttributesClauseContext ctx) {
2401
    for (IoTDBSqlParser.DatabaseAttributeClauseContext attribute : ctx.databaseAttributeClause()) {
×
2402
      IoTDBSqlParser.DatabaseAttributeKeyContext attributeKey = attribute.databaseAttributeKey();
×
2403
      if (attributeKey.TTL() != null) {
×
2404
        long ttl = Long.parseLong(attribute.INTEGER_LITERAL().getText());
×
2405
        databaseSchemaStatement.setTtl(ttl);
×
2406
      } else if (attributeKey.SCHEMA_REPLICATION_FACTOR() != null) {
×
2407
        int schemaReplicationFactor = Integer.parseInt(attribute.INTEGER_LITERAL().getText());
×
2408
        databaseSchemaStatement.setSchemaReplicationFactor(schemaReplicationFactor);
×
2409
      } else if (attributeKey.DATA_REPLICATION_FACTOR() != null) {
×
2410
        int dataReplicationFactor = Integer.parseInt(attribute.INTEGER_LITERAL().getText());
×
2411
        databaseSchemaStatement.setDataReplicationFactor(dataReplicationFactor);
×
2412
      } else if (attributeKey.TIME_PARTITION_INTERVAL() != null) {
×
2413
        long timePartitionInterval = Long.parseLong(attribute.INTEGER_LITERAL().getText());
×
2414
        databaseSchemaStatement.setTimePartitionInterval(timePartitionInterval);
×
2415
      } else if (attributeKey.SCHEMA_REGION_GROUP_NUM() != null) {
×
2416
        int schemaRegionGroupNum = Integer.parseInt(attribute.INTEGER_LITERAL().getText());
×
2417
        databaseSchemaStatement.setSchemaRegionGroupNum(schemaRegionGroupNum);
×
2418
      } else if (attributeKey.DATA_REGION_GROUP_NUM() != null) {
×
2419
        int dataRegionGroupNum = Integer.parseInt(attribute.INTEGER_LITERAL().getText());
×
2420
        databaseSchemaStatement.setDataRegionGroupNum(dataRegionGroupNum);
×
2421
      }
2422
    }
×
2423
  }
×
2424

2425
  @Override
2426
  public Statement visitSetTTL(IoTDBSqlParser.SetTTLContext ctx) {
2427
    SetTTLStatement setTTLStatement = new SetTTLStatement();
1✔
2428
    PartialPath path = parsePrefixPath(ctx.prefixPath());
1✔
2429
    long ttl = Long.parseLong(ctx.INTEGER_LITERAL().getText());
1✔
2430
    setTTLStatement.setDatabasePath(path);
1✔
2431
    setTTLStatement.setTTL(ttl);
1✔
2432
    return setTTLStatement;
1✔
2433
  }
2434

2435
  @Override
2436
  public Statement visitUnsetTTL(IoTDBSqlParser.UnsetTTLContext ctx) {
2437
    UnSetTTLStatement unSetTTLStatement = new UnSetTTLStatement();
1✔
2438
    PartialPath partialPath = parsePrefixPath(ctx.prefixPath());
1✔
2439
    unSetTTLStatement.setDatabasePath(partialPath);
1✔
2440
    return unSetTTLStatement;
1✔
2441
  }
2442

2443
  @Override
2444
  public Statement visitShowTTL(IoTDBSqlParser.ShowTTLContext ctx) {
2445
    ShowTTLStatement showTTLStatement = new ShowTTLStatement();
1✔
2446
    for (IoTDBSqlParser.PrefixPathContext prefixPathContext : ctx.prefixPath()) {
1✔
2447
      PartialPath partialPath = parsePrefixPath(prefixPathContext);
1✔
2448
      showTTLStatement.addPathPatterns(partialPath);
1✔
2449
    }
1✔
2450
    return showTTLStatement;
1✔
2451
  }
2452

2453
  @Override
2454
  public Statement visitShowAllTTL(IoTDBSqlParser.ShowAllTTLContext ctx) {
2455
    ShowTTLStatement showTTLStatement = new ShowTTLStatement();
1✔
2456
    showTTLStatement.setAll(true);
1✔
2457
    return showTTLStatement;
1✔
2458
  }
2459

2460
  @Override
2461
  public Statement visitShowVariables(IoTDBSqlParser.ShowVariablesContext ctx) {
2462
    return new ShowVariablesStatement();
×
2463
  }
2464

2465
  @Override
2466
  public Statement visitShowCluster(IoTDBSqlParser.ShowClusterContext ctx) {
2467
    ShowClusterStatement showClusterStatement = new ShowClusterStatement();
×
2468
    if (ctx.DETAILS() != null) {
×
2469
      showClusterStatement.setDetails(true);
×
2470
    }
2471
    return showClusterStatement;
×
2472
  }
2473

2474
  @Override
2475
  public Statement visitDropDatabase(IoTDBSqlParser.DropDatabaseContext ctx) {
2476
    DeleteDatabaseStatement dropDatabaseStatement = new DeleteDatabaseStatement();
×
2477
    List<IoTDBSqlParser.PrefixPathContext> prefixPathContexts = ctx.prefixPath();
×
2478
    List<String> paths = new ArrayList<>();
×
2479
    for (IoTDBSqlParser.PrefixPathContext prefixPathContext : prefixPathContexts) {
×
2480
      paths.add(parsePrefixPath(prefixPathContext).getFullPath());
×
2481
    }
×
2482
    dropDatabaseStatement.setPrefixPath(paths);
×
2483
    return dropDatabaseStatement;
×
2484
  }
2485

2486
  // Explain ========================================================================
2487
  @Override
2488
  public Statement visitExplain(IoTDBSqlParser.ExplainContext ctx) {
2489
    QueryStatement queryStatement = (QueryStatement) visitSelectStatement(ctx.selectStatement());
×
2490
    return new ExplainStatement(queryStatement);
×
2491
  }
2492

2493
  @Override
2494
  public Statement visitDeleteStatement(IoTDBSqlParser.DeleteStatementContext ctx) {
2495
    DeleteDataStatement statement = new DeleteDataStatement();
×
2496
    List<IoTDBSqlParser.PrefixPathContext> prefixPaths = ctx.prefixPath();
×
2497
    List<PartialPath> pathList = new ArrayList<>();
×
2498
    for (IoTDBSqlParser.PrefixPathContext prefixPath : prefixPaths) {
×
2499
      pathList.add(parsePrefixPath(prefixPath));
×
2500
    }
×
2501
    statement.setPathList(pathList);
×
2502
    if (ctx.whereClause() != null) {
×
2503
      WhereCondition whereCondition = parseWhereClause(ctx.whereClause());
×
2504
      TimeRange timeRange = parseDeleteTimeRange(whereCondition.getPredicate());
×
2505
      statement.setTimeRange(timeRange);
×
2506
    } else {
×
2507
      statement.setTimeRange(new TimeRange(Long.MIN_VALUE, Long.MAX_VALUE));
×
2508
    }
2509
    return statement;
×
2510
  }
2511

2512
  private TimeRange parseDeleteTimeRange(Expression predicate) {
2513
    if (predicate instanceof LogicAndExpression) {
×
2514
      TimeRange leftTimeRange =
×
2515
          parseDeleteTimeRange(((LogicAndExpression) predicate).getLeftExpression());
×
2516
      TimeRange rightTimeRange =
×
2517
          parseDeleteTimeRange(((LogicAndExpression) predicate).getRightExpression());
×
2518
      return new TimeRange(
×
2519
          Math.max(leftTimeRange.getMin(), rightTimeRange.getMin()),
×
2520
          Math.min(leftTimeRange.getMax(), rightTimeRange.getMax()));
×
2521
    } else if (predicate instanceof CompareBinaryExpression) {
×
2522
      if (((CompareBinaryExpression) predicate).getLeftExpression() instanceof TimestampOperand) {
×
2523
        return parseTimeRangeForDeleteTimeRange(
×
2524
            predicate.getExpressionType(),
×
2525
            ((CompareBinaryExpression) predicate).getLeftExpression(),
×
2526
            ((CompareBinaryExpression) predicate).getRightExpression());
×
2527
      } else {
2528
        return parseTimeRangeForDeleteTimeRange(
×
2529
            predicate.getExpressionType(),
×
2530
            ((CompareBinaryExpression) predicate).getRightExpression(),
×
2531
            ((CompareBinaryExpression) predicate).getLeftExpression());
×
2532
      }
2533
    } else {
2534
      throw new SemanticException(DELETE_RANGE_ERROR_MSG);
×
2535
    }
2536
  }
2537

2538
  private TimeRange parseTimeRangeForDeleteTimeRange(
2539
      ExpressionType expressionType, Expression timeExpression, Expression valueExpression) {
2540
    if (!(timeExpression instanceof TimestampOperand)
×
2541
        || !(valueExpression instanceof ConstantOperand)) {
2542
      throw new SemanticException(DELETE_ONLY_SUPPORT_TIME_EXP_ERROR_MSG);
×
2543
    }
2544

2545
    if (((ConstantOperand) valueExpression).getDataType() != TSDataType.INT64) {
×
2546
      throw new SemanticException("The datatype of timestamp should be LONG.");
×
2547
    }
2548

2549
    long time = Long.parseLong(((ConstantOperand) valueExpression).getValueString());
×
2550
    switch (expressionType) {
×
2551
      case LESS_THAN:
2552
        return new TimeRange(Long.MIN_VALUE, time - 1);
×
2553
      case LESS_EQUAL:
2554
        return new TimeRange(Long.MIN_VALUE, time);
×
2555
      case GREATER_THAN:
2556
        return new TimeRange(time + 1, Long.MAX_VALUE);
×
2557
      case GREATER_EQUAL:
2558
        return new TimeRange(time, Long.MAX_VALUE);
×
2559
      case EQUAL_TO:
2560
        return new TimeRange(time, time);
×
2561
      default:
2562
        throw new SemanticException(DELETE_RANGE_ERROR_MSG);
×
2563
    }
2564
  }
2565

2566
  /** function for parsing file path used by LOAD statement. */
2567
  public String parseFilePath(String src) {
2568
    return src.substring(1, src.length() - 1);
×
2569
  }
2570

2571
  // Expression & Predicate ========================================================================
2572

2573
  private Expression parseExpression(
2574
      IoTDBSqlParser.ExpressionContext context, boolean canUseFullPath) {
2575
    if (context.unaryInBracket != null) {
1✔
2576
      return parseExpression(context.unaryInBracket, canUseFullPath);
1✔
2577
    }
2578

2579
    if (context.expressionAfterUnaryOperator != null) {
1✔
2580
      if (context.MINUS() != null) {
×
2581
        return new NegationExpression(
×
2582
            parseExpression(context.expressionAfterUnaryOperator, canUseFullPath));
×
2583
      }
2584
      if (context.operator_not() != null) {
×
2585
        return new LogicNotExpression(
×
2586
            parseExpression(context.expressionAfterUnaryOperator, canUseFullPath));
×
2587
      }
2588
      return parseExpression(context.expressionAfterUnaryOperator, canUseFullPath);
×
2589
    }
2590

2591
    if (context.leftExpression != null && context.rightExpression != null) {
1✔
2592
      Expression leftExpression = parseExpression(context.leftExpression, canUseFullPath);
1✔
2593
      Expression rightExpression = parseExpression(context.rightExpression, canUseFullPath);
1✔
2594
      if (context.STAR() != null) {
1✔
2595
        return new MultiplicationExpression(leftExpression, rightExpression);
1✔
2596
      }
2597
      if (context.DIV() != null) {
1✔
2598
        return new DivisionExpression(leftExpression, rightExpression);
1✔
2599
      }
2600
      if (context.MOD() != null) {
1✔
2601
        return new ModuloExpression(leftExpression, rightExpression);
1✔
2602
      }
2603
      if (context.PLUS() != null) {
1✔
2604
        return new AdditionExpression(leftExpression, rightExpression);
1✔
2605
      }
2606
      if (context.MINUS() != null) {
1✔
2607
        return new SubtractionExpression(leftExpression, rightExpression);
1✔
2608
      }
2609
      if (context.OPERATOR_GT() != null) {
1✔
2610
        return new GreaterThanExpression(leftExpression, rightExpression);
1✔
2611
      }
2612
      if (context.OPERATOR_GTE() != null) {
1✔
2613
        return new GreaterEqualExpression(leftExpression, rightExpression);
1✔
2614
      }
2615
      if (context.OPERATOR_LT() != null) {
1✔
2616
        return new LessThanExpression(leftExpression, rightExpression);
1✔
2617
      }
2618
      if (context.OPERATOR_LTE() != null) {
1✔
2619
        return new LessEqualExpression(leftExpression, rightExpression);
1✔
2620
      }
2621
      if (context.OPERATOR_DEQ() != null || context.OPERATOR_SEQ() != null) {
1✔
2622
        return new EqualToExpression(leftExpression, rightExpression);
1✔
2623
      }
2624
      if (context.OPERATOR_NEQ() != null) {
1✔
2625
        return new NonEqualExpression(leftExpression, rightExpression);
1✔
2626
      }
2627
      if (context.operator_and() != null) {
1✔
2628
        return new LogicAndExpression(leftExpression, rightExpression);
1✔
2629
      }
2630
      if (context.operator_or() != null) {
1✔
2631
        return new LogicOrExpression(leftExpression, rightExpression);
1✔
2632
      }
2633
      throw new UnsupportedOperationException();
×
2634
    }
2635

2636
    if (context.unaryBeforeRegularOrLikeExpression != null) {
1✔
2637
      if (context.REGEXP() != null) {
×
2638
        return parseRegularExpression(context, canUseFullPath);
×
2639
      }
2640
      if (context.LIKE() != null) {
×
2641
        return parseLikeExpression(context, canUseFullPath);
×
2642
      }
2643
      throw new UnsupportedOperationException();
×
2644
    }
2645

2646
    if (context.unaryBeforeIsNullExpression != null) {
1✔
2647
      return parseIsNullExpression(context, canUseFullPath);
×
2648
    }
2649

2650
    if (context.firstExpression != null
1✔
2651
        && context.secondExpression != null
2652
        && context.thirdExpression != null) {
2653
      Expression firstExpression = parseExpression(context.firstExpression, canUseFullPath);
×
2654
      Expression secondExpression = parseExpression(context.secondExpression, canUseFullPath);
×
2655
      Expression thirdExpression = parseExpression(context.thirdExpression, canUseFullPath);
×
2656

2657
      if (context.operator_between() != null) {
×
2658
        return new BetweenExpression(
×
2659
            firstExpression, secondExpression, thirdExpression, context.operator_not() != null);
×
2660
      }
2661
      throw new UnsupportedOperationException();
×
2662
    }
2663

2664
    if (context.unaryBeforeInExpression != null) {
1✔
2665
      return parseInExpression(context, canUseFullPath);
×
2666
    }
2667

2668
    if (context.scalarFunctionExpression() != null) {
1✔
2669
      return parseScalarFunctionExpression(context.scalarFunctionExpression(), canUseFullPath);
×
2670
    }
2671

2672
    if (context.functionName() != null) {
1✔
2673
      return parseFunctionExpression(context, canUseFullPath);
1✔
2674
    }
2675

2676
    if (context.fullPathInExpression() != null) {
1✔
2677
      return new TimeSeriesOperand(
1✔
2678
          parseFullPathInExpression(context.fullPathInExpression(), canUseFullPath));
1✔
2679
    }
2680

2681
    if (context.time != null) {
1✔
2682
      return new TimestampOperand();
1✔
2683
    }
2684

2685
    if (context.constant() != null && !context.constant().isEmpty()) {
1✔
2686
      return parseConstantOperand(context.constant(0));
1✔
2687
    }
2688

2689
    if (context.caseWhenThenExpression() != null) {
×
2690
      return parseCaseWhenThenExpression(context.caseWhenThenExpression(), canUseFullPath);
×
2691
    }
2692

2693
    throw new UnsupportedOperationException();
×
2694
  }
2695

2696
  private Expression parseScalarFunctionExpression(
2697
      IoTDBSqlParser.ScalarFunctionExpressionContext context, boolean canUseFullPath) {
2698
    if (context.CAST() != null) {
×
2699
      return parseCastFunction(context, canUseFullPath);
×
2700
    } else if (context.REPLACE() != null) {
×
2701
      return parseReplaceFunction(context, canUseFullPath);
×
2702
    } else if (context.ROUND() != null) {
×
2703
      return parseRoundFunction(context, canUseFullPath);
×
2704
    } else if (context.SUBSTRING() != null) {
×
2705
      return parseSubStrFunction(context, canUseFullPath);
×
2706
    }
2707
    throw new UnsupportedOperationException();
×
2708
  }
2709

2710
  private Expression parseCastFunction(
2711
      IoTDBSqlParser.ScalarFunctionExpressionContext castClause, boolean canUseFullPath) {
2712
    FunctionExpression functionExpression = new FunctionExpression(CAST_FUNCTION);
×
2713
    functionExpression.addExpression(parseExpression(castClause.castInput, canUseFullPath));
×
2714
    functionExpression.addAttribute(CAST_TYPE, parseAttributeValue(castClause.attributeValue()));
×
2715
    return functionExpression;
×
2716
  }
2717

2718
  private Expression parseReplaceFunction(
2719
      IoTDBSqlParser.ScalarFunctionExpressionContext replaceClause, boolean canUseFullPath) {
2720
    FunctionExpression functionExpression = new FunctionExpression(REPLACE_FUNCTION);
×
2721
    functionExpression.addExpression(parseExpression(replaceClause.text, canUseFullPath));
×
2722
    functionExpression.addAttribute(REPLACE_FROM, parseStringLiteral(replaceClause.from.getText()));
×
2723
    functionExpression.addAttribute(REPLACE_TO, parseStringLiteral(replaceClause.to.getText()));
×
2724
    return functionExpression;
×
2725
  }
2726

2727
  private Expression parseSubStrFunction(
2728
      IoTDBSqlParser.ScalarFunctionExpressionContext subStrClause, boolean canUseFullPath) {
2729
    FunctionExpression functionExpression = new FunctionExpression(SUBSTRING_FUNCTION);
×
2730
    IoTDBSqlParser.SubStringExpressionContext subStringExpression =
×
2731
        subStrClause.subStringExpression();
×
2732
    functionExpression.addExpression(parseExpression(subStringExpression.input, canUseFullPath));
×
2733
    if (subStringExpression.startPosition != null) {
×
2734
      functionExpression.addAttribute(SUBSTRING_START, subStringExpression.startPosition.getText());
×
2735
      if (subStringExpression.length != null) {
×
2736
        functionExpression.addAttribute(SUBSTRING_LENGTH, subStringExpression.length.getText());
×
2737
      }
2738
    }
2739
    if (subStringExpression.from != null) {
×
2740
      functionExpression.addAttribute(SUBSTRING_IS_STANDARD, "0");
×
2741
      functionExpression.addAttribute(
×
2742
          SUBSTRING_START, parseStringLiteral(subStringExpression.from.getText()));
×
2743
      if (subStringExpression.forLength != null) {
×
2744
        functionExpression.addAttribute(SUBSTRING_LENGTH, subStringExpression.forLength.getText());
×
2745
      }
2746
    }
2747
    return functionExpression;
×
2748
  }
2749

2750
  private Expression parseRoundFunction(
2751
      IoTDBSqlParser.ScalarFunctionExpressionContext roundClause, boolean canUseFullPath) {
2752
    FunctionExpression functionExpression = new FunctionExpression(ROUND_FUNCTION);
×
2753
    functionExpression.addExpression(parseExpression(roundClause.input, canUseFullPath));
×
2754
    if (roundClause.places != null) {
×
2755
      functionExpression.addAttribute(ROUND_PLACES, parseConstant(roundClause.constant()));
×
2756
    }
2757
    return functionExpression;
×
2758
  }
2759

2760
  private CaseWhenThenExpression parseCaseWhenThenExpression(
2761
      IoTDBSqlParser.CaseWhenThenExpressionContext context, boolean canUseFullPath) {
2762
    // handle CASE
2763
    Expression caseExpression = null;
×
2764
    boolean simpleCase = false;
×
2765
    if (context.caseExpression != null) {
×
2766
      caseExpression = parseExpression(context.caseExpression, canUseFullPath);
×
2767
      simpleCase = true;
×
2768
    }
2769
    // handle WHEN-THEN
2770
    List<WhenThenExpression> whenThenList = new ArrayList<>();
×
2771
    if (simpleCase) {
×
2772
      for (IoTDBSqlParser.WhenThenExpressionContext whenThenExpressionContext :
2773
          context.whenThenExpression()) {
×
2774
        Expression when = parseExpression(whenThenExpressionContext.whenExpression, canUseFullPath);
×
2775
        Expression then = parseExpression(whenThenExpressionContext.thenExpression, canUseFullPath);
×
2776
        Expression comparison = new EqualToExpression(caseExpression, when);
×
2777
        whenThenList.add(new WhenThenExpression(comparison, then));
×
2778
      }
×
2779
    } else {
2780
      for (IoTDBSqlParser.WhenThenExpressionContext whenThenExpressionContext :
2781
          context.whenThenExpression()) {
×
2782
        whenThenList.add(
×
2783
            new WhenThenExpression(
2784
                parseExpression(whenThenExpressionContext.whenExpression, canUseFullPath),
×
2785
                parseExpression(whenThenExpressionContext.thenExpression, canUseFullPath)));
×
2786
      }
×
2787
    }
2788
    // handle ELSE
2789
    Expression elseExpression = new NullOperand();
×
2790
    if (context.elseExpression != null) {
×
2791
      elseExpression = parseExpression(context.elseExpression, canUseFullPath);
×
2792
    }
2793
    return new CaseWhenThenExpression(whenThenList, elseExpression);
×
2794
  }
2795

2796
  private Expression parseFunctionExpression(
2797
      IoTDBSqlParser.ExpressionContext functionClause, boolean canUseFullPath) {
2798
    FunctionExpression functionExpression =
1✔
2799
        new FunctionExpression(parseIdentifier(functionClause.functionName().getText()));
1✔
2800

2801
    // expressions
2802
    boolean hasNonPureConstantSubExpression = false;
1✔
2803
    for (IoTDBSqlParser.ExpressionContext expression : functionClause.expression()) {
1✔
2804
      Expression subexpression = parseExpression(expression, canUseFullPath);
1✔
2805
      if (!subexpression.isConstantOperand()) {
1✔
2806
        hasNonPureConstantSubExpression = true;
1✔
2807
      }
2808
      if (subexpression instanceof EqualToExpression) {
1✔
2809
        Expression subLeftExpression = ((EqualToExpression) subexpression).getLeftExpression();
1✔
2810
        Expression subRightExpression = ((EqualToExpression) subexpression).getRightExpression();
1✔
2811
        if (subLeftExpression.isConstantOperand()
1✔
2812
            && (!(subRightExpression.isConstantOperand()
1✔
2813
                && ((ConstantOperand) subRightExpression).getDataType().equals(TSDataType.TEXT)))) {
1✔
2814
          throw new SemanticException("Attributes of functions should be quoted with '' or \"\"");
×
2815
        }
2816
        if (subLeftExpression.isConstantOperand() && subRightExpression.isConstantOperand()) {
1✔
2817
          // parse attribute
2818
          functionExpression.addAttribute(
1✔
2819
              ((ConstantOperand) subLeftExpression).getValueString(),
1✔
2820
              ((ConstantOperand) subRightExpression).getValueString());
1✔
2821
        } else {
2822
          functionExpression.addExpression(subexpression);
×
2823
        }
2824
      } else {
1✔
2825
        functionExpression.addExpression(subexpression);
1✔
2826
      }
2827
    }
1✔
2828

2829
    // It is not allowed to have function expressions like F(1, 1.0). There should be at least one
2830
    // non-pure-constant sub-expression, otherwise the timestamp of the row cannot be inferred.
2831
    if (!hasNonPureConstantSubExpression) {
1✔
2832
      throw new SemanticException(
×
2833
          "Invalid function expression, all the arguments are constant operands: "
2834
              + functionClause.getText());
×
2835
    }
2836

2837
    // check size of input expressions
2838
    // type check of input expressions is put in ExpressionTypeAnalyzer
2839
    if (functionExpression.isBuiltInAggregationFunctionExpression()) {
1✔
2840
      checkAggregationFunctionInput(functionExpression);
1✔
2841
    } else if (functionExpression.isBuiltInScalarFunction()) {
1✔
2842
      checkBuiltInScalarFunctionInput(functionExpression);
1✔
2843
    }
2844
    return functionExpression;
1✔
2845
  }
2846

2847
  private void checkAggregationFunctionInput(FunctionExpression functionExpression) {
2848
    final String functionName = functionExpression.getFunctionName().toLowerCase();
1✔
2849
    switch (functionName) {
1✔
2850
      case SqlConstant.MIN_TIME:
2851
      case SqlConstant.MAX_TIME:
2852
      case SqlConstant.COUNT:
2853
      case SqlConstant.MIN_VALUE:
2854
      case SqlConstant.LAST_VALUE:
2855
      case SqlConstant.FIRST_VALUE:
2856
      case SqlConstant.MAX_VALUE:
2857
      case SqlConstant.EXTREME:
2858
      case SqlConstant.AVG:
2859
      case SqlConstant.SUM:
2860
      case SqlConstant.TIME_DURATION:
2861
      case SqlConstant.MODE:
2862
        checkFunctionExpressionInputSize(
1✔
2863
            functionExpression.getExpressionString(),
1✔
2864
            functionExpression.getExpressions().size(),
1✔
2865
            1);
2866
        return;
1✔
2867
      case SqlConstant.COUNT_IF:
2868
        checkFunctionExpressionInputSize(
×
2869
            functionExpression.getExpressionString(),
×
2870
            functionExpression.getExpressions().size(),
×
2871
            2);
2872
        return;
×
2873
      default:
2874
        throw new IllegalArgumentException(
×
2875
            "Invalid Aggregation function: " + functionExpression.getFunctionName());
×
2876
    }
2877
  }
2878

2879
  private void checkBuiltInScalarFunctionInput(FunctionExpression functionExpression) {
2880
    BuiltInScalarFunctionHelperFactory.createHelper(functionExpression.getFunctionName())
1✔
2881
        .checkBuiltInScalarFunctionInputSize(functionExpression);
1✔
2882
  }
1✔
2883

2884
  public static void checkFunctionExpressionInputSize(
2885
      String expressionString, int actual, int... expected) {
2886
    for (int expect : expected) {
1✔
2887
      if (expect == actual) {
1✔
2888
        return;
1✔
2889
      }
2890
    }
2891
    throw new SemanticException(
×
2892
        String.format(
×
2893
            "Error size of input expressions. expression: %s, actual size: %s, expected size: %s.",
2894
            expressionString, actual, Arrays.toString(expected)));
×
2895
  }
2896

2897
  private Expression parseRegularExpression(ExpressionContext context, boolean canUseFullPath) {
2898
    return new RegularExpression(
×
2899
        parseExpression(context.unaryBeforeRegularOrLikeExpression, canUseFullPath),
×
2900
        parseStringLiteral(context.STRING_LITERAL().getText()));
×
2901
  }
2902

2903
  private Expression parseLikeExpression(ExpressionContext context, boolean canUseFullPath) {
2904
    return new LikeExpression(
×
2905
        parseExpression(context.unaryBeforeRegularOrLikeExpression, canUseFullPath),
×
2906
        parseStringLiteral(context.STRING_LITERAL().getText()));
×
2907
  }
2908

2909
  private Expression parseIsNullExpression(ExpressionContext context, boolean canUseFullPath) {
2910
    return new IsNullExpression(
×
2911
        parseExpression(context.unaryBeforeIsNullExpression, canUseFullPath),
×
2912
        context.operator_not() != null);
×
2913
  }
2914

2915
  private Expression parseInExpression(ExpressionContext context, boolean canUseFullPath) {
2916
    Expression childExpression = parseExpression(context.unaryBeforeInExpression, canUseFullPath);
×
2917
    LinkedHashSet<String> values = new LinkedHashSet<>();
×
2918
    for (ConstantContext constantContext : context.constant()) {
×
2919
      values.add(parseConstant(constantContext));
×
2920
    }
×
2921
    return new InExpression(childExpression, context.operator_not() != null, values);
×
2922
  }
2923

2924
  private String parseConstant(ConstantContext constantContext) {
2925
    String text = constantContext.getText();
×
2926
    if (constantContext.boolean_literal() != null
×
2927
        || constantContext.INTEGER_LITERAL() != null
×
2928
        || constantContext.realLiteral() != null) {
×
2929
      return text;
×
2930
    } else if (constantContext.STRING_LITERAL() != null) {
×
2931
      return parseStringLiteral(text);
×
2932
    } else if (constantContext.dateExpression() != null) {
×
2933
      return String.valueOf(parseDateExpression(constantContext.dateExpression()));
×
2934
    } else {
2935
      throw new IllegalArgumentException("Unsupported constant value: " + text);
×
2936
    }
2937
  }
2938

2939
  private Expression parseConstantOperand(ConstantContext constantContext) {
2940
    String text = constantContext.getText();
1✔
2941
    if (constantContext.boolean_literal() != null) {
1✔
2942
      return new ConstantOperand(TSDataType.BOOLEAN, text);
×
2943
    } else if (constantContext.STRING_LITERAL() != null) {
1✔
2944
      return new ConstantOperand(TSDataType.TEXT, parseStringLiteral(text));
1✔
2945
    } else if (constantContext.INTEGER_LITERAL() != null) {
1✔
2946
      return new ConstantOperand(TSDataType.INT64, text);
1✔
2947
    } else if (constantContext.realLiteral() != null) {
×
2948
      return parseRealLiteral(text);
×
2949
    } else if (constantContext.dateExpression() != null) {
×
2950
      return new ConstantOperand(
×
2951
          TSDataType.INT64, String.valueOf(parseDateExpression(constantContext.dateExpression())));
×
2952
    } else {
2953
      throw new SemanticException("Unsupported constant operand: " + text);
×
2954
    }
2955
  }
2956

2957
  private Expression parseRealLiteral(String value) {
2958
    // 3.33 is float by default
2959
    return new ConstantOperand(
×
2960
        CONFIG.getFloatingStringInferType().equals(TSDataType.DOUBLE)
×
2961
            ? TSDataType.DOUBLE
×
2962
            : TSDataType.FLOAT,
×
2963
        value);
2964
  }
2965

2966
  /**
2967
   * parse time expression, which is addition and subtraction expression of duration time, now() or
2968
   * DataTimeFormat time.
2969
   *
2970
   * <p>eg. now() + 1d - 2h
2971
   */
2972
  private Long parseDateExpression(IoTDBSqlParser.DateExpressionContext ctx) {
2973
    long time;
2974
    time = parseDateFormat(ctx.getChild(0).getText());
×
2975
    for (int i = 1; i < ctx.getChildCount(); i = i + 2) {
×
2976
      if ("+".equals(ctx.getChild(i).getText())) {
×
2977
        time += DateTimeUtils.convertDurationStrToLong(time, ctx.getChild(i + 1).getText());
×
2978
      } else {
2979
        time -= DateTimeUtils.convertDurationStrToLong(time, ctx.getChild(i + 1).getText());
×
2980
      }
2981
    }
2982
    return time;
×
2983
  }
2984

2985
  private Long parseDateExpression(IoTDBSqlParser.DateExpressionContext ctx, long currentTime) {
2986
    long time;
2987
    time = parseDateFormat(ctx.getChild(0).getText(), currentTime);
×
2988
    for (int i = 1; i < ctx.getChildCount(); i = i + 2) {
×
2989
      if ("+".equals(ctx.getChild(i).getText())) {
×
2990
        time += DateTimeUtils.convertDurationStrToLong(time, ctx.getChild(i + 1).getText());
×
2991
      } else {
2992
        time -= DateTimeUtils.convertDurationStrToLong(time, ctx.getChild(i + 1).getText());
×
2993
      }
2994
    }
2995
    return time;
×
2996
  }
2997

2998
  private long parseTimeValue(IoTDBSqlParser.TimeValueContext ctx, long currentTime) {
2999
    if (ctx.INTEGER_LITERAL() != null) {
1✔
3000
      try {
3001
        if (ctx.MINUS() != null) {
1✔
3002
          return -Long.parseLong(ctx.INTEGER_LITERAL().getText());
×
3003
        }
3004
        return Long.parseLong(ctx.INTEGER_LITERAL().getText());
1✔
3005
      } catch (NumberFormatException e) {
×
3006
        throw new SemanticException(
×
3007
            String.format("Can not parse %s to long value", ctx.INTEGER_LITERAL().getText()));
×
3008
      }
3009
    } else if (ctx.dateExpression() != null) {
1✔
3010
      return parseDateExpression(ctx.dateExpression(), currentTime);
×
3011
    } else {
3012
      return parseDateFormat(ctx.datetimeLiteral().getText(), currentTime);
1✔
3013
    }
3014
  }
3015

3016
  /** Utils. */
3017
  private void setMap(IoTDBSqlParser.AlterClauseContext ctx, Map<String, String> alterMap) {
3018
    List<IoTDBSqlParser.AttributePairContext> tagsList = ctx.attributePair();
×
3019
    String key;
3020
    if (ctx.attributePair(0) != null) {
×
3021
      for (IoTDBSqlParser.AttributePairContext attributePair : tagsList) {
×
3022
        key = parseAttributeKey(attributePair.attributeKey());
×
3023
        alterMap.computeIfPresent(
×
3024
            key,
3025
            (k, v) -> {
3026
              throw new SemanticException(
×
3027
                  String.format("There's duplicate [%s] in tag or attribute clause.", k));
×
3028
            });
3029
        alterMap.put(key, parseAttributeValue(attributePair.attributeValue()));
×
3030
      }
×
3031
    }
3032
  }
×
3033

3034
  private Map<String, String> extractMap(
3035
      List<IoTDBSqlParser.AttributePairContext> attributePair2,
3036
      IoTDBSqlParser.AttributePairContext attributePair3) {
3037
    Map<String, String> tags = new HashMap<>(attributePair2.size());
1✔
3038
    if (attributePair3 != null) {
1✔
3039
      String key;
3040
      for (IoTDBSqlParser.AttributePairContext attributePair : attributePair2) {
1✔
3041
        key = parseAttributeKey(attributePair.attributeKey());
1✔
3042
        tags.computeIfPresent(
1✔
3043
            key,
3044
            (k, v) -> {
3045
              throw new SemanticException(
×
3046
                  String.format("There's duplicate [%s] in tag or attribute clause.", k));
×
3047
            });
3048
        tags.put(key, parseAttributeValue(attributePair.attributeValue()));
1✔
3049
      }
1✔
3050
    }
3051
    return tags;
1✔
3052
  }
3053

3054
  private String parseAttributeKey(IoTDBSqlParser.AttributeKeyContext ctx) {
3055
    if (ctx.constant() != null) {
1✔
3056
      return parseStringLiteral(ctx.getText());
1✔
3057
    }
3058
    return parseIdentifier(ctx.getText());
×
3059
  }
3060

3061
  private String parseAttributeValue(IoTDBSqlParser.AttributeValueContext ctx) {
3062
    if (ctx.constant() != null) {
1✔
3063
      return parseStringLiteral(ctx.getText());
1✔
3064
    }
3065
    return parseIdentifier(ctx.getText());
×
3066
  }
3067

3068
  // Merge
3069
  @Override
3070
  public Statement visitMerge(IoTDBSqlParser.MergeContext ctx) {
3071
    MergeStatement mergeStatement = new MergeStatement(StatementType.MERGE);
×
3072
    if (ctx.CLUSTER() != null && !IoTDBDescriptor.getInstance().getConfig().isClusterMode()) {
×
3073
      throw new SemanticException("MERGE ON CLUSTER is not supported in standalone mode");
×
3074
    }
3075
    mergeStatement.setOnCluster(ctx.LOCAL() == null);
×
3076
    return mergeStatement;
×
3077
  }
3078

3079
  @Override
3080
  public Statement visitFullMerge(IoTDBSqlParser.FullMergeContext ctx) {
3081
    MergeStatement mergeStatement = new MergeStatement(StatementType.FULL_MERGE);
×
3082
    if (ctx.CLUSTER() != null && !IoTDBDescriptor.getInstance().getConfig().isClusterMode()) {
×
3083
      throw new SemanticException("FULL MERGE ON CLUSTER is not supported in standalone mode");
×
3084
    }
3085
    mergeStatement.setOnCluster(ctx.LOCAL() == null);
×
3086
    return mergeStatement;
×
3087
  }
3088

3089
  // Flush
3090

3091
  @Override
3092
  public Statement visitFlush(IoTDBSqlParser.FlushContext ctx) {
3093
    FlushStatement flushStatement = new FlushStatement(StatementType.FLUSH);
×
3094
    List<PartialPath> storageGroups = null;
×
3095
    if (ctx.boolean_literal() != null) {
×
3096
      flushStatement.setSeq(Boolean.parseBoolean(ctx.boolean_literal().getText()));
×
3097
    }
3098
    if (ctx.CLUSTER() != null && !IoTDBDescriptor.getInstance().getConfig().isClusterMode()) {
×
3099
      throw new SemanticException("FLUSH ON CLUSTER is not supported in standalone mode");
×
3100
    }
3101
    flushStatement.setOnCluster(ctx.LOCAL() == null);
×
3102
    if (ctx.prefixPath(0) != null) {
×
3103
      storageGroups = new ArrayList<>();
×
3104
      for (IoTDBSqlParser.PrefixPathContext prefixPathContext : ctx.prefixPath()) {
×
3105
        storageGroups.add(parsePrefixPath(prefixPathContext));
×
3106
      }
×
3107
    }
3108
    flushStatement.setStorageGroups(storageGroups);
×
3109
    return flushStatement;
×
3110
  }
3111

3112
  // Clear Cache
3113

3114
  @Override
3115
  public Statement visitClearCache(IoTDBSqlParser.ClearCacheContext ctx) {
3116
    ClearCacheStatement clearCacheStatement = new ClearCacheStatement(StatementType.CLEAR_CACHE);
×
3117
    if (ctx.CLUSTER() != null && !IoTDBDescriptor.getInstance().getConfig().isClusterMode()) {
×
3118
      throw new SemanticException("CLEAR CACHE ON CLUSTER is not supported in standalone mode");
×
3119
    }
3120
    clearCacheStatement.setOnCluster(ctx.LOCAL() == null);
×
3121
    return clearCacheStatement;
×
3122
  }
3123

3124
  // Load Configuration
3125

3126
  @Override
3127
  public Statement visitLoadConfiguration(IoTDBSqlParser.LoadConfigurationContext ctx) {
3128
    LoadConfigurationStatement loadConfigurationStatement =
×
3129
        new LoadConfigurationStatement(StatementType.LOAD_CONFIGURATION);
3130
    if (ctx.CLUSTER() != null && !IoTDBDescriptor.getInstance().getConfig().isClusterMode()) {
×
3131
      throw new SemanticException(
×
3132
          "LOAD CONFIGURATION ON CLUSTER is not supported in standalone mode");
3133
    }
3134
    loadConfigurationStatement.setOnCluster(ctx.LOCAL() == null);
×
3135
    return loadConfigurationStatement;
×
3136
  }
3137

3138
  // Set System Status
3139

3140
  @Override
3141
  public Statement visitSetSystemStatus(IoTDBSqlParser.SetSystemStatusContext ctx) {
3142
    SetSystemStatusStatement setSystemStatusStatement = new SetSystemStatusStatement();
×
3143
    if (ctx.CLUSTER() != null && !IoTDBDescriptor.getInstance().getConfig().isClusterMode()) {
×
3144
      throw new SemanticException(
×
3145
          "SET SYSTEM STATUS ON CLUSTER is not supported in standalone mode");
3146
    }
3147
    setSystemStatusStatement.setOnCluster(ctx.LOCAL() == null);
×
3148
    if (ctx.RUNNING() != null) {
×
3149
      setSystemStatusStatement.setStatus(NodeStatus.Running);
×
3150
    } else if (ctx.READONLY() != null) {
×
3151
      setSystemStatusStatement.setStatus(NodeStatus.ReadOnly);
×
3152
    } else {
3153
      throw new SemanticException("Unknown system status in set system command.");
×
3154
    }
3155
    return setSystemStatusStatement;
×
3156
  }
3157

3158
  // Kill Query
3159
  @Override
3160
  public Statement visitKillQuery(IoTDBSqlParser.KillQueryContext ctx) {
3161
    if (ctx.queryId != null) {
×
3162
      return new KillQueryStatement(parseStringLiteral(ctx.queryId.getText()));
×
3163
    }
3164
    return new KillQueryStatement();
×
3165
  }
3166

3167
  // show query processlist
3168

3169
  @Override
3170
  public Statement visitShowQueries(IoTDBSqlParser.ShowQueriesContext ctx) {
3171
    ShowQueriesStatement showQueriesStatement = new ShowQueriesStatement();
×
3172
    // parse WHERE
3173
    if (ctx.whereClause() != null) {
×
3174
      showQueriesStatement.setWhereCondition(parseWhereClause(ctx.whereClause()));
×
3175
    }
3176

3177
    // parse ORDER BY
3178
    if (ctx.orderByClause() != null) {
×
3179
      showQueriesStatement.setOrderByComponent(
×
3180
          parseOrderByClause(
×
3181
              ctx.orderByClause(),
×
3182
              ImmutableSet.of(
×
3183
                  OrderByKey.TIME,
3184
                  OrderByKey.QUERYID,
3185
                  OrderByKey.DATANODEID,
3186
                  OrderByKey.ELAPSEDTIME,
3187
                  OrderByKey.STATEMENT)));
3188
    }
3189

3190
    // parse LIMIT & OFFSET
3191
    if (ctx.rowPaginationClause() != null) {
×
3192
      if (ctx.rowPaginationClause().limitClause() != null) {
×
3193
        showQueriesStatement.setRowLimit(parseLimitClause(ctx.rowPaginationClause().limitClause()));
×
3194
      }
3195
      if (ctx.rowPaginationClause().offsetClause() != null) {
×
3196
        showQueriesStatement.setRowOffset(
×
3197
            parseOffsetClause(ctx.rowPaginationClause().offsetClause()));
×
3198
      }
3199
    }
3200

3201
    showQueriesStatement.setZoneId(zoneId);
×
3202
    return showQueriesStatement;
×
3203
  }
3204

3205
  // show region
3206

3207
  @Override
3208
  public Statement visitShowRegions(IoTDBSqlParser.ShowRegionsContext ctx) {
3209
    ShowRegionStatement showRegionStatement = new ShowRegionStatement();
×
3210
    // TODO: Maybe add a show ConfigNode region in the future
3211
    if (ctx.DATA() != null) {
×
3212
      showRegionStatement.setRegionType(TConsensusGroupType.DataRegion);
×
3213
    } else if (ctx.SCHEMA() != null) {
×
3214
      showRegionStatement.setRegionType(TConsensusGroupType.SchemaRegion);
×
3215
    } else {
3216
      showRegionStatement.setRegionType(null);
×
3217
    }
3218

3219
    if (ctx.OF() != null) {
×
3220
      List<PartialPath> storageGroups = null;
×
3221
      if (ctx.prefixPath(0) != null) {
×
3222
        storageGroups = new ArrayList<>();
×
3223
        for (IoTDBSqlParser.PrefixPathContext prefixPathContext : ctx.prefixPath()) {
×
3224
          storageGroups.add(parsePrefixPath(prefixPathContext));
×
3225
        }
×
3226
      }
3227
      showRegionStatement.setStorageGroups(storageGroups);
×
3228
    } else {
×
3229
      showRegionStatement.setStorageGroups(null);
×
3230
    }
3231

3232
    if (ctx.ON() != null) {
×
3233
      List<Integer> nodeIds = new ArrayList<>();
×
3234
      for (TerminalNode nodeid : ctx.INTEGER_LITERAL()) {
×
3235
        nodeIds.add(Integer.parseInt(nodeid.getText()));
×
3236
      }
×
3237
      showRegionStatement.setNodeIds(nodeIds);
×
3238
    } else {
×
3239
      showRegionStatement.setNodeIds(null);
×
3240
    }
3241
    return showRegionStatement;
×
3242
  }
3243

3244
  // show datanodes
3245

3246
  @Override
3247
  public Statement visitShowDataNodes(IoTDBSqlParser.ShowDataNodesContext ctx) {
3248
    return new ShowDataNodesStatement();
×
3249
  }
3250

3251
  // show confignodes
3252

3253
  @Override
3254
  public Statement visitShowConfigNodes(IoTDBSqlParser.ShowConfigNodesContext ctx) {
3255
    return new ShowConfigNodesStatement();
×
3256
  }
3257

3258
  // schema template
3259

3260
  @Override
3261
  public Statement visitCreateSchemaTemplate(IoTDBSqlParser.CreateSchemaTemplateContext ctx) {
3262
    String name = parseIdentifier(ctx.templateName.getText());
×
3263
    List<List<String>> measurementsList = new ArrayList<>();
×
3264
    List<List<TSDataType>> dataTypesList = new ArrayList<>();
×
3265
    List<List<TSEncoding>> encodingsList = new ArrayList<>();
×
3266
    List<List<CompressionType>> compressorsList = new ArrayList<>();
×
3267

3268
    if (ctx.ALIGNED() != null) {
×
3269
      // aligned
3270
      List<String> measurements = new ArrayList<>();
×
3271
      List<TSDataType> dataTypes = new ArrayList<>();
×
3272
      List<TSEncoding> encodings = new ArrayList<>();
×
3273
      List<CompressionType> compressors = new ArrayList<>();
×
3274
      for (IoTDBSqlParser.TemplateMeasurementClauseContext templateClauseContext :
3275
          ctx.templateMeasurementClause()) {
×
3276
        measurements.add(
×
3277
            parseNodeNameWithoutWildCard(templateClauseContext.nodeNameWithoutWildcard()));
×
3278
        parseAttributeClauseForSchemaTemplate(
×
3279
            templateClauseContext.attributeClauses(), dataTypes, encodings, compressors);
×
3280
      }
×
3281
      measurementsList.add(measurements);
×
3282
      dataTypesList.add(dataTypes);
×
3283
      encodingsList.add(encodings);
×
3284
      compressorsList.add(compressors);
×
3285
    } else {
×
3286
      // non-aligned
3287
      for (IoTDBSqlParser.TemplateMeasurementClauseContext templateClauseContext :
3288
          ctx.templateMeasurementClause()) {
×
3289
        List<String> measurements = new ArrayList<>();
×
3290
        List<TSDataType> dataTypes = new ArrayList<>();
×
3291
        List<TSEncoding> encodings = new ArrayList<>();
×
3292
        List<CompressionType> compressors = new ArrayList<>();
×
3293
        measurements.add(
×
3294
            parseNodeNameWithoutWildCard(templateClauseContext.nodeNameWithoutWildcard()));
×
3295
        parseAttributeClauseForSchemaTemplate(
×
3296
            templateClauseContext.attributeClauses(), dataTypes, encodings, compressors);
×
3297
        measurementsList.add(measurements);
×
3298
        dataTypesList.add(dataTypes);
×
3299
        encodingsList.add(encodings);
×
3300
        compressorsList.add(compressors);
×
3301
      }
×
3302
    }
3303

3304
    return new CreateSchemaTemplateStatement(
×
3305
        name,
3306
        measurementsList,
3307
        dataTypesList,
3308
        encodingsList,
3309
        compressorsList,
3310
        ctx.ALIGNED() != null);
×
3311
  }
3312

3313
  @Override
3314
  public Statement visitAlterSchemaTemplate(IoTDBSqlParser.AlterSchemaTemplateContext ctx) {
3315
    String name = parseIdentifier(ctx.templateName.getText());
×
3316
    List<String> measurements = new ArrayList<>();
×
3317
    List<TSDataType> dataTypes = new ArrayList<>();
×
3318
    List<TSEncoding> encodings = new ArrayList<>();
×
3319
    List<CompressionType> compressors = new ArrayList<>();
×
3320

3321
    for (IoTDBSqlParser.TemplateMeasurementClauseContext templateClauseContext :
3322
        ctx.templateMeasurementClause()) {
×
3323
      measurements.add(
×
3324
          parseNodeNameWithoutWildCard(templateClauseContext.nodeNameWithoutWildcard()));
×
3325
      parseAttributeClauseForSchemaTemplate(
×
3326
          templateClauseContext.attributeClauses(), dataTypes, encodings, compressors);
×
3327
    }
×
3328

3329
    return new AlterSchemaTemplateStatement(
×
3330
        name,
3331
        measurements,
3332
        dataTypes,
3333
        encodings,
3334
        compressors,
3335
        TemplateAlterOperationType.EXTEND_TEMPLATE);
3336
  }
3337

3338
  void parseAttributeClauseForSchemaTemplate(
3339
      IoTDBSqlParser.AttributeClausesContext ctx,
3340
      List<TSDataType> dataTypes,
3341
      List<TSEncoding> encodings,
3342
      List<CompressionType> compressors) {
3343
    if (ctx.aliasNodeName() != null) {
×
3344
      throw new SemanticException("Schema template: alias is not supported yet.");
×
3345
    }
3346

3347
    TSDataType dataType = parseDataTypeAttribute(ctx);
×
3348
    dataTypes.add(dataType);
×
3349

3350
    Map<String, String> props = new HashMap<>();
×
3351
    if (ctx.attributePair() != null) {
×
3352
      for (int i = 0; i < ctx.attributePair().size(); i++) {
×
3353
        props.put(
×
3354
            parseAttributeKey(ctx.attributePair(i).attributeKey()).toLowerCase(),
×
3355
            parseAttributeValue(ctx.attributePair(i).attributeValue()));
×
3356
      }
3357
    }
3358

3359
    TSEncoding encoding = IoTDBDescriptor.getInstance().getDefaultEncodingByType(dataType);
×
3360
    if (props.containsKey(IoTDBConstant.COLUMN_TIMESERIES_ENCODING.toLowerCase())) {
×
3361
      String encodingString =
×
3362
          props.get(IoTDBConstant.COLUMN_TIMESERIES_ENCODING.toLowerCase()).toUpperCase();
×
3363
      try {
3364
        encoding = TSEncoding.valueOf(encodingString);
×
3365
        encodings.add(encoding);
×
3366
        props.remove(IoTDBConstant.COLUMN_TIMESERIES_ENCODING.toLowerCase());
×
3367
      } catch (Exception e) {
×
3368
        throw new SemanticException(String.format("Unsupported encoding: %s", encodingString));
×
3369
      }
×
3370
    } else {
×
3371
      encodings.add(encoding);
×
3372
    }
3373

3374
    CompressionType compressor = TSFileDescriptor.getInstance().getConfig().getCompressor();
×
3375
    if (props.containsKey(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSOR.toLowerCase())) {
×
3376
      String compressorString =
×
3377
          props.get(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSOR.toLowerCase()).toUpperCase();
×
3378
      try {
3379
        compressor = CompressionType.valueOf(compressorString);
×
3380
        compressors.add(compressor);
×
3381
        props.remove(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSOR.toLowerCase());
×
3382
      } catch (Exception e) {
×
3383
        throw new SemanticException(String.format("Unsupported compressor: %s", compressorString));
×
3384
      }
×
3385
    } else if (props.containsKey(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSION.toLowerCase())) {
×
3386
      String compressionString =
×
3387
          props.get(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSION.toLowerCase()).toUpperCase();
×
3388
      try {
3389
        compressor = CompressionType.valueOf(compressionString);
×
3390
        compressors.add(compressor);
×
3391
        props.remove(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSION.toLowerCase());
×
3392
      } catch (Exception e) {
×
3393
        throw new SemanticException(
×
3394
            String.format("Unsupported compression: %s", compressionString));
×
3395
      }
×
3396
    } else {
×
3397
      compressors.add(compressor);
×
3398
    }
3399

3400
    if (props.size() > 0) {
×
3401
      throw new SemanticException("Schema template: property is not supported yet.");
×
3402
    }
3403

3404
    if (ctx.tagClause() != null) {
×
3405
      throw new SemanticException("Schema template: tag is not supported yet.");
×
3406
    }
3407

3408
    if (ctx.attributeClause() != null) {
×
3409
      throw new SemanticException("Schema template: attribute is not supported yet.");
×
3410
    }
3411
  }
×
3412

3413
  private TSDataType parseDataTypeAttribute(IoTDBSqlParser.AttributeClausesContext ctx) {
3414
    TSDataType dataType = null;
1✔
3415
    if (ctx.dataType != null) {
1✔
3416
      if (ctx.attributeKey() != null
1✔
3417
          && !parseAttributeKey(ctx.attributeKey())
×
3418
              .equalsIgnoreCase(IoTDBConstant.COLUMN_TIMESERIES_DATATYPE)) {
×
3419
        throw new SemanticException("Expecting datatype");
×
3420
      }
3421
      String dataTypeString = ctx.dataType.getText().toUpperCase();
1✔
3422
      try {
3423
        dataType = TSDataType.valueOf(dataTypeString);
1✔
3424
      } catch (Exception e) {
×
3425
        throw new SemanticException(String.format("Unsupported datatype: %s", dataTypeString));
×
3426
      }
1✔
3427
    }
3428
    return dataType;
1✔
3429
  }
3430

3431
  @Override
3432
  public Statement visitShowSchemaTemplates(IoTDBSqlParser.ShowSchemaTemplatesContext ctx) {
3433
    return new ShowSchemaTemplateStatement();
×
3434
  }
3435

3436
  @Override
3437
  public Statement visitShowNodesInSchemaTemplate(
3438
      IoTDBSqlParser.ShowNodesInSchemaTemplateContext ctx) {
3439
    String templateName = parseIdentifier(ctx.templateName.getText());
×
3440
    return new ShowNodesInSchemaTemplateStatement(templateName);
×
3441
  }
3442

3443
  @Override
3444
  public Statement visitSetSchemaTemplate(IoTDBSqlParser.SetSchemaTemplateContext ctx) {
3445
    String templateName = parseIdentifier(ctx.templateName.getText());
×
3446
    return new SetSchemaTemplateStatement(templateName, parsePrefixPath(ctx.prefixPath()));
×
3447
  }
3448

3449
  @Override
3450
  public Statement visitShowPathsSetSchemaTemplate(
3451
      IoTDBSqlParser.ShowPathsSetSchemaTemplateContext ctx) {
3452
    String templateName = parseIdentifier(ctx.templateName.getText());
×
3453
    return new ShowPathSetTemplateStatement(templateName);
×
3454
  }
3455

3456
  @Override
3457
  public Statement visitCreateTimeseriesUsingSchemaTemplate(
3458
      IoTDBSqlParser.CreateTimeseriesUsingSchemaTemplateContext ctx) {
3459
    ActivateTemplateStatement statement = new ActivateTemplateStatement();
×
3460
    statement.setPath(parsePrefixPath(ctx.prefixPath()));
×
3461
    return statement;
×
3462
  }
3463

3464
  @Override
3465
  public Statement visitShowPathsUsingSchemaTemplate(
3466
      IoTDBSqlParser.ShowPathsUsingSchemaTemplateContext ctx) {
3467
    PartialPath pathPattern;
3468
    if (ctx.prefixPath() == null) {
×
3469
      pathPattern = new PartialPath(SqlConstant.getSingleRootArray());
×
3470
    } else {
3471
      pathPattern = parsePrefixPath(ctx.prefixPath());
×
3472
    }
3473
    return new ShowPathsUsingTemplateStatement(
×
3474
        pathPattern, parseIdentifier(ctx.templateName.getText()));
×
3475
  }
3476

3477
  @Override
3478
  public Statement visitDropTimeseriesOfSchemaTemplate(
3479
      IoTDBSqlParser.DropTimeseriesOfSchemaTemplateContext ctx) {
3480
    DeactivateTemplateStatement statement = new DeactivateTemplateStatement();
×
3481
    if (ctx.templateName != null) {
×
3482
      statement.setTemplateName(parseIdentifier(ctx.templateName.getText()));
×
3483
    }
3484
    List<PartialPath> pathPatternList = new ArrayList<>();
×
3485
    for (IoTDBSqlParser.PrefixPathContext prefixPathContext : ctx.prefixPath()) {
×
3486
      pathPatternList.add(parsePrefixPath(prefixPathContext));
×
3487
    }
×
3488
    statement.setPathPatternList(pathPatternList);
×
3489
    return statement;
×
3490
  }
3491

3492
  @Override
3493
  public Statement visitUnsetSchemaTemplate(IoTDBSqlParser.UnsetSchemaTemplateContext ctx) {
3494
    String templateName = parseIdentifier(ctx.templateName.getText());
×
3495
    PartialPath path = parsePrefixPath(ctx.prefixPath());
×
3496
    return new UnsetSchemaTemplateStatement(templateName, path);
×
3497
  }
3498

3499
  @Override
3500
  public Statement visitDropSchemaTemplate(IoTDBSqlParser.DropSchemaTemplateContext ctx) {
3501
    return new DropSchemaTemplateStatement(parseIdentifier(ctx.templateName.getText()));
×
3502
  }
3503

3504
  public Map<String, String> parseSyncAttributeClauses(
3505
      IoTDBSqlParser.SyncAttributeClausesContext ctx) {
3506

3507
    Map<String, String> attributes = new HashMap<>();
×
3508

3509
    List<IoTDBSqlParser.AttributePairContext> attributePairs = ctx.attributePair();
×
3510
    if (ctx.attributePair(0) != null) {
×
3511
      for (IoTDBSqlParser.AttributePairContext attributePair : attributePairs) {
×
3512
        attributes.put(
×
3513
            parseAttributeKey(attributePair.attributeKey()).toLowerCase(),
×
3514
            parseAttributeValue(attributePair.attributeValue()).toLowerCase());
×
3515
      }
×
3516
    }
3517

3518
    return attributes;
×
3519
  }
3520

3521
  // PIPE
3522

3523
  @Override
3524
  public Statement visitCreatePipe(IoTDBSqlParser.CreatePipeContext ctx) {
3525
    final CreatePipeStatement createPipeStatement =
×
3526
        new CreatePipeStatement(StatementType.CREATE_PIPE);
3527

3528
    if (ctx.pipeName != null) {
×
3529
      createPipeStatement.setPipeName(ctx.pipeName.getText());
×
3530
    } else {
3531
      throw new SemanticException(
×
3532
          "Not support for this sql in CREATEPIPE, please enter pipe name.");
3533
    }
3534
    if (ctx.extractorAttributesClause() != null) {
×
3535
      createPipeStatement.setExtractorAttributes(
×
3536
          parseExtractorAttributesClause(ctx.extractorAttributesClause()));
×
3537
    } else {
3538
      createPipeStatement.setExtractorAttributes(new HashMap<>());
×
3539
    }
3540
    if (ctx.processorAttributesClause() != null) {
×
3541
      createPipeStatement.setProcessorAttributes(
×
3542
          parseProcessorAttributesClause(ctx.processorAttributesClause()));
×
3543
    } else {
3544
      createPipeStatement.setProcessorAttributes(new HashMap<>());
×
3545
    }
3546
    createPipeStatement.setConnectorAttributes(
×
3547
        parseConnectorAttributesClause(ctx.connectorAttributesClause()));
×
3548
    return createPipeStatement;
×
3549
  }
3550

3551
  private Map<String, String> parseExtractorAttributesClause(
3552
      IoTDBSqlParser.ExtractorAttributesClauseContext ctx) {
3553
    final Map<String, String> collectorMap = new HashMap<>();
×
3554
    for (IoTDBSqlParser.ExtractorAttributeClauseContext singleCtx :
3555
        ctx.extractorAttributeClause()) {
×
3556
      collectorMap.put(
×
3557
          parseStringLiteral(singleCtx.extractorKey.getText()),
×
3558
          parseStringLiteral(singleCtx.extractorValue.getText()));
×
3559
    }
×
3560
    return collectorMap;
×
3561
  }
3562

3563
  private Map<String, String> parseProcessorAttributesClause(
3564
      IoTDBSqlParser.ProcessorAttributesClauseContext ctx) {
3565
    final Map<String, String> processorMap = new HashMap<>();
×
3566
    for (IoTDBSqlParser.ProcessorAttributeClauseContext singleCtx :
3567
        ctx.processorAttributeClause()) {
×
3568
      processorMap.put(
×
3569
          parseStringLiteral(singleCtx.processorKey.getText()),
×
3570
          parseStringLiteral(singleCtx.processorValue.getText()));
×
3571
    }
×
3572
    return processorMap;
×
3573
  }
3574

3575
  private Map<String, String> parseConnectorAttributesClause(
3576
      IoTDBSqlParser.ConnectorAttributesClauseContext ctx) {
3577
    final Map<String, String> connectorMap = new HashMap<>();
×
3578
    for (IoTDBSqlParser.ConnectorAttributeClauseContext singleCtx :
3579
        ctx.connectorAttributeClause()) {
×
3580
      connectorMap.put(
×
3581
          parseStringLiteral(singleCtx.connectorKey.getText()),
×
3582
          parseStringLiteral(singleCtx.connectorValue.getText()));
×
3583
    }
×
3584
    return connectorMap;
×
3585
  }
3586

3587
  @Override
3588
  public Statement visitDropPipe(IoTDBSqlParser.DropPipeContext ctx) {
3589
    final DropPipeStatement dropPipeStatement = new DropPipeStatement(StatementType.DROP_PIPE);
×
3590

3591
    if (ctx.pipeName != null) {
×
3592
      dropPipeStatement.setPipeName(ctx.pipeName.getText());
×
3593
    } else {
3594
      throw new SemanticException("Not support for this sql in DROP PIPE, please enter pipename.");
×
3595
    }
3596

3597
    return dropPipeStatement;
×
3598
  }
3599

3600
  @Override
3601
  public Statement visitStartPipe(IoTDBSqlParser.StartPipeContext ctx) {
3602
    final StartPipeStatement startPipeStatement = new StartPipeStatement(StatementType.START_PIPE);
×
3603

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

3610
    return startPipeStatement;
×
3611
  }
3612

3613
  @Override
3614
  public Statement visitStopPipe(IoTDBSqlParser.StopPipeContext ctx) {
3615
    final StopPipeStatement stopPipeStatement = new StopPipeStatement(StatementType.STOP_PIPE);
×
3616

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

3623
    return stopPipeStatement;
×
3624
  }
3625

3626
  @Override
3627
  public Statement visitShowPipes(IoTDBSqlParser.ShowPipesContext ctx) {
3628
    final ShowPipesStatement showPipesStatement = new ShowPipesStatement();
×
3629

3630
    if (ctx.pipeName != null) {
×
3631
      showPipesStatement.setPipeName(parseIdentifier(ctx.pipeName.getText()));
×
3632
    }
3633
    showPipesStatement.setWhereClause(ctx.CONNECTOR() != null);
×
3634

3635
    return showPipesStatement;
×
3636
  }
3637

3638
  @Override
3639
  public Statement visitGetRegionId(IoTDBSqlParser.GetRegionIdContext ctx) {
3640
    TConsensusGroupType type =
3641
        ctx.DATA() == null ? TConsensusGroupType.SchemaRegion : TConsensusGroupType.DataRegion;
×
3642
    GetRegionIdStatement getRegionIdStatement = new GetRegionIdStatement(type);
×
3643
    if (ctx.database != null) {
×
3644
      getRegionIdStatement.setDatabase(ctx.database.getText());
×
3645
    } else {
3646
      getRegionIdStatement.setDevice(ctx.device.getText());
×
3647
    }
3648
    if (ctx.time != null) {
×
3649
      long timestamp = parseTimeValue(ctx.time, DateTimeUtils.currentTime());
×
3650
      if (timestamp < 0) {
×
3651
        throw new SemanticException(NEGATIVE_TIMESTAMP_ERROR_MSG);
×
3652
      } else {
3653
        getRegionIdStatement.setTimeStamp(timestamp);
×
3654
      }
3655
    }
3656
    return getRegionIdStatement;
×
3657
  }
3658

3659
  @Override
3660
  public Statement visitGetSeriesSlotList(IoTDBSqlParser.GetSeriesSlotListContext ctx) {
3661
    TConsensusGroupType type =
3662
        ctx.DATA() == null ? TConsensusGroupType.SchemaRegion : TConsensusGroupType.DataRegion;
×
3663
    return new GetSeriesSlotListStatement(ctx.database.getText(), type);
×
3664
  }
3665

3666
  @Override
3667
  public Statement visitGetTimeSlotList(IoTDBSqlParser.GetTimeSlotListContext ctx) {
3668
    GetTimeSlotListStatement getTimeSlotListStatement = new GetTimeSlotListStatement();
×
3669
    if (ctx.database != null) {
×
3670
      getTimeSlotListStatement.setDatabase(ctx.database.getText());
×
3671
    } else if (ctx.device != null) {
×
3672
      getTimeSlotListStatement.setDevice(ctx.device.getText());
×
3673
    } else if (ctx.regionId != null) {
×
3674
      getTimeSlotListStatement.setRegionId(Integer.parseInt(ctx.regionId.getText()));
×
3675
    }
3676
    if (ctx.startTime != null) {
×
3677
      long timestamp = parseTimeValue(ctx.startTime, DateTimeUtils.currentTime());
×
3678
      if (timestamp < 0) {
×
3679
        throw new SemanticException(NEGATIVE_TIMESTAMP_ERROR_MSG);
×
3680
      } else {
3681
        getTimeSlotListStatement.setStartTime(timestamp);
×
3682
      }
3683
    }
3684
    if (ctx.endTime != null) {
×
3685
      long timestamp = parseTimeValue(ctx.endTime, DateTimeUtils.currentTime());
×
3686
      if (timestamp < 0) {
×
3687
        throw new SemanticException(NEGATIVE_TIMESTAMP_ERROR_MSG);
×
3688
      } else {
3689
        getTimeSlotListStatement.setEndTime(timestamp);
×
3690
      }
3691
    }
3692
    return getTimeSlotListStatement;
×
3693
  }
3694

3695
  @Override
3696
  public Statement visitCountTimeSlotList(IoTDBSqlParser.CountTimeSlotListContext ctx) {
3697
    CountTimeSlotListStatement countTimeSlotListStatement = new CountTimeSlotListStatement();
×
3698
    if (ctx.database != null) {
×
3699
      countTimeSlotListStatement.setDatabase(ctx.database.getText());
×
3700
    } else if (ctx.device != null) {
×
3701
      countTimeSlotListStatement.setDevice(ctx.device.getText());
×
3702
    } else if (ctx.regionId != null) {
×
3703
      countTimeSlotListStatement.setRegionId(Integer.parseInt(ctx.regionId.getText()));
×
3704
    }
3705
    if (ctx.startTime != null) {
×
3706
      countTimeSlotListStatement.setStartTime(Long.parseLong(ctx.startTime.getText()));
×
3707
    }
3708
    if (ctx.endTime != null) {
×
3709
      countTimeSlotListStatement.setEndTime(Long.parseLong(ctx.endTime.getText()));
×
3710
    }
3711
    return countTimeSlotListStatement;
×
3712
  }
3713

3714
  @Override
3715
  public Statement visitMigrateRegion(IoTDBSqlParser.MigrateRegionContext ctx) {
3716
    return new MigrateRegionStatement(
×
3717
        Integer.parseInt(ctx.regionId.getText()),
×
3718
        Integer.parseInt(ctx.fromId.getText()),
×
3719
        Integer.parseInt(ctx.toId.getText()));
×
3720
  }
3721

3722
  // Quota
3723
  @Override
3724
  public Statement visitSetSpaceQuota(IoTDBSqlParser.SetSpaceQuotaContext ctx) {
3725
    if (!IoTDBDescriptor.getInstance().getConfig().isQuotaEnable()) {
×
3726
      throw new SemanticException(LIMIT_CONFIGURATION_ENABLED_ERROR_MSG);
×
3727
    }
3728
    SetSpaceQuotaStatement setSpaceQuotaStatement = new SetSpaceQuotaStatement();
×
3729
    List<IoTDBSqlParser.PrefixPathContext> prefixPathContexts = ctx.prefixPath();
×
3730
    List<String> paths = new ArrayList<>();
×
3731
    for (IoTDBSqlParser.PrefixPathContext prefixPathContext : prefixPathContexts) {
×
3732
      paths.add(parsePrefixPath(prefixPathContext).getFullPath());
×
3733
    }
×
3734
    setSpaceQuotaStatement.setPrefixPathList(paths);
×
3735

3736
    Map<String, String> quotas = new HashMap<>();
×
3737
    for (IoTDBSqlParser.AttributePairContext attributePair : ctx.attributePair()) {
×
3738
      quotas.put(
×
3739
          parseAttributeKey(attributePair.attributeKey()),
×
3740
          parseAttributeValue(attributePair.attributeValue()));
×
3741
    }
×
3742

3743
    quotas
×
3744
        .keySet()
×
3745
        .forEach(
×
3746
            quotaType -> {
3747
              switch (quotaType) {
×
3748
                case IoTDBConstant.COLUMN_DEVICES:
3749
                  break;
×
3750
                case IoTDBConstant.COLUMN_TIMESERIES:
3751
                  break;
×
3752
                case IoTDBConstant.SPACE_QUOTA_DISK:
3753
                  break;
×
3754
                default:
3755
                  throw new SemanticException("Wrong space quota type: " + quotaType);
×
3756
              }
3757
            });
×
3758

3759
    if (quotas.containsKey(IoTDBConstant.COLUMN_DEVICES)) {
×
3760
      if (quotas.get(IoTDBConstant.COLUMN_DEVICES).equals(IoTDBConstant.QUOTA_UNLIMITED)) {
×
3761
        setSpaceQuotaStatement.setDeviceNum(IoTDBConstant.UNLIMITED_VALUE);
×
3762
      } else if (Long.parseLong(quotas.get(IoTDBConstant.COLUMN_DEVICES)) <= 0) {
×
3763
        throw new SemanticException("Please set the number of devices greater than 0");
×
3764
      } else {
3765
        setSpaceQuotaStatement.setDeviceNum(
×
3766
            Long.parseLong(quotas.get(IoTDBConstant.COLUMN_DEVICES)));
×
3767
      }
3768
    }
3769
    if (quotas.containsKey(IoTDBConstant.COLUMN_TIMESERIES)) {
×
3770
      if (quotas.get(IoTDBConstant.COLUMN_TIMESERIES).equals(IoTDBConstant.QUOTA_UNLIMITED)) {
×
3771
        setSpaceQuotaStatement.setTimeSeriesNum(IoTDBConstant.UNLIMITED_VALUE);
×
3772
      } else if (Long.parseLong(quotas.get(IoTDBConstant.COLUMN_TIMESERIES)) <= 0) {
×
3773
        throw new SemanticException("Please set the number of timeseries greater than 0");
×
3774
      } else {
3775
        setSpaceQuotaStatement.setTimeSeriesNum(
×
3776
            Long.parseLong(quotas.get(IoTDBConstant.COLUMN_TIMESERIES)));
×
3777
      }
3778
    }
3779
    if (quotas.containsKey(IoTDBConstant.SPACE_QUOTA_DISK)) {
×
3780
      if (quotas.get(IoTDBConstant.SPACE_QUOTA_DISK).equals(IoTDBConstant.QUOTA_UNLIMITED)) {
×
3781
        setSpaceQuotaStatement.setDiskSize(IoTDBConstant.UNLIMITED_VALUE);
×
3782
      } else {
3783
        setSpaceQuotaStatement.setDiskSize(
×
3784
            parseSpaceQuotaSizeUnit(quotas.get(IoTDBConstant.SPACE_QUOTA_DISK)));
×
3785
      }
3786
    }
3787
    return setSpaceQuotaStatement;
×
3788
  }
3789

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

3837
    if (quotas.containsKey(IoTDBConstant.REQUEST_SIZE_PER_UNIT_TIME)) {
×
3838
      TTimedQuota timedQuota;
3839
      String size = quotas.get(IoTDBConstant.REQUEST_SIZE_PER_UNIT_TIME);
×
3840
      if (size.equals(IoTDBConstant.QUOTA_UNLIMITED)) {
×
3841
        timedQuota = new TTimedQuota(IoTDBConstant.SEC, Long.MAX_VALUE);
×
3842
      } else {
3843
        String[] split = size.toLowerCase().split("/");
×
3844
        timedQuota =
×
3845
            new TTimedQuota(
3846
                parseThrottleQuotaTimeUnit(split[1]), parseThrottleQuotaSizeUnit(split[0]));
×
3847
      }
3848
      if (quotas.get(IoTDBConstant.REQUEST_TYPE) == null) {
×
3849
        throttleLimit.put(ThrottleType.REQUEST_SIZE, timedQuota);
×
3850
      } else {
3851
        switch (quotas.get(IoTDBConstant.REQUEST_TYPE)) {
×
3852
          case IoTDBConstant.REQUEST_TYPE_READ:
3853
            throttleLimit.put(ThrottleType.READ_SIZE, timedQuota);
×
3854
            break;
×
3855
          case IoTDBConstant.REQUEST_TYPE_WRITE:
3856
            throttleLimit.put(ThrottleType.WRITE_SIZE, timedQuota);
×
3857
            break;
×
3858
          default:
3859
            throw new SemanticException(
×
3860
                "Please set the correct request type: " + quotas.get(IoTDBConstant.REQUEST_TYPE));
×
3861
        }
3862
      }
3863
    }
3864

3865
    if (quotas.containsKey(IoTDBConstant.MEMORY_SIZE_PER_READ)) {
×
3866
      String mem = quotas.get(IoTDBConstant.MEMORY_SIZE_PER_READ);
×
3867
      if (mem.equals(IoTDBConstant.QUOTA_UNLIMITED)) {
×
3868
        setThrottleQuotaStatement.setMemLimit(IoTDBConstant.UNLIMITED_VALUE);
×
3869
      } else {
3870
        setThrottleQuotaStatement.setMemLimit(parseThrottleQuotaSizeUnit(mem));
×
3871
      }
3872
    }
3873

3874
    if (quotas.containsKey(IoTDBConstant.CPU_NUMBER_PER_READ)) {
×
3875
      String cpuLimit = quotas.get(IoTDBConstant.CPU_NUMBER_PER_READ);
×
3876
      if (cpuLimit.contains(IoTDBConstant.QUOTA_UNLIMITED)) {
×
3877
        setThrottleQuotaStatement.setCpuLimit(IoTDBConstant.UNLIMITED_VALUE);
×
3878
      } else {
3879
        int cpuNum = Integer.parseInt(cpuLimit);
×
3880
        if (cpuNum <= 0) {
×
3881
          throw new SemanticException("Please set the number of cpu greater than 0");
×
3882
        }
3883
        setThrottleQuotaStatement.setCpuLimit(cpuNum);
×
3884
      }
3885
    }
3886
    setThrottleQuotaStatement.setThrottleLimit(throttleLimit);
×
3887
    return setThrottleQuotaStatement;
×
3888
  }
3889

3890
  @Override
3891
  public Statement visitShowThrottleQuota(IoTDBSqlParser.ShowThrottleQuotaContext ctx) {
3892
    if (!IoTDBDescriptor.getInstance().getConfig().isQuotaEnable()) {
×
3893
      throw new SemanticException(LIMIT_CONFIGURATION_ENABLED_ERROR_MSG);
×
3894
    }
3895
    ShowThrottleQuotaStatement showThrottleQuotaStatement = new ShowThrottleQuotaStatement();
×
3896
    if (ctx.userName != null) {
×
3897
      showThrottleQuotaStatement.setUserName(parseIdentifier(ctx.userName.getText()));
×
3898
    }
3899
    return showThrottleQuotaStatement;
×
3900
  }
3901

3902
  private long parseThrottleQuotaTimeUnit(String timeUnit) {
3903
    switch (timeUnit.toLowerCase()) {
×
3904
      case IoTDBConstant.SEC_UNIT:
3905
        return IoTDBConstant.SEC;
×
3906
      case IoTDBConstant.MIN_UNIT:
3907
        return IoTDBConstant.MIN;
×
3908
      case IoTDBConstant.HOUR_UNIT:
3909
        return IoTDBConstant.HOUR;
×
3910
      case IoTDBConstant.DAY_UNIT:
3911
        return IoTDBConstant.DAY;
×
3912
      default:
3913
        throw new SemanticException(
×
3914
            "When setting the request, the unit is incorrect. Please use 'sec', 'min', 'hour', 'day' as the unit");
3915
    }
3916
  }
3917

3918
  private long parseThrottleQuotaSizeUnit(String data) {
3919
    String unit = data.substring(data.length() - 1);
×
3920
    long size = Long.parseLong(data.substring(0, data.length() - 1));
×
3921
    if (size <= 0) {
×
3922
      throw new SemanticException("Please set the size greater than 0");
×
3923
    }
3924
    switch (unit.toUpperCase()) {
×
3925
      case IoTDBConstant.B_UNIT:
3926
        return size;
×
3927
      case IoTDBConstant.KB_UNIT:
3928
        return size * IoTDBConstant.KB;
×
3929
      case IoTDBConstant.MB_UNIT:
3930
        return size * IoTDBConstant.MB;
×
3931
      case IoTDBConstant.GB_UNIT:
3932
        return size * IoTDBConstant.GB;
×
3933
      case IoTDBConstant.TB_UNIT:
3934
        return size * IoTDBConstant.TB;
×
3935
      case IoTDBConstant.PB_UNIT:
3936
        return size * IoTDBConstant.PB;
×
3937
      default:
3938
        throw new SemanticException(
×
3939
            "When setting the size/time, the unit is incorrect. Please use 'B', 'K', 'M', 'G', 'P', 'T' as the unit");
3940
    }
3941
  }
3942

3943
  private long parseSpaceQuotaSizeUnit(String data) {
3944
    String unit = data.substring(data.length() - 1);
×
3945
    long disk = Long.parseLong(data.substring(0, data.length() - 1));
×
3946
    if (disk <= 0) {
×
3947
      throw new SemanticException("Please set the disk size greater than 0");
×
3948
    }
3949
    switch (unit.toUpperCase()) {
×
3950
      case IoTDBConstant.MB_UNIT:
3951
        return disk;
×
3952
      case IoTDBConstant.GB_UNIT:
3953
        return disk * IoTDBConstant.KB;
×
3954
      case IoTDBConstant.TB_UNIT:
3955
        return disk * IoTDBConstant.MB;
×
3956
      case IoTDBConstant.PB_UNIT:
3957
        return disk * IoTDBConstant.GB;
×
3958
      default:
3959
        throw new SemanticException(
×
3960
            "When setting the disk size, the unit is incorrect. Please use 'M', 'G', 'P', 'T' as the unit");
3961
    }
3962
  }
3963

3964
  @Override
3965
  public Statement visitShowSpaceQuota(IoTDBSqlParser.ShowSpaceQuotaContext ctx) {
3966
    if (!IoTDBDescriptor.getInstance().getConfig().isQuotaEnable()) {
×
3967
      throw new SemanticException(LIMIT_CONFIGURATION_ENABLED_ERROR_MSG);
×
3968
    }
3969
    ShowSpaceQuotaStatement showSpaceQuotaStatement = new ShowSpaceQuotaStatement();
×
3970
    if (ctx.prefixPath() != null) {
×
3971
      List<PartialPath> databases = new ArrayList<>();
×
3972
      for (IoTDBSqlParser.PrefixPathContext prefixPathContext : ctx.prefixPath()) {
×
3973
        databases.add(parsePrefixPath(prefixPathContext));
×
3974
      }
×
3975
      showSpaceQuotaStatement.setDatabases(databases);
×
3976
    } else {
×
3977
      showSpaceQuotaStatement.setDatabases(null);
×
3978
    }
3979
    return showSpaceQuotaStatement;
×
3980
  }
3981
}
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