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

apache / iotdb / #10019

07 Sep 2023 04:50AM UTC coverage: 47.489% (-0.2%) from 47.655%
#10019

push

travis_ci

web-flow
Pipe: Fix ConcurrentModificationException caused by concurrently iterating through CachedSchemaPatternMatcher.extractors when an PipeHeartbeatEvent is being assigned (#11074)

* try to fix ConcurrentModificationException when assigning PipeHeartbeatEvent

* Update CachedSchemaPatternMatcher.java

---------

Co-authored-by: 马子坤 <55695098+DanielWang2035@users.noreply.github.com>

1 of 1 new or added line in 1 file covered. (100.0%)

80551 of 169622 relevant lines covered (47.49%)

0.47 hits per line

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

27.61
/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.ShowTrialsStatement;
163
import org.apache.iotdb.db.queryengine.plan.statement.metadata.pipe.CreatePipeStatement;
164
import org.apache.iotdb.db.queryengine.plan.statement.metadata.pipe.DropPipeStatement;
165
import org.apache.iotdb.db.queryengine.plan.statement.metadata.pipe.ShowPipesStatement;
166
import org.apache.iotdb.db.queryengine.plan.statement.metadata.pipe.StartPipeStatement;
167
import org.apache.iotdb.db.queryengine.plan.statement.metadata.pipe.StopPipeStatement;
168
import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.ActivateTemplateStatement;
169
import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.AlterSchemaTemplateStatement;
170
import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.CreateSchemaTemplateStatement;
171
import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.DeactivateTemplateStatement;
172
import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.DropSchemaTemplateStatement;
173
import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.SetSchemaTemplateStatement;
174
import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.ShowNodesInSchemaTemplateStatement;
175
import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.ShowPathSetTemplateStatement;
176
import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.ShowPathsUsingTemplateStatement;
177
import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.ShowSchemaTemplateStatement;
178
import org.apache.iotdb.db.queryengine.plan.statement.metadata.template.UnsetSchemaTemplateStatement;
179
import org.apache.iotdb.db.queryengine.plan.statement.metadata.view.AlterLogicalViewStatement;
180
import org.apache.iotdb.db.queryengine.plan.statement.metadata.view.CreateLogicalViewStatement;
181
import org.apache.iotdb.db.queryengine.plan.statement.metadata.view.DeleteLogicalViewStatement;
182
import org.apache.iotdb.db.queryengine.plan.statement.metadata.view.ShowLogicalViewStatement;
183
import org.apache.iotdb.db.queryengine.plan.statement.sys.AuthorStatement;
184
import org.apache.iotdb.db.queryengine.plan.statement.sys.ClearCacheStatement;
185
import org.apache.iotdb.db.queryengine.plan.statement.sys.ExplainStatement;
186
import org.apache.iotdb.db.queryengine.plan.statement.sys.FlushStatement;
187
import org.apache.iotdb.db.queryengine.plan.statement.sys.KillQueryStatement;
188
import org.apache.iotdb.db.queryengine.plan.statement.sys.LoadConfigurationStatement;
189
import org.apache.iotdb.db.queryengine.plan.statement.sys.MergeStatement;
190
import org.apache.iotdb.db.queryengine.plan.statement.sys.SetSystemStatusStatement;
191
import org.apache.iotdb.db.queryengine.plan.statement.sys.ShowQueriesStatement;
192
import org.apache.iotdb.db.queryengine.plan.statement.sys.ShowVersionStatement;
193
import org.apache.iotdb.db.queryengine.plan.statement.sys.quota.SetSpaceQuotaStatement;
194
import org.apache.iotdb.db.queryengine.plan.statement.sys.quota.SetThrottleQuotaStatement;
195
import org.apache.iotdb.db.queryengine.plan.statement.sys.quota.ShowSpaceQuotaStatement;
196
import org.apache.iotdb.db.queryengine.plan.statement.sys.quota.ShowThrottleQuotaStatement;
197
import org.apache.iotdb.db.schemaengine.template.TemplateAlterOperationType;
198
import org.apache.iotdb.db.utils.DateTimeUtils;
199
import org.apache.iotdb.db.utils.constant.SqlConstant;
200
import org.apache.iotdb.trigger.api.enums.TriggerEvent;
201
import org.apache.iotdb.trigger.api.enums.TriggerType;
202
import org.apache.iotdb.tsfile.common.conf.TSFileDescriptor;
203
import org.apache.iotdb.tsfile.common.constant.TsFileConstant;
204
import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
205
import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
206
import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
207
import org.apache.iotdb.tsfile.read.common.TimeRange;
208

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

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

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

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

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

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

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

258
  private static final String 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
  private boolean lastLevelUseWildcard = false;
1✔
267

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

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

282
  /** Data Definition Language (DDL). */
283

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

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

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

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

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

340
    createTimeSeriesStatement.setProps(props);
1✔
341
    checkPropsInCreateTimeSeries(createTimeSeriesStatement);
1✔
342

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

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

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

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

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

424
    TSDataType dataType = parseDataTypeAttribute(ctx);
1✔
425
    createAlignedTimeSeriesStatement.addDataType(dataType);
1✔
426

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

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

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

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

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

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

494
  // Tag & Property & Attribute
495

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

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

519
  // Alter Timeseries ========================================================================
520

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

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

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

577
  // Drop Timeseries ======================================================================
578

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

590
  // Show Timeseries ========================================================================
591

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

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

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

659
  // SHOW DATABASES
660

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

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

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

676
    return showDatabaseStatement;
×
677
  }
678

679
  // Show Devices ========================================================================
680

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

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

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

715
  // Count Devices ========================================================================
716

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

930
    statement.setCqId(parseIdentifier(ctx.cqId.getText()));
×
931

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

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

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

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

955
    return statement;
×
956
  }
957

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

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

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

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

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

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

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

1024
    return createLogicalViewStatement;
×
1025
  }
1026

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

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

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

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

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

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

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

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

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

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

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

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

1234
    Map<String, String> hyperParameters = new HashMap<>();
×
1235
    for (IoTDBSqlParser.HparamPairContext attribute : ctx.hparamPair()) {
×
1236
      hyperParameters.put(
×
1237
          parseAttributeKey(attribute.hparamKey).toLowerCase(),
×
1238
          parseHparamValue(attribute.hparamValue()));
×
1239
    }
×
1240
    createModelStatement.setHyperparameters(hyperParameters);
×
1241

1242
    createModelStatement.setDatasetStatement(
×
1243
        (QueryStatement) visitSelectStatement(ctx.selectStatement()));
×
1244
    return createModelStatement;
×
1245
  }
1246

1247
  private String parseHparamValue(IoTDBSqlParser.HparamValueContext ctx) {
1248
    if (ctx.attributeValue() != null) {
×
1249
      return parseAttributeValue(ctx.attributeValue());
×
1250
    } else if (ctx.hparamRange() != null) {
×
1251
      return parseAttributeValue(ctx.hparamRange().hparamRangeStart)
×
1252
          + ","
1253
          + parseAttributeValue(ctx.hparamRange().hparamRangeEnd);
×
1254
    } else if (ctx.hparamCandidates() != null) {
×
1255
      List<String> candidates = new ArrayList<>();
×
1256
      for (IoTDBSqlParser.AttributeValueContext candidate :
1257
          ctx.hparamCandidates().attributeValue()) {
×
1258
        candidates.add(parseAttributeValue(candidate));
×
1259
      }
×
1260
      return Arrays.toString(candidates.toArray());
×
1261
    } else {
1262
      throw new IllegalArgumentException();
×
1263
    }
1264
  }
1265

1266
  // Drop Model =====================================================================
1267
  @Override
1268
  public Statement visitDropModel(IoTDBSqlParser.DropModelContext ctx) {
1269
    return new DropModelStatement(parseIdentifier(ctx.modelId.getText()));
×
1270
  }
1271

1272
  // Show Models =====================================================================
1273
  @Override
1274
  public Statement visitShowModels(IoTDBSqlParser.ShowModelsContext ctx) {
1275
    return new ShowModelsStatement();
×
1276
  }
1277

1278
  // Show Trails =====================================================================
1279
  @Override
1280
  public Statement visitShowTrials(IoTDBSqlParser.ShowTrialsContext ctx) {
1281
    return new ShowTrialsStatement(parseIdentifier(ctx.modelId.getText()));
×
1282
  }
1283

1284
  /** Data Manipulation Language (DML). */
1285

1286
  // Select Statement ========================================================================
1287
  @Override
1288
  public Statement visitSelectStatement(IoTDBSqlParser.SelectStatementContext ctx) {
1289
    QueryStatement queryStatement = new QueryStatement();
1✔
1290

1291
    // parse SELECT & FROM
1292
    queryStatement.setSelectComponent(parseSelectClause(ctx.selectClause(), queryStatement));
1✔
1293
    queryStatement.setFromComponent(parseFromClause(ctx.fromClause()));
1✔
1294

1295
    // parse INTO
1296
    if (ctx.intoClause() != null) {
1✔
1297
      queryStatement.setIntoComponent(parseIntoClause(ctx.intoClause()));
1✔
1298
    }
1299

1300
    // parse WHERE
1301
    if (ctx.whereClause() != null) {
1✔
1302
      queryStatement.setWhereCondition(parseWhereClause(ctx.whereClause()));
1✔
1303
    }
1304

1305
    // parse GROUP BY
1306
    if (ctx.groupByClause() != null) {
1✔
1307
      Set<String> groupByKeys = new HashSet<>();
1✔
1308
      List<IoTDBSqlParser.GroupByAttributeClauseContext> groupByAttributes =
1✔
1309
          ctx.groupByClause().groupByAttributeClause();
1✔
1310
      for (IoTDBSqlParser.GroupByAttributeClauseContext groupByAttribute : groupByAttributes) {
1✔
1311
        if (groupByAttribute.TIME() != null || groupByAttribute.interval != null) {
1✔
1312
          if (groupByKeys.contains("COMMON")) {
1✔
1313
            throw new SemanticException(GROUP_BY_COMMON_ONLY_ONE_MSG);
×
1314
          }
1315

1316
          groupByKeys.add("COMMON");
1✔
1317
          queryStatement.setGroupByTimeComponent(parseGroupByTimeClause(groupByAttribute));
1✔
1318
        } else if (groupByAttribute.LEVEL() != null) {
1✔
1319
          if (groupByKeys.contains("LEVEL")) {
1✔
1320
            throw new SemanticException("duplicated group by key: LEVEL");
×
1321
          }
1322

1323
          groupByKeys.add("LEVEL");
1✔
1324
          queryStatement.setGroupByLevelComponent(parseGroupByLevelClause(groupByAttribute));
1✔
1325
        } else if (groupByAttribute.TAGS() != null) {
1✔
1326
          if (groupByKeys.contains("TAGS")) {
1✔
1327
            throw new SemanticException("duplicated group by key: TAGS");
×
1328
          }
1329

1330
          groupByKeys.add("TAGS");
1✔
1331
          queryStatement.setGroupByTagComponent(parseGroupByTagClause(groupByAttribute));
1✔
1332
        } else if (groupByAttribute.VARIATION() != null) {
1✔
1333
          if (groupByKeys.contains("COMMON")) {
1✔
1334
            throw new SemanticException(GROUP_BY_COMMON_ONLY_ONE_MSG);
×
1335
          }
1336

1337
          groupByKeys.add("COMMON");
1✔
1338
          queryStatement.setGroupByComponent(
1✔
1339
              parseGroupByClause(groupByAttribute, WindowType.VARIATION_WINDOW));
1✔
1340
        } else if (groupByAttribute.CONDITION() != null) {
×
1341
          if (groupByKeys.contains("COMMON")) {
×
1342
            throw new SemanticException(GROUP_BY_COMMON_ONLY_ONE_MSG);
×
1343
          }
1344

1345
          groupByKeys.add("COMMON");
×
1346
          queryStatement.setGroupByComponent(
×
1347
              parseGroupByClause(groupByAttribute, WindowType.CONDITION_WINDOW));
×
1348
        } else if (groupByAttribute.SESSION() != null) {
×
1349
          if (groupByKeys.contains("COMMON")) {
×
1350
            throw new SemanticException(GROUP_BY_COMMON_ONLY_ONE_MSG);
×
1351
          }
1352

1353
          groupByKeys.add("COMMON");
×
1354
          queryStatement.setGroupByComponent(
×
1355
              parseGroupByClause(groupByAttribute, WindowType.SESSION_WINDOW));
×
1356
        } else if (groupByAttribute.COUNT() != null) {
×
1357
          if (groupByKeys.contains("COMMON")) {
×
1358
            throw new SemanticException(GROUP_BY_COMMON_ONLY_ONE_MSG);
×
1359
          }
1360

1361
          groupByKeys.add("COMMON");
×
1362
          queryStatement.setGroupByComponent(
×
1363
              parseGroupByClause(groupByAttribute, WindowType.COUNT_WINDOW));
×
1364

1365
        } else {
1366
          throw new SemanticException("Unknown GROUP BY type.");
×
1367
        }
1368
      }
1✔
1369
    }
1370

1371
    // parse HAVING
1372
    if (ctx.havingClause() != null) {
1✔
1373
      queryStatement.setHavingCondition(parseHavingClause(ctx.havingClause()));
1✔
1374
    }
1375

1376
    // parse ORDER BY
1377
    if (ctx.orderByClause() != null) {
1✔
1378
      queryStatement.setOrderByComponent(
1✔
1379
          parseOrderByClause(
1✔
1380
              ctx.orderByClause(),
1✔
1381
              ImmutableSet.of(OrderByKey.TIME, OrderByKey.DEVICE, OrderByKey.TIMESERIES)));
1✔
1382
    }
1383

1384
    // parse FILL
1385
    if (ctx.fillClause() != null) {
1✔
1386
      queryStatement.setFillComponent(parseFillClause(ctx.fillClause()));
1✔
1387
    }
1388

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

1394
    if (ctx.paginationClause() != null) {
1✔
1395
      // parse SLIMIT & SOFFSET
1396
      if (ctx.paginationClause().seriesPaginationClause() != null) {
1✔
1397
        if (ctx.paginationClause().seriesPaginationClause().slimitClause() != null) {
1✔
1398
          queryStatement.setSeriesLimit(
1✔
1399
              parseSLimitClause(ctx.paginationClause().seriesPaginationClause().slimitClause()));
1✔
1400
        }
1401
        if (ctx.paginationClause().seriesPaginationClause().soffsetClause() != null) {
1✔
1402
          queryStatement.setSeriesOffset(
1✔
1403
              parseSOffsetClause(ctx.paginationClause().seriesPaginationClause().soffsetClause()));
1✔
1404
        }
1405
      }
1406

1407
      // parse LIMIT & OFFSET
1408
      if (ctx.paginationClause().rowPaginationClause() != null) {
1✔
1409
        if (ctx.paginationClause().rowPaginationClause().limitClause() != null) {
1✔
1410
          queryStatement.setRowLimit(
1✔
1411
              parseLimitClause(ctx.paginationClause().rowPaginationClause().limitClause()));
1✔
1412
        }
1413
        if (ctx.paginationClause().rowPaginationClause().offsetClause() != null) {
1✔
1414
          queryStatement.setRowOffset(
1✔
1415
              parseOffsetClause(ctx.paginationClause().rowPaginationClause().offsetClause()));
1✔
1416
        }
1417
        if (canPushDownLimitOffsetToGroupByTime(queryStatement)) {
1✔
1418
          pushDownLimitOffsetToTimeParameter(queryStatement);
1✔
1419
        }
1420
      }
1421
    }
1422

1423
    queryStatement.setUseWildcard(useWildcard);
1✔
1424
    queryStatement.setLastLevelUseWildcard(lastLevelUseWildcard);
1✔
1425
    return queryStatement;
1✔
1426
  }
1427

1428
  // ---- Select Clause
1429
  private SelectComponent parseSelectClause(
1430
      IoTDBSqlParser.SelectClauseContext ctx, QueryStatement queryStatement) {
1431
    SelectComponent selectComponent = new SelectComponent(zoneId);
1✔
1432

1433
    // parse LAST
1434
    if (ctx.LAST() != null) {
1✔
1435
      selectComponent.setHasLast(true);
1✔
1436
    }
1437

1438
    // parse resultColumn
1439
    Map<String, Expression> aliasToColumnMap = new HashMap<>();
1✔
1440
    for (IoTDBSqlParser.ResultColumnContext resultColumnContext : ctx.resultColumn()) {
1✔
1441
      ResultColumn resultColumn = parseResultColumn(resultColumnContext);
1✔
1442
      // __endTime shouldn't be included in resultColumns
1443
      if (resultColumn.getExpression().getExpressionString().equals(ColumnHeaderConstant.ENDTIME)) {
1✔
1444
        queryStatement.setOutputEndTime(true);
×
1445
        continue;
×
1446
      }
1447
      if (resultColumn.hasAlias()) {
1✔
1448
        String alias = resultColumn.getAlias();
1✔
1449
        if (aliasToColumnMap.containsKey(alias)) {
1✔
1450
          throw new SemanticException("duplicate alias in select clause");
×
1451
        }
1452
        aliasToColumnMap.put(alias, resultColumn.getExpression());
1✔
1453
      }
1454
      selectComponent.addResultColumn(resultColumn);
1✔
1455
    }
1✔
1456
    selectComponent.setAliasToColumnMap(aliasToColumnMap);
1✔
1457

1458
    return selectComponent;
1✔
1459
  }
