This is an automated email from the ASF dual-hosted git repository. qiaojialin pushed a commit to branch show_limit in repository https://gitbox.apache.org/repos/asf/incubator-iotdb.git
commit 9006c520314891294927a539485fa6c433393782 Author: qiaojialin <[email protected]> AuthorDate: Wed Apr 22 14:02:35 2020 +0800 add limit&slimit to show timeseries --- .../org/apache/iotdb/db/qp/strategy/SqlBase.g4 | 4 +- .../org/apache/iotdb/db/metadata/MManager.java | 43 ++++++++++++++-------- .../apache/iotdb/db/qp/executor/PlanExecutor.java | 2 +- .../db/qp/logical/sys/ShowTimeSeriesOperator.java | 18 +++++++++ .../db/qp/physical/sys/ShowTimeSeriesPlan.java | 22 +++++++++-- .../iotdb/db/qp/strategy/LogicalGenerator.java | 22 +++++++---- .../iotdb/db/qp/strategy/PhysicalGenerator.java | 5 ++- .../iotdb/db/integration/IoTDBSimpleQueryIT.java | 25 +++++++++++++ .../iotdb/db/qp/plan/LogicalPlanSmallTest.java | 8 ++-- .../apache/iotdb/db/qp/plan/PhysicalPlanTest.java | 11 ++++++ 10 files changed, 127 insertions(+), 33 deletions(-) diff --git a/server/src/main/antlr4/org/apache/iotdb/db/qp/strategy/SqlBase.g4 b/server/src/main/antlr4/org/apache/iotdb/db/qp/strategy/SqlBase.g4 index 34fbee9..a505f87 100644 --- a/server/src/main/antlr4/org/apache/iotdb/db/qp/strategy/SqlBase.g4 +++ b/server/src/main/antlr4/org/apache/iotdb/db/qp/strategy/SqlBase.g4 @@ -65,7 +65,7 @@ statement | SHOW FLUSH TASK INFO #showFlushTaskInfo | SHOW DYNAMIC PARAMETER #showDynamicParameter | SHOW VERSION #showVersion - | SHOW TIMESERIES prefixPath? showWhereClause? #showTimeseries + | SHOW TIMESERIES prefixPath? showWhereClause? limitClause? #showTimeseries | SHOW STORAGE GROUP #showStorageGroup | SHOW CHILD PATHS prefixPath? #showChildPaths | SHOW DEVICES prefixPath? #showDevices @@ -189,6 +189,7 @@ specialLimit limitClause : LIMIT INT offsetClause? + | offsetClause? LIMIT INT ; offsetClause @@ -197,6 +198,7 @@ offsetClause slimitClause : SLIMIT INT soffsetClause? + | soffsetClause? SLIMIT INT ; soffsetClause diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java b/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java index 110e3d2..8cdc136 100644 --- a/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java +++ b/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java @@ -738,29 +738,42 @@ public class MManager { } /** - * Get all timeseries paths under the given path. + * Get the result of ShowTimeseriesPlan * - * @param path can be root, root.* root.*.*.a etc.. if the wildcard is not at the tail, then each - * wildcard can only match one level, otherwise it can match to the tail. + * @param plan show time series query plan */ - public List<ShowTimeSeriesResult> getAllTimeseriesSchema(String path) throws MetadataException { + public List<ShowTimeSeriesResult> showTimeseries(ShowTimeSeriesPlan plan) throws MetadataException { lock.readLock().lock(); try { - List<String[]> ans = mtree.getAllMeasurementSchema(path); + List<String[]> ans = mtree.getAllMeasurementSchema(plan.getPath().getFullPath()); + int count = 0; + int offset = plan.getOffset(); List<ShowTimeSeriesResult> res = new LinkedList<>(); - for (String[] ansString : ans) { - long offset = Long.parseLong(ansString[6]); + for (int i = 0; i < ans.size(); i++) { + if (i < offset) { + continue; + } + + String[] ansString = ans.get(i); + if (count >= plan.getLimit()) { + return res; + } + + long tagFileOffset = Long.parseLong(ansString[6]); try { - if (offset < 0) { + if (tagFileOffset < 0) { + // no tags/attributes + res.add(new ShowTimeSeriesResult(ansString[0], ansString[1], ansString[2], + ansString[3], ansString[4], ansString[5], Collections.emptyMap())); + } else { + // has tags/attributes + Pair<Map<String, String>, Map<String, String>> pair = + tagLogFile.read(config.getTagAttributeTotalSize(), tagFileOffset); + pair.left.putAll(pair.right); res.add(new ShowTimeSeriesResult(ansString[0], ansString[1], ansString[2], - ansString[3], ansString[4], ansString[5], Collections.emptyMap())); - continue; + ansString[3], ansString[4], ansString[5], pair.left)); } - Pair<Map<String, String>, Map<String, String>> pair = - tagLogFile.read(config.getTagAttributeTotalSize(), offset); - pair.left.putAll(pair.right); - res.add(new ShowTimeSeriesResult(ansString[0], ansString[1], ansString[2], - ansString[3], ansString[4], ansString[5], pair.left)); + count ++; } catch (IOException e) { throw new MetadataException( "Something went wrong while deserialize tag info of " + ansString[0], e); diff --git a/server/src/main/java/org/apache/iotdb/db/qp/executor/PlanExecutor.java b/server/src/main/java/org/apache/iotdb/db/qp/executor/PlanExecutor.java index fb3c57d..551cf5a 100644 --- a/server/src/main/java/org/apache/iotdb/db/qp/executor/PlanExecutor.java +++ b/server/src/main/java/org/apache/iotdb/db/qp/executor/PlanExecutor.java @@ -367,7 +367,7 @@ public class PlanExecutor implements IPlanExecutor { private QueryDataSet processShowTimeseries(ShowTimeSeriesPlan timeSeriesPlan) throws MetadataException { List<ShowTimeSeriesResult> timeseriesList = MManager.getInstance() - .getAllTimeseriesSchema(timeSeriesPlan.getPath().toString()); + .showTimeseries(timeSeriesPlan); return getQueryDataSet(timeseriesList); } diff --git a/server/src/main/java/org/apache/iotdb/db/qp/logical/sys/ShowTimeSeriesOperator.java b/server/src/main/java/org/apache/iotdb/db/qp/logical/sys/ShowTimeSeriesOperator.java index be6083b..3701941 100644 --- a/server/src/main/java/org/apache/iotdb/db/qp/logical/sys/ShowTimeSeriesOperator.java +++ b/server/src/main/java/org/apache/iotdb/db/qp/logical/sys/ShowTimeSeriesOperator.java @@ -27,6 +27,8 @@ public class ShowTimeSeriesOperator extends ShowOperator { private boolean isContains; private String key; private String value; + private int limit = Integer.MAX_VALUE; + private int offset = 0; public ShowTimeSeriesOperator(int tokeIntType, Path path) { super(tokeIntType); @@ -60,4 +62,20 @@ public class ShowTimeSeriesOperator extends ShowOperator { public void setValue(String value) { this.value = value; } + + public int getLimit() { + return limit; + } + + public void setLimit(int limit) { + this.limit = limit; + } + + public int getOffset() { + return offset; + } + + public void setOffset(int offset) { + this.offset = offset; + } } diff --git a/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/ShowTimeSeriesPlan.java b/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/ShowTimeSeriesPlan.java index 3610a61..48a6491 100644 --- a/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/ShowTimeSeriesPlan.java +++ b/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/ShowTimeSeriesPlan.java @@ -20,18 +20,26 @@ package org.apache.iotdb.db.qp.physical.sys; import org.apache.iotdb.tsfile.read.common.Path; -public class ShowTimeSeriesPlan extends ShowPlan{ +public class ShowTimeSeriesPlan extends ShowPlan { + + // path can be root, root.* root.*.*.a etc.. if the wildcard is not at the tail, then each + // * wildcard can only match one level, otherwise it can match to the tail. private Path path; private boolean isContains; private String key; private String value; + private int limit; + private int offset; - public ShowTimeSeriesPlan(ShowContentType showContentType, Path path, boolean isContains, String key, String value) { + public ShowTimeSeriesPlan(ShowContentType showContentType, Path path, boolean isContains, + String key, String value, int limit, int offset) { super(showContentType); this.path = path; this.isContains = isContains; this.key = key; this.value = value; + this.limit = limit; + this.offset = offset; } public Path getPath() { @@ -49,4 +57,12 @@ public class ShowTimeSeriesPlan extends ShowPlan{ public String getValue() { return value; } -} + + public int getLimit() { + return limit; + } + + public int getOffset() { + return offset; + } +} \ No newline at end of file diff --git a/server/src/main/java/org/apache/iotdb/db/qp/strategy/LogicalGenerator.java b/server/src/main/java/org/apache/iotdb/db/qp/strategy/LogicalGenerator.java index 330345a..3769fcb 100644 --- a/server/src/main/java/org/apache/iotdb/db/qp/strategy/LogicalGenerator.java +++ b/server/src/main/java/org/apache/iotdb/db/qp/strategy/LogicalGenerator.java @@ -738,7 +738,11 @@ public class LogicalGenerator extends SqlBaseBaseListener { if (limit <= 0) { throw new SQLParserException("LIMIT <N>: N should be greater than 0."); } - queryOp.setRowLimit(limit); + if (initializedOperator instanceof ShowTimeSeriesOperator) { + ((ShowTimeSeriesOperator) initializedOperator).setLimit(limit); + } else { + queryOp.setRowLimit(limit); + } } @Override @@ -751,10 +755,14 @@ public class LogicalGenerator extends SqlBaseBaseListener { throw new SQLParserException( "Out of range. OFFSET <OFFSETValue>: OFFSETValue should be Int32."); } - if (offset <= 0) { - throw new SQLParserException("OFFSET <OFFSETValue>: OFFSETValue should be greater than 0."); + if (offset < 0) { + throw new SQLParserException("OFFSET <OFFSETValue>: OFFSETValue should >= 0."); + } + if (initializedOperator instanceof ShowTimeSeriesOperator) { + ((ShowTimeSeriesOperator) initializedOperator).setOffset(offset); + } else { + queryOp.setRowOffset(offset); } - queryOp.setRowOffset(offset); } @Override @@ -783,9 +791,9 @@ public class LogicalGenerator extends SqlBaseBaseListener { throw new SQLParserException( "Out of range. SOFFSET <SOFFSETValue>: SOFFSETValue should be Int32."); } - if (soffset <= 0) { + if (soffset < 0) { throw new SQLParserException( - "SOFFSET <SOFFSETValue>: SOFFSETValue should be greater than 0."); + "SOFFSET <SOFFSETValue>: SOFFSETValue should >= 0."); } queryOp.setSeriesOffset(soffset); } @@ -1067,7 +1075,7 @@ public class LogicalGenerator extends SqlBaseBaseListener { } @Override - public void enterShowWhereClause(SqlBaseParser.ShowWhereClauseContext ctx) { + public void enterShowWhereClause(ShowWhereClauseContext ctx) { super.enterShowWhereClause(ctx); ShowTimeSeriesOperator operator = (ShowTimeSeriesOperator) initializedOperator; diff --git a/server/src/main/java/org/apache/iotdb/db/qp/strategy/PhysicalGenerator.java b/server/src/main/java/org/apache/iotdb/db/qp/strategy/PhysicalGenerator.java index fbb5b8f..5cfc547 100644 --- a/server/src/main/java/org/apache/iotdb/db/qp/strategy/PhysicalGenerator.java +++ b/server/src/main/java/org/apache/iotdb/db/qp/strategy/PhysicalGenerator.java @@ -127,8 +127,9 @@ public class PhysicalGenerator { case SQLConstant.TOK_TIMESERIES: ShowTimeSeriesOperator showTimeSeriesOperator = (ShowTimeSeriesOperator) operator; return new ShowTimeSeriesPlan(ShowContentType.TIMESERIES, - showTimeSeriesOperator.getPath(), showTimeSeriesOperator.isContains(), - showTimeSeriesOperator.getKey(), showTimeSeriesOperator.getValue()); + showTimeSeriesOperator.getPath(), showTimeSeriesOperator.isContains(), + showTimeSeriesOperator.getKey(), showTimeSeriesOperator.getValue(), + showTimeSeriesOperator.getLimit(), showTimeSeriesOperator.getOffset()); case SQLConstant.TOK_STORAGE_GROUP: return new ShowPlan(ShowContentType.STORAGE_GROUP); case SQLConstant.TOK_DEVICES: diff --git a/server/src/test/java/org/apache/iotdb/db/integration/IoTDBSimpleQueryIT.java b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBSimpleQueryIT.java index 0425390..28e6727 100644 --- a/server/src/test/java/org/apache/iotdb/db/integration/IoTDBSimpleQueryIT.java +++ b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBSimpleQueryIT.java @@ -102,6 +102,31 @@ public class IoTDBSimpleQueryIT { @Test + public void testShowTimeseriesWithLimitOffset() throws SQLException, ClassNotFoundException { + Class.forName(Config.JDBC_DRIVER_NAME); + try(Connection connection = DriverManager + .getConnection(Config.IOTDB_URL_PREFIX + "127.0.0.1:6667/", "root", "root"); + Statement statement = connection.createStatement()){ + + String[] exps = new String[]{"root.sg1.d0.s2", "root.sg1.d0.s3"}; + + statement.execute("INSERT INTO root.sg1.d0(timestamp, s1) VALUES (5, 5)"); + statement.execute("INSERT INTO root.sg1.d0(timestamp, s2) VALUES (5, 5)"); + statement.execute("INSERT INTO root.sg1.d0(timestamp, s3) VALUES (5, 5)"); + + ResultSet resultSet = statement.executeQuery("show timeseries limit 2 offset 1"); + + int count = 0; + + while(resultSet.next()) { + Assert.assertEquals(exps[count++], resultSet.getString(1)); + } + + resultSet.close(); + } + } + + @Test public void testFirstOverlappedPageFiltered() throws SQLException, ClassNotFoundException { Class.forName(Config.JDBC_DRIVER_NAME); try(Connection connection = DriverManager diff --git a/server/src/test/java/org/apache/iotdb/db/qp/plan/LogicalPlanSmallTest.java b/server/src/test/java/org/apache/iotdb/db/qp/plan/LogicalPlanSmallTest.java index fb6e582..916594a 100644 --- a/server/src/test/java/org/apache/iotdb/db/qp/plan/LogicalPlanSmallTest.java +++ b/server/src/test/java/org/apache/iotdb/db/qp/plan/LogicalPlanSmallTest.java @@ -132,10 +132,10 @@ public class LogicalPlanSmallTest { @Test(expected = SQLParserException.class) public void testOffsetNotPositive() { - String sqlStr = "select * from root.vehicle.d1 where s1 < 20 and time <= now() limit 1 offset 0"; + String sqlStr = "select * from root.vehicle.d1 where s1 < 20 and time <= now() limit 1 offset -1"; RootOperator operator = (RootOperator) parseDriver .parse(sqlStr, IoTDBDescriptor.getInstance().getConfig().getZoneID()); - // expected to throw SQLParserException: OFFSET <OFFSETValue>: OFFSETValue should be greater than 0. + // expected to throw SQLParserException: OFFSET <OFFSETValue>: OFFSETValue should >= 0. } @Test(expected = SQLParserException.class) @@ -165,10 +165,10 @@ public class LogicalPlanSmallTest { @Test(expected = SQLParserException.class) public void testSoffsetNotPositive() { - String sqlStr = "select * from root.vehicle.d1 where s1 < 20 and time <= now() slimit 1 soffset 0"; + String sqlStr = "select * from root.vehicle.d1 where s1 < 20 and time <= now() slimit 1 soffset -1"; RootOperator operator = (RootOperator) parseDriver .parse(sqlStr, IoTDBDescriptor.getInstance().getConfig().getZoneID()); - // expected to throw SQLParserException: SOFFSET <SOFFSETValue>: SOFFSETValue should be greater than 0. + // expected to throw SQLParserException: SOFFSET <SOFFSETValue>: SOFFSETValue should >= 0. } @Test(expected = LogicalOptimizeException.class) diff --git a/server/src/test/java/org/apache/iotdb/db/qp/plan/PhysicalPlanTest.java b/server/src/test/java/org/apache/iotdb/db/qp/plan/PhysicalPlanTest.java index 78acafd..ac4fb6b 100644 --- a/server/src/test/java/org/apache/iotdb/db/qp/plan/PhysicalPlanTest.java +++ b/server/src/test/java/org/apache/iotdb/db/qp/plan/PhysicalPlanTest.java @@ -465,6 +465,17 @@ public class PhysicalPlanTest { } @Test + public void testOffsetLimit() throws QueryProcessException { + String sqlStr = "SELECT s1 FROM root.vehicle.d1,root.vehicle.d2 WHERE time < 10 " + + "offset 10 limit 100 soffset 1 slimit 1"; + QueryPlan plan = (QueryPlan) processor.parseSQLToPhysicalPlan(sqlStr); + assertEquals(100, plan.getRowLimit()); + assertEquals(10, plan.getRowOffset()); + // NOTE that the parameters of the SLIMIT clause is not stored in the physicalPlan, + // because the SLIMIT clause takes effect before the physicalPlan is finally generated. + } + + @Test public void testQueryFloat1() throws QueryProcessException { String sqlStr = "SELECT s1 FROM root.vehicle.d1 WHERE s1 > 20.5e3"; PhysicalPlan plan = processor.parseSQLToPhysicalPlan(sqlStr);