1460

1461
  private ResultColumn parseResultColumn(IoTDBSqlParser.ResultColumnContext resultColumnContext) {
1462
    Expression expression = parseExpression(resultColumnContext.expression(), false);
1✔
1463
    if (expression.isConstantOperand()) {
1✔
1464
      throw new SemanticException("Constant operand is not allowed: " + expression);
×
1465
    }
1466
    String alias = null;
1✔
1467
    if (resultColumnContext.AS() != null) {
1✔
1468
      alias = parseAlias(resultColumnContext.alias());
1✔
1469
    }
1470
    ResultColumn.ColumnType columnType =
1✔
1471
        ExpressionAnalyzer.identifyOutputColumnType(expression, true);
1✔
1472
    return new ResultColumn(expression, alias, columnType);
1✔
1473
  }
1474

1475
  // ---- From Clause
1476
  private FromComponent parseFromClause(IoTDBSqlParser.FromClauseContext ctx) {
1477
    FromComponent fromComponent = new FromComponent();
1✔
1478
    List<IoTDBSqlParser.PrefixPathContext> prefixFromPaths = ctx.prefixPath();
1✔
1479
    for (IoTDBSqlParser.PrefixPathContext prefixFromPath : prefixFromPaths) {
1✔
1480
      PartialPath path = parsePrefixPath(prefixFromPath);
1✔
1481
      fromComponent.addPrefixPath(path);
1✔
1482
    }
1✔
1483
    return fromComponent;
1✔
1484
  }
1485

1486
  // ---- Into Clause
1487
  private IntoComponent parseIntoClause(IoTDBSqlParser.IntoClauseContext ctx) {
1488
    List<IntoItem> intoItems = new ArrayList<>();
1✔
1489
    for (IoTDBSqlParser.IntoItemContext intoItemContext : ctx.intoItem()) {
1✔
1490
      intoItems.add(parseIntoItem(intoItemContext));
1✔
1491
    }
1✔
1492
    return new IntoComponent(intoItems);
1✔
1493
  }
1494

1495
  private IntoItem parseIntoItem(IoTDBSqlParser.IntoItemContext intoItemContext) {
1496
    boolean isAligned = intoItemContext.ALIGNED() != null;
1✔
1497
    PartialPath intoDevice = parseIntoPath(intoItemContext.intoPath());
1✔
1498
    List<String> intoMeasurements =
1✔
1499
        intoItemContext.nodeNameInIntoPath().stream()
1✔
1500
            .map(this::parseNodeNameInIntoPath)
1✔
1501
            .collect(Collectors.toList());
1✔
1502
    return new IntoItem(intoDevice, intoMeasurements, isAligned);
1✔
1503
  }
1504

1505
  private PartialPath parseIntoPath(IoTDBSqlParser.IntoPathContext intoPathContext) {
1506
    if (intoPathContext instanceof IoTDBSqlParser.FullPathInIntoPathContext) {
1✔
1507
      return parseFullPathInIntoPath((IoTDBSqlParser.FullPathInIntoPathContext) intoPathContext);
1✔
1508
    } else {
1509
      List<IoTDBSqlParser.NodeNameInIntoPathContext> nodeNames =
1✔
1510
          ((IoTDBSqlParser.SuffixPathInIntoPathContext) intoPathContext).nodeNameInIntoPath();
1✔
1511
      String[] path = new String[nodeNames.size()];
1✔
1512
      for (int i = 0; i < nodeNames.size(); i++) {
1✔
1513
        path[i] = parseNodeNameInIntoPath(nodeNames.get(i));
1✔
1514
      }
1515
      return new PartialPath(path);
1✔
1516
    }
1517
  }
1518

1519
  // ---- Where Clause
1520
  private WhereCondition parseWhereClause(IoTDBSqlParser.WhereClauseContext ctx) {
1521
    Expression predicate = parseExpression(ctx.expression(), true);
1✔
1522
    return new WhereCondition(predicate);
1✔
1523
  }
1524

1525
  // ---- Group By Clause
1526
  private GroupByTimeComponent parseGroupByTimeClause(
1527
      IoTDBSqlParser.GroupByAttributeClauseContext ctx) {
1528
    GroupByTimeComponent groupByTimeComponent = new GroupByTimeComponent();
1✔
1529

1530
    // Parse time range
1531
    if (ctx.timeRange() != null) {
1✔
1532
      parseTimeRangeForGroupByTime(ctx.timeRange(), groupByTimeComponent);
1✔
1533
      groupByTimeComponent.setLeftCRightO(ctx.timeRange().LS_BRACKET() != null);
1✔
1534
    }
1535

1536
    // Parse time interval
1537
    groupByTimeComponent.setInterval(
1✔
1538
        parseTimeIntervalOrSlidingStep(ctx.interval.getText(), true, groupByTimeComponent));
1✔
1539
    if (groupByTimeComponent.getInterval() <= 0) {
1✔
1540
      throw new SemanticException(
×
1541
          "The second parameter time interval should be a positive integer.");
1542
    }
1543

1544
    // parse sliding step
1545
    if (ctx.step != null) {
1✔
1546
      groupByTimeComponent.setSlidingStep(
1✔
1547
          parseTimeIntervalOrSlidingStep(ctx.step.getText(), false, groupByTimeComponent));
1✔
1548
    } else {
1549
      groupByTimeComponent.setSlidingStep(groupByTimeComponent.getInterval());
1✔
1550
      groupByTimeComponent.setSlidingStepByMonth(groupByTimeComponent.isIntervalByMonth());
1✔
1551
    }
1552

1553
    return groupByTimeComponent;
1✔
1554
  }
1555

1556
  /**
1557
   * Parse time range (startTime and endTime) in group by time.
1558
   *
1559
   * @throws SemanticException if startTime is larger or equals to endTime in timeRange
1560
   */
1561
  private void parseTimeRangeForGroupByTime(
1562
      IoTDBSqlParser.TimeRangeContext timeRange, GroupByTimeComponent groupByClauseComponent) {
1563
    long currentTime = DateTimeUtils.currentTime();
1✔
1564
    long startTime = parseTimeValue(timeRange.timeValue(0), currentTime);
1✔
1565
    long endTime = parseTimeValue(timeRange.timeValue(1), currentTime);
1✔
1566
    groupByClauseComponent.setStartTime(startTime);
1✔
1567
    groupByClauseComponent.setEndTime(endTime);
1✔
1568
    if (startTime >= endTime) {
1✔
1569
      throw new SemanticException("Start time should be smaller than endTime in GroupBy");
×
1570
    }
1571
  }
1✔
1572

1573
  /**
1574
   * parse time interval or sliding step in group by query.
1575
   *
1576
   * @param duration represent duration string like: 12d8m9ns, 1y1d, etc.
1577
   * @return time in milliseconds, microseconds, or nanoseconds depending on the profile
1578
   */
1579
  private long parseTimeIntervalOrSlidingStep(
1580
      String duration, boolean isParsingTimeInterval, GroupByTimeComponent groupByTimeComponent) {
1581
    if (duration.toLowerCase().contains("mo")) {
1✔
1582
      if (isParsingTimeInterval) {
×
1583
        groupByTimeComponent.setIntervalByMonth(true);
×
1584
      } else {
1585
        groupByTimeComponent.setSlidingStepByMonth(true);
×
1586
      }
1587
    }
1588
    return DateTimeUtils.convertDurationStrToLong(duration);
1✔
1589
  }
1590

1591
  private GroupByComponent parseGroupByClause(
1592
      GroupByAttributeClauseContext ctx, WindowType windowType) {
1593

1594
    boolean ignoringNull = true;
1✔
1595
    if (ctx.attributePair() != null
1✔
1596
        && !ctx.attributePair().isEmpty()
×
1597
        && ctx.attributePair().key.getText().equalsIgnoreCase(IGNORENULL)) {
×
1598
      ignoringNull = Boolean.parseBoolean(ctx.attributePair().value.getText());
×
1599
    }
1600
    List<ExpressionContext> expressions = ctx.expression();
1✔
1601
    if (windowType == WindowType.VARIATION_WINDOW) {
1✔
1602
      ExpressionContext expressionContext = expressions.get(0);
1✔
1603
      GroupByVariationComponent groupByVariationComponent = new GroupByVariationComponent();
1✔
1604
      groupByVariationComponent.setControlColumnExpression(
1✔
1605
          parseExpression(expressionContext, true));
1✔
1606
      groupByVariationComponent.setDelta(
1✔
1607
          ctx.delta == null ? 0 : Double.parseDouble(ctx.delta.getText()));
1✔
1608
      groupByVariationComponent.setIgnoringNull(ignoringNull);
1✔
1609
      return groupByVariationComponent;
1✔
1610
    } else if (windowType == WindowType.CONDITION_WINDOW) {
×
1611
      ExpressionContext conditionExpressionContext = expressions.get(0);
×
1612
      GroupByConditionComponent groupByConditionComponent = new GroupByConditionComponent();
×
1613
      groupByConditionComponent.setControlColumnExpression(
×
1614
          parseExpression(conditionExpressionContext, true));
×
1615
      if (expressions.size() == 2) {
×
1616
        groupByConditionComponent.setKeepExpression(parseExpression(expressions.get(1), true));
×
1617
      }
1618
      groupByConditionComponent.setIgnoringNull(ignoringNull);
×
1619
      return groupByConditionComponent;
×
1620
    } else if (windowType == WindowType.SESSION_WINDOW) {
×
1621
      long interval = DateTimeUtils.convertDurationStrToLong(ctx.timeInterval.getText());
×
1622
      return new GroupBySessionComponent(interval);
×
1623
    } else if (windowType == WindowType.COUNT_WINDOW) {
×
1624
      ExpressionContext countExpressionContext = expressions.get(0);
×
1625
      long countNumber = Long.parseLong(ctx.countNumber.getText());
×
1626
      GroupByCountComponent groupByCountComponent = new GroupByCountComponent(countNumber);
×
1627
      groupByCountComponent.setControlColumnExpression(
×
1628
          parseExpression(countExpressionContext, true));
×
1629
      groupByCountComponent.setIgnoringNull(ignoringNull);
×
1630
      return groupByCountComponent;
×
1631
    } else {
1632
      throw new SemanticException("Unsupported window type");
×
1633
    }
1634
  }
1635

1636
  private GroupByLevelComponent parseGroupByLevelClause(
1637
      IoTDBSqlParser.GroupByAttributeClauseContext ctx) {
1638
    GroupByLevelComponent groupByLevelComponent = new GroupByLevelComponent();
1✔
1639
    int[] levels = new int[ctx.INTEGER_LITERAL().size()];
1✔
1640
    for (int i = 0; i < ctx.INTEGER_LITERAL().size(); i++) {
1✔
1641
      levels[i] = Integer.parseInt(ctx.INTEGER_LITERAL().get(i).getText());
1✔
1642
    }
1643
    groupByLevelComponent.setLevels(levels);
1✔
1644
    return groupByLevelComponent;
1✔
1645
  }
1646

1647
  private GroupByTagComponent parseGroupByTagClause(
1648
      IoTDBSqlParser.GroupByAttributeClauseContext ctx) {
1649
    Set<String> tagKeys = new LinkedHashSet<>();
1✔
1650
    for (IdentifierContext identifierContext : ctx.identifier()) {
1✔
1651
      String key = parseIdentifier(identifierContext.getText());
1✔
1652
      if (tagKeys.contains(key)) {
1✔
1653
        throw new SemanticException("duplicated key in GROUP BY TAGS: " + key);
1✔
1654
      }
1655
      tagKeys.add(key);
1✔
1656
    }
1✔
1657
    return new GroupByTagComponent(new ArrayList<>(tagKeys));
1✔
1658
  }
1659

1660
  // ---- Having Clause
1661
  private HavingCondition parseHavingClause(IoTDBSqlParser.HavingClauseContext ctx) {
1662
    Expression predicate = parseExpression(ctx.expression(), true);
1✔
1663
    return new HavingCondition(predicate);
1✔
1664
  }
1665

1666
  // ---- Order By Clause
1667
  // all SortKeys should be contained by limitSet
1668
  private OrderByComponent parseOrderByClause(
1669
      IoTDBSqlParser.OrderByClauseContext ctx, ImmutableSet<String> limitSet) {
1670
    OrderByComponent orderByComponent = new OrderByComponent();
1✔
1671
    Set<String> sortKeySet = new HashSet<>();
1✔
1672
    for (IoTDBSqlParser.OrderByAttributeClauseContext orderByAttributeClauseContext :
1673
        ctx.orderByAttributeClause()) {
1✔
1674
      // if the order by clause is unique, then the following sort keys will be ignored
1675
      if (orderByComponent.isUnique()) {
1✔
1676
        break;
×
1677
      }
1678
      SortItem sortItem = parseOrderByAttributeClause(orderByAttributeClauseContext, limitSet);
1✔
1679

1680
      String sortKey = sortItem.getSortKey();
1✔
1681
      if (sortKeySet.contains(sortKey)) {
1✔
1682
        continue;
×
1683
      } else {
1684
        sortKeySet.add(sortKey);
1✔
1685
      }
1686

1687
      if (sortItem.isExpression()) {
1✔
1688
        orderByComponent.addExpressionSortItem(sortItem);
1✔
1689
      } else {
1690
        orderByComponent.addSortItem(sortItem);
1✔
1691
      }
1692
    }
1✔
1693
    return orderByComponent;
1✔
1694
  }
1695

1696
  private SortItem parseOrderByAttributeClause(
1697
      IoTDBSqlParser.OrderByAttributeClauseContext ctx, ImmutableSet<String> limitSet) {
1698
    if (ctx.sortKey() != null) {
1✔
1699
      String sortKey = ctx.sortKey().getText().toUpperCase();
1✔
1700
      if (!limitSet.contains(sortKey)) {
1✔
1701
        throw new SemanticException(
×
1702
            String.format("ORDER BY: sort key[%s] is not contained in '%s'", sortKey, limitSet));
×
1703
      }
1704
      return new SortItem(sortKey, ctx.DESC() != null ? Ordering.DESC : Ordering.ASC);
1✔
1705
    } else {
1706
      Expression sortExpression = parseExpression(ctx.expression(), true);
1✔
1707
      return new SortItem(
1✔
1708
          sortExpression,
1709
          ctx.DESC() != null ? Ordering.DESC : Ordering.ASC,
1✔
1710
          ctx.FIRST() != null ? NullOrdering.FIRST : NullOrdering.LAST);
1✔
1711
    }
1712
  }
1713

1714
  // ---- Fill Clause
1715
  public FillComponent parseFillClause(IoTDBSqlParser.FillClauseContext ctx) {
1716
    FillComponent fillComponent = new FillComponent();
1✔
1717
    if (ctx.LINEAR() != null) {
1✔
1718
      fillComponent.setFillPolicy(FillPolicy.LINEAR);
1✔
1719
    } else if (ctx.PREVIOUS() != null) {
1✔
1720
      fillComponent.setFillPolicy(FillPolicy.PREVIOUS);
1✔
1721
    } else if (ctx.constant() != null) {
1✔
1722
      fillComponent.setFillPolicy(FillPolicy.VALUE);
1✔
1723
      Literal fillValue = parseLiteral(ctx.constant());
1✔
1724
      fillComponent.setFillValue(fillValue);
1✔
1725
    } else {
1✔
1726
      throw new SemanticException("Unknown FILL type.");
×
1727
    }
1728
    return fillComponent;
1✔
1729
  }
1730

1731
  private Literal parseLiteral(ConstantContext constantContext) {
1732
    String text = constantContext.getText();
1✔
1733
    if (constantContext.boolean_literal() != null) {
1✔
1734
      return new BooleanLiteral(text);
×
1735
    } else if (constantContext.STRING_LITERAL() != null) {
1✔
1736
      return new StringLiteral(parseStringLiteral(text));
×
1737
    } else if (constantContext.INTEGER_LITERAL() != null) {
1✔
1738
      return new LongLiteral(text);
1✔
1739
    } else if (constantContext.realLiteral() != null) {
×
1740
      return new DoubleLiteral(text);
×
1741
    } else if (constantContext.dateExpression() != null) {
×
1742
      return new LongLiteral(parseDateExpression(constantContext.dateExpression()));
×
1743
    } else {
1744
      throw new SemanticException("Unsupported constant value in FILL: " + text);
×
1745
    }
1746
  }
1747

1748
  // parse LIMIT & OFFSET
1749
  private long parseLimitClause(IoTDBSqlParser.LimitClauseContext ctx) {
1750
    long limit;
1751
    try {
1752
      limit = Long.parseLong(ctx.INTEGER_LITERAL().getText());
1✔
1753
    } catch (NumberFormatException e) {
×
1754
      throw new SemanticException("Out of range. LIMIT <N>: N should be Int64.");
×
1755
    }
1✔
1756
    if (limit <= 0) {
1✔
1757
      throw new SemanticException("LIMIT <N>: N should be greater than 0.");
×
1758
    }
1759
    return limit;
1✔
1760
  }
1761

1762
  private long parseOffsetClause(IoTDBSqlParser.OffsetClauseContext ctx) {
1763
    long offset;
1764
    try {
1765
      offset = Long.parseLong(ctx.INTEGER_LITERAL().getText());
1✔
1766
    } catch (NumberFormatException e) {
×
1767
      throw new SemanticException(
×
1768
          "Out of range. OFFSET <OFFSETValue>: OFFSETValue should be Int64.");
1769
    }
1✔
1770
    if (offset < 0) {
1✔
1771
      throw new SemanticException("OFFSET <OFFSETValue>: OFFSETValue should >= 0.");
×
1772
    }
1773
    return offset;
1✔
1774
  }
1775

1776
  // parse SLIMIT & SOFFSET
1777
  private int parseSLimitClause(IoTDBSqlParser.SlimitClauseContext ctx) {
1778
    int slimit;
1779
    try {
1780
      slimit = Integer.parseInt(ctx.INTEGER_LITERAL().getText());
1✔
1781
    } catch (NumberFormatException e) {
×
1782
      throw new SemanticException("Out of range. SLIMIT <SN>: SN should be Int32.");
×
1783
    }
1✔
1784
    if (slimit <= 0) {
1✔
1785
      throw new SemanticException("SLIMIT <SN>: SN should be greater than 0.");
×
1786
    }
1787
    return slimit;
1✔
1788
  }
1789

1790
  // parse SOFFSET
1791
  public int parseSOffsetClause(IoTDBSqlParser.SoffsetClauseContext ctx) {
1792
    int soffset;
1793
    try {
1794
      soffset = Integer.parseInt(ctx.INTEGER_LITERAL().getText());
1✔
1795
    } catch (NumberFormatException e) {
×
1796
      throw new SemanticException(
×
1797
          "Out of range. SOFFSET <SOFFSETValue>: SOFFSETValue should be Int32.");
1798
    }
1✔
1799
    if (soffset < 0) {
1✔
1800
      throw new SemanticException("SOFFSET <SOFFSETValue>: SOFFSETValue should >= 0.");
×
1801
    }
1802
    return soffset;
1✔
1803
  }
1804

1805
  // ---- Align By Clause
1806
  private ResultSetFormat parseAlignBy(IoTDBSqlParser.AlignByClauseContext ctx) {
1807
    if (ctx.DEVICE() != null) {
1✔
1808
      return ResultSetFormat.ALIGN_BY_DEVICE;
1✔
1809
    } else {
1810
      return ResultSetFormat.ALIGN_BY_TIME;
×
1811
    }
1812
  }
1813

1814
  // Insert Statement ========================================================================
1815

1816
  @Override
1817
  public Statement visitInsertStatement(IoTDBSqlParser.InsertStatementContext ctx) {
1818
    InsertStatement insertStatement = new InsertStatement();
1✔
1819
    insertStatement.setDevice(parsePrefixPath(ctx.prefixPath()));
1✔
1820
    boolean isTimeDefault = parseInsertColumnSpec(ctx.insertColumnsSpec(), insertStatement);
1✔
1821
    parseInsertValuesSpec(ctx.insertValuesSpec(), insertStatement, isTimeDefault);
1✔
1822
    insertStatement.setAligned(ctx.ALIGNED() != null);
1✔
1823
    return insertStatement;
1✔
1824
  }
1825

1826
  private boolean parseInsertColumnSpec(
1827
      IoTDBSqlParser.InsertColumnsSpecContext ctx, InsertStatement insertStatement) {
1828
    List<String> measurementList = new ArrayList<>();
1✔
1829
    for (IoTDBSqlParser.NodeNameWithoutWildcardContext measurementName :
1830
        ctx.nodeNameWithoutWildcard()) {
1✔
1831
      measurementList.add(parseNodeNameWithoutWildCard(measurementName));
1✔
1832
    }
1✔
1833
    insertStatement.setMeasurementList(measurementList.toArray(new String[0]));
1✔
1834
    return (ctx.TIME() == null && ctx.TIMESTAMP() == null);
1✔
1835
  }
1836

1837
  private void parseInsertValuesSpec(
1838
      IoTDBSqlParser.InsertValuesSpecContext ctx,
1839
      InsertStatement insertStatement,
1840
      boolean isTimeDefault) {
1841
    List<IoTDBSqlParser.InsertMultiValueContext> insertMultiValues = ctx.insertMultiValue();
1✔
1842
    List<String[]> valuesList = new ArrayList<>();
1✔
1843
    long[] timeArray = new long[insertMultiValues.size()];
1✔
1844
    for (int i = 0; i < insertMultiValues.size(); i++) {
1✔
1845
      // parse timestamp
1846
      long timestamp;
1847
      List<String> valueList = new ArrayList<>();
1✔
1848

1849
      if (insertMultiValues.get(i).timeValue() != null) {
1✔
1850
        if (isTimeDefault) {
1✔
1851
          if (insertMultiValues.size() != 1) {
×
1852
            throw new SemanticException("need timestamps when insert multi rows");
×
1853
          }
1854
          valueList.add(insertMultiValues.get(i).timeValue().getText());
×
1855
          timestamp = DateTimeUtils.currentTime();
×
1856
        } else {
1857
          timestamp =
1✔
1858
              parseTimeValue(insertMultiValues.get(i).timeValue(), DateTimeUtils.currentTime());
1✔
1859
        }
1860
      } else {
1861
        if (!isTimeDefault) {
×
1862
          throw new SemanticException(
×
1863
              "the measurementList's size is not consistent with the valueList's size");
1864
        }
1865
        if (insertMultiValues.size() != 1) {
×
1866
          throw new SemanticException("need timestamps when insert multi rows");
×
1867
        }
1868
        timestamp = parseDateFormat(SqlConstant.NOW_FUNC);
×
1869
      }
1870
      timeArray[i] = timestamp;
1✔
1871

1872
      // parse values
1873
      List<IoTDBSqlParser.MeasurementValueContext> values =
1✔
1874
          insertMultiValues.get(i).measurementValue();
1✔
1875
      for (IoTDBSqlParser.MeasurementValueContext value : values) {
1✔
1876
        for (IoTDBSqlParser.ConstantContext constant : value.constant()) {
1✔
1877
          if (constant.STRING_LITERAL() != null) {
1✔
1878
            valueList.add(parseStringLiteralInInsertValue(constant.getText()));
×
1879
          } else {
1880
            valueList.add(constant.getText());
1✔
1881
          }
1882
        }
1✔
1883
      }
1✔
1884
      valuesList.add(valueList.toArray(new String[0]));
1✔
1885
    }
1886
    insertStatement.setTimes(timeArray);
1✔
1887
    insertStatement.setValuesList(valuesList);
1✔
1888
  }
1✔
1889

1890
  // Load File
1891

1892
  @Override
1893
  public Statement visitLoadFile(IoTDBSqlParser.LoadFileContext ctx) {
1894
    try {
1895
      LoadTsFileStatement loadTsFileStatement =
×
1896
          new LoadTsFileStatement(parseStringLiteral(ctx.fileName.getText()));
×
1897
      if (ctx.loadFileAttributeClauses() != null) {
×
1898
        for (IoTDBSqlParser.LoadFileAttributeClauseContext attributeContext :
1899
            ctx.loadFileAttributeClauses().loadFileAttributeClause()) {
×
1900
          parseLoadFileAttributeClause(loadTsFileStatement, attributeContext);
×
1901
        }
×
1902
      }
1903
      return loadTsFileStatement;
×
1904
    } catch (FileNotFoundException e) {
×
1905
      throw new SemanticException(e.getMessage());
×
1906
    }
1907
  }
1908

1909
  /**
1910
   * Used for parsing load tsfile, context will be one of "SCHEMA, LEVEL, METADATA", and maybe
1911
   * followed by a recursion property statement.
1912
   *
1913
   * @param loadTsFileStatement the result statement, setting by clause context
1914
   * @param ctx context of property statement
1915
   * @throws SemanticException if AUTOREGISTER | SGLEVEL | VERIFY are not specified
1916
   */
1917
  private void parseLoadFileAttributeClause(
1918
      LoadTsFileStatement loadTsFileStatement, IoTDBSqlParser.LoadFileAttributeClauseContext ctx) {
1919
    if (ctx.ONSUCCESS() != null) {
×
1920
      loadTsFileStatement.setDeleteAfterLoad(ctx.DELETE() != null);
×
1921
    } else if (ctx.SGLEVEL() != null) {
×
1922
      loadTsFileStatement.setDatabaseLevel(Integer.parseInt(ctx.INTEGER_LITERAL().getText()));
×
1923
    } else if (ctx.VERIFY() != null) {
×
1924
      loadTsFileStatement.setVerifySchema(Boolean.parseBoolean(ctx.boolean_literal().getText()));
×
1925
    } else {
1926
      throw new SemanticException(
×
1927
          String.format(
×
1928
              "Load tsfile format %s error, please input AUTOREGISTER | SGLEVEL | VERIFY.",
1929
              ctx.getText()));
×
1930
    }
1931
  }
×
1932

1933
  /** Common Parsers. */
1934

1935
  // IoTDB Objects ========================================================================
1936
  private PartialPath parseFullPath(IoTDBSqlParser.FullPathContext ctx) {
1937
    List<IoTDBSqlParser.NodeNameWithoutWildcardContext> nodeNamesWithoutStar =
1✔
1938
        ctx.nodeNameWithoutWildcard();
1✔
1939
    String[] path = new String[nodeNamesWithoutStar.size() + 1];
1✔
1940
    int i = 0;
1✔
1941
    if (ctx.ROOT() != null) {
1✔
1942
      path[0] = ctx.ROOT().getText();
1✔
1943
    }
1944
    for (IoTDBSqlParser.NodeNameWithoutWildcardContext nodeNameWithoutStar : nodeNamesWithoutStar) {
1✔
1945
      i++;
1✔
1946
      path[i] = parseNodeNameWithoutWildCard(nodeNameWithoutStar);
1✔
1947
    }
1✔
1948
    return new PartialPath(path);
1✔
1949
  }
1950

1951
  private PartialPath parseFullPathInExpression(
1952
      IoTDBSqlParser.FullPathInExpressionContext ctx, boolean canUseFullPath) {
1953
    List<IoTDBSqlParser.NodeNameContext> nodeNames = ctx.nodeName();
1✔
1954
    int size = nodeNames.size();
1✔
1955
    if (ctx.ROOT() != null) {
1✔
1956
      if (!canUseFullPath) {
1✔
1957
        // now full path cannot occur in SELECT only
1958
        throw new SemanticException("Path can not start with root in select clause.");
×
1959
      }
1960
      size++;
1✔
1961
    }
1962
    String[] path = new String[size];
1✔
1963
    if (ctx.ROOT() != null) {
1✔
1964
      path[0] = ctx.ROOT().getText();
1✔
1965
      for (int i = 0; i < nodeNames.size(); i++) {
1✔
1966
        path[i + 1] = parseNodeName(nodeNames.get(i));
1✔
1967
      }
1968
    } else {
1969
      for (int i = 0; i < nodeNames.size(); i++) {
1✔
1970
        path[i] = parseNodeName(nodeNames.get(i));
1✔
1971
      }
1972
    }
1973
    if (!lastLevelUseWildcard
1✔
1974
        && !nodeNames.isEmpty()
1✔
1975
        && !nodeNames.get(nodeNames.size() - 1).wildcard().isEmpty()) {
1✔
1976
      lastLevelUseWildcard = true;
1✔
1977
    }
1978
    return new PartialPath(path);
1✔
1979
  }
1980

1981
  private PartialPath parseFullPathInIntoPath(IoTDBSqlParser.FullPathInIntoPathContext ctx) {
1982
    List<IoTDBSqlParser.NodeNameInIntoPathContext> nodeNames = ctx.nodeNameInIntoPath();
1✔
1983
    String[] path = new String[nodeNames.size() + 1];
1✔
1984
    int i = 0;
1✔
1985
    if (ctx.ROOT() != null) {
1✔
1986
      path[0] = ctx.ROOT().getText();
1✔
1987
    }
1988
    for (IoTDBSqlParser.NodeNameInIntoPathContext nodeName : nodeNames) {
1✔
1989
      i++;
1✔
1990
      path[i] = parseNodeNameInIntoPath(nodeName);
1✔
1991
    }
1✔
1992
    return new PartialPath(path);
1✔
1993
  }
1994

1995
  private PartialPath parsePrefixPath(IoTDBSqlParser.PrefixPathContext ctx) {
1996
    List<IoTDBSqlParser.NodeNameContext> nodeNames = ctx.nodeName();
1✔
1997
    String[] path = new String[nodeNames.size() + 1];
1✔
1998
    path[0] = ctx.ROOT().getText();
1✔
1999
    for (int i = 0; i < nodeNames.size(); i++) {
1✔
2000
      path[i + 1] = parseNodeName(nodeNames.get(i));
1✔
2001
    }
2002
    return new PartialPath(path);
1✔
2003
  }
2004

2005
  private String parseNodeName(IoTDBSqlParser.NodeNameContext ctx) {
2006
    if (!useWildcard && !ctx.wildcard().isEmpty()) {
1✔
2007
      useWildcard = true;
1✔
2008
    }
2009
    return parseNodeString(ctx.getText());
1✔
2010
  }
2011

2012
  private String parseNodeNameWithoutWildCard(IoTDBSqlParser.NodeNameWithoutWildcardContext ctx) {
2013
    return parseNodeString(ctx.getText());
1✔
2014
  }
2015

2016
  private String parseNodeNameInIntoPath(IoTDBSqlParser.NodeNameInIntoPathContext ctx) {
2017
    return parseNodeStringInIntoPath(ctx.getText());
1✔
2018
  }
2019

2020
  private String parseNodeString(String nodeName) {
2021
    if (nodeName.equals(IoTDBConstant.ONE_LEVEL_PATH_WILDCARD)
1✔
2022
        || nodeName.equals(IoTDBConstant.MULTI_LEVEL_PATH_WILDCARD)) {
1✔
2023
      return nodeName;
1✔
2024
    }
2025
    if (nodeName.startsWith(TsFileConstant.BACK_QUOTE_STRING)
1✔
2026
        && nodeName.endsWith(TsFileConstant.BACK_QUOTE_STRING)) {
×
2027
      return PathUtils.removeBackQuotesIfNecessary(nodeName);
×
2028
    }
2029
    checkNodeName(nodeName);
1✔
2030
    return nodeName;
1✔
2031
  }
2032

2033
  private String parseNodeStringInIntoPath(String nodeName) {
2034
    if (nodeName.equals(IoTDBConstant.DOUBLE_COLONS)) {
1✔
2035
      return nodeName;
1✔
2036
    }
2037
    if (nodeName.startsWith(TsFileConstant.BACK_QUOTE_STRING)
1✔
2038
        && nodeName.endsWith(TsFileConstant.BACK_QUOTE_STRING)) {
×
2039
      return PathUtils.removeBackQuotesIfNecessary(nodeName);
×
2040
    }
2041
    checkNodeNameInIntoPath(nodeName);
1✔
2042
    return nodeName;
1✔
2043
  }
2044

2045
  private void checkNodeName(String src) {
2046
    // node name could start with * and end with *
2047
    if (!TsFileConstant.NODE_NAME_PATTERN.matcher(src).matches()) {
1✔
2048
      throw new SemanticException(
×
2049
          String.format(
×
2050
              "%s is illegal, unquoted node name can only consist of digits, characters and underscore, or start or end with wildcard",
2051
              src));
2052
    }
2053
  }
1✔
2054

2055
  private void checkNodeNameInIntoPath(String src) {
2056
    // ${} are allowed
2057
    if (!TsFileConstant.NODE_NAME_IN_INTO_PATH_PATTERN.matcher(src).matches()) {
1✔
2058
      throw new SemanticException(
×
2059
          String.format(
×
2060
              "%s is illegal, unquoted node name in select into clause can only consist of digits, characters, $, { and }",
2061
              src));
2062
    }
2063
  }
1✔
2064

2065
  private static void checkIdentifier(String src) {
2066
    if (!TsFileConstant.IDENTIFIER_PATTERN.matcher(src).matches() || PathUtils.isRealNumber(src)) {
1✔
2067
      throw new SemanticException(
×
2068
          String.format(
×
2069
              "%s is illegal, identifier not enclosed with backticks can only consist of digits, characters and underscore.",
2070
              src));
2071
    }
2072
  }
1✔
2073

2074
  // Literals ========================================================================
2075

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

2095
  public long parseDateFormat(String timestampStr, long currentTime) {
2096
    if (timestampStr == null || "".equals(timestampStr.trim())) {
1✔
2097
      throw new SemanticException("input timestamp cannot be empty");
×
2098
    }
2099
    if (timestampStr.equalsIgnoreCase(SqlConstant.NOW_FUNC)) {
1✔
2100
      return currentTime;
×
2101
    }
2102
    try {
2103
      return DateTimeUtils.convertDatetimeStrToLong(timestampStr, zoneId);
1✔
2104
    } catch (Exception e) {
×
2105
      throw new SemanticException(
×
2106
          String.format(
×
2107
              "Input time format %s error. "
2108
                  + "Input like yyyy-MM-dd HH:mm:ss, yyyy-MM-ddTHH:mm:ss or "
2109
                  + "refer to user document for more info.",
2110
              timestampStr));
2111
    }
2112
  }
2113

2114
  private String parseStringLiteral(String src) {
2115
    if (2 <= src.length()) {
1✔
2116
      // do not unescape string
2117
      String unWrappedString = src.substring(1, src.length() - 1);
1✔
2118
      if (src.charAt(0) == '\"' && src.charAt(src.length() - 1) == '\"') {
1✔
2119
        // replace "" with "
2120
        String replaced = unWrappedString.replace("\"\"", "\"");
×
2121
        return replaced.length() == 0 ? "" : replaced;
×
2122
      }
2123
      if ((src.charAt(0) == '\'' && src.charAt(src.length() - 1) == '\'')) {
1✔
2124
        // replace '' with '
2125
        String replaced = unWrappedString.replace("''", "'");
1✔
2126
        return replaced.length() == 0 ? "" : replaced;
1✔
2127
      }
2128
    }
2129
    return src;
×
2130
  }
2131

2132
  private String parseStringLiteralInInsertValue(String src) {
2133
    if (2 <= src.length()
×
2134
        && ((src.charAt(0) == '\"' && src.charAt(src.length() - 1) == '\"')
×
2135
            || (src.charAt(0) == '\'' && src.charAt(src.length() - 1) == '\''))) {
×
2136
      return "'" + parseStringLiteral(src) + "'";
×
2137
    }
2138
    return src;
×
2139
  }
2140

2141
  public static String parseIdentifier(String src) {
2142
    if (src.startsWith(TsFileConstant.BACK_QUOTE_STRING)
1✔
2143
        && src.endsWith(TsFileConstant.BACK_QUOTE_STRING)) {
×
2144
      return src.substring(1, src.length() - 1)
×
2145
          .replace(TsFileConstant.DOUBLE_BACK_QUOTE_STRING, TsFileConstant.BACK_QUOTE_STRING);
×
2146
    }
2147
    checkIdentifier(src);
1✔
2148
    return src;
1✔
2149
  }
2150

2151
  // Alias
2152

2153
  /** Function for parsing Alias of ResultColumn. */
2154
  private String parseAlias(IoTDBSqlParser.AliasContext ctx) {
2155
    String alias;
2156
    if (ctx.constant() != null) {
1✔
2157
      alias = parseConstant(ctx.constant());
×
2158
    } else {
2159
      alias = parseIdentifier(ctx.identifier().getText());
1✔
2160
    }
2161
    return alias;
1✔
2162
  }
2163

2164
  /**
2165
   * Function for parsing AliasNode.
2166
   *
2167
   * @throws SemanticException if the alias pattern is not supported
2168
   */
2169
  private String parseAliasNode(IoTDBSqlParser.AliasContext ctx) {
2170
    String alias;
2171
    if (ctx.constant() != null) {
×
2172
      alias = parseConstant(ctx.constant());
×
2173
      if (PathUtils.isRealNumber(alias)
×
2174
          || !TsFileConstant.IDENTIFIER_PATTERN.matcher(alias).matches()) {
×
2175
        throw new SemanticException("Not support for this alias, Please enclose in back quotes.");
×
2176
      }
2177
    } else {
2178
      alias = parseNodeString(ctx.identifier().getText());
×
2179
    }
2180
    return alias;
×
2181
  }
2182

2183
  /** Data Control Language (DCL). */
2184

2185
  // Create User
2186
  @Override
2187
  public Statement visitCreateUser(IoTDBSqlParser.CreateUserContext ctx) {
2188
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.CREATE_USER);
×
2189
    authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
×
2190
    authorStatement.setPassWord(parseStringLiteral(ctx.password.getText()));
×
2191
    return authorStatement;
×
2192
  }
2193

2194
  // Create Role
2195

2196
  @Override
2197
  public Statement visitCreateRole(IoTDBSqlParser.CreateRoleContext ctx) {
2198
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.CREATE_ROLE);
×
2199
    authorStatement.setRoleName(parseIdentifier(ctx.roleName.getText()));
×
2200
    return authorStatement;
×
2201
  }
2202

2203
  // Alter Password
2204

2205
  @Override
2206
  public Statement visitAlterUser(IoTDBSqlParser.AlterUserContext ctx) {
2207
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.UPDATE_USER);
×
2208
    authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
×
2209
    authorStatement.setNewPassword(parseStringLiteral(ctx.password.getText()));
×
2210
    return authorStatement;
×
2211
  }
2212

2213
  // Grant User Privileges
2214

2215
  @Override
2216
  public Statement visitGrantUser(IoTDBSqlParser.GrantUserContext ctx) {
2217
    String[] privileges = parsePrivilege(ctx.privileges());
×
2218
    List<PartialPath> nodeNameList =
×
2219
        ctx.prefixPath().stream()
×
2220
            .map(this::parsePrefixPath)
×
2221
            .distinct()
×
2222
            .collect(Collectors.toList());
×
2223
    checkGrantRevokePrivileges(privileges, nodeNameList);
×
2224

2225
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.GRANT_USER);
×
2226
    authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
×
2227
    authorStatement.setPrivilegeList(privileges);
×
2228
    authorStatement.setNodeNameList(nodeNameList);
×
2229
    return authorStatement;
×
2230
  }
2231

2232
  // Grant Role Privileges
2233

2234
  @Override
2235
  public Statement visitGrantRole(IoTDBSqlParser.GrantRoleContext ctx) {
2236
    String[] privileges = parsePrivilege(ctx.privileges());
×
2237
    List<PartialPath> nodeNameList =
×
2238
        ctx.prefixPath().stream()
×
2239
            .map(this::parsePrefixPath)
×
2240
            .distinct()
×
2241
            .collect(Collectors.toList());
×
2242
    checkGrantRevokePrivileges(privileges, nodeNameList);
×
2243

2244
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.GRANT_ROLE);
×
2245
    authorStatement.setRoleName(parseIdentifier(ctx.roleName.getText()));
×
2246
    authorStatement.setPrivilegeList(privileges);
×
2247
    authorStatement.setNodeNameList(nodeNameList);
×
2248
    return authorStatement;
×
2249
  }
2250

2251
  // Grant User Role
2252

2253
  @Override
2254
  public Statement visitGrantRoleToUser(IoTDBSqlParser.GrantRoleToUserContext ctx) {
2255
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.GRANT_USER_ROLE);
×
2256
    authorStatement.setRoleName(parseIdentifier(ctx.roleName.getText()));
×
2257
    authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
×
2258
    return authorStatement;
×
2259
  }
2260

2261
  // Revoke User Privileges
2262

2263
  @Override
2264
  public Statement visitRevokeUser(IoTDBSqlParser.RevokeUserContext ctx) {
2265
    String[] privileges = parsePrivilege(ctx.privileges());
×
2266
    List<PartialPath> nodeNameList =
×
2267
        ctx.prefixPath().stream()
×
2268
            .map(this::parsePrefixPath)
×
2269
            .distinct()
×
2270
            .collect(Collectors.toList());
×
2271
    checkGrantRevokePrivileges(privileges, nodeNameList);
×
2272

2273
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.REVOKE_USER);
×
2274
    authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
×
2275
    authorStatement.setPrivilegeList(privileges);
×
2276
    authorStatement.setNodeNameList(nodeNameList);
×
2277
    return authorStatement;
×
2278
  }
2279

2280
  // Revoke Role Privileges
2281

2282
  @Override
2283
  public Statement visitRevokeRole(IoTDBSqlParser.RevokeRoleContext ctx) {
2284
    String[] privileges = parsePrivilege(ctx.privileges());
×
2285
    List<PartialPath> nodeNameList =
×
2286
        ctx.prefixPath().stream()
×
2287
            .map(this::parsePrefixPath)
×
2288
            .distinct()
×
2289
            .collect(Collectors.toList());
×
2290
    checkGrantRevokePrivileges(privileges, nodeNameList);
×
2291

2292
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.REVOKE_ROLE);
×
2293
    authorStatement.setRoleName(parseIdentifier(ctx.roleName.getText()));
×
2294
    authorStatement.setPrivilegeList(privileges);
×
2295
    authorStatement.setNodeNameList(nodeNameList);
×
2296
    return authorStatement;
×
2297
  }
2298

2299
  private void checkGrantRevokePrivileges(String[] privileges, List<PartialPath> nodeNameList) {
2300
    if (nodeNameList.isEmpty()) {
×
2301
      nodeNameList.add(new PartialPath(ALL_RESULT_NODES));
×
2302
      return;
×
2303
    }
2304
    boolean pathRelevant = true;
×
2305
    String errorPrivilegeName = "";
×
2306
    for (String privilege : privileges) {
×
2307
      if (!PrivilegeType.valueOf(privilege.toUpperCase()).isPathRelevant()) {
×
2308
        pathRelevant = false;
×
2309
        errorPrivilegeName = privilege.toUpperCase();
×
2310
        break;
×
2311
      }
2312
    }
2313
    if (!(pathRelevant
×
2314
        || (nodeNameList.size() == 1
×
2315
            && nodeNameList.contains(new PartialPath(ALL_RESULT_NODES))))) {
×
2316
      throw new SemanticException(
×
2317
          String.format(
×
2318
              "path independent privilege: [%s] can only be set on path: root.**",
2319
              errorPrivilegeName));
2320
    }
2321
  }
×
2322

2323
  // Revoke Role From User
2324

2325
  @Override
2326
  public Statement visitRevokeRoleFromUser(IoTDBSqlParser.RevokeRoleFromUserContext ctx) {
2327
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.REVOKE_USER_ROLE);
×
2328
    authorStatement.setRoleName(parseIdentifier(ctx.roleName.getText()));
×
2329
    authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
×
2330
    return authorStatement;
×
2331
  }
2332

2333
  // Drop User
2334

2335
  @Override
2336
  public Statement visitDropUser(IoTDBSqlParser.DropUserContext ctx) {
2337
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.DROP_USER);
×
2338
    authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
×
2339
    return authorStatement;
×
2340
  }
2341

2342
  // Drop Role
2343

2344
  @Override
2345
  public Statement visitDropRole(IoTDBSqlParser.DropRoleContext ctx) {
2346
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.DROP_ROLE);
×
2347
    authorStatement.setRoleName(parseIdentifier(ctx.roleName.getText()));
×
2348
    return authorStatement;
×
2349
  }
2350

2351
  // List Users
2352

2353
  @Override
2354
  public Statement visitListUser(IoTDBSqlParser.ListUserContext ctx) {
2355
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.LIST_USER);
×
2356
    if (ctx.roleName != null) {
×
2357
      authorStatement.setRoleName(parseIdentifier(ctx.roleName.getText()));
×
2358
    }
2359
    return authorStatement;
×
2360
  }
2361

2362
  // List Roles
2363

2364
  @Override
2365
  public Statement visitListRole(IoTDBSqlParser.ListRoleContext ctx) {
2366
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.LIST_ROLE);
×
2367
    if (ctx.userName != null) {
×
2368
      authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
×
2369
    }
2370
    return authorStatement;
×
2371
  }
2372

2373
  // List Privileges
2374

2375
  @Override
2376
  public Statement visitListPrivilegesUser(IoTDBSqlParser.ListPrivilegesUserContext ctx) {
2377
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.LIST_USER_PRIVILEGE);
×
2378
    authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
×
2379
    List<PartialPath> nodeNameList =
×
2380
        ctx.prefixPath().stream().map(this::parsePrefixPath).collect(Collectors.toList());
×
2381
    authorStatement.setNodeNameList(nodeNameList);
×
2382
    return authorStatement;
×
2383
  }
2384

2385
  // List Privileges of Roles On Specific Path
2386

2387
  @Override
2388
  public Statement visitListPrivilegesRole(IoTDBSqlParser.ListPrivilegesRoleContext ctx) {
2389
    AuthorStatement authorStatement = new AuthorStatement(AuthorType.LIST_ROLE_PRIVILEGE);
×
2390
    authorStatement.setRoleName(parseIdentifier(ctx.roleName.getText()));
×
2391
    List<PartialPath> nodeNameList =
×
2392
        ctx.prefixPath().stream().map(this::parsePrefixPath).collect(Collectors.toList());
×
2393
    authorStatement.setNodeNameList(nodeNameList);
×
2394
    return authorStatement;
×
2395
  }
2396

2397
  private String[] parsePrivilege(IoTDBSqlParser.PrivilegesContext ctx) {
2398
    List<IoTDBSqlParser.PrivilegeValueContext> privilegeList = ctx.privilegeValue();
×
2399
    List<String> privileges = new ArrayList<>();
×
2400
    for (IoTDBSqlParser.PrivilegeValueContext privilegeValue : privilegeList) {
×
2401
      privileges.add(privilegeValue.getText());
×
2402
    }
×
2403
    return privileges.toArray(new String[0]);
×
2404
  }
2405

2406
  // Create database
2407
  @Override
2408
  public Statement visitCreateDatabase(IoTDBSqlParser.CreateDatabaseContext ctx) {
2409
    DatabaseSchemaStatement databaseSchemaStatement =
×
2410
        new DatabaseSchemaStatement(DatabaseSchemaStatement.DatabaseSchemaStatementType.CREATE);
2411
    PartialPath path = parsePrefixPath(ctx.prefixPath());
×
2412
    databaseSchemaStatement.setDatabasePath(path);
×
2413
    if (ctx.databaseAttributesClause() != null) {
×
2414
      parseDatabaseAttributesClause(databaseSchemaStatement, ctx.databaseAttributesClause());
×
2415
    }
2416
    return databaseSchemaStatement;
×
2417
  }
2418

2419
  @Override
2420
  public Statement visitAlterDatabase(IoTDBSqlParser.AlterDatabaseContext ctx) {
2421
    DatabaseSchemaStatement databaseSchemaStatement =
×
2422
        new DatabaseSchemaStatement(DatabaseSchemaStatement.DatabaseSchemaStatementType.ALTER);
2423
    PartialPath path = parsePrefixPath(ctx.prefixPath());
×
2424
    databaseSchemaStatement.setDatabasePath(path);
×
2425
    parseDatabaseAttributesClause(databaseSchemaStatement, ctx.databaseAttributesClause());
×
2426
    return databaseSchemaStatement;
×
2427
  }
2428

2429
  private void parseDatabaseAttributesClause(
2430
      DatabaseSchemaStatement databaseSchemaStatement,
2431
      IoTDBSqlParser.DatabaseAttributesClauseContext ctx) {
2432
    for (IoTDBSqlParser.DatabaseAttributeClauseContext attribute : ctx.databaseAttributeClause()) {
×
2433
      IoTDBSqlParser.DatabaseAttributeKeyContext attributeKey = attribute.databaseAttributeKey();
×
2434
      if (attributeKey.TTL() != null) {
×
2435
        long ttl = Long.parseLong(attribute.INTEGER_LITERAL().getText());
×
2436
        databaseSchemaStatement.setTtl(ttl);
×
2437
      } else if (attributeKey.SCHEMA_REPLICATION_FACTOR() != null) {
×
2438
        int schemaReplicationFactor = Integer.parseInt(attribute.INTEGER_LITERAL().getText());
×
2439
        databaseSchemaStatement.setSchemaReplicationFactor(schemaReplicationFactor);
×
2440
      } else if (attributeKey.DATA_REPLICATION_FACTOR() != null) {
×
2441
        int dataReplicationFactor = Integer.parseInt(attribute.INTEGER_LITERAL().getText());
×
2442
        databaseSchemaStatement.setDataReplicationFactor(dataReplicationFactor);
×
2443
      } else if (attributeKey.TIME_PARTITION_INTERVAL() != null) {
×
2444
        long timePartitionInterval = Long.parseLong(attribute.INTEGER_LITERAL().getText());
×
2445
        databaseSchemaStatement.setTimePartitionInterval(timePartitionInterval);
×
2446
      } else if (attributeKey.SCHEMA_REGION_GROUP_NUM() != null) {
×
2447
        int schemaRegionGroupNum = Integer.parseInt(attribute.INTEGER_LITERAL().getText());
×
2448
        databaseSchemaStatement.setSchemaRegionGroupNum(schemaRegionGroupNum);
×
2449
      } else if (attributeKey.DATA_REGION_GROUP_NUM() != null) {
×
2450
        int dataRegionGroupNum = Integer.parseInt(attribute.INTEGER_LITERAL().getText());
×
2451
        databaseSchemaStatement.setDataRegionGroupNum(dataRegionGroupNum);
×
2452
      }
2453
    }
×
2454
  }
×
2455

2456
  @Override
2457
  public Statement visitSetTTL(IoTDBSqlParser.SetTTLContext ctx) {
2458
    SetTTLStatement setTTLStatement = new SetTTLStatement();
1✔
2459
    PartialPath path = parsePrefixPath(ctx.prefixPath());
1✔
2460
    long ttl = Long.parseLong(ctx.INTEGER_LITERAL().getText());
1✔
2461
    setTTLStatement.setDatabasePath(path);
1✔
2462
    setTTLStatement.setTTL(ttl);
1✔
2463
    return setTTLStatement;
1✔
2464
  }
2465

2466
  @Override
2467
  public Statement visitUnsetTTL(IoTDBSqlParser.UnsetTTLContext ctx) {
2468
    UnSetTTLStatement unSetTTLStatement = new UnSetTTLStatement();
1✔
2469
    PartialPath partialPath = parsePrefixPath(ctx.prefixPath());
1✔
2470
    unSetTTLStatement.setDatabasePath(partialPath);
1✔
2471
    return unSetTTLStatement;
1✔
2472
  }
2473

2474
  @Override
2475
  public Statement visitShowTTL(IoTDBSqlParser.ShowTTLContext ctx) {
2476
    ShowTTLStatement showTTLStatement = new ShowTTLStatement();
1✔
2477
    for (IoTDBSqlParser.PrefixPathContext prefixPathContext : ctx.prefixPath()) {
1✔
2478
      PartialPath partialPath = parsePrefixPath(prefixPathContext);
1✔
2479
      showTTLStatement.addPathPatterns(partialPath);
1✔
2480
    }
1✔
2481
    return showTTLStatement;
1✔
2482
  }
2483

2484
  @Override
2485
  public Statement visitShowAllTTL(IoTDBSqlParser.ShowAllTTLContext ctx) {
2486
    ShowTTLStatement showTTLStatement = new ShowTTLStatement();
1✔
2487
    showTTLStatement.setAll(true);
1✔
2488
    return showTTLStatement;
1✔
2489
  }
2490

2491
  @Override
2492
  public Statement visitShowVariables(IoTDBSqlParser.ShowVariablesContext ctx) {
2493
    return new ShowVariablesStatement();
×
2494
  }
2495

2496
  @Override
2497
  public Statement visitShowCluster(IoTDBSqlParser.ShowClusterContext ctx) {
2498
    ShowClusterStatement showClusterStatement = new ShowClusterStatement();
×
2499
    if (ctx.DETAILS() != null) {
×
2500
      showClusterStatement.setDetails(true);
×
2501
    }
2502
    return showClusterStatement;
×
2503
  }
2504

2505
  @Override
2506
  public Statement visitDropDatabase(IoTDBSqlParser.DropDatabaseContext ctx) {
2507
    DeleteDatabaseStatement dropDatabaseStatement = new DeleteDatabaseStatement();
×
2508
    List<IoTDBSqlParser.PrefixPathContext> prefixPathContexts = ctx.prefixPath();
×
2509
    List<String> paths = new ArrayList<>();
×
2510
    for (IoTDBSqlParser.PrefixPathContext prefixPathContext : prefixPathContexts) {
×
2511
      paths.add(parsePrefixPath(prefixPathContext).getFullPath());
×
2512
    }
×
2513
    dropDatabaseStatement.setPrefixPath(paths);
×
2514
    return dropDatabaseStatement;
×
2515
  }
2516

2517
  // Explain ========================================================================
2518
  @Override
2519
  public Statement visitExplain(IoTDBSqlParser.ExplainContext ctx) {
2520
    QueryStatement queryStatement = (QueryStatement) visitSelectStatement(ctx.selectStatement());
×
2521
    return new ExplainStatement(queryStatement);
×
2522
  }
2523

2524
  @Override
2525
  public Statement visitDeleteStatement(IoTDBSqlParser.DeleteStatementContext ctx) {
2526
    DeleteDataStatement statement = new DeleteDataStatement();
×
2527
    List<IoTDBSqlParser.PrefixPathContext> prefixPaths = ctx.prefixPath();
×
2528
    List<PartialPath> pathList = new ArrayList<>();
×
2529
    for (IoTDBSqlParser.PrefixPathContext prefixPath : prefixPaths) {
×
2530
      pathList.add(parsePrefixPath(prefixPath));
×
2531
    }
×
2532
    statement.setPathList(pathList);
×
2533
    if (ctx.whereClause() != null) {
×
2534
      WhereCondition whereCondition = parseWhereClause(ctx.whereClause());
×
2535
      TimeRange timeRange = parseDeleteTimeRange(whereCondition.getPredicate());
×
2536
      statement.setTimeRange(timeRange);
×
2537
    } else {
×
2538
      statement.setTimeRange(new TimeRange(Long.MIN_VALUE, Long.MAX_VALUE));
×
2539
    }
2540
    return statement;
×
2541
  }
2542

2543
  private TimeRange parseDeleteTimeRange(Expression predicate) {
2544
    if (predicate instanceof LogicAndExpression) {
×
2545
      TimeRange leftTimeRange =
×
2546
          parseDeleteTimeRange(((LogicAndExpression) predicate).getLeftExpression());
×
2547
      TimeRange rightTimeRange =
×
2548
          parseDeleteTimeRange(((LogicAndExpression) predicate).getRightExpression());
×
2549
      return new TimeRange(
×
2550
          Math.max(leftTimeRange.getMin(), rightTimeRange.getMin()),
×
2551
          Math.min(leftTimeRange.getMax(), rightTimeRange.getMax()));
×
2552
    } else if (predicate instanceof CompareBinaryExpression) {
×
2553
      if (((CompareBinaryExpression) predicate).getLeftExpression() instanceof TimestampOperand) {
×
2554
        return parseTimeRangeForDeleteTimeRange(
×
2555
            predicate.getExpressionType(),
×
2556
            ((CompareBinaryExpression) predicate).getLeftExpression(),
×
2557
            ((CompareBinaryExpression) predicate).getRightExpression());
×
2558
      } else {
2559
        return parseTimeRangeForDeleteTimeRange(
×
2560
            predicate.getExpressionType(),
×
2561
            ((CompareBinaryExpression) predicate).getRightExpression(),
×
2562
            ((CompareBinaryExpression) predicate).getLeftExpression());
×
2563
      }
2564
    } else {
2565
      throw new SemanticException(DELETE_RANGE_ERROR_MSG);
×
2566
    }
2567
  }
2568

2569
  private TimeRange parseTimeRangeForDeleteTimeRange(
2570
      ExpressionType expressionType, Expression timeExpression, Expression valueExpression) {
2571
    if (!(timeExpression instanceof TimestampOperand)
×
2572
        || !(valueExpression instanceof ConstantOperand)) {
2573
      throw new SemanticException(DELETE_ONLY_SUPPORT_TIME_EXP_ERROR_MSG);
×
2574
    }
2575

2576
    if (((ConstantOperand) valueExpression).getDataType() != TSDataType.INT64) {
×
2577
      throw new SemanticException("The datatype of timestamp should be LONG.");
×
2578
    }
2579

2580
    long time = Long.parseLong(((ConstantOperand) valueExpression).getValueString());
×
2581
    switch (expressionType) {
×
2582
      case LESS_THAN:
2583
        return new TimeRange(Long.MIN_VALUE, time - 1);
×
2584
      case LESS_EQUAL:
2585
        return new TimeRange(Long.MIN_VALUE, time);
×
2586
      case GREATER_THAN:
2587
        return new TimeRange(time + 1, Long.MAX_VALUE);
×
2588
      case GREATER_EQUAL:
2589
        return new TimeRange(time, Long.MAX_VALUE);
×
2590
      case EQUAL_TO:
2591
        return new TimeRange(time, time);
×
2592
      default:
2593
        throw new SemanticException(DELETE_RANGE_ERROR_MSG);
×
2594
    }
2595
  }
2596

2597
  /** function for parsing file path used by LOAD statement. */
2598
  public String parseFilePath(String src) {
2599
    return src.substring(1, src.length() - 1);
×
2600
  }
2601

2602
  // Expression & Predicate ========================================================================
2603

2604
  private Expression parseExpression(
2605
      IoTDBSqlParser.ExpressionContext context, boolean canUseFullPath) {
2606
    if (context.unaryInBracket != null) {
1✔
2607
      return parseExpression(context.unaryInBracket, canUseFullPath);
1✔
2608
    }
2609

2610
    if (context.expressionAfterUnaryOperator != null) {
1✔
2611
      if (context.MINUS() != null) {
×
2612
        return new NegationExpression(
×
2613
            parseExpression(context.expressionAfterUnaryOperator, canUseFullPath));
×
2614
      }
2615
      if (context.operator_not() != null) {
×
2616
        return new LogicNotExpression(
×
2617
            parseExpression(context.expressionAfterUnaryOperator, canUseFullPath));
×
2618
      }
2619
      return parseExpression(context.expressionAfterUnaryOperator, canUseFullPath);
×
2620
    }
2621

2622
    if (context.leftExpression != null && context.rightExpression != null) {
1✔
2623
      Expression leftExpression = parseExpression(context.leftExpression, canUseFullPath);
1✔
2624
      Expression rightExpression = parseExpression(context.rightExpression, canUseFullPath);
1✔
2625
      if (context.STAR() != null) {
1✔
2626
        return new MultiplicationExpression(leftExpression, rightExpression);
1✔
2627
      }
2628
      if (context.DIV() != null) {
1✔
2629
        return new DivisionExpression(leftExpression, rightExpression);
1✔
2630
      }
2631
      if (context.MOD() != null) {
1✔
2632
        return new ModuloExpression(leftExpression, rightExpression);
1✔
2633
      }
2634
      if (context.PLUS() != null) {
1✔
2635
        return new AdditionExpression(leftExpression, rightExpression);
1✔
2636
      }
2637
      if (context.MINUS() != null) {
1✔
2638
        return new SubtractionExpression(leftExpression, rightExpression);
1✔
2639
      }
2640
      if (context.OPERATOR_GT() != null) {
1✔
2641
        return new GreaterThanExpression(leftExpression, rightExpression);
1✔
2642
      }
2643
      if (context.OPERATOR_GTE() != null) {
1✔
2644
        return new GreaterEqualExpression(leftExpression, rightExpression);
1✔
2645
      }
2646
      if (context.OPERATOR_LT() != null) {
1✔
2647
        return new LessThanExpression(leftExpression, rightExpression);
1✔
2648
      }
2649
      if (context.OPERATOR_LTE() != null) {
1✔
2650
        return new LessEqualExpression(leftExpression, rightExpression);
1✔
2651
      }
2652
      if (context.OPERATOR_DEQ() != null || context.OPERATOR_SEQ() != null) {
1✔
2653
        return new EqualToExpression(leftExpression, rightExpression);
1✔
2654
      }
2655
      if (context.OPERATOR_NEQ() != null) {
1✔
2656
        return new NonEqualExpression(leftExpression, rightExpression);
1✔
2657
      }
2658
      if (context.operator_and() != null) {
1✔
2659
        return new LogicAndExpression(leftExpression, rightExpression);
1✔
2660
      }
2661
      if (context.operator_or() != null) {
1✔
2662
        return new LogicOrExpression(leftExpression, rightExpression);
1✔
2663
      }
2664
      throw new UnsupportedOperationException();
×
2665
    }
2666

2667
    if (context.unaryBeforeRegularOrLikeExpression != null) {
1✔
2668
      if (context.REGEXP() != null) {
×
2669
        return parseRegularExpression(context, canUseFullPath);
×
2670
      }
2671
      if (context.LIKE() != null) {
×
2672
        return parseLikeExpression(context, canUseFullPath);
×
2673
      }
2674
      throw new UnsupportedOperationException();
×
2675
    }
2676

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

2681
    if (context.firstExpression != null
1✔
2682
        && context.secondExpression != null
2683
        && context.thirdExpression != null) {
2684
      Expression firstExpression = parseExpression(context.firstExpression, canUseFullPath);
×
2685
      Expression secondExpression = parseExpression(context.secondExpression, canUseFullPath);
×
2686
      Expression thirdExpression = parseExpression(context.thirdExpression, canUseFullPath);
×
2687

2688
      if (context.operator_between() != null) {
×
2689
        return new BetweenExpression(
×
2690
            firstExpression, secondExpression, thirdExpression, context.operator_not() != null);
×
2691
      }
2692
      throw new UnsupportedOperationException();
×
2693
    }
2694

2695
    if (context.unaryBeforeInExpression != null) {
1✔
2696
      return parseInExpression(context, canUseFullPath);
×
2697
    }
2698

2699
    if (context.scalarFunctionExpression() != null) {
1✔
2700
      return parseScalarFunctionExpression(context.scalarFunctionExpression(), canUseFullPath);
×
2701
    }
2702

2703
    if (context.functionName() != null) {
1✔
2704
      return parseFunctionExpression(context, canUseFullPath);
1✔
2705
    }
2706

2707
    if (context.fullPathInExpression() != null) {
1✔
2708
      return new TimeSeriesOperand(
1✔
2709
          parseFullPathInExpression(context.fullPathInExpression(), canUseFullPath));
1✔
2710
    }
2711

2712
    if (context.time != null) {
1✔
2713
      return new TimestampOperand();
1✔
2714
    }
2715

2716
    if (context.constant() != null && !context.constant().isEmpty()) {
1✔
2717
      return parseConstantOperand(context.constant(0));
1✔
2718
    }
2719

2720
    if (context.caseWhenThenExpression() != null) {
×
2721
      return parseCaseWhenThenExpression(context.caseWhenThenExpression(), canUseFullPath);
×
2722
    }
2723

2724
    throw new UnsupportedOperationException();
×
2725
  }
2726

2727
  private Expression parseScalarFunctionExpression(
2728
      IoTDBSqlParser.ScalarFunctionExpressionContext context, boolean canUseFullPath) {
2729
    if (context.CAST() != null) {
×
2730
      return parseCastFunction(context, canUseFullPath);
×
2731
    } else if (context.REPLACE() != null) {
×
2732
      return parseReplaceFunction(context, canUseFullPath);
×
2733
    } else if (context.ROUND() != null) {
×
2734
      return parseRoundFunction(context, canUseFullPath);
×
2735
    } else if (context.SUBSTRING() != null) {
×
2736
      return parseSubStrFunction(context, canUseFullPath);
×
2737
    }
2738
    throw new UnsupportedOperationException();
×
2739
  }
2740

2741
  private Expression parseCastFunction(
2742
      IoTDBSqlParser.ScalarFunctionExpressionContext castClause, boolean canUseFullPath) {
2743
    FunctionExpression functionExpression = new FunctionExpression(CAST_FUNCTION);
×
2744
    functionExpression.addExpression(parseExpression(castClause.castInput, canUseFullPath));
×
2745
    functionExpression.addAttribute(CAST_TYPE, parseAttributeValue(castClause.attributeValue()));
×
2746
    return functionExpression;
×
2747
  }
2748

2749
  private Expression parseReplaceFunction(
2750
      IoTDBSqlParser.ScalarFunctionExpressionContext replaceClause, boolean canUseFullPath) {
2751
    FunctionExpression functionExpression = new FunctionExpression(REPLACE_FUNCTION);
×
2752
    functionExpression.addExpression(parseExpression(replaceClause.text, canUseFullPath));
×
2753
    functionExpression.addAttribute(REPLACE_FROM, parseStringLiteral(replaceClause.from.getText()));
×
2754
    functionExpression.addAttribute(REPLACE_TO, parseStringLiteral(replaceClause.to.getText()));
×
2755
    return functionExpression;
×
2756
  }
2757

2758
  private Expression parseSubStrFunction(
2759
      IoTDBSqlParser.ScalarFunctionExpressionContext subStrClause, boolean canUseFullPath) {
2760
    FunctionExpression functionExpression = new FunctionExpression(SUBSTRING_FUNCTION);
×
2761
    IoTDBSqlParser.SubStringExpressionContext subStringExpression =
×
2762
        subStrClause.subStringExpression();
×
2763
    functionExpression.addExpression(parseExpression(subStringExpression.input, canUseFullPath));
×
2764
    if (subStringExpression.startPosition != null) {
×
2765
      functionExpression.addAttribute(SUBSTRING_START, subStringExpression.startPosition.getText());
×
2766
      if (subStringExpression.length != null) {
×
2767
        functionExpression.addAttribute(SUBSTRING_LENGTH, subStringExpression.length.getText());
×
2768
      }
2769
    }
2770
    if (subStringExpression.from != null) {
×
2771
      functionExpression.addAttribute(SUBSTRING_IS_STANDARD, "0");
×
2772
      functionExpression.addAttribute(
×
2773
          SUBSTRING_START, parseStringLiteral(subStringExpression.from.getText()));
×
2774
      if (subStringExpression.forLength != null) {
×
2775
        functionExpression.addAttribute(SUBSTRING_LENGTH, subStringExpression.forLength.getText());
×
2776
      }
2777
    }
2778
    return functionExpression;
×
2779
  }
2780

2781
  private Expression parseRoundFunction(
2782
      IoTDBSqlParser.ScalarFunctionExpressionContext roundClause, boolean canUseFullPath) {
2783
    FunctionExpression functionExpression = new FunctionExpression(ROUND_FUNCTION);
×
2784
    functionExpression.addExpression(parseExpression(roundClause.input, canUseFullPath));
×
2785
    if (roundClause.places != null) {
×
2786
      functionExpression.addAttribute(ROUND_PLACES, parseConstant(roundClause.constant()));
×
2787
    }
2788
    return functionExpression;
×
2789
  }
2790

2791
  private CaseWhenThenExpression parseCaseWhenThenExpression(
2792
      IoTDBSqlParser.CaseWhenThenExpressionContext context, boolean canUseFullPath) {
2793
    // handle CASE
2794
    Expression caseExpression = null;
×
2795
    boolean simpleCase = false;
×
2796
    if (context.caseExpression != null) {
×
2797
      caseExpression = parseExpression(context.caseExpression, canUseFullPath);
×
2798
      simpleCase = true;
×
2799
    }
2800
    // handle WHEN-THEN
2801
    List<WhenThenExpression> whenThenList = new ArrayList<>();
×
2802
    if (simpleCase) {
×
2803
      for (IoTDBSqlParser.WhenThenExpressionContext whenThenExpressionContext :
2804
          context.whenThenExpression()) {
×
2805
        Expression when = parseExpression(whenThenExpressionContext.whenExpression, canUseFullPath);
×
2806
        Expression then = parseExpression(whenThenExpressionContext.thenExpression, canUseFullPath);
×
2807
        Expression comparison = new EqualToExpression(caseExpression, when);
×
2808
        whenThenList.add(new WhenThenExpression(comparison, then));
×
2809
      }
×
2810
    } else {
2811
      for (IoTDBSqlParser.WhenThenExpressionContext whenThenExpressionContext :
2812
          context.whenThenExpression()) {
×
2813
        whenThenList.add(
×
2814
            new WhenThenExpression(
2815
                parseExpression(whenThenExpressionContext.whenExpression, canUseFullPath),
×
2816
                parseExpression(whenThenExpressionContext.thenExpression, canUseFullPath)));
×
2817
      }
×
2818
    }
2819
    // handle ELSE
2820
    Expression elseExpression = new NullOperand();
×
2821
    if (context.elseExpression != null) {
×
2822
      elseExpression = parseExpression(context.elseExpression, canUseFullPath);
×
2823
    }
2824
    return new CaseWhenThenExpression(whenThenList, elseExpression);
×
2825
  }
2826

2827
  private Expression parseFunctionExpression(
2828
      IoTDBSqlParser.ExpressionContext functionClause, boolean canUseFullPath) {
2829
    FunctionExpression functionExpression =
1✔
2830
        new FunctionExpression(parseIdentifier(functionClause.functionName().getText()));
1✔
2831

2832
    // expressions
2833
    boolean hasNonPureConstantSubExpression = false;
1✔
2834
    for (IoTDBSqlParser.ExpressionContext expression : functionClause.expression()) {
1✔
2835
      Expression subexpression = parseExpression(expression, canUseFullPath);
1✔
2836
      if (!subexpression.isConstantOperand()) {
1✔
2837
        hasNonPureConstantSubExpression = true;
1✔
2838
      }
2839
      if (subexpression instanceof EqualToExpression) {
1✔
2840
        Expression subLeftExpression = ((EqualToExpression) subexpression).getLeftExpression();
1✔
2841
        Expression subRightExpression = ((EqualToExpression) subexpression).getRightExpression();
1✔
2842
        if (subLeftExpression.isConstantOperand()
1✔
2843
            && (!(subRightExpression.isConstantOperand()
1✔
2844
                && ((ConstantOperand) subRightExpression).getDataType().equals(TSDataType.TEXT)))) {
1✔
2845
          throw new SemanticException("Attributes of functions should be quoted with '' or \"\"");
×
2846
        }
2847
        if (subLeftExpression.isConstantOperand() && subRightExpression.isConstantOperand()) {
1✔
2848
          // parse attribute
2849
          functionExpression.addAttribute(
1✔
2850
              ((ConstantOperand) subLeftExpression).getValueString(),
1✔
2851
              ((ConstantOperand) subRightExpression).getValueString());
1✔
2852
        } else {
2853
          functionExpression.addExpression(subexpression);
×
2854
        }
2855
      } else {
1✔
2856
        functionExpression.addExpression(subexpression);
1✔
2857
      }
2858
    }
1✔
2859

2860
    // It is not allowed to have function expressions like F(1, 1.0). There should be at least one
2861
    // non-pure-constant sub-expression, otherwise the timestamp of the row cannot be inferred.
2862
    if (!hasNonPureConstantSubExpression) {
1✔
2863
      throw new SemanticException(
×
2864
          "Invalid function expression, all the arguments are constant operands: "
2865
              + functionClause.getText());
×
2866
    }
2867

2868
    // check size of input expressions
2869
    // type check of input expressions is put in ExpressionTypeAnalyzer
2870
    if (functionExpression.isBuiltInAggregationFunctionExpression()) {
1✔
2871
      checkAggregationFunctionInput(functionExpression);
1✔
2872
    } else if (functionExpression.isBuiltInScalarFunction()) {
1✔
2873
      checkBuiltInScalarFunctionInput(functionExpression);
1✔
2874
    }
2875
    return functionExpression;
1✔
2876
  }
2877

2878
  private void checkAggregationFunctionInput(FunctionExpression functionExpression) {
2879
    final String functionName = functionExpression.getFunctionName().toLowerCase();
1✔
2880
    switch (functionName) {
1✔
2881
      case SqlConstant.MIN_TIME:
2882
      case SqlConstant.MAX_TIME:
2883
      case SqlConstant.COUNT:
2884
      case SqlConstant.COUNT_TIME:
2885
      case SqlConstant.MIN_VALUE:
2886
      case SqlConstant.LAST_VALUE:
2887
      case SqlConstant.FIRST_VALUE:
2888
      case SqlConstant.MAX_VALUE:
2889
      case SqlConstant.EXTREME:
2890
      case SqlConstant.AVG:
2891
      case SqlConstant.SUM:
2892
      case SqlConstant.TIME_DURATION:
2893
      case SqlConstant.MODE:
2894
        checkFunctionExpressionInputSize(
1✔
2895
            functionExpression.getExpressionString(),
1✔
2896
            functionExpression.getExpressions().size(),
1✔
2897
            1);
2898
        return;
1✔
2899
      case SqlConstant.COUNT_IF:
2900
        checkFunctionExpressionInputSize(
×
2901
            functionExpression.getExpressionString(),
×
2902
            functionExpression.getExpressions().size(),
×
2903
            2);
2904
        return;
×
2905
      default:
2906
        throw new IllegalArgumentException(
×
2907
            "Invalid Aggregation function: " + functionExpression.getFunctionName());
×
2908
    }
2909
  }
2910

2911
  private void checkBuiltInScalarFunctionInput(FunctionExpression functionExpression) {
2912
    BuiltInScalarFunctionHelperFactory.createHelper(functionExpression.getFunctionName())
1✔
2913
        .checkBuiltInScalarFunctionInputSize(functionExpression);
1✔
2914
  }
1✔
2915

2916
  public static void checkFunctionExpressionInputSize(
2917
      String expressionString, int actual, int... expected) {
2918
    for (int expect : expected) {
1✔
2919
      if (expect == actual) {
1✔
2920
        return;
1✔
2921
      }
2922
    }
2923
    throw new SemanticException(
×
2924
        String.format(
×
2925
            "Error size of input expressions. expression: %s, actual size: %s, expected size: %s.",
2926
            expressionString, actual, Arrays.toString(expected)));
×
2927
  }
2928

2929
  private Expression parseRegularExpression(ExpressionContext context, boolean canUseFullPath) {
2930
    return new RegularExpression(
×
2931
        parseExpression(context.unaryBeforeRegularOrLikeExpression, canUseFullPath),
×
2932
        parseStringLiteral(context.STRING_LITERAL().getText()));
×
2933
  }
2934

2935
  private Expression parseLikeExpression(ExpressionContext context, boolean canUseFullPath) {
2936
    return new LikeExpression(
×
2937
        parseExpression(context.unaryBeforeRegularOrLikeExpression, canUseFullPath),
×
2938
        parseStringLiteral(context.STRING_LITERAL().getText()));
×
2939
  }
2940

2941
  private Expression parseIsNullExpression(ExpressionContext context, boolean canUseFullPath) {
2942
    return new IsNullExpression(
×
2943
        parseExpression(context.unaryBeforeIsNullExpression, canUseFullPath),
×
2944
        context.operator_not() != null);
×
2945
  }
2946

2947
  private Expression parseInExpression(ExpressionContext context, boolean canUseFullPath) {
2948
    Expression childExpression = parseExpression(context.unaryBeforeInExpression, canUseFullPath);
×
2949
    LinkedHashSet<String> values = new LinkedHashSet<>();
×
2950
    for (ConstantContext constantContext : context.constant()) {
×
2951
      values.add(parseConstant(constantContext));
×
2952
    }
×
2953
    return new InExpression(childExpression, context.operator_not() != null, values);
×
2954
  }
2955

2956
  private String parseConstant(ConstantContext constantContext) {
2957
    String text = constantContext.getText();
×
2958
    if (constantContext.boolean_literal() != null
×
2959
        || constantContext.INTEGER_LITERAL() != null
×
2960
        || constantContext.realLiteral() != null) {
×
2961
      return text;
×
2962
    } else if (constantContext.STRING_LITERAL() != null) {
×
2963
      return parseStringLiteral(text);
×
2964
    } else if (constantContext.dateExpression() != null) {
×
2965
      return String.valueOf(parseDateExpression(constantContext.dateExpression()));
×
2966
    } else {
2967
      throw new IllegalArgumentException("Unsupported constant value: " + text);
×
2968
    }
2969
  }
2970

2971
  private Expression parseConstantOperand(ConstantContext constantContext) {
2972
    String text = constantContext.getText();
1✔
2973
    if (constantContext.boolean_literal() != null) {
1✔
2974
      return new ConstantOperand(TSDataType.BOOLEAN, text);
×
2975
    } else if (constantContext.STRING_LITERAL() != null) {
1✔
2976
      return new ConstantOperand(TSDataType.TEXT, parseStringLiteral(text));
1✔
2977
    } else if (constantContext.INTEGER_LITERAL() != null) {
1✔
2978
      return new ConstantOperand(TSDataType.INT64, text);
1✔
2979
    } else if (constantContext.realLiteral() != null) {
×
2980
      return parseRealLiteral(text);
×
2981
    } else if (constantContext.dateExpression() != null) {
×
2982
      return new ConstantOperand(
×
2983
          TSDataType.INT64, String.valueOf(parseDateExpression(constantContext.dateExpression())));
×
2984
    } else {
2985
      throw new SemanticException("Unsupported constant operand: " + text);
×
2986
    }
2987
  }
2988

2989
  private Expression parseRealLiteral(String value) {
2990
    // 3.33 is float by default
2991
    return new ConstantOperand(
×
2992
        CONFIG.getFloatingStringInferType().equals(TSDataType.DOUBLE)
×
2993
            ? TSDataType.DOUBLE
×
2994
            : TSDataType.FLOAT,
×
2995
        value);
2996
  }
2997

2998
  /**
2999
   * parse time expression, which is addition and subtraction expression of duration time, now() or
3000
   * DataTimeFormat time.
3001
   *
3002
   * <p>eg. now() + 1d - 2h
3003
   */
3004
  private Long parseDateExpression(IoTDBSqlParser.DateExpressionContext ctx) {
3005
    long time;
3006
    time = parseDateFormat(ctx.getChild(0).getText());
×
3007
    for (int i = 1; i < ctx.getChildCount(); i = i + 2) {
×
3008
      if ("+".equals(ctx.getChild(i).getText())) {
×
3009
        time += DateTimeUtils.convertDurationStrToLong(time, ctx.getChild(i + 1).getText());
×
3010
      } else {
3011
        time -= DateTimeUtils.convertDurationStrToLong(time, ctx.getChild(i + 1).getText());
×
3012
      }
3013
    }
3014
    return time;
×
3015
  }
3016

3017
  private Long parseDateExpression(IoTDBSqlParser.DateExpressionContext ctx, long currentTime) {
3018
    long time;
3019
    time = parseDateFormat(ctx.getChild(0).getText(), currentTime);
×
3020
    for (int i = 1; i < ctx.getChildCount(); i = i + 2) {
×
3021
      if ("+".equals(ctx.getChild(i).getText())) {
×
3022
        time += DateTimeUtils.convertDurationStrToLong(time, ctx.getChild(i + 1).getText());
×
3023
      } else {
3024
        time -= DateTimeUtils.convertDurationStrToLong(time, ctx.getChild(i + 1).getText());
×
3025
      }
3026
    }
3027
    return time;
×
3028
  }
3029

3030
  private long parseTimeValue(IoTDBSqlParser.TimeValueContext ctx, long currentTime) {
3031
    if (ctx.INTEGER_LITERAL() != null) {
1✔
3032
      try {
3033
        if (ctx.MINUS() != null) {
1✔
3034
          return -Long.parseLong(ctx.INTEGER_LITERAL().getText());
×
3035
        }
3036
        return Long.parseLong(ctx.INTEGER_LITERAL().getText());
1✔
3037
      } catch (NumberFormatException e) {
×
3038
        throw new SemanticException(
×
3039
            String.format("Can not parse %s to long value", ctx.INTEGER_LITERAL().getText()));
×
3040
      }
3041
    } else if (ctx.dateExpression() != null) {
1✔
3042
      return parseDateExpression(ctx.dateExpression(), currentTime);
×
3043
    } else {
3044
      return parseDateFormat(ctx.datetimeLiteral().getText(), currentTime);
1✔
3045
    }
3046
  }
3047

3048
  /** Utils. */
3049
  private void setMap(IoTDBSqlParser.AlterClauseContext ctx, Map<String, String> alterMap) {
3050
    List<IoTDBSqlParser.AttributePairContext> tagsList = ctx.attributePair();
×
3051
    String key;
3052
    if (ctx.attributePair(0) != null) {
×
3053
      for (IoTDBSqlParser.AttributePairContext attributePair : tagsList) {
×
3054
        key = parseAttributeKey(attributePair.attributeKey());
×
3055
        alterMap.computeIfPresent(
×
3056
            key,
3057
            (k, v) -> {
3058
              throw new SemanticException(
×
3059
                  String.format("There's duplicate [%s] in tag or attribute clause.", k));
×
3060
            });
3061
        alterMap.put(key, parseAttributeValue(attributePair.attributeValue()));
×
3062
      }
×
3063
    }
3064
  }
×
3065

3066
  private Map<String, String> extractMap(
3067
      List<IoTDBSqlParser.AttributePairContext> attributePair2,
3068
      IoTDBSqlParser.AttributePairContext attributePair3) {
3069
    Map<String, String> tags = new HashMap<>(attributePair2.size());
1✔
3070
    if (attributePair3 != null) {
1✔
3071
      String key;
3072
      for (IoTDBSqlParser.AttributePairContext attributePair : attributePair2) {
1✔
3073
        key = parseAttributeKey(attributePair.attributeKey());
1✔
3074
        tags.computeIfPresent(
1✔
3075
            key,
3076
            (k, v) -> {
3077
              throw new SemanticException(
×
3078
                  String.format("There's duplicate [%s] in tag or attribute clause.", k));
×
3079
            });
3080
        tags.put(key, parseAttributeValue(attributePair.attributeValue()));
1✔
3081
      }
1✔
3082
    }
3083
    return tags;
1✔
3084
  }
3085

3086
  private String parseAttributeKey(IoTDBSqlParser.AttributeKeyContext ctx) {
3087
    if (ctx.constant() != null) {
1✔
3088
      return parseStringLiteral(ctx.getText());
1✔
3089
    }
3090
    return parseIdentifier(ctx.getText());
×
3091
  }
3092

3093
  private String parseAttributeValue(IoTDBSqlParser.AttributeValueContext ctx) {
3094
    if (ctx.constant() != null) {
1✔
3095
      return parseStringLiteral(ctx.getText());
1✔
3096
    }
3097
    return parseIdentifier(ctx.getText());
×
3098
  }
3099

3100
  // Merge
3101
  @Override
3102
  public Statement visitMerge(IoTDBSqlParser.MergeContext ctx) {
3103
    MergeStatement mergeStatement = new MergeStatement(StatementType.MERGE);
×
3104
    if (ctx.CLUSTER() != null && !IoTDBDescriptor.getInstance().getConfig().isClusterMode()) {
×
3105
      throw new SemanticException("MERGE ON CLUSTER is not supported in standalone mode");
×
3106
    }
3107
    mergeStatement.setOnCluster(ctx.LOCAL() == null);
×
3108
    return mergeStatement;
×
3109
  }
3110

3111
  @Override
3112
  public Statement visitFullMerge(IoTDBSqlParser.FullMergeContext ctx) {
3113
    MergeStatement mergeStatement = new MergeStatement(StatementType.FULL_MERGE);
×
3114
    if (ctx.CLUSTER() != null && !IoTDBDescriptor.getInstance().getConfig().isClusterMode()) {
×
3115
      throw new SemanticException("FULL MERGE ON CLUSTER is not supported in standalone mode");
×
3116
    }
3117
    mergeStatement.setOnCluster(ctx.LOCAL() == null);
×
3118
    return mergeStatement;
×
3119
  }
3120

3121
  // Flush
3122

3123
  @Override
3124
  public Statement visitFlush(IoTDBSqlParser.FlushContext ctx) {
3125
    FlushStatement flushStatement = new FlushStatement(StatementType.FLUSH);
×
3126
    List<PartialPath> storageGroups = null;
×
3127
    if (ctx.boolean_literal() != null) {
×
3128
      flushStatement.setSeq(Boolean.parseBoolean(ctx.boolean_literal().getText()));
×
3129
    }
3130
    if (ctx.CLUSTER() != null && !IoTDBDescriptor.getInstance().getConfig().isClusterMode()) {
×
3131
      throw new SemanticException("FLUSH ON CLUSTER is not supported in standalone mode");
×
3132
    }
3133
    flushStatement.setOnCluster(ctx.LOCAL() == null);
×
3134
    if (ctx.prefixPath(0) != null) {
×
3135
      storageGroups = new ArrayList<>();
×
3136
      for (IoTDBSqlParser.PrefixPathContext prefixPathContext : ctx.prefixPath()) {
×
3137
        storageGroups.add(parsePrefixPath(prefixPathContext));
×
3138
      }
×
3139
    }
3140
    flushStatement.setStorageGroups(storageGroups);
×
3141
    return flushStatement;
×
3142
  }
3143

3144
  // Clear Cache
3145

3146
  @Override
3147
  public Statement visitClearCache(IoTDBSqlParser.ClearCacheContext ctx) {
3148
    ClearCacheStatement clearCacheStatement = new ClearCacheStatement(StatementType.CLEAR_CACHE);
×
3149
    if (ctx.CLUSTER() != null && !IoTDBDescriptor.getInstance().getConfig().isClusterMode()) {
×
3150
      throw new SemanticException("CLEAR CACHE ON CLUSTER is not supported in standalone mode");
×
3151
    }
3152
    clearCacheStatement.setOnCluster(ctx.LOCAL() == null);
×
3153
    return clearCacheStatement;
×
3154
  }
3155

3156
  // Load Configuration
3157

3158
  @Override
3159
  public Statement visitLoadConfiguration(IoTDBSqlParser.LoadConfigurationContext ctx) {
3160
    LoadConfigurationStatement loadConfigurationStatement =
×
3161
        new LoadConfigurationStatement(StatementType.LOAD_CONFIGURATION);
3162
    if (ctx.CLUSTER() != null && !IoTDBDescriptor.getInstance().getConfig().isClusterMode()) {
×
3163
      throw new SemanticException(
×
3164
          "LOAD CONFIGURATION ON CLUSTER is not supported in standalone mode");
3165
    }
3166
    loadConfigurationStatement.setOnCluster(ctx.LOCAL() == null);
×
3167
    return loadConfigurationStatement;
×
3168
  }
3169

3170
  // Set System Status
3171

3172
  @Override
3173
  public Statement visitSetSystemStatus(IoTDBSqlParser.SetSystemStatusContext ctx) {
3174
    SetSystemStatusStatement setSystemStatusStatement = new SetSystemStatusStatement();
×
3175
    if (ctx.CLUSTER() != null && !IoTDBDescriptor.getInstance().getConfig().isClusterMode()) {
×
3176
      throw new SemanticException(
×
3177
          "SET SYSTEM STATUS ON CLUSTER is not supported in standalone mode");
3178
    }
3179
    setSystemStatusStatement.setOnCluster(ctx.LOCAL() == null);
×
3180
    if (ctx.RUNNING() != null) {
×
3181
      setSystemStatusStatement.setStatus(NodeStatus.Running);
×
3182
    } else if (ctx.READONLY() != null) {
×
3183
      setSystemStatusStatement.setStatus(NodeStatus.ReadOnly);
×
3184
    } else {
3185
      throw new SemanticException("Unknown system status in set system command.");
×
3186
    }
3187
    return setSystemStatusStatement;
×
3188
  }
3189

3190
  // Kill Query
3191
  @Override
3192
  public Statement visitKillQuery(IoTDBSqlParser.KillQueryContext ctx) {
3193
    if (ctx.queryId != null) {
×
3194
      return new KillQueryStatement(parseStringLiteral(ctx.queryId.getText()));
×
3195
    }
3196
    return new KillQueryStatement();
×
3197
  }
3198

3199
  // show query processlist
3200

3201
  @Override
3202
  public Statement visitShowQueries(IoTDBSqlParser.ShowQueriesContext ctx) {
3203
    ShowQueriesStatement showQueriesStatement = new ShowQueriesStatement();
×
3204
    // parse WHERE
3205
    if (ctx.whereClause() != null) {
×
3206
      showQueriesStatement.setWhereCondition(parseWhereClause(ctx.whereClause()));
×
3207
    }
3208

3209
    // parse ORDER BY
3210
    if (ctx.orderByClause() != null) {
×
3211
      showQueriesStatement.setOrderByComponent(
×
3212
          parseOrderByClause(
×
3213
              ctx.orderByClause(),
×
3214
              ImmutableSet.of(
×
3215
                  OrderByKey.TIME,
3216
                  OrderByKey.QUERYID,
3217
                  OrderByKey.DATANODEID,
3218
                  OrderByKey.ELAPSEDTIME,
3219
                  OrderByKey.STATEMENT)));
3220
    }
3221

3222
    // parse LIMIT & OFFSET
3223
    if (ctx.rowPaginationClause() != null) {
×
3224
      if (ctx.rowPaginationClause().limitClause() != null) {
×
3225
        showQueriesStatement.setRowLimit(parseLimitClause(ctx.rowPaginationClause().limitClause()));
×
3226
      }
3227
      if (ctx.rowPaginationClause().offsetClause() != null) {
×
3228
        showQueriesStatement.setRowOffset(
×
3229
            parseOffsetClause(ctx.rowPaginationClause().offsetClause()));
×
3230
      }
3231
    }
3232

3233
    showQueriesStatement.setZoneId(zoneId);
×
3234
    return showQueriesStatement;
×
3235
  }
3236

3237
  // show region
3238

3239
  @Override
3240
  public Statement visitShowRegions(IoTDBSqlParser.ShowRegionsContext ctx) {
3241
    ShowRegionStatement showRegionStatement = new ShowRegionStatement();
×
3242
    // TODO: Maybe add a show ConfigNode region in the future
3243
    if (ctx.DATA() != null) {
×
3244
      showRegionStatement.setRegionType(TConsensusGroupType.DataRegion);
×
3245
    } else if (ctx.SCHEMA() != null) {
×
3246
      showRegionStatement.setRegionType(TConsensusGroupType.SchemaRegion);
×
3247
    } else {
3248
      showRegionStatement.setRegionType(null);
×
3249
    }
3250

3251
    if (ctx.OF() != null) {
×
3252
      List<PartialPath> storageGroups = null;
×
3253
      if (ctx.prefixPath(0) != null) {
×
3254
        storageGroups = new ArrayList<>();
×
3255
        for (IoTDBSqlParser.PrefixPathContext prefixPathContext : ctx.prefixPath()) {
×
3256
          storageGroups.add(parsePrefixPath(prefixPathContext));
×
3257
        }
×
3258
      }
3259
      showRegionStatement.setStorageGroups(storageGroups);
×
3260
    } else {
×
3261
      showRegionStatement.setStorageGroups(null);
×
3262
    }
3263

3264
    if (ctx.ON() != null) {
×
3265
      List<Integer> nodeIds = new ArrayList<>();
×
3266
      for (TerminalNode nodeid : ctx.INTEGER_LITERAL()) {
×
3267
        nodeIds.add(Integer.parseInt(nodeid.getText()));
×
3268
      }
×
3269
      showRegionStatement.setNodeIds(nodeIds);
×
3270
    } else {
×
3271
      showRegionStatement.setNodeIds(null);
×
3272
    }
3273
    return showRegionStatement;
×
3274
  }
3275

3276
  // show datanodes
3277

3278
  @Override
3279
  public Statement visitShowDataNodes(IoTDBSqlParser.ShowDataNodesContext ctx) {
3280
    return new ShowDataNodesStatement();
×
3281
  }
3282

3283
  // show confignodes
3284

3285
  @Override
3286
  public Statement visitShowConfigNodes(IoTDBSqlParser.ShowConfigNodesContext ctx) {
3287
    return new ShowConfigNodesStatement();
×
3288
  }
3289

3290
  // schema template
3291

3292
  @Override
3293
  public Statement visitCreateSchemaTemplate(IoTDBSqlParser.CreateSchemaTemplateContext ctx) {
3294
    String name = parseIdentifier(ctx.templateName.getText());
×
3295
    List<List<String>> measurementsList = new ArrayList<>();
×
3296
    List<List<TSDataType>> dataTypesList = new ArrayList<>();
×
3297
    List<List<TSEncoding>> encodingsList = new ArrayList<>();
×
3298
    List<List<CompressionType>> compressorsList = new ArrayList<>();
×
3299

3300
    if (ctx.ALIGNED() != null) {
×
3301
      // aligned
3302
      List<String> measurements = new ArrayList<>();
×
3303
      List<TSDataType> dataTypes = new ArrayList<>();
×
3304
      List<TSEncoding> encodings = new ArrayList<>();
×
3305
      List<CompressionType> compressors = new ArrayList<>();
×
3306
      for (IoTDBSqlParser.TemplateMeasurementClauseContext templateClauseContext :
3307
          ctx.templateMeasurementClause()) {
×
3308
        measurements.add(
×
3309
            parseNodeNameWithoutWildCard(templateClauseContext.nodeNameWithoutWildcard()));
×
3310
        parseAttributeClauseForSchemaTemplate(
×
3311
            templateClauseContext.attributeClauses(), dataTypes, encodings, compressors);
×
3312
      }
×
3313
      measurementsList.add(measurements);
×
3314
      dataTypesList.add(dataTypes);
×
3315
      encodingsList.add(encodings);
×
3316
      compressorsList.add(compressors);
×
3317
    } else {
×
3318
      // non-aligned
3319
      for (IoTDBSqlParser.TemplateMeasurementClauseContext templateClauseContext :
3320
          ctx.templateMeasurementClause()) {
×
3321
        List<String> measurements = new ArrayList<>();
×
3322
        List<TSDataType> dataTypes = new ArrayList<>();
×
3323
        List<TSEncoding> encodings = new ArrayList<>();
×
3324
        List<CompressionType> compressors = new ArrayList<>();
×
3325
        measurements.add(
×
3326
            parseNodeNameWithoutWildCard(templateClauseContext.nodeNameWithoutWildcard()));
×
3327
        parseAttributeClauseForSchemaTemplate(
×
3328
            templateClauseContext.attributeClauses(), dataTypes, encodings, compressors);
×
3329
        measurementsList.add(measurements);
×
3330
        dataTypesList.add(dataTypes);
×
3331
        encodingsList.add(encodings);
×
3332
        compressorsList.add(compressors);
×
3333
      }
×
3334
    }
3335

3336
    return new CreateSchemaTemplateStatement(
×
3337
        name,
3338
        measurementsList,
3339
        dataTypesList,
3340
        encodingsList,
3341
        compressorsList,
3342
        ctx.ALIGNED() != null);
×
3343
  }
3344

3345
  @Override
3346
  public Statement visitAlterSchemaTemplate(IoTDBSqlParser.AlterSchemaTemplateContext ctx) {
3347
    String name = parseIdentifier(ctx.templateName.getText());
×
3348
    List<String> measurements = new ArrayList<>();
×
3349
    List<TSDataType> dataTypes = new ArrayList<>();
×
3350
    List<TSEncoding> encodings = new ArrayList<>();
×
3351
    List<CompressionType> compressors = new ArrayList<>();
×
3352

3353
    for (IoTDBSqlParser.TemplateMeasurementClauseContext templateClauseContext :
3354
        ctx.templateMeasurementClause()) {
×
3355
      measurements.add(
×
3356
          parseNodeNameWithoutWildCard(templateClauseContext.nodeNameWithoutWildcard()));
×
3357
      parseAttributeClauseForSchemaTemplate(
×
3358
          templateClauseContext.attributeClauses(), dataTypes, encodings, compressors);
×
3359
    }
×
3360

3361
    return new AlterSchemaTemplateStatement(
×
3362
        name,
3363
        measurements,
3364
        dataTypes,
3365
        encodings,
3366
        compressors,
3367
        TemplateAlterOperationType.EXTEND_TEMPLATE);
3368
  }
3369

3370
  void parseAttributeClauseForSchemaTemplate(
3371
      IoTDBSqlParser.AttributeClausesContext ctx,
3372
      List<TSDataType> dataTypes,
3373
      List<TSEncoding> encodings,
3374
      List<CompressionType> compressors) {
3375
    if (ctx.aliasNodeName() != null) {
×
3376
      throw new SemanticException("Schema template: alias is not supported yet.");
×
3377
    }
3378

3379
    TSDataType dataType = parseDataTypeAttribute(ctx);
×
3380
    dataTypes.add(dataType);
×
3381

3382
    Map<String, String> props = new HashMap<>();
×
3383
    if (ctx.attributePair() != null) {
×
3384
      for (int i = 0; i < ctx.attributePair().size(); i++) {
×
3385
        props.put(
×
3386
            parseAttributeKey(ctx.attributePair(i).attributeKey()).toLowerCase(),
×
3387
            parseAttributeValue(ctx.attributePair(i).attributeValue()));
×
3388
      }
3389
    }
3390

3391
    TSEncoding encoding = IoTDBDescriptor.getInstance().getDefaultEncodingByType(dataType);
×
3392
    if (props.containsKey(IoTDBConstant.COLUMN_TIMESERIES_ENCODING.toLowerCase())) {
×
3393
      String encodingString =
×
3394
          props.get(IoTDBConstant.COLUMN_TIMESERIES_ENCODING.toLowerCase()).toUpperCase();
×
3395
      try {
3396
        encoding = TSEncoding.valueOf(encodingString);
×
3397
        encodings.add(encoding);
×
3398
        props.remove(IoTDBConstant.COLUMN_TIMESERIES_ENCODING.toLowerCase());
×
3399
      } catch (Exception e) {
×
3400
        throw new SemanticException(String.format("Unsupported encoding: %s", encodingString));
×
3401
      }
×
3402
    } else {
×
3403
      encodings.add(encoding);
×
3404
    }
3405

3406
    CompressionType compressor = TSFileDescriptor.getInstance().getConfig().getCompressor();
×
3407
    if (props.containsKey(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSOR.toLowerCase())) {
×
3408
      String compressorString =
×
3409
          props.get(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSOR.toLowerCase()).toUpperCase();
×
3410
      try {
3411
        compressor = CompressionType.valueOf(compressorString);
×
3412
        compressors.add(compressor);
×
3413
        props.remove(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSOR.toLowerCase());
×
3414
      } catch (Exception e) {
×
3415
        throw new SemanticException(String.format("Unsupported compressor: %s", compressorString));
×
3416
      }
×
3417
    } else if (props.containsKey(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSION.toLowerCase())) {
×
3418
      String compressionString =
×
3419
          props.get(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSION.toLowerCase()).toUpperCase();
×
3420
      try {
3421
        compressor = CompressionType.valueOf(compressionString);
×
3422
        compressors.add(compressor);
×
3423
        props.remove(IoTDBConstant.COLUMN_TIMESERIES_COMPRESSION.toLowerCase());
×
3424
      } catch (Exception e) {
×
3425
        throw new SemanticException(
×
3426
            String.format("Unsupported compression: %s", compressionString));
×
3427
      }
×
3428
    } else {
×
3429
      compressors.add(compressor);
×
3430
    }
3431

3432
    if (props.size() > 0) {
×
3433
      throw new SemanticException("Schema template: property is not supported yet.");
×
3434
    }
3435

3436
    if (ctx.tagClause() != null) {
×
3437
      throw new SemanticException("Schema template: tag is not supported yet.");
×
3438
    }
3439

3440
    if (ctx.attributeClause() != null) {
×
3441
      throw new SemanticException("Schema template: attribute is not supported yet.");
×
3442
    }
3443
  }
×
3444

3445
  private TSDataType parseDataTypeAttribute(IoTDBSqlParser.AttributeClausesContext ctx) {
3446
    TSDataType dataType = null;
1✔
3447
    if (ctx.dataType != null) {
1✔
3448
      if (ctx.attributeKey() != null
1✔
3449
          && !parseAttributeKey(ctx.attributeKey())
×
3450
              .equalsIgnoreCase(IoTDBConstant.COLUMN_TIMESERIES_DATATYPE)) {
×
3451
        throw new SemanticException("Expecting datatype");
×
3452
      }
3453
      String dataTypeString = ctx.dataType.getText().toUpperCase();
1✔
3454
      try {
3455
        dataType = TSDataType.valueOf(dataTypeString);
1✔
3456
      } catch (Exception e) {
×
3457
        throw new SemanticException(String.format("Unsupported datatype: %s", dataTypeString));
×
3458
      }
1✔
3459
    }
3460
    return dataType;
1✔
3461
  }
3462

3463
  @Override
3464
  public Statement visitShowSchemaTemplates(IoTDBSqlParser.ShowSchemaTemplatesContext ctx) {
3465
    return new ShowSchemaTemplateStatement();
×
3466
  }
3467

3468
  @Override
3469
  public Statement visitShowNodesInSchemaTemplate(
3470
      IoTDBSqlParser.ShowNodesInSchemaTemplateContext ctx) {
3471
    String templateName = parseIdentifier(ctx.templateName.getText());
×
3472
    return new ShowNodesInSchemaTemplateStatement(templateName);
×
3473
  }
3474

3475
  @Override
3476
  public Statement visitSetSchemaTemplate(IoTDBSqlParser.SetSchemaTemplateContext ctx) {
3477
    String templateName = parseIdentifier(ctx.templateName.getText());
×
3478
    return new SetSchemaTemplateStatement(templateName, parsePrefixPath(ctx.prefixPath()));
×
3479
  }
3480

3481
  @Override
3482
  public Statement visitShowPathsSetSchemaTemplate(
3483
      IoTDBSqlParser.ShowPathsSetSchemaTemplateContext ctx) {
3484
    String templateName = parseIdentifier(ctx.templateName.getText());
×
3485
    return new ShowPathSetTemplateStatement(templateName);
×
3486
  }
3487

3488
  @Override
3489
  public Statement visitCreateTimeseriesUsingSchemaTemplate(
3490
      IoTDBSqlParser.CreateTimeseriesUsingSchemaTemplateContext ctx) {
3491
    ActivateTemplateStatement statement = new ActivateTemplateStatement();
×
3492
    statement.setPath(parsePrefixPath(ctx.prefixPath()));
×
3493
    return statement;
×
3494
  }
3495

3496
  @Override
3497
  public Statement visitShowPathsUsingSchemaTemplate(
3498
      IoTDBSqlParser.ShowPathsUsingSchemaTemplateContext ctx) {
3499
    PartialPath pathPattern;
3500
    if (ctx.prefixPath() == null) {
×
3501
      pathPattern = new PartialPath(SqlConstant.getSingleRootArray());
×
3502
    } else {
3503
      pathPattern = parsePrefixPath(ctx.prefixPath());
×
3504
    }
3505
    return new ShowPathsUsingTemplateStatement(
×
3506
        pathPattern, parseIdentifier(ctx.templateName.getText()));
×
3507
  }
3508

3509
  @Override
3510
  public Statement visitDropTimeseriesOfSchemaTemplate(
3511
      IoTDBSqlParser.DropTimeseriesOfSchemaTemplateContext ctx) {
3512
    DeactivateTemplateStatement statement = new DeactivateTemplateStatement();
×
3513
    if (ctx.templateName != null) {
×
3514
      statement.setTemplateName(parseIdentifier(ctx.templateName.getText()));
×
3515
    }
3516
    List<PartialPath> pathPatternList = new ArrayList<>();
×
3517
    for (IoTDBSqlParser.PrefixPathContext prefixPathContext : ctx.prefixPath()) {
×
3518
      pathPatternList.add(parsePrefixPath(prefixPathContext));
×
3519
    }
×
3520
    statement.setPathPatternList(pathPatternList);
×
3521
    return statement;
×
3522
  }
3523

3524
  @Override
3525
  public Statement visitUnsetSchemaTemplate(IoTDBSqlParser.UnsetSchemaTemplateContext ctx) {
3526
    String templateName = parseIdentifier(ctx.templateName.getText());
×
3527
    PartialPath path = parsePrefixPath(ctx.prefixPath());
×
3528
    return new UnsetSchemaTemplateStatement(templateName, path);
×
3529
  }
3530

3531
  @Override
3532
  public Statement visitDropSchemaTemplate(IoTDBSqlParser.DropSchemaTemplateContext ctx) {
3533
    return new DropSchemaTemplateStatement(parseIdentifier(ctx.templateName.getText()));
×
3534
  }
3535

3536
  public Map<String, String> parseSyncAttributeClauses(
3537
      IoTDBSqlParser.SyncAttributeClausesContext ctx) {
3538

3539
    Map<String, String> attributes = new HashMap<>();
×
3540

3541
    List<IoTDBSqlParser.AttributePairContext> attributePairs = ctx.attributePair();
×
3542
    if (ctx.attributePair(0) != null) {
×
3543
      for (IoTDBSqlParser.AttributePairContext attributePair : attributePairs) {
×
3544
        attributes.put(
×
3545
            parseAttributeKey(attributePair.attributeKey()).toLowerCase(),
×
3546
            parseAttributeValue(attributePair.attributeValue()).toLowerCase());
×
3547
      }
×
3548
    }
3549

3550
    return attributes;
×
3551
  }
3552

3553
  // PIPE
3554

3555
  @Override
3556
  public Statement visitCreatePipe(IoTDBSqlParser.CreatePipeContext ctx) {
3557
    final CreatePipeStatement createPipeStatement =
×
3558
        new CreatePipeStatement(StatementType.CREATE_PIPE);
3559

3560
    if (ctx.pipeName != null) {
×
3561
      createPipeStatement.setPipeName(ctx.pipeName.getText());
×
3562
    } else {
3563
      throw new SemanticException(
×
3564
          "Not support for this sql in CREATEPIPE, please enter pipe name.");
3565
    }
3566
    if (ctx.extractorAttributesClause() != null) {
×
3567
      createPipeStatement.setExtractorAttributes(
×
3568
          parseExtractorAttributesClause(ctx.extractorAttributesClause()));
×
3569
    } else {
3570
      createPipeStatement.setExtractorAttributes(new HashMap<>());
×
3571
    }
3572
    if (ctx.processorAttributesClause() != null) {
×
3573
      createPipeStatement.setProcessorAttributes(
×
3574
          parseProcessorAttributesClause(ctx.processorAttributesClause()));
×
3575
    } else {
3576
      createPipeStatement.setProcessorAttributes(new HashMap<>());
×
3577
    }
3578
    createPipeStatement.setConnectorAttributes(
×
3579
        parseConnectorAttributesClause(ctx.connectorAttributesClause()));
×
3580
    return createPipeStatement;
×
3581
  }
3582

3583
  private Map<String, String> parseExtractorAttributesClause(
3584
      IoTDBSqlParser.ExtractorAttributesClauseContext ctx) {
3585
    final Map<String, String> collectorMap = new HashMap<>();
×
3586
    for (IoTDBSqlParser.ExtractorAttributeClauseContext singleCtx :
3587
        ctx.extractorAttributeClause()) {
×
3588
      collectorMap.put(
×
3589
          parseStringLiteral(singleCtx.extractorKey.getText()),
×
3590
          parseStringLiteral(singleCtx.extractorValue.getText()));
×
3591
    }
×
3592
    return collectorMap;
×
3593
  }
3594

3595
  private Map<String, String> parseProcessorAttributesClause(
3596
      IoTDBSqlParser.ProcessorAttributesClauseContext ctx) {
3597
    final Map<String, String> processorMap = new HashMap<>();
×
3598
    for (IoTDBSqlParser.ProcessorAttributeClauseContext singleCtx :
3599
        ctx.processorAttributeClause()) {
×
3600
      processorMap.put(
×
3601
          parseStringLiteral(singleCtx.processorKey.getText()),
×
3602
          parseStringLiteral(singleCtx.processorValue.getText()));
×
3603
    }
×
3604
    return processorMap;
×
3605
  }
3606

3607
  private Map<String, String> parseConnectorAttributesClause(
3608
      IoTDBSqlParser.ConnectorAttributesClauseContext ctx) {
3609
    final Map<String, String> connectorMap = new HashMap<>();
×
3610
    for (IoTDBSqlParser.ConnectorAttributeClauseContext singleCtx :
3611
        ctx.connectorAttributeClause()) {
×
3612
      connectorMap.put(
×
3613
          parseStringLiteral(singleCtx.connectorKey.getText()),
×
3614
          parseStringLiteral(singleCtx.connectorValue.getText()));
×
3615
    }
×
3616
    return connectorMap;
×
3617
  }
3618

3619
  @Override
3620
  public Statement visitDropPipe(IoTDBSqlParser.DropPipeContext ctx) {
3621
    final DropPipeStatement dropPipeStatement = new DropPipeStatement(StatementType.DROP_PIPE);
×
3622

3623
    if (ctx.pipeName != null) {
×
3624
      dropPipeStatement.setPipeName(ctx.pipeName.getText());
×
3625
    } else {
3626
      throw new SemanticException("Not support for this sql in DROP PIPE, please enter pipename.");
×
3627
    }
3628

3629
    return dropPipeStatement;
×
3630
  }
3631

3632
  @Override
3633
  public Statement visitStartPipe(IoTDBSqlParser.StartPipeContext ctx) {
3634
    final StartPipeStatement startPipeStatement = new StartPipeStatement(StatementType.START_PIPE);
×
3635

3636
    if (ctx.pipeName != null) {
×
3637
      startPipeStatement.setPipeName(ctx.pipeName.getText());
×
3638
    } else {
3639
      throw new SemanticException("Not support for this sql in START PIPE, please enter pipename.");
×
3640
    }
3641

3642
    return startPipeStatement;
×
3643
  }
3644

3645
  @Override
3646
  public Statement visitStopPipe(IoTDBSqlParser.StopPipeContext ctx) {
3647
    final StopPipeStatement stopPipeStatement = new StopPipeStatement(StatementType.STOP_PIPE);
×
3648

3649
    if (ctx.pipeName != null) {
×
3650
      stopPipeStatement.setPipeName(ctx.pipeName.getText());
×
3651
    } else {
3652
      throw new SemanticException("Not support for this sql in STOP PIPE, please enter pipename.");
×
3653
    }
3654

3655
    return stopPipeStatement;
×
3656
  }
3657

3658
  @Override
3659
  public Statement visitShowPipes(IoTDBSqlParser.ShowPipesContext ctx) {
3660
    final ShowPipesStatement showPipesStatement = new ShowPipesStatement();
×
3661

3662
    if (ctx.pipeName != null) {
×
3663
      showPipesStatement.setPipeName(parseIdentifier(ctx.pipeName.getText()));
×
3664
    }
3665
    showPipesStatement.setWhereClause(ctx.CONNECTOR() != null);
×
3666

3667
    return showPipesStatement;
×
3668
  }
3669

3670
  @Override
3671
  public Statement visitGetRegionId(IoTDBSqlParser.GetRegionIdContext ctx) {
3672
    TConsensusGroupType type =
3673
        ctx.DATA() == null ? TConsensusGroupType.SchemaRegion : TConsensusGroupType.DataRegion;
×
3674
    GetRegionIdStatement getRegionIdStatement = new GetRegionIdStatement(type);
×
3675
    if (ctx.database != null) {
×
3676
      getRegionIdStatement.setDatabase(ctx.database.getText());
×
3677
    } else {
3678
      getRegionIdStatement.setDevice(ctx.device.getText());
×
3679
    }
3680
    if (ctx.time != null) {
×
3681
      long timestamp = parseTimeValue(ctx.time, DateTimeUtils.currentTime());
×
3682
      getRegionIdStatement.setTimeStamp(timestamp);
×
3683
    }
3684
    return getRegionIdStatement;
×
3685
  }
3686

3687
  @Override
3688
  public Statement visitGetSeriesSlotList(IoTDBSqlParser.GetSeriesSlotListContext ctx) {
3689
    TConsensusGroupType type =
3690
        ctx.DATA() == null ? TConsensusGroupType.SchemaRegion : TConsensusGroupType.DataRegion;
×
3691
    return new GetSeriesSlotListStatement(ctx.database.getText(), type);
×
3692
  }
3693

3694
  @Override
3695
  public Statement visitGetTimeSlotList(IoTDBSqlParser.GetTimeSlotListContext ctx) {
3696
    GetTimeSlotListStatement getTimeSlotListStatement = new GetTimeSlotListStatement();
×
3697
    if (ctx.database != null) {
×
3698
      getTimeSlotListStatement.setDatabase(ctx.database.getText());
×
3699
    } else if (ctx.device != null) {
×
3700
      getTimeSlotListStatement.setDevice(ctx.device.getText());
×
3701
    } else if (ctx.regionId != null) {
×
3702
      getTimeSlotListStatement.setRegionId(Integer.parseInt(ctx.regionId.getText()));
×
3703
    }
3704
    if (ctx.startTime != null) {
×
3705
      long timestamp = parseTimeValue(ctx.startTime, DateTimeUtils.currentTime());
×
3706
      getTimeSlotListStatement.setStartTime(timestamp);
×
3707
    }
3708
    if (ctx.endTime != null) {
×
3709
      long timestamp = parseTimeValue(ctx.endTime, DateTimeUtils.currentTime());
×
3710
      getTimeSlotListStatement.setEndTime(timestamp);
×
3711
    }
3712
    return getTimeSlotListStatement;
×
3713
  }
3714

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

3734
  @Override
3735
  public Statement visitMigrateRegion(IoTDBSqlParser.MigrateRegionContext ctx) {
3736
    return new MigrateRegionStatement(
×
3737
        Integer.parseInt(ctx.regionId.getText()),
×
3738
        Integer.parseInt(ctx.fromId.getText()),
×
3739
        Integer.parseInt(ctx.toId.getText()));
×
3740
  }
3741

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

3756
    Map<String, String> quotas = new HashMap<>();
×
3757
    for (IoTDBSqlParser.AttributePairContext attributePair : ctx.attributePair()) {
×
3758
      quotas.put(
×
3759
          parseAttributeKey(attributePair.attributeKey()),
×
3760
          parseAttributeValue(attributePair.attributeValue()));
×
3761
    }
×
3762

3763
    quotas
×
3764
        .keySet()
×
3765
        .forEach(
×
3766
            quotaType -> {
3767
              switch (quotaType) {
×
3768
                case IoTDBConstant.COLUMN_DEVICES:
3769
                  break;
×
3770
                case IoTDBConstant.COLUMN_TIMESERIES:
3771
                  break;
×
3772
                case IoTDBConstant.SPACE_QUOTA_DISK:
3773
                  break;
×
3774
                default:
3775
                  throw new SemanticException("Wrong space quota type: " + quotaType);
×
3776
              }
3777
            });
×
3778

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

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

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

3885
    if (quotas.containsKey(IoTDBConstant.MEMORY_SIZE_PER_READ)) {
×
3886
      String mem = quotas.get(IoTDBConstant.MEMORY_SIZE_PER_READ);
×
3887
      if (mem.equals(IoTDBConstant.QUOTA_UNLIMITED)) {
×
3888
        setThrottleQuotaStatement.setMemLimit(IoTDBConstant.UNLIMITED_VALUE);
×
3889
      } else {
3890
        setThrottleQuotaStatement.setMemLimit(parseThrottleQuotaSizeUnit(mem));
×
3891
      }
3892
    }
3893

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

3910
  @Override
3911
  public Statement visitShowThrottleQuota(IoTDBSqlParser.ShowThrottleQuotaContext ctx) {
3912
    if (!IoTDBDescriptor.getInstance().getConfig().isQuotaEnable()) {
×
3913
      throw new SemanticException(LIMIT_CONFIGURATION_ENABLED_ERROR_MSG);
×
3914
    }
3915
    ShowThrottleQuotaStatement showThrottleQuotaStatement = new ShowThrottleQuotaStatement();
×
3916
    if (ctx.userName != null) {
×
3917
      showThrottleQuotaStatement.setUserName(parseIdentifier(ctx.userName.getText()));
×
3918
    }
3919
    return showThrottleQuotaStatement;
×
3920
  }
3921

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

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

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

3984
  @Override
3985
  public Statement visitShowSpaceQuota(IoTDBSqlParser.ShowSpaceQuotaContext ctx) {
3986
    if (!IoTDBDescriptor.getInstance().getConfig().isQuotaEnable()) {
×
3987
      throw new SemanticException(LIMIT_CONFIGURATION_ENABLED_ERROR_MSG);
×
3988
    }
3989
    ShowSpaceQuotaStatement showSpaceQuotaStatement = new ShowSpaceQuotaStatement();
×
3990
    if (ctx.prefixPath() != null) {
×
3991
      List<PartialPath> databases = new ArrayList<>();
×
3992
      for (IoTDBSqlParser.PrefixPathContext prefixPathContext : ctx.prefixPath()) {
×
3993
        databases.add(parsePrefixPath(prefixPathContext));
×
3994
      }
×
3995
      showSpaceQuotaStatement.setDatabases(databases);
×
3996
    } else {
×
3997
      showSpaceQuotaStatement.setDatabases(null);
×
3998
    }
3999
    return showSpaceQuotaStatement;
×
4000
  }
4001
}
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

© 2026 Coveralls, Inc