From a4ae3d1fadef813f02c306460ece8786a488108e Mon Sep 17 00:00:00 2001 From: RemHero <1104304963@qq.com> Date: Tue, 4 Jun 2024 22:55:00 +0800 Subject: [PATCH 001/138] fix show columns --- .../engine/physical/storage/IStorage.java | 4 +- .../execute/StoragePhysicalTaskExecutor.java | 43 ++++++------------- .../iginx/filesystem/FileSystemStorage.java | 7 ++- .../iginx/filesystem/exec/Executor.java | 3 +- .../iginx/filesystem/exec/LocalExecutor.java | 39 +++++++++++++---- .../iginx/filesystem/exec/RemoteExecutor.java | 12 +++--- .../filesystem/server/FileSystemWorker.java | 4 +- .../tsinghua/iginx/iotdb/IoTDBStorage.java | 29 ++++++++++--- .../expansion/BaseCapacityExpansionIT.java | 17 ++++++++ .../filesystem}/datasource/DataSourceIT.java | 2 +- thrift/src/main/proto/filesystem.thrift | 2 +- 11 files changed, 104 insertions(+), 58 deletions(-) rename test/src/test/java/cn/edu/tsinghua/iginx/integration/{ => expansion/filesystem}/datasource/DataSourceIT.java (99%) diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/IStorage.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/IStorage.java index b2d83e47c7..dda2f745f7 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/IStorage.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/IStorage.java @@ -26,10 +26,12 @@ import cn.edu.tsinghua.iginx.engine.shared.operator.Insert; import cn.edu.tsinghua.iginx.engine.shared.operator.Project; import cn.edu.tsinghua.iginx.engine.shared.operator.Select; +import cn.edu.tsinghua.iginx.engine.shared.operator.tag.TagFilter; import cn.edu.tsinghua.iginx.metadata.entity.ColumnsInterval; import cn.edu.tsinghua.iginx.metadata.entity.KeyInterval; import cn.edu.tsinghua.iginx.utils.Pair; import java.util.List; +import java.util.Set; public interface IStorage { /** 对非叠加分片查询数据 */ @@ -55,7 +57,7 @@ TaskExecuteResult executeProjectDummyWithSelect( TaskExecuteResult executeInsert(Insert insert, DataArea dataArea); /** 获取所有列信息 */ - List getColumns() throws PhysicalException; + List getColumns(Set pattern, TagFilter tagFilter) throws PhysicalException; /** 获取指定前缀的数据边界 */ Pair getBoundaryOfStorage(String prefix) throws PhysicalException; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java index 074e5f1834..061cedc8a7 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java @@ -31,7 +31,6 @@ import cn.edu.tsinghua.iginx.engine.physical.storage.domain.Column; import cn.edu.tsinghua.iginx.engine.physical.storage.domain.DataArea; import cn.edu.tsinghua.iginx.engine.physical.storage.queue.StoragePhysicalTaskQueue; -import cn.edu.tsinghua.iginx.engine.physical.storage.utils.TagKVUtils; import cn.edu.tsinghua.iginx.engine.physical.task.GlobalPhysicalTask; import cn.edu.tsinghua.iginx.engine.physical.task.MemoryPhysicalTask; import cn.edu.tsinghua.iginx.engine.physical.task.StoragePhysicalTask; @@ -54,13 +53,12 @@ import cn.edu.tsinghua.iginx.monitor.HotSpotMonitor; import cn.edu.tsinghua.iginx.monitor.RequestsMonitor; import cn.edu.tsinghua.iginx.utils.Pair; -import cn.edu.tsinghua.iginx.utils.StringUtils; + import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadPoolExecutor; -import java.util.regex.Pattern; import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -324,7 +322,12 @@ public TaskExecuteResult executeShowColumns(ShowColumns showColumns) { continue; } try { - List columnList = pair.k.getColumns(); + Set patternSet = showColumns.getPathRegexSet(); + TagFilter tagFilter = showColumns.getTagFilter(); + if (storage.getDataPrefix() != null) { + patternSet.add(storage.getDataPrefix()+".*"); + } + List columnList = pair.k.getColumns(patternSet, tagFilter); // fix the schemaPrefix String schemaPrefix = storage.getSchemaPrefix(); if (schemaPrefix != null) { @@ -340,40 +343,18 @@ public TaskExecuteResult executeShowColumns(ShowColumns showColumns) { } } - Set pathRegexSet = showColumns.getPathRegexSet(); - TagFilter tagFilter = showColumns.getTagFilter(); - - TreeSet tsSetAfterFilter = new TreeSet<>(Comparator.comparing(Column::getPhysicalPath)); - for (Column column : columnSet) { - boolean isTarget = true; - if (!pathRegexSet.isEmpty()) { - isTarget = false; - for (String pathRegex : pathRegexSet) { - if (Pattern.matches(StringUtils.reformatPath(pathRegex), column.getPath())) { - isTarget = true; - break; - } - } - } - if (tagFilter != null) { - if (!TagKVUtils.match(column.getTags(), tagFilter)) { - isTarget = false; - } - } - if (isTarget) { - tsSetAfterFilter.add(column); - } - } + TreeSet columnSetAfterFilter = new TreeSet<>(Comparator.comparing(Column::getPhysicalPath)); + columnSetAfterFilter.addAll(columnSet); int limit = showColumns.getLimit(); int offset = showColumns.getOffset(); if (limit == Integer.MAX_VALUE && offset == 0) { - return new TaskExecuteResult(Column.toRowStream(tsSetAfterFilter)); + return new TaskExecuteResult(Column.toRowStream(columnSetAfterFilter)); } else { // only need part of data. List tsList = new ArrayList<>(); - int cur = 0, size = tsSetAfterFilter.size(); - for (Iterator iter = tsSetAfterFilter.iterator(); iter.hasNext(); cur++) { + int cur = 0, size = columnSetAfterFilter.size(); + for (Iterator iter = columnSetAfterFilter.iterator(); iter.hasNext(); cur++) { if (cur >= size || cur - offset >= limit) { break; } diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/FileSystemStorage.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/FileSystemStorage.java index 9c32e4fd9d..b42e783c7b 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/FileSystemStorage.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/FileSystemStorage.java @@ -32,6 +32,7 @@ import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Filter; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.KeyFilter; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Op; +import cn.edu.tsinghua.iginx.engine.shared.operator.tag.TagFilter; import cn.edu.tsinghua.iginx.filesystem.exec.Executor; import cn.edu.tsinghua.iginx.filesystem.exec.LocalExecutor; import cn.edu.tsinghua.iginx.filesystem.exec.RemoteExecutor; @@ -43,6 +44,8 @@ import cn.edu.tsinghua.iginx.utils.Pair; import java.util.Arrays; import java.util.List; +import java.util.Set; + import org.apache.thrift.transport.TTransportException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -149,8 +152,8 @@ public TaskExecuteResult executeDelete(Delete delete, DataArea dataArea) { } @Override - public List getColumns() throws PhysicalException { - return executor.getColumnsOfStorageUnit(WILDCARD); + public List getColumns(Set pattern, TagFilter tagFilter) throws PhysicalException { + return executor.getColumnsOfStorageUnit(WILDCARD, pattern, tagFilter); } @Override diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/Executor.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/Executor.java index 5c59a40c50..66926d37d8 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/Executor.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/Executor.java @@ -11,6 +11,7 @@ import cn.edu.tsinghua.iginx.metadata.entity.KeyInterval; import cn.edu.tsinghua.iginx.utils.Pair; import java.util.List; +import java.util.Set; public interface Executor { @@ -26,7 +27,7 @@ TaskExecuteResult executeProjectTask( TaskExecuteResult executeDeleteTask( List paths, List keyRanges, TagFilter tagFilter, String storageUnit); - List getColumnsOfStorageUnit(String storageUnit) throws PhysicalException; + List getColumnsOfStorageUnit(String storageUnit, Set pattern, TagFilter tagFilter) throws PhysicalException; Pair getBoundaryOfStorage(String dataPrefix) throws PhysicalException; diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java index e7510fb036..ff0787193a 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java @@ -7,6 +7,7 @@ import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; import cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream.EmptyRowStream; import cn.edu.tsinghua.iginx.engine.physical.storage.domain.Column; +import cn.edu.tsinghua.iginx.engine.physical.storage.utils.TagKVUtils; import cn.edu.tsinghua.iginx.engine.physical.task.TaskExecuteResult; import cn.edu.tsinghua.iginx.engine.shared.KeyRange; import cn.edu.tsinghua.iginx.engine.shared.data.read.RowStream; @@ -34,6 +35,10 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.regex.Pattern; + +import cn.edu.tsinghua.iginx.utils.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -309,27 +314,45 @@ public TaskExecuteResult executeDeleteTask( } @Override - public List getColumnsOfStorageUnit(String storageUnit) throws PhysicalException { + public List getColumnsOfStorageUnit(String storageUnit, Set pattern, TagFilter tagFilter) throws PhysicalException { List columns = new ArrayList<>(); if (root != null) { File directory = new File(FilePathUtils.toIginxPath(root, storageUnit, null)); for (File file : fileSystemManager.getAllFiles(directory, false)) { FileMeta meta = fileSystemManager.getFileMeta(file); + String columnPath = FilePathUtils.convertAbsolutePathToPath(root, file.getAbsolutePath(), storageUnit); + boolean isChosen = true; if (meta == null) { throw new PhysicalException( String.format( "encounter error when getting columns of storage unit because file meta %s is null", file.getAbsolutePath())); } - columns.add( - new Column( - FilePathUtils.convertAbsolutePathToPath(root, file.getAbsolutePath(), storageUnit), - meta.getDataType(), - meta.getTags(), - false)); + // get columns by pattern + if (!pattern.isEmpty()) { + for (String pathRegex : pattern) { + if (!Pattern.matches(StringUtils.reformatPath(pathRegex), columnPath)) { + isChosen = false; + break; + } + } + } + if (!isChosen) { + continue; + } + // get columns by tag filter + if (tagFilter != null && !TagKVUtils.match(meta.getTags(), tagFilter)) { + columns.add( + new Column( + columnPath, + meta.getDataType(), + meta.getTags(), + false)); + } } } - if (hasData && dummyRoot != null) { + // get columns from dummy storage unit + if (hasData && dummyRoot != null && tagFilter==null) { for (File file : fileSystemManager.getAllFiles(new File(realDummyRoot), true)) { columns.add( new Column( diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/RemoteExecutor.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/RemoteExecutor.java index 32c9c31087..2c55bf3a2d 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/RemoteExecutor.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/RemoteExecutor.java @@ -28,10 +28,7 @@ import cn.edu.tsinghua.iginx.utils.Pair; import cn.edu.tsinghua.iginx.utils.ThriftConnPool; import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; import org.apache.thrift.TException; import org.apache.thrift.protocol.TBinaryProtocol; @@ -207,11 +204,11 @@ public TaskExecuteResult executeDeleteTask( } @Override - public List getColumnsOfStorageUnit(String storageUnit) throws PhysicalException { + public List getColumnsOfStorageUnit(String storageUnit, Set pattern, TagFilter tagFilter) throws PhysicalException { try { TTransport transport = thriftConnPool.borrowTransport(); Client client = new Client(new TBinaryProtocol(transport)); - GetColumnsOfStorageUnitResp resp = client.getColumnsOfStorageUnit(storageUnit); + GetColumnsOfStorageUnitResp resp = client.getColumnsOfStorageUnit(storageUnit, pattern, constructRawTagFilter(tagFilter)); thriftConnPool.returnTransport(transport); List columns = new ArrayList<>(); resp.getPathList() @@ -254,6 +251,9 @@ public void close() { private RawTagFilter constructRawTagFilter(TagFilter tagFilter) { RawTagFilter filter = null; + if(tagFilter == null) { + return null; + } switch (tagFilter.getType()) { case Base: { diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/server/FileSystemWorker.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/server/FileSystemWorker.java index 73383ae362..1503c8397e 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/server/FileSystemWorker.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/server/FileSystemWorker.java @@ -198,10 +198,10 @@ public Status executeDelete(DeleteReq req) throws TException { } @Override - public GetColumnsOfStorageUnitResp getColumnsOfStorageUnit(String storageUnit) throws TException { + public GetColumnsOfStorageUnitResp getColumnsOfStorageUnit(String storageUnit, Set pattern, RawTagFilter tagFilter) throws TException { List ret = new ArrayList<>(); try { - List columns = executor.getColumnsOfStorageUnit(storageUnit); + List columns = executor.getColumnsOfStorageUnit(storageUnit, pattern, resolveRawTagFilter(tagFilter)); columns.forEach( column -> { FSColumn fsColumn = diff --git a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java b/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java index 74be91517d..b2e1cb4705 100644 --- a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java +++ b/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java @@ -192,13 +192,13 @@ public void release() throws PhysicalException { } @Override - public List getColumns() throws PhysicalException { + public List getColumns(Set pattern, TagFilter tagFilter) throws PhysicalException { List columns = new ArrayList<>(); - getColumns2StorageUnit(columns, null); + getColumns2StorageUnit(columns, null, pattern, tagFilter); return columns; } - private void getColumns2StorageUnit(List columns, Map columns2StorageUnit) + private void getColumns2StorageUnit(List columns, Map columns2StorageUnit, Set pattern, TagFilter tagFilter) throws PhysicalException { try { SessionDataSetWrapper dataSet = sessionPool.executeQueryStatement(SHOW_TIMESERIES); @@ -221,6 +221,25 @@ private void getColumns2StorageUnit(List columns, Map co if (columns2StorageUnit != null) { columns2StorageUnit.put(pair.k, fragment); } + boolean isChosen = true; + // get columns by pattern + if (!pattern.isEmpty()) { + for (String pathRegex : pattern) { + if (!Pattern.matches(StringUtils.reformatPath(pathRegex), pair.k)) { + isChosen = false; + break; + } + } + } else { + if (isDummy) continue; + } + if (!isChosen) { + continue; + } + // get columns by tag filter + if (tagFilter != null && !TagKVUtils.match(pair.v, tagFilter)) { + continue; + } switch (dataTypeName) { case "BOOLEAN": @@ -790,7 +809,7 @@ private List determineDeletePathList(String storageUnit, Delete delete) } else { List patterns = delete.getPatterns(); TagFilter tagFilter = delete.getTagFilter(); - List timeSeries = getColumns(); + List timeSeries = getColumns(new HashSet<>(), null); List pathList = new ArrayList<>(); for (Column ts : timeSeries) { @@ -859,7 +878,7 @@ private String getFilterString(Filter filter, String storageUnit) throws Physica if (filterStr.contains("*")) { List columns = new ArrayList<>(); Map columns2Fragment = new HashMap<>(); - getColumns2StorageUnit(columns, columns2Fragment); + getColumns2StorageUnit(columns, columns2Fragment, new HashSet<>(), null); filterStr = FilterTransformer.toString( expandFilterWildcard(filter.copy(), columns, columns2Fragment, storageUnit)); diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java index 1577c7587b..ece1882bf6 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java @@ -14,6 +14,7 @@ import cn.edu.tsinghua.iginx.integration.expansion.utils.SQLTestTools; import cn.edu.tsinghua.iginx.integration.tool.ConfLoader; import cn.edu.tsinghua.iginx.session.ClusterInfo; +import cn.edu.tsinghua.iginx.session.Column; import cn.edu.tsinghua.iginx.session.QueryDataSet; import cn.edu.tsinghua.iginx.session.Session; import cn.edu.tsinghua.iginx.thrift.RemovedStorageEngineInfo; @@ -465,6 +466,14 @@ private void testAddAndRemoveStorageEngineWithPrefix() { List> valuesList = EXP_VALUES_LIST1; + // 测试 show columns + try { + List columns = session.showColumns(); + LOGGER.info("columns: {}", columns); + } catch (SessionException e) { + LOGGER.error("show columns error: ", e); + } + // 添加不同 schemaPrefix,相同 dataPrefix addStorageEngine(expPort, true, true, dataPrefix1, schemaPrefix1, extraParams); @@ -473,6 +482,14 @@ private void testAddAndRemoveStorageEngineWithPrefix() { List pathList = Arrays.asList("nt.wf03.wt01.status2", "p1.nt.wf03.wt01.status2"); SQLTestTools.executeAndCompare(session, statement, pathList, REPEAT_EXP_VALUES_LIST1); + // 测试添加节点后的 show columns + try { + List columns = session.showColumns(); + LOGGER.info("columns: {}", columns); + } catch (SessionException e) { + LOGGER.error("show columns error: ", e); + } + addStorageEngine(expPort, true, true, dataPrefix1, schemaPrefix2, extraParams); addStorageEngine(expPort, true, true, dataPrefix1, null, extraParams); testShowClusterInfo(5); diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/datasource/DataSourceIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/datasource/DataSourceIT.java similarity index 99% rename from test/src/test/java/cn/edu/tsinghua/iginx/integration/datasource/DataSourceIT.java rename to test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/datasource/DataSourceIT.java index aede81abd9..a004fbdadd 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/datasource/DataSourceIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/datasource/DataSourceIT.java @@ -1,4 +1,4 @@ -package cn.edu.tsinghua.iginx.integration.datasource; +package cn.edu.tsinghua.iginx.integration.expansion.filesystem.datasource; import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; diff --git a/thrift/src/main/proto/filesystem.thrift b/thrift/src/main/proto/filesystem.thrift index 51a6a5f180..384d407ff6 100644 --- a/thrift/src/main/proto/filesystem.thrift +++ b/thrift/src/main/proto/filesystem.thrift @@ -157,7 +157,7 @@ service FileSystemService { Status executeDelete(1: DeleteReq req); - GetColumnsOfStorageUnitResp getColumnsOfStorageUnit(1: string storageUnit); + GetColumnsOfStorageUnitResp getColumnsOfStorageUnit(1: string storageUnit, 2: set patterns, 3: RawTagFilter tagFilter); GetBoundaryOfStorageResp getBoundaryOfStorage(1: string dataPrefix); From a406f2ff409d995951ae53cd601bb902d13da708 Mon Sep 17 00:00:00 2001 From: RemHero <1104304963@qq.com> Date: Tue, 4 Jun 2024 22:56:36 +0800 Subject: [PATCH 002/138] test --- .github/workflows/DB-CE.yml | 2 +- .../workflows/standalone-test-pushdown.yml | 208 +++++----- .github/workflows/standalone-test.yml | 380 +++++++++--------- dataSources/pom.xml | 10 +- test/pom.xml | 8 +- 5 files changed, 304 insertions(+), 304 deletions(-) diff --git a/.github/workflows/DB-CE.yml b/.github/workflows/DB-CE.yml index a6a941df54..c331810ec8 100644 --- a/.github/workflows/DB-CE.yml +++ b/.github/workflows/DB-CE.yml @@ -27,7 +27,7 @@ on: description: "The database to run the test on" type: string required: false - default: '["FileSystem", "IoTDB12", "InfluxDB", "PostgreSQL", "Redis", "MongoDB", "Parquet", "MySQL"]' + default: '["FileSystem", "IoTDB12"]' env: VERSION: 0.6.0-SNAPSHOT diff --git a/.github/workflows/standalone-test-pushdown.yml b/.github/workflows/standalone-test-pushdown.yml index c4116604e3..cebca0d776 100644 --- a/.github/workflows/standalone-test-pushdown.yml +++ b/.github/workflows/standalone-test-pushdown.yml @@ -1,104 +1,104 @@ -name: "Union Database Test With Push Down" - -on: - workflow_call: - inputs: - java-matrix: - description: "The java version to run the test on" - type: string - required: false - default: '["8"]' - python-matrix: - description: "The python version to run the test on" - type: string - required: false - default: '["3.9"]' - os-matrix: - description: "The operating system to run the test on" - type: string - required: false - default: '["ubuntu-latest", "macos-13", "windows-latest"]' - metadata-matrix: - description: "The metadata to run the test on" - type: string - required: false - default: '["zookeeper", "etcd"]' - db-matrix: - description: "The database to run the test on" - type: string - required: false - default: '["FileSystem", "IoTDB12", "InfluxDB", "PostgreSQL", "Redis", "MongoDB", "Parquet", "MySQL"]' - -env: - VERSION: 0.6.0-SNAPSHOT - -jobs: - Union-DB-Test-Push_Down: - timeout-minutes: 35 - strategy: - fail-fast: false - matrix: - java: ${{ fromJSON(inputs.java-matrix) }} - python-version: ${{ fromJSON(inputs.python-matrix) }} - os: ${{ fromJSON(inputs.os-matrix) }} - metadata: ${{ fromJSON(inputs.metadata-matrix) }} - DB-name: ${{ fromJSON(inputs.db-matrix) }} - runs-on: ${{ matrix.os }} - steps: - - uses: actions/checkout@v4 - - name: Environment dependence - uses: ./.github/actions/dependence - with: - python-version: ${{ matrix.python-version }} - java: ${{ matrix.java }} - - - if: runner.os == 'Windows' - name: Set JAVA_OPTS - run: echo "JAVA_OPTS=-Xmx4g -Xmx2g" >> $GITHUB_ENV - - - name: Run Metadata - uses: ./.github/actions/metadataRunner - with: - metadata: ${{ matrix.metadata }} - - - name: Run DB - uses: ./.github/actions/dbRunner - with: - DB-name: ${{ matrix.DB-name }} - - - name: Install IGinX with Maven - shell: bash - run: | - mvn clean package -DskipTests -P-format -q - - - name: Change IGinX config - uses: ./.github/actions/confWriter - with: - DB-name: ${{ matrix.DB-name }} - Push-Down: "true" - Set-Filter-Fragment-OFF: "true" - Metadata: ${{ matrix.metadata }} - - - name: Start IGinX - uses: ./.github/actions/iginxRunner - - - name: TestController IT - if: always() - shell: bash - env: - METADATA_STORAGE: ${{ matrix.metadata }} - run: | - chmod +x "${GITHUB_WORKSPACE}/.github/scripts/test/test_union.sh" - mvn test -q -Dtest=Controller -DfailIfNoTests=false -P-format - - - name: Show test result - if: always() - shell: bash - run: | - cat ${GITHUB_WORKSPACE}/test/src/test/resources/testResult.txt - - - name: Show IGinX log - if: always() - shell: bash - run: | - cat iginx-*.log +#name: "Union Database Test With Push Down" +# +#on: +# workflow_call: +# inputs: +# java-matrix: +# description: "The java version to run the test on" +# type: string +# required: false +# default: '["8"]' +# python-matrix: +# description: "The python version to run the test on" +# type: string +# required: false +# default: '["3.9"]' +# os-matrix: +# description: "The operating system to run the test on" +# type: string +# required: false +# default: '["ubuntu-latest", "macos-13", "windows-latest"]' +# metadata-matrix: +# description: "The metadata to run the test on" +# type: string +# required: false +# default: '["zookeeper", "etcd"]' +# db-matrix: +# description: "The database to run the test on" +# type: string +# required: false +# default: '["FileSystem", "IoTDB12", "InfluxDB", "PostgreSQL", "Redis", "MongoDB", "Parquet", "MySQL"]' +# +#env: +# VERSION: 0.6.0-SNAPSHOT +# +#jobs: +# Union-DB-Test-Push_Down: +# timeout-minutes: 35 +# strategy: +# fail-fast: false +# matrix: +# java: ${{ fromJSON(inputs.java-matrix) }} +# python-version: ${{ fromJSON(inputs.python-matrix) }} +# os: ${{ fromJSON(inputs.os-matrix) }} +# metadata: ${{ fromJSON(inputs.metadata-matrix) }} +# DB-name: ${{ fromJSON(inputs.db-matrix) }} +# runs-on: ${{ matrix.os }} +# steps: +# - uses: actions/checkout@v4 +# - name: Environment dependence +# uses: ./.github/actions/dependence +# with: +# python-version: ${{ matrix.python-version }} +# java: ${{ matrix.java }} +# +# - if: runner.os == 'Windows' +# name: Set JAVA_OPTS +# run: echo "JAVA_OPTS=-Xmx4g -Xmx2g" >> $GITHUB_ENV +# +# - name: Run Metadata +# uses: ./.github/actions/metadataRunner +# with: +# metadata: ${{ matrix.metadata }} +# +# - name: Run DB +# uses: ./.github/actions/dbRunner +# with: +# DB-name: ${{ matrix.DB-name }} +# +# - name: Install IGinX with Maven +# shell: bash +# run: | +# mvn clean package -DskipTests -P-format -q +# +# - name: Change IGinX config +# uses: ./.github/actions/confWriter +# with: +# DB-name: ${{ matrix.DB-name }} +# Push-Down: "true" +# Set-Filter-Fragment-OFF: "true" +# Metadata: ${{ matrix.metadata }} +# +# - name: Start IGinX +# uses: ./.github/actions/iginxRunner +# +# - name: TestController IT +# if: always() +# shell: bash +# env: +# METADATA_STORAGE: ${{ matrix.metadata }} +# run: | +# chmod +x "${GITHUB_WORKSPACE}/.github/scripts/test/test_union.sh" +# mvn test -q -Dtest=Controller -DfailIfNoTests=false -P-format +# +# - name: Show test result +# if: always() +# shell: bash +# run: | +# cat ${GITHUB_WORKSPACE}/test/src/test/resources/testResult.txt +# +# - name: Show IGinX log +# if: always() +# shell: bash +# run: | +# cat iginx-*.log diff --git a/.github/workflows/standalone-test.yml b/.github/workflows/standalone-test.yml index e9f202c6e3..417ceeb6aa 100644 --- a/.github/workflows/standalone-test.yml +++ b/.github/workflows/standalone-test.yml @@ -1,190 +1,190 @@ -name: "Union Database Test" - -on: - workflow_call: - inputs: - java-matrix: - description: "The java version to run the test on" - type: string - required: false - default: '["8"]' - python-matrix: - description: "The python version to run the test on" - type: string - required: false - default: '["3.9"]' - os-matrix: - description: "The operating system to run the test on" - type: string - required: false - default: '["ubuntu-latest", "macos-13", "windows-latest"]' - metadata-matrix: - description: "The metadata to run the test on" - type: string - required: false - default: '["zookeeper", "etcd"]' - db-matrix: - description: "The database to run the test on" - type: string - required: false - default: '["FileSystem", "IoTDB12", "InfluxDB", "PostgreSQL", "Redis", "MongoDB", "Parquet", "MySQL"]' - -env: - VERSION: 0.6.0-SNAPSHOT - -jobs: - Union-DB-Test: - timeout-minutes: 40 - strategy: - fail-fast: false - matrix: - java: ${{ fromJSON(inputs.java-matrix) }} - python-version: ${{ fromJSON(inputs.python-matrix) }} - os: ${{ fromJSON(inputs.os-matrix) }} - metadata: ${{ fromJSON(inputs.metadata-matrix) }} - DB-name: ${{ fromJSON(inputs.db-matrix) }} - runs-on: ${{ matrix.os }} - steps: - - uses: actions/checkout@v4 - - name: Environment dependence - uses: ./.github/actions/dependence - with: - python-version: ${{ matrix.python-version }} - java: ${{ matrix.java }} - - - name: Run Metadata - uses: ./.github/actions/metadataRunner - with: - metadata: ${{ matrix.metadata }} - - - name: Run DB - uses: ./.github/actions/dbRunner - with: - DB-name: ${{ matrix.DB-name }} - - - name: Install IGinX with Maven - shell: bash - run: | - mvn clean package -DskipTests -P-format -q - - - name: Change IGinX config - uses: ./.github/actions/confWriter - with: - DB-name: ${{ matrix.DB-name }} - Set-Filter-Fragment-OFF: "true" - Metadata: ${{ matrix.metadata }} - - # start udf path test first to avoid being effected - - name: Start IGinX - uses: ./.github/actions/iginxRunner - with: - version: ${VERSION} - if-test-udf: "true" - - - name: Run UDF path test - if: always() - shell: bash - run: | - mvn test -q -Dtest=UDFPathIT -DfailIfNoTests=false -P-format - if [ "$RUNNER_OS" == "Linux" ]; then - chmod +x "${GITHUB_WORKSPACE}/.github/scripts/test/cli/test_py_register.sh" - "${GITHUB_WORKSPACE}/.github/scripts/test/cli/test_py_register.sh" ${VERSION} - elif [ "$RUNNER_OS" == "Windows" ]; then - chmod +x "${GITHUB_WORKSPACE}/.github/scripts/test/cli/test_py_register_windows.sh" - "${GITHUB_WORKSPACE}/.github/scripts/test/cli/test_py_register_windows.sh" ${VERSION} - elif [ "$RUNNER_OS" == "macOS" ]; then - chmod +x "${GITHUB_WORKSPACE}/.github/scripts/test/cli/test_py_register_macos.sh" - "${GITHUB_WORKSPACE}/.github/scripts/test/cli/test_py_register_macos.sh" ${VERSION} - fi - - - name: set client test context - uses: ./.github/actions/context - with: - work-name: restart-iginx-meta - metadata: ${{ matrix.metadata }} - - - name: set client test context - uses: ./.github/actions/context - with: - DB-name: ${{ matrix.DB-name }} - shell: client-before - - # large image export only tested in FileSystem and Parquet - - name: Test Client Export File - if: always() - shell: bash - run: | - if [[ "${{ matrix.DB-name }}" == "FileSystem" || "${{ matrix.DB-name }}" == "Parquet" ]]; then - mvn test -q -Dtest=ExportFileIT -DfailIfNoTests=false -P-format - else - mvn test -q -Dtest=ExportFileIT#checkExportByteStream -DfailIfNoTests=false -P-format - mvn test -q -Dtest=ExportFileIT#checkExportCsv -DfailIfNoTests=false -P-format - fi - - - name: Stop IGinX and Metadata, Clear Metadata Data, then Start Them - uses: ./.github/actions/context - with: - work-name: restart-iginx-meta - metadata: ${{ matrix.metadata }} - - - name: set client test context - uses: ./.github/actions/context - with: - shell: client-after - - - name: Test Client Import File - if: always() - shell: bash - run: | - mvn test -q -Dtest=ImportFileIT -DfailIfNoTests=false -P-format - - - name: clean metadata and restart IGinX - uses: ./.github/actions/context - with: - work-name: restart-iginx-meta - metadata: ${{ matrix.metadata }} - - - name: TestController IT - if: always() - shell: bash - env: - METADATA_STORAGE: ${{ matrix.metadata }} - run: | - chmod +x "${GITHUB_WORKSPACE}/.github/scripts/test/test_union.sh" - mvn test -q -Dtest=Controller -DfailIfNoTests=false -P-format - - - name: Show IGinX log - if: always() - shell: bash - run: | - cat iginx-*.log - - - name: Change IGinX config - uses: ./.github/actions/confWriter - with: - Set-Key-Range-Test-Policy: "true" - - - name: clean metadata and restart IGinX - uses: ./.github/actions/context - with: - work-name: restart-iginx-meta - metadata: ${{ matrix.metadata }} - - - name: FilterFragmentRuleTest IT - if: always() - shell: bash - run: | - chmod +x "${GITHUB_WORKSPACE}/.github/scripts/test/test_union.sh" - mvn test -q -Dtest=SQLSessionIT#testFilterFragmentOptimizer -DfailIfNoTests=false -P-format - - - name: Show test result - if: always() - shell: bash - run: | - cat ${GITHUB_WORKSPACE}/test/src/test/resources/testResult.txt - - - name: Show IGinX log - if: always() - shell: bash - run: | - cat iginx-*.log +#name: "Union Database Test" +# +#on: +# workflow_call: +# inputs: +# java-matrix: +# description: "The java version to run the test on" +# type: string +# required: false +# default: '["8"]' +# python-matrix: +# description: "The python version to run the test on" +# type: string +# required: false +# default: '["3.9"]' +# os-matrix: +# description: "The operating system to run the test on" +# type: string +# required: false +# default: '["ubuntu-latest", "macos-13", "windows-latest"]' +# metadata-matrix: +# description: "The metadata to run the test on" +# type: string +# required: false +# default: '["zookeeper", "etcd"]' +# db-matrix: +# description: "The database to run the test on" +# type: string +# required: false +# default: '["FileSystem", "IoTDB12", "InfluxDB", "PostgreSQL", "Redis", "MongoDB", "Parquet", "MySQL"]' +# +#env: +# VERSION: 0.6.0-SNAPSHOT +# +#jobs: +# Union-DB-Test: +# timeout-minutes: 40 +# strategy: +# fail-fast: false +# matrix: +# java: ${{ fromJSON(inputs.java-matrix) }} +# python-version: ${{ fromJSON(inputs.python-matrix) }} +# os: ${{ fromJSON(inputs.os-matrix) }} +# metadata: ${{ fromJSON(inputs.metadata-matrix) }} +# DB-name: ${{ fromJSON(inputs.db-matrix) }} +# runs-on: ${{ matrix.os }} +# steps: +# - uses: actions/checkout@v4 +# - name: Environment dependence +# uses: ./.github/actions/dependence +# with: +# python-version: ${{ matrix.python-version }} +# java: ${{ matrix.java }} +# +# - name: Run Metadata +# uses: ./.github/actions/metadataRunner +# with: +# metadata: ${{ matrix.metadata }} +# +# - name: Run DB +# uses: ./.github/actions/dbRunner +# with: +# DB-name: ${{ matrix.DB-name }} +# +# - name: Install IGinX with Maven +# shell: bash +# run: | +# mvn clean package -DskipTests -P-format -q +# +# - name: Change IGinX config +# uses: ./.github/actions/confWriter +# with: +# DB-name: ${{ matrix.DB-name }} +# Set-Filter-Fragment-OFF: "true" +# Metadata: ${{ matrix.metadata }} +# +# # start udf path test first to avoid being effected +# - name: Start IGinX +# uses: ./.github/actions/iginxRunner +# with: +# version: ${VERSION} +# if-test-udf: "true" +# +# - name: Run UDF path test +# if: always() +# shell: bash +# run: | +# mvn test -q -Dtest=UDFPathIT -DfailIfNoTests=false -P-format +# if [ "$RUNNER_OS" == "Linux" ]; then +# chmod +x "${GITHUB_WORKSPACE}/.github/scripts/test/cli/test_py_register.sh" +# "${GITHUB_WORKSPACE}/.github/scripts/test/cli/test_py_register.sh" ${VERSION} +# elif [ "$RUNNER_OS" == "Windows" ]; then +# chmod +x "${GITHUB_WORKSPACE}/.github/scripts/test/cli/test_py_register_windows.sh" +# "${GITHUB_WORKSPACE}/.github/scripts/test/cli/test_py_register_windows.sh" ${VERSION} +# elif [ "$RUNNER_OS" == "macOS" ]; then +# chmod +x "${GITHUB_WORKSPACE}/.github/scripts/test/cli/test_py_register_macos.sh" +# "${GITHUB_WORKSPACE}/.github/scripts/test/cli/test_py_register_macos.sh" ${VERSION} +# fi +# +# - name: set client test context +# uses: ./.github/actions/context +# with: +# work-name: restart-iginx-meta +# metadata: ${{ matrix.metadata }} +# +# - name: set client test context +# uses: ./.github/actions/context +# with: +# DB-name: ${{ matrix.DB-name }} +# shell: client-before +# +# # large image export only tested in FileSystem and Parquet +# - name: Test Client Export File +# if: always() +# shell: bash +# run: | +# if [[ "${{ matrix.DB-name }}" == "FileSystem" || "${{ matrix.DB-name }}" == "Parquet" ]]; then +# mvn test -q -Dtest=ExportFileIT -DfailIfNoTests=false -P-format +# else +# mvn test -q -Dtest=ExportFileIT#checkExportByteStream -DfailIfNoTests=false -P-format +# mvn test -q -Dtest=ExportFileIT#checkExportCsv -DfailIfNoTests=false -P-format +# fi +# +# - name: Stop IGinX and Metadata, Clear Metadata Data, then Start Them +# uses: ./.github/actions/context +# with: +# work-name: restart-iginx-meta +# metadata: ${{ matrix.metadata }} +# +# - name: set client test context +# uses: ./.github/actions/context +# with: +# shell: client-after +# +# - name: Test Client Import File +# if: always() +# shell: bash +# run: | +# mvn test -q -Dtest=ImportFileIT -DfailIfNoTests=false -P-format +# +# - name: clean metadata and restart IGinX +# uses: ./.github/actions/context +# with: +# work-name: restart-iginx-meta +# metadata: ${{ matrix.metadata }} +# +# - name: TestController IT +# if: always() +# shell: bash +# env: +# METADATA_STORAGE: ${{ matrix.metadata }} +# run: | +# chmod +x "${GITHUB_WORKSPACE}/.github/scripts/test/test_union.sh" +# mvn test -q -Dtest=Controller -DfailIfNoTests=false -P-format +# +# - name: Show IGinX log +# if: always() +# shell: bash +# run: | +# cat iginx-*.log +# +# - name: Change IGinX config +# uses: ./.github/actions/confWriter +# with: +# Set-Key-Range-Test-Policy: "true" +# +# - name: clean metadata and restart IGinX +# uses: ./.github/actions/context +# with: +# work-name: restart-iginx-meta +# metadata: ${{ matrix.metadata }} +# +# - name: FilterFragmentRuleTest IT +# if: always() +# shell: bash +# run: | +# chmod +x "${GITHUB_WORKSPACE}/.github/scripts/test/test_union.sh" +# mvn test -q -Dtest=SQLSessionIT#testFilterFragmentOptimizer -DfailIfNoTests=false -P-format +# +# - name: Show test result +# if: always() +# shell: bash +# run: | +# cat ${GITHUB_WORKSPACE}/test/src/test/resources/testResult.txt +# +# - name: Show IGinX log +# if: always() +# shell: bash +# run: | +# cat iginx-*.log diff --git a/dataSources/pom.xml b/dataSources/pom.xml index a1cdc62a91..4b7542f6b6 100644 --- a/dataSources/pom.xml +++ b/dataSources/pom.xml @@ -29,12 +29,12 @@ filesystem - influxdb + iotdb12 - mongodb - parquet - redis - relational + + + + diff --git a/test/pom.xml b/test/pom.xml index d2d0c8dc6c..3aa6b81cac 100644 --- a/test/pom.xml +++ b/test/pom.xml @@ -44,10 +44,10 @@ cn.edu.tsinghua parquet - - cn.edu.tsinghua - relational - + + + + cn.edu.tsinghua redis From 918a7604a0b4a9cc1260e19f559798e9b229ad44 Mon Sep 17 00:00:00 2001 From: RemHero <1104304963@qq.com> Date: Tue, 4 Jun 2024 23:18:36 +0800 Subject: [PATCH 003/138] test --- .../workflows/standalone-test-pushdown.yml | 208 +++++----- .github/workflows/standalone-test.yml | 380 +++++++++--------- 2 files changed, 294 insertions(+), 294 deletions(-) diff --git a/.github/workflows/standalone-test-pushdown.yml b/.github/workflows/standalone-test-pushdown.yml index cebca0d776..c4116604e3 100644 --- a/.github/workflows/standalone-test-pushdown.yml +++ b/.github/workflows/standalone-test-pushdown.yml @@ -1,104 +1,104 @@ -#name: "Union Database Test With Push Down" -# -#on: -# workflow_call: -# inputs: -# java-matrix: -# description: "The java version to run the test on" -# type: string -# required: false -# default: '["8"]' -# python-matrix: -# description: "The python version to run the test on" -# type: string -# required: false -# default: '["3.9"]' -# os-matrix: -# description: "The operating system to run the test on" -# type: string -# required: false -# default: '["ubuntu-latest", "macos-13", "windows-latest"]' -# metadata-matrix: -# description: "The metadata to run the test on" -# type: string -# required: false -# default: '["zookeeper", "etcd"]' -# db-matrix: -# description: "The database to run the test on" -# type: string -# required: false -# default: '["FileSystem", "IoTDB12", "InfluxDB", "PostgreSQL", "Redis", "MongoDB", "Parquet", "MySQL"]' -# -#env: -# VERSION: 0.6.0-SNAPSHOT -# -#jobs: -# Union-DB-Test-Push_Down: -# timeout-minutes: 35 -# strategy: -# fail-fast: false -# matrix: -# java: ${{ fromJSON(inputs.java-matrix) }} -# python-version: ${{ fromJSON(inputs.python-matrix) }} -# os: ${{ fromJSON(inputs.os-matrix) }} -# metadata: ${{ fromJSON(inputs.metadata-matrix) }} -# DB-name: ${{ fromJSON(inputs.db-matrix) }} -# runs-on: ${{ matrix.os }} -# steps: -# - uses: actions/checkout@v4 -# - name: Environment dependence -# uses: ./.github/actions/dependence -# with: -# python-version: ${{ matrix.python-version }} -# java: ${{ matrix.java }} -# -# - if: runner.os == 'Windows' -# name: Set JAVA_OPTS -# run: echo "JAVA_OPTS=-Xmx4g -Xmx2g" >> $GITHUB_ENV -# -# - name: Run Metadata -# uses: ./.github/actions/metadataRunner -# with: -# metadata: ${{ matrix.metadata }} -# -# - name: Run DB -# uses: ./.github/actions/dbRunner -# with: -# DB-name: ${{ matrix.DB-name }} -# -# - name: Install IGinX with Maven -# shell: bash -# run: | -# mvn clean package -DskipTests -P-format -q -# -# - name: Change IGinX config -# uses: ./.github/actions/confWriter -# with: -# DB-name: ${{ matrix.DB-name }} -# Push-Down: "true" -# Set-Filter-Fragment-OFF: "true" -# Metadata: ${{ matrix.metadata }} -# -# - name: Start IGinX -# uses: ./.github/actions/iginxRunner -# -# - name: TestController IT -# if: always() -# shell: bash -# env: -# METADATA_STORAGE: ${{ matrix.metadata }} -# run: | -# chmod +x "${GITHUB_WORKSPACE}/.github/scripts/test/test_union.sh" -# mvn test -q -Dtest=Controller -DfailIfNoTests=false -P-format -# -# - name: Show test result -# if: always() -# shell: bash -# run: | -# cat ${GITHUB_WORKSPACE}/test/src/test/resources/testResult.txt -# -# - name: Show IGinX log -# if: always() -# shell: bash -# run: | -# cat iginx-*.log +name: "Union Database Test With Push Down" + +on: + workflow_call: + inputs: + java-matrix: + description: "The java version to run the test on" + type: string + required: false + default: '["8"]' + python-matrix: + description: "The python version to run the test on" + type: string + required: false + default: '["3.9"]' + os-matrix: + description: "The operating system to run the test on" + type: string + required: false + default: '["ubuntu-latest", "macos-13", "windows-latest"]' + metadata-matrix: + description: "The metadata to run the test on" + type: string + required: false + default: '["zookeeper", "etcd"]' + db-matrix: + description: "The database to run the test on" + type: string + required: false + default: '["FileSystem", "IoTDB12", "InfluxDB", "PostgreSQL", "Redis", "MongoDB", "Parquet", "MySQL"]' + +env: + VERSION: 0.6.0-SNAPSHOT + +jobs: + Union-DB-Test-Push_Down: + timeout-minutes: 35 + strategy: + fail-fast: false + matrix: + java: ${{ fromJSON(inputs.java-matrix) }} + python-version: ${{ fromJSON(inputs.python-matrix) }} + os: ${{ fromJSON(inputs.os-matrix) }} + metadata: ${{ fromJSON(inputs.metadata-matrix) }} + DB-name: ${{ fromJSON(inputs.db-matrix) }} + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + - name: Environment dependence + uses: ./.github/actions/dependence + with: + python-version: ${{ matrix.python-version }} + java: ${{ matrix.java }} + + - if: runner.os == 'Windows' + name: Set JAVA_OPTS + run: echo "JAVA_OPTS=-Xmx4g -Xmx2g" >> $GITHUB_ENV + + - name: Run Metadata + uses: ./.github/actions/metadataRunner + with: + metadata: ${{ matrix.metadata }} + + - name: Run DB + uses: ./.github/actions/dbRunner + with: + DB-name: ${{ matrix.DB-name }} + + - name: Install IGinX with Maven + shell: bash + run: | + mvn clean package -DskipTests -P-format -q + + - name: Change IGinX config + uses: ./.github/actions/confWriter + with: + DB-name: ${{ matrix.DB-name }} + Push-Down: "true" + Set-Filter-Fragment-OFF: "true" + Metadata: ${{ matrix.metadata }} + + - name: Start IGinX + uses: ./.github/actions/iginxRunner + + - name: TestController IT + if: always() + shell: bash + env: + METADATA_STORAGE: ${{ matrix.metadata }} + run: | + chmod +x "${GITHUB_WORKSPACE}/.github/scripts/test/test_union.sh" + mvn test -q -Dtest=Controller -DfailIfNoTests=false -P-format + + - name: Show test result + if: always() + shell: bash + run: | + cat ${GITHUB_WORKSPACE}/test/src/test/resources/testResult.txt + + - name: Show IGinX log + if: always() + shell: bash + run: | + cat iginx-*.log diff --git a/.github/workflows/standalone-test.yml b/.github/workflows/standalone-test.yml index 417ceeb6aa..e9f202c6e3 100644 --- a/.github/workflows/standalone-test.yml +++ b/.github/workflows/standalone-test.yml @@ -1,190 +1,190 @@ -#name: "Union Database Test" -# -#on: -# workflow_call: -# inputs: -# java-matrix: -# description: "The java version to run the test on" -# type: string -# required: false -# default: '["8"]' -# python-matrix: -# description: "The python version to run the test on" -# type: string -# required: false -# default: '["3.9"]' -# os-matrix: -# description: "The operating system to run the test on" -# type: string -# required: false -# default: '["ubuntu-latest", "macos-13", "windows-latest"]' -# metadata-matrix: -# description: "The metadata to run the test on" -# type: string -# required: false -# default: '["zookeeper", "etcd"]' -# db-matrix: -# description: "The database to run the test on" -# type: string -# required: false -# default: '["FileSystem", "IoTDB12", "InfluxDB", "PostgreSQL", "Redis", "MongoDB", "Parquet", "MySQL"]' -# -#env: -# VERSION: 0.6.0-SNAPSHOT -# -#jobs: -# Union-DB-Test: -# timeout-minutes: 40 -# strategy: -# fail-fast: false -# matrix: -# java: ${{ fromJSON(inputs.java-matrix) }} -# python-version: ${{ fromJSON(inputs.python-matrix) }} -# os: ${{ fromJSON(inputs.os-matrix) }} -# metadata: ${{ fromJSON(inputs.metadata-matrix) }} -# DB-name: ${{ fromJSON(inputs.db-matrix) }} -# runs-on: ${{ matrix.os }} -# steps: -# - uses: actions/checkout@v4 -# - name: Environment dependence -# uses: ./.github/actions/dependence -# with: -# python-version: ${{ matrix.python-version }} -# java: ${{ matrix.java }} -# -# - name: Run Metadata -# uses: ./.github/actions/metadataRunner -# with: -# metadata: ${{ matrix.metadata }} -# -# - name: Run DB -# uses: ./.github/actions/dbRunner -# with: -# DB-name: ${{ matrix.DB-name }} -# -# - name: Install IGinX with Maven -# shell: bash -# run: | -# mvn clean package -DskipTests -P-format -q -# -# - name: Change IGinX config -# uses: ./.github/actions/confWriter -# with: -# DB-name: ${{ matrix.DB-name }} -# Set-Filter-Fragment-OFF: "true" -# Metadata: ${{ matrix.metadata }} -# -# # start udf path test first to avoid being effected -# - name: Start IGinX -# uses: ./.github/actions/iginxRunner -# with: -# version: ${VERSION} -# if-test-udf: "true" -# -# - name: Run UDF path test -# if: always() -# shell: bash -# run: | -# mvn test -q -Dtest=UDFPathIT -DfailIfNoTests=false -P-format -# if [ "$RUNNER_OS" == "Linux" ]; then -# chmod +x "${GITHUB_WORKSPACE}/.github/scripts/test/cli/test_py_register.sh" -# "${GITHUB_WORKSPACE}/.github/scripts/test/cli/test_py_register.sh" ${VERSION} -# elif [ "$RUNNER_OS" == "Windows" ]; then -# chmod +x "${GITHUB_WORKSPACE}/.github/scripts/test/cli/test_py_register_windows.sh" -# "${GITHUB_WORKSPACE}/.github/scripts/test/cli/test_py_register_windows.sh" ${VERSION} -# elif [ "$RUNNER_OS" == "macOS" ]; then -# chmod +x "${GITHUB_WORKSPACE}/.github/scripts/test/cli/test_py_register_macos.sh" -# "${GITHUB_WORKSPACE}/.github/scripts/test/cli/test_py_register_macos.sh" ${VERSION} -# fi -# -# - name: set client test context -# uses: ./.github/actions/context -# with: -# work-name: restart-iginx-meta -# metadata: ${{ matrix.metadata }} -# -# - name: set client test context -# uses: ./.github/actions/context -# with: -# DB-name: ${{ matrix.DB-name }} -# shell: client-before -# -# # large image export only tested in FileSystem and Parquet -# - name: Test Client Export File -# if: always() -# shell: bash -# run: | -# if [[ "${{ matrix.DB-name }}" == "FileSystem" || "${{ matrix.DB-name }}" == "Parquet" ]]; then -# mvn test -q -Dtest=ExportFileIT -DfailIfNoTests=false -P-format -# else -# mvn test -q -Dtest=ExportFileIT#checkExportByteStream -DfailIfNoTests=false -P-format -# mvn test -q -Dtest=ExportFileIT#checkExportCsv -DfailIfNoTests=false -P-format -# fi -# -# - name: Stop IGinX and Metadata, Clear Metadata Data, then Start Them -# uses: ./.github/actions/context -# with: -# work-name: restart-iginx-meta -# metadata: ${{ matrix.metadata }} -# -# - name: set client test context -# uses: ./.github/actions/context -# with: -# shell: client-after -# -# - name: Test Client Import File -# if: always() -# shell: bash -# run: | -# mvn test -q -Dtest=ImportFileIT -DfailIfNoTests=false -P-format -# -# - name: clean metadata and restart IGinX -# uses: ./.github/actions/context -# with: -# work-name: restart-iginx-meta -# metadata: ${{ matrix.metadata }} -# -# - name: TestController IT -# if: always() -# shell: bash -# env: -# METADATA_STORAGE: ${{ matrix.metadata }} -# run: | -# chmod +x "${GITHUB_WORKSPACE}/.github/scripts/test/test_union.sh" -# mvn test -q -Dtest=Controller -DfailIfNoTests=false -P-format -# -# - name: Show IGinX log -# if: always() -# shell: bash -# run: | -# cat iginx-*.log -# -# - name: Change IGinX config -# uses: ./.github/actions/confWriter -# with: -# Set-Key-Range-Test-Policy: "true" -# -# - name: clean metadata and restart IGinX -# uses: ./.github/actions/context -# with: -# work-name: restart-iginx-meta -# metadata: ${{ matrix.metadata }} -# -# - name: FilterFragmentRuleTest IT -# if: always() -# shell: bash -# run: | -# chmod +x "${GITHUB_WORKSPACE}/.github/scripts/test/test_union.sh" -# mvn test -q -Dtest=SQLSessionIT#testFilterFragmentOptimizer -DfailIfNoTests=false -P-format -# -# - name: Show test result -# if: always() -# shell: bash -# run: | -# cat ${GITHUB_WORKSPACE}/test/src/test/resources/testResult.txt -# -# - name: Show IGinX log -# if: always() -# shell: bash -# run: | -# cat iginx-*.log +name: "Union Database Test" + +on: + workflow_call: + inputs: + java-matrix: + description: "The java version to run the test on" + type: string + required: false + default: '["8"]' + python-matrix: + description: "The python version to run the test on" + type: string + required: false + default: '["3.9"]' + os-matrix: + description: "The operating system to run the test on" + type: string + required: false + default: '["ubuntu-latest", "macos-13", "windows-latest"]' + metadata-matrix: + description: "The metadata to run the test on" + type: string + required: false + default: '["zookeeper", "etcd"]' + db-matrix: + description: "The database to run the test on" + type: string + required: false + default: '["FileSystem", "IoTDB12", "InfluxDB", "PostgreSQL", "Redis", "MongoDB", "Parquet", "MySQL"]' + +env: + VERSION: 0.6.0-SNAPSHOT + +jobs: + Union-DB-Test: + timeout-minutes: 40 + strategy: + fail-fast: false + matrix: + java: ${{ fromJSON(inputs.java-matrix) }} + python-version: ${{ fromJSON(inputs.python-matrix) }} + os: ${{ fromJSON(inputs.os-matrix) }} + metadata: ${{ fromJSON(inputs.metadata-matrix) }} + DB-name: ${{ fromJSON(inputs.db-matrix) }} + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + - name: Environment dependence + uses: ./.github/actions/dependence + with: + python-version: ${{ matrix.python-version }} + java: ${{ matrix.java }} + + - name: Run Metadata + uses: ./.github/actions/metadataRunner + with: + metadata: ${{ matrix.metadata }} + + - name: Run DB + uses: ./.github/actions/dbRunner + with: + DB-name: ${{ matrix.DB-name }} + + - name: Install IGinX with Maven + shell: bash + run: | + mvn clean package -DskipTests -P-format -q + + - name: Change IGinX config + uses: ./.github/actions/confWriter + with: + DB-name: ${{ matrix.DB-name }} + Set-Filter-Fragment-OFF: "true" + Metadata: ${{ matrix.metadata }} + + # start udf path test first to avoid being effected + - name: Start IGinX + uses: ./.github/actions/iginxRunner + with: + version: ${VERSION} + if-test-udf: "true" + + - name: Run UDF path test + if: always() + shell: bash + run: | + mvn test -q -Dtest=UDFPathIT -DfailIfNoTests=false -P-format + if [ "$RUNNER_OS" == "Linux" ]; then + chmod +x "${GITHUB_WORKSPACE}/.github/scripts/test/cli/test_py_register.sh" + "${GITHUB_WORKSPACE}/.github/scripts/test/cli/test_py_register.sh" ${VERSION} + elif [ "$RUNNER_OS" == "Windows" ]; then + chmod +x "${GITHUB_WORKSPACE}/.github/scripts/test/cli/test_py_register_windows.sh" + "${GITHUB_WORKSPACE}/.github/scripts/test/cli/test_py_register_windows.sh" ${VERSION} + elif [ "$RUNNER_OS" == "macOS" ]; then + chmod +x "${GITHUB_WORKSPACE}/.github/scripts/test/cli/test_py_register_macos.sh" + "${GITHUB_WORKSPACE}/.github/scripts/test/cli/test_py_register_macos.sh" ${VERSION} + fi + + - name: set client test context + uses: ./.github/actions/context + with: + work-name: restart-iginx-meta + metadata: ${{ matrix.metadata }} + + - name: set client test context + uses: ./.github/actions/context + with: + DB-name: ${{ matrix.DB-name }} + shell: client-before + + # large image export only tested in FileSystem and Parquet + - name: Test Client Export File + if: always() + shell: bash + run: | + if [[ "${{ matrix.DB-name }}" == "FileSystem" || "${{ matrix.DB-name }}" == "Parquet" ]]; then + mvn test -q -Dtest=ExportFileIT -DfailIfNoTests=false -P-format + else + mvn test -q -Dtest=ExportFileIT#checkExportByteStream -DfailIfNoTests=false -P-format + mvn test -q -Dtest=ExportFileIT#checkExportCsv -DfailIfNoTests=false -P-format + fi + + - name: Stop IGinX and Metadata, Clear Metadata Data, then Start Them + uses: ./.github/actions/context + with: + work-name: restart-iginx-meta + metadata: ${{ matrix.metadata }} + + - name: set client test context + uses: ./.github/actions/context + with: + shell: client-after + + - name: Test Client Import File + if: always() + shell: bash + run: | + mvn test -q -Dtest=ImportFileIT -DfailIfNoTests=false -P-format + + - name: clean metadata and restart IGinX + uses: ./.github/actions/context + with: + work-name: restart-iginx-meta + metadata: ${{ matrix.metadata }} + + - name: TestController IT + if: always() + shell: bash + env: + METADATA_STORAGE: ${{ matrix.metadata }} + run: | + chmod +x "${GITHUB_WORKSPACE}/.github/scripts/test/test_union.sh" + mvn test -q -Dtest=Controller -DfailIfNoTests=false -P-format + + - name: Show IGinX log + if: always() + shell: bash + run: | + cat iginx-*.log + + - name: Change IGinX config + uses: ./.github/actions/confWriter + with: + Set-Key-Range-Test-Policy: "true" + + - name: clean metadata and restart IGinX + uses: ./.github/actions/context + with: + work-name: restart-iginx-meta + metadata: ${{ matrix.metadata }} + + - name: FilterFragmentRuleTest IT + if: always() + shell: bash + run: | + chmod +x "${GITHUB_WORKSPACE}/.github/scripts/test/test_union.sh" + mvn test -q -Dtest=SQLSessionIT#testFilterFragmentOptimizer -DfailIfNoTests=false -P-format + + - name: Show test result + if: always() + shell: bash + run: | + cat ${GITHUB_WORKSPACE}/test/src/test/resources/testResult.txt + + - name: Show IGinX log + if: always() + shell: bash + run: | + cat iginx-*.log From e083c74591948c663bb71d8d89c091cf707fd369 Mon Sep 17 00:00:00 2001 From: RemHero <1104304963@qq.com> Date: Wed, 5 Jun 2024 17:11:31 +0800 Subject: [PATCH 004/138] test --- .github/workflows/standard-test-suite.yml | 40 +++++----- .../execute/StoragePhysicalTaskExecutor.java | 6 +- .../iginx/filesystem/FileSystemStorage.java | 4 +- .../iginx/filesystem/exec/Executor.java | 3 +- .../iginx/filesystem/exec/LocalExecutor.java | 18 ++--- .../iginx/filesystem/exec/RemoteExecutor.java | 8 +- .../filesystem/server/FileSystemWorker.java | 6 +- .../tsinghua/iginx/iotdb/IoTDBStorage.java | 9 ++- dataSources/pom.xml | 10 +-- test/pom.xml | 8 +- .../expansion/BaseCapacityExpansionIT.java | 75 ++++++++++++++----- 11 files changed, 115 insertions(+), 72 deletions(-) diff --git a/.github/workflows/standard-test-suite.yml b/.github/workflows/standard-test-suite.yml index a4f8234894..f5b7a22f3b 100644 --- a/.github/workflows/standard-test-suite.yml +++ b/.github/workflows/standard-test-suite.yml @@ -11,27 +11,27 @@ concurrency: cancel-in-progress: true jobs: - unit-test: - uses: ./.github/workflows/unit-test.yml - unit-mds: - uses: ./.github/workflows/unit-mds.yml - case-regression: - uses: ./.github/workflows/case-regression.yml - with: - metadata-matrix: '["zookeeper"]' - standalone-test: - uses: ./.github/workflows/standalone-test.yml - with: - metadata-matrix: '["zookeeper"]' - standalone-test-pushdown: - uses: ./.github/workflows/standalone-test-pushdown.yml - with: - metadata-matrix: '["zookeeper"]' +# unit-test: +# uses: ./.github/workflows/unit-test.yml +# unit-mds: +# uses: ./.github/workflows/unit-mds.yml +# case-regression: +# uses: ./.github/workflows/case-regression.yml +# with: +# metadata-matrix: '["zookeeper"]' +# standalone-test: +# uses: ./.github/workflows/standalone-test.yml +# with: +# metadata-matrix: '["zookeeper"]' +# standalone-test-pushdown: +# uses: ./.github/workflows/standalone-test-pushdown.yml +# with: +# metadata-matrix: '["zookeeper"]' db-ce: uses: ./.github/workflows/DB-CE.yml with: metadata-matrix: '["zookeeper"]' - remote-test: - uses: ./.github/workflows/remote-test.yml - with: - metadata-matrix: '["zookeeper"]' +# remote-test: +# uses: ./.github/workflows/remote-test.yml +# with: +# metadata-matrix: '["zookeeper"]' diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java index 061cedc8a7..7735275b22 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java @@ -53,7 +53,6 @@ import cn.edu.tsinghua.iginx.monitor.HotSpotMonitor; import cn.edu.tsinghua.iginx.monitor.RequestsMonitor; import cn.edu.tsinghua.iginx.utils.Pair; - import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; @@ -325,7 +324,7 @@ public TaskExecuteResult executeShowColumns(ShowColumns showColumns) { Set patternSet = showColumns.getPathRegexSet(); TagFilter tagFilter = showColumns.getTagFilter(); if (storage.getDataPrefix() != null) { - patternSet.add(storage.getDataPrefix()+".*"); + patternSet.add(storage.getDataPrefix() + ".*"); } List columnList = pair.k.getColumns(patternSet, tagFilter); // fix the schemaPrefix @@ -343,7 +342,8 @@ public TaskExecuteResult executeShowColumns(ShowColumns showColumns) { } } - TreeSet columnSetAfterFilter = new TreeSet<>(Comparator.comparing(Column::getPhysicalPath)); + TreeSet columnSetAfterFilter = + new TreeSet<>(Comparator.comparing(Column::getPhysicalPath)); columnSetAfterFilter.addAll(columnSet); int limit = showColumns.getLimit(); diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/FileSystemStorage.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/FileSystemStorage.java index b42e783c7b..6f31d9e666 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/FileSystemStorage.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/FileSystemStorage.java @@ -45,7 +45,6 @@ import java.util.Arrays; import java.util.List; import java.util.Set; - import org.apache.thrift.transport.TTransportException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -152,7 +151,8 @@ public TaskExecuteResult executeDelete(Delete delete, DataArea dataArea) { } @Override - public List getColumns(Set pattern, TagFilter tagFilter) throws PhysicalException { + public List getColumns(Set pattern, TagFilter tagFilter) + throws PhysicalException { return executor.getColumnsOfStorageUnit(WILDCARD, pattern, tagFilter); } diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/Executor.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/Executor.java index 66926d37d8..b5b71fa32a 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/Executor.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/Executor.java @@ -27,7 +27,8 @@ TaskExecuteResult executeProjectTask( TaskExecuteResult executeDeleteTask( List paths, List keyRanges, TagFilter tagFilter, String storageUnit); - List getColumnsOfStorageUnit(String storageUnit, Set pattern, TagFilter tagFilter) throws PhysicalException; + List getColumnsOfStorageUnit(String storageUnit, Set pattern, TagFilter tagFilter) + throws PhysicalException; Pair getBoundaryOfStorage(String dataPrefix) throws PhysicalException; diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java index ff0787193a..90cbf66cd6 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java @@ -30,6 +30,7 @@ import cn.edu.tsinghua.iginx.metadata.entity.KeyInterval; import cn.edu.tsinghua.iginx.thrift.DataType; import cn.edu.tsinghua.iginx.utils.Pair; +import cn.edu.tsinghua.iginx.utils.StringUtils; import java.io.File; import java.io.IOException; import java.util.ArrayList; @@ -37,8 +38,6 @@ import java.util.Map; import java.util.Set; import java.util.regex.Pattern; - -import cn.edu.tsinghua.iginx.utils.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -314,13 +313,15 @@ public TaskExecuteResult executeDeleteTask( } @Override - public List getColumnsOfStorageUnit(String storageUnit, Set pattern, TagFilter tagFilter) throws PhysicalException { + public List getColumnsOfStorageUnit( + String storageUnit, Set pattern, TagFilter tagFilter) throws PhysicalException { List columns = new ArrayList<>(); if (root != null) { File directory = new File(FilePathUtils.toIginxPath(root, storageUnit, null)); for (File file : fileSystemManager.getAllFiles(directory, false)) { FileMeta meta = fileSystemManager.getFileMeta(file); - String columnPath = FilePathUtils.convertAbsolutePathToPath(root, file.getAbsolutePath(), storageUnit); + String columnPath = + FilePathUtils.convertAbsolutePathToPath(root, file.getAbsolutePath(), storageUnit); boolean isChosen = true; if (meta == null) { throw new PhysicalException( @@ -342,17 +343,12 @@ public List getColumnsOfStorageUnit(String storageUnit, Set patt } // get columns by tag filter if (tagFilter != null && !TagKVUtils.match(meta.getTags(), tagFilter)) { - columns.add( - new Column( - columnPath, - meta.getDataType(), - meta.getTags(), - false)); + columns.add(new Column(columnPath, meta.getDataType(), meta.getTags(), false)); } } } // get columns from dummy storage unit - if (hasData && dummyRoot != null && tagFilter==null) { + if (hasData && dummyRoot != null && tagFilter == null) { for (File file : fileSystemManager.getAllFiles(new File(realDummyRoot), true)) { columns.add( new Column( diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/RemoteExecutor.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/RemoteExecutor.java index 2c55bf3a2d..21e2dacd23 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/RemoteExecutor.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/RemoteExecutor.java @@ -204,11 +204,13 @@ public TaskExecuteResult executeDeleteTask( } @Override - public List getColumnsOfStorageUnit(String storageUnit, Set pattern, TagFilter tagFilter) throws PhysicalException { + public List getColumnsOfStorageUnit( + String storageUnit, Set pattern, TagFilter tagFilter) throws PhysicalException { try { TTransport transport = thriftConnPool.borrowTransport(); Client client = new Client(new TBinaryProtocol(transport)); - GetColumnsOfStorageUnitResp resp = client.getColumnsOfStorageUnit(storageUnit, pattern, constructRawTagFilter(tagFilter)); + GetColumnsOfStorageUnitResp resp = + client.getColumnsOfStorageUnit(storageUnit, pattern, constructRawTagFilter(tagFilter)); thriftConnPool.returnTransport(transport); List columns = new ArrayList<>(); resp.getPathList() @@ -251,7 +253,7 @@ public void close() { private RawTagFilter constructRawTagFilter(TagFilter tagFilter) { RawTagFilter filter = null; - if(tagFilter == null) { + if (tagFilter == null) { return null; } switch (tagFilter.getType()) { diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/server/FileSystemWorker.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/server/FileSystemWorker.java index 1503c8397e..fb44573bf6 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/server/FileSystemWorker.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/server/FileSystemWorker.java @@ -198,10 +198,12 @@ public Status executeDelete(DeleteReq req) throws TException { } @Override - public GetColumnsOfStorageUnitResp getColumnsOfStorageUnit(String storageUnit, Set pattern, RawTagFilter tagFilter) throws TException { + public GetColumnsOfStorageUnitResp getColumnsOfStorageUnit( + String storageUnit, Set pattern, RawTagFilter tagFilter) throws TException { List ret = new ArrayList<>(); try { - List columns = executor.getColumnsOfStorageUnit(storageUnit, pattern, resolveRawTagFilter(tagFilter)); + List columns = + executor.getColumnsOfStorageUnit(storageUnit, pattern, resolveRawTagFilter(tagFilter)); columns.forEach( column -> { FSColumn fsColumn = diff --git a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java b/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java index b2e1cb4705..a31aa6e56d 100644 --- a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java +++ b/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java @@ -192,13 +192,18 @@ public void release() throws PhysicalException { } @Override - public List getColumns(Set pattern, TagFilter tagFilter) throws PhysicalException { + public List getColumns(Set pattern, TagFilter tagFilter) + throws PhysicalException { List columns = new ArrayList<>(); getColumns2StorageUnit(columns, null, pattern, tagFilter); return columns; } - private void getColumns2StorageUnit(List columns, Map columns2StorageUnit, Set pattern, TagFilter tagFilter) + private void getColumns2StorageUnit( + List columns, + Map columns2StorageUnit, + Set pattern, + TagFilter tagFilter) throws PhysicalException { try { SessionDataSetWrapper dataSet = sessionPool.executeQueryStatement(SHOW_TIMESERIES); diff --git a/dataSources/pom.xml b/dataSources/pom.xml index 4b7542f6b6..abf7da3715 100644 --- a/dataSources/pom.xml +++ b/dataSources/pom.xml @@ -29,12 +29,12 @@ filesystem - + iotdb12 - - - - + + + + diff --git a/test/pom.xml b/test/pom.xml index 3aa6b81cac..61b03d3eee 100644 --- a/test/pom.xml +++ b/test/pom.xml @@ -44,10 +44,10 @@ cn.edu.tsinghua parquet - - - - + + + + cn.edu.tsinghua redis diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java index ece1882bf6..a2959c9e1e 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java @@ -3,8 +3,7 @@ import static cn.edu.tsinghua.iginx.integration.controller.Controller.SUPPORT_KEY; import static cn.edu.tsinghua.iginx.integration.expansion.constant.Constant.*; import static cn.edu.tsinghua.iginx.integration.expansion.utils.SQLTestTools.executeShellScript; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; +import static org.junit.Assert.*; import cn.edu.tsinghua.iginx.exception.SessionException; import cn.edu.tsinghua.iginx.integration.controller.Controller; @@ -17,12 +16,15 @@ import cn.edu.tsinghua.iginx.session.Column; import cn.edu.tsinghua.iginx.session.QueryDataSet; import cn.edu.tsinghua.iginx.session.Session; +import cn.edu.tsinghua.iginx.thrift.DataType; import cn.edu.tsinghua.iginx.thrift.RemovedStorageEngineInfo; import cn.edu.tsinghua.iginx.thrift.StorageEngineType; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; + import org.junit.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -324,6 +326,16 @@ protected void queryExtendedKeyDummy() { statement = "select wf05.wt01.status, wf05.wt01.temperature from tm;"; SQLTestTools.executeAndContainValue( session, statement, READ_ONLY_PATH_LIST, READ_ONLY_EXTEND_VALUES_LIST); + + // test show columns + testShowColumns(Arrays.asList( + new Column("mn.wf01.wt01.temperature", DataType.DOUBLE), + new Column("mn.wf01.wt01.status", DataType.LONG), + new Column("nt.wf03.wt01.status2", DataType.LONG), + new Column("nt.wf04.wt01.temperature", DataType.DOUBLE), + new Column("tm.wf05.wt01.status", DataType.LONG), + new Column("tm.wf05.wt01.temperature", DataType.DOUBLE) + )); } protected void queryExtendedColDummy() { @@ -456,6 +468,29 @@ private void queryAllNewData() { SQLTestTools.executeAndCompare(session, statement, expect); } + private void testShowColumns(List expectColumns) { + try { + List columns = session.showColumns(); + LOGGER.info("show columns: {}", columns); + + // 对期望列表和实际列表中的Column对象按路径排序 + List sortedExpectPaths = expectColumns.stream() + .map(Column::getPath) + .sorted() + .collect(Collectors.toList()); + + List sortedActualPaths = columns.stream() + .map(Column::getPath) + .sorted() + .collect(Collectors.toList()); + + // 检查排序后的路径列表是否相同 + assertArrayEquals(sortedExpectPaths.toArray(), sortedActualPaths.toArray()); + } catch (SessionException e) { + LOGGER.error("show columns error: ", e); + } + } + private void testAddAndRemoveStorageEngineWithPrefix() { String dataPrefix1 = "nt.wf03"; String dataPrefix2 = "nt.wf04"; @@ -466,30 +501,32 @@ private void testAddAndRemoveStorageEngineWithPrefix() { List> valuesList = EXP_VALUES_LIST1; - // 测试 show columns - try { - List columns = session.showColumns(); - LOGGER.info("columns: {}", columns); - } catch (SessionException e) { - LOGGER.error("show columns error: ", e); - } + testShowColumns(Arrays.asList( + new Column("b.b.b", DataType.LONG), + new Column("ln.wf02.status", DataType.BOOLEAN), + new Column("ln.wf02.version", DataType.BINARY), + new Column("nt.wf03.wt01.status2", DataType.LONG), + new Column("nt.wf04.wt01.temperature", DataType.DOUBLE), + new Column("zzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzzzz", DataType.LONG) + )); // 添加不同 schemaPrefix,相同 dataPrefix addStorageEngine(expPort, true, true, dataPrefix1, schemaPrefix1, extraParams); + testShowColumns(Arrays.asList( + new Column("b.b.b", DataType.LONG), + new Column("ln.wf02.status", DataType.BOOLEAN), + new Column("ln.wf02.version", DataType.BINARY), + new Column("nt.wf03.wt01.status2", DataType.LONG),new Column("p1.nt.wf03.wt01.status2", DataType.LONG), + new Column("nt.wf04.wt01.temperature", DataType.DOUBLE), + new Column("zzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzzzz", DataType.LONG) + )); + // 添加节点 dataPrefix = dataPrefix1 && schemaPrefix = p1 后查询 String statement = "select status2 from *;"; List pathList = Arrays.asList("nt.wf03.wt01.status2", "p1.nt.wf03.wt01.status2"); SQLTestTools.executeAndCompare(session, statement, pathList, REPEAT_EXP_VALUES_LIST1); - // 测试添加节点后的 show columns - try { - List columns = session.showColumns(); - LOGGER.info("columns: {}", columns); - } catch (SessionException e) { - LOGGER.error("show columns error: ", e); - } - addStorageEngine(expPort, true, true, dataPrefix1, schemaPrefix2, extraParams); addStorageEngine(expPort, true, true, dataPrefix1, null, extraParams); testShowClusterInfo(5); @@ -697,8 +734,8 @@ private void testSameKeyWarning() { QueryDataSet res = session.executeQuery(statement); if ((res.getWarningMsg() == null - || res.getWarningMsg().isEmpty() - || !res.getWarningMsg().contains("The query results contain overlapped keys.")) + || res.getWarningMsg().isEmpty() + || !res.getWarningMsg().contains("The query results contain overlapped keys.")) && SUPPORT_KEY.get(testConf.getStorageType())) { LOGGER.error("未抛出重叠key的警告"); fail(); From 4a4c7981fca09c2e8b9d13fe894d9589d697800d Mon Sep 17 00:00:00 2001 From: RemHero <1104304963@qq.com> Date: Wed, 5 Jun 2024 17:28:33 +0800 Subject: [PATCH 005/138] fix pom --- dataSources/pom.xml | 10 +++++----- test/pom.xml | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/dataSources/pom.xml b/dataSources/pom.xml index abf7da3715..a1cdc62a91 100644 --- a/dataSources/pom.xml +++ b/dataSources/pom.xml @@ -29,12 +29,12 @@ filesystem - + influxdb iotdb12 - - - - + mongodb + parquet + redis + relational diff --git a/test/pom.xml b/test/pom.xml index 61b03d3eee..d2d0c8dc6c 100644 --- a/test/pom.xml +++ b/test/pom.xml @@ -44,10 +44,10 @@ cn.edu.tsinghua parquet - - - - + + cn.edu.tsinghua + relational + cn.edu.tsinghua redis From 621cf38f0e21338c3d40d125e56b896fd75080af Mon Sep 17 00:00:00 2001 From: RemHero <1104304963@qq.com> Date: Thu, 6 Jun 2024 10:11:06 +0800 Subject: [PATCH 006/138] add interface --- .../java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java | 2 +- .../java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java | 2 +- .../java/cn/edu/tsinghua/iginx/parquet/ParquetStorage.java | 5 ++++- .../main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java | 2 +- .../cn/edu/tsinghua/iginx/relational/RelationalStorage.java | 4 ++-- 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java index ece91da52a..ca623f630b 100644 --- a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java +++ b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java @@ -230,7 +230,7 @@ private String findExtremeRecordPath( } @Override - public List getColumns() { + public List getColumns(Set pattern, TagFilter tagFilter) { List timeseries = new ArrayList<>(); for (Bucket bucket : diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java index 2dde3d2ca8..ca8b450d6b 100644 --- a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java +++ b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java @@ -295,7 +295,7 @@ private static long getDuplicateKey(WriteError error) { } @Override - public List getColumns() { + public List getColumns(Set pattern, TagFilter tagFilter) { List columns = new ArrayList<>(); for (String dbName : getDatabaseNames(this.client)) { MongoDatabase db = this.client.getDatabase(dbName); diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/ParquetStorage.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/ParquetStorage.java index d39b62d931..12c69e5149 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/ParquetStorage.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/ParquetStorage.java @@ -32,6 +32,7 @@ import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Filter; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.KeyFilter; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Op; +import cn.edu.tsinghua.iginx.engine.shared.operator.tag.TagFilter; import cn.edu.tsinghua.iginx.metadata.entity.*; import cn.edu.tsinghua.iginx.parquet.exec.Executor; import cn.edu.tsinghua.iginx.parquet.exec.LocalExecutor; @@ -44,6 +45,8 @@ import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.Set; + import org.apache.thrift.transport.TTransportException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -174,7 +177,7 @@ public TaskExecuteResult executeInsert(Insert insert, DataArea dataArea) { } @Override - public List getColumns() throws PhysicalException { + public List getColumns(Set pattern, TagFilter tagFilter) throws PhysicalException { return executor.getColumnsOfStorageUnit("*"); } diff --git a/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java b/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java index 831a7b9c1c..37ecff2dc2 100644 --- a/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java +++ b/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java @@ -467,7 +467,7 @@ public TaskExecuteResult executeInsert(Insert insert, DataArea dataArea) { } @Override - public List getColumns() { + public List getColumns(Set pattern, TagFilter tagFilter) { List ret = new ArrayList<>(); getIginxColumns(ret::add); getDummyColumns(ret::add); diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java index 484814477d..072723874b 100644 --- a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java +++ b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java @@ -335,7 +335,7 @@ private boolean filterContainsType(List types, Filter filter) { } @Override - public List getColumns() throws RelationalTaskExecuteFailureException { + public List getColumns(Set pattern, TagFilter tagFilter) throws RelationalTaskExecuteFailureException { List columns = new ArrayList<>(); Map extraParams = meta.getExtraParams(); try { @@ -1833,7 +1833,7 @@ private void executeBatchInsert( private List> determineDeletedPaths( List paths, TagFilter tagFilter) { try { - List columns = getColumns(); + List columns = getColumns(null, null); List> deletedPaths = new ArrayList<>(); for (Column column : columns) { From f0655629a03488e1716ce2ceee8fab3366eb796e Mon Sep 17 00:00:00 2001 From: RemHero <1104304963@qq.com> Date: Thu, 6 Jun 2024 11:30:12 +0800 Subject: [PATCH 007/138] fix --- .../execute/StoragePhysicalTaskExecutor.java | 39 ++++++++++++++----- .../iginx/filesystem/exec/LocalExecutor.java | 30 ++++++++------ .../tsinghua/iginx/iotdb/IoTDBStorage.java | 8 ++-- 3 files changed, 50 insertions(+), 27 deletions(-) diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java index 7735275b22..fc7b6314b1 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java @@ -58,7 +58,10 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadPoolExecutor; +import java.util.regex.Pattern; import java.util.stream.Collectors; + +import cn.edu.tsinghua.iginx.utils.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -314,6 +317,8 @@ public TaskExecuteResult executeGlobalTask(GlobalPhysicalTask task) { public TaskExecuteResult executeShowColumns(ShowColumns showColumns) { List storageList = metaManager.getStorageEngineList(); Set columnSet = new HashSet<>(); + TreeSet columnSetAfterFilter = + new TreeSet<>(Comparator.comparing(Column::getPhysicalPath)); for (StorageEngineMeta storage : storageList) { long id = storage.getId(); Pair pair = storageManager.getStorage(id); @@ -323,18 +328,36 @@ public TaskExecuteResult executeShowColumns(ShowColumns showColumns) { try { Set patternSet = showColumns.getPathRegexSet(); TagFilter tagFilter = showColumns.getTagFilter(); - if (storage.getDataPrefix() != null) { - patternSet.add(storage.getDataPrefix() + ".*"); - } + List columnList = pair.k.getColumns(patternSet, tagFilter); - // fix the schemaPrefix + + // fix the schemaPrefix and dataPrefix String schemaPrefix = storage.getSchemaPrefix(); - if (schemaPrefix != null) { + String dataPrefixRegex = StringUtils.reformatPath(storage.getDataPrefix() + ".*"); + if (tagFilter == null) { for (Column column : columnList) { if (column.isDummy()) { - column.setPath(schemaPrefix + "." + column.getPath()); + if (Pattern.matches(dataPrefixRegex, column.getPath())) { + if (schemaPrefix != null) { + column.setPath(schemaPrefix + "." + column.getPath()); + boolean isMatch = false; + for (String pathRegex : patternSet) { + if (Pattern.matches(StringUtils.reformatPath(pathRegex), column.getPath())) { + isMatch=true; + break; + } + } + if (isMatch) { + columnSetAfterFilter.add(column); + } + } + } + } else { + columnSetAfterFilter.addAll(columnList); } } + } else { + columnSetAfterFilter.addAll(columnList); } columnSet.addAll(columnList); } catch (PhysicalException e) { @@ -342,10 +365,6 @@ public TaskExecuteResult executeShowColumns(ShowColumns showColumns) { } } - TreeSet columnSetAfterFilter = - new TreeSet<>(Comparator.comparing(Column::getPhysicalPath)); - columnSetAfterFilter.addAll(columnSet); - int limit = showColumns.getLimit(); int offset = showColumns.getOffset(); if (limit == Integer.MAX_VALUE && offset == 0) { diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java index 90cbf66cd6..44c44696e3 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java @@ -312,6 +312,18 @@ public TaskExecuteResult executeDeleteTask( return new TaskExecuteResult(null, null); } + boolean isPathMatchPattern(String path, Set pattern) { + if (pattern.isEmpty()) { + return true; + } + for (String pathRegex : pattern) { + if (Pattern.matches(StringUtils.reformatPath(pathRegex), path)) { + return true; + } + } + return false; + } + @Override public List getColumnsOfStorageUnit( String storageUnit, Set pattern, TagFilter tagFilter) throws PhysicalException { @@ -322,7 +334,6 @@ public List getColumnsOfStorageUnit( FileMeta meta = fileSystemManager.getFileMeta(file); String columnPath = FilePathUtils.convertAbsolutePathToPath(root, file.getAbsolutePath(), storageUnit); - boolean isChosen = true; if (meta == null) { throw new PhysicalException( String.format( @@ -330,15 +341,7 @@ public List getColumnsOfStorageUnit( file.getAbsolutePath())); } // get columns by pattern - if (!pattern.isEmpty()) { - for (String pathRegex : pattern) { - if (!Pattern.matches(StringUtils.reformatPath(pathRegex), columnPath)) { - isChosen = false; - break; - } - } - } - if (!isChosen) { + if(!isPathMatchPattern(columnPath, pattern)) { continue; } // get columns by tag filter @@ -350,10 +353,13 @@ public List getColumnsOfStorageUnit( // get columns from dummy storage unit if (hasData && dummyRoot != null && tagFilter == null) { for (File file : fileSystemManager.getAllFiles(new File(realDummyRoot), true)) { + String dummyPath = FilePathUtils.convertAbsolutePathToPath(dummyRoot, file.getAbsolutePath(), storageUnit); + if(!isPathMatchPattern(dummyPath, pattern)) { + continue; + } columns.add( new Column( - FilePathUtils.convertAbsolutePathToPath( - dummyRoot, file.getAbsolutePath(), storageUnit), + dummyPath, DataType.BINARY, null, true)); diff --git a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java b/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java index a31aa6e56d..3685bbd823 100644 --- a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java +++ b/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java @@ -226,17 +226,15 @@ private void getColumns2StorageUnit( if (columns2StorageUnit != null) { columns2StorageUnit.put(pair.k, fragment); } - boolean isChosen = true; + boolean isChosen = false; // get columns by pattern if (!pattern.isEmpty()) { for (String pathRegex : pattern) { - if (!Pattern.matches(StringUtils.reformatPath(pathRegex), pair.k)) { - isChosen = false; + if (Pattern.matches(StringUtils.reformatPath(pathRegex), pair.k)) { + isChosen = true; break; } } - } else { - if (isDummy) continue; } if (!isChosen) { continue; From e16e2aeba55ed15ae6046d16acad1869127786e8 Mon Sep 17 00:00:00 2001 From: RemHero <1104304963@qq.com> Date: Thu, 6 Jun 2024 13:45:43 +0800 Subject: [PATCH 008/138] fix --- .../iginx/filesystem/exec/LocalExecutor.java | 3 ++- .../tsinghua/iginx/iotdb/IoTDBStorage.java | 23 +++++++++++-------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java index 44c44696e3..85c7e3bcc2 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java @@ -346,8 +346,9 @@ public List getColumnsOfStorageUnit( } // get columns by tag filter if (tagFilter != null && !TagKVUtils.match(meta.getTags(), tagFilter)) { - columns.add(new Column(columnPath, meta.getDataType(), meta.getTags(), false)); + continue; } + columns.add(new Column(columnPath, meta.getDataType(), meta.getTags(), false)); } } // get columns from dummy storage unit diff --git a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java b/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java index 3685bbd823..092f4bcd6c 100644 --- a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java +++ b/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java @@ -199,6 +199,18 @@ public List getColumns(Set pattern, TagFilter tagFilter) return columns; } + boolean isPathMatchPattern(String path, Set pattern) { + if (pattern.isEmpty()) { + return true; + } + for (String pathRegex : pattern) { + if (Pattern.matches(StringUtils.reformatPath(pathRegex), path)) { + return true; + } + } + return false; + } + private void getColumns2StorageUnit( List columns, Map columns2StorageUnit, @@ -226,17 +238,8 @@ private void getColumns2StorageUnit( if (columns2StorageUnit != null) { columns2StorageUnit.put(pair.k, fragment); } - boolean isChosen = false; // get columns by pattern - if (!pattern.isEmpty()) { - for (String pathRegex : pattern) { - if (Pattern.matches(StringUtils.reformatPath(pathRegex), pair.k)) { - isChosen = true; - break; - } - } - } - if (!isChosen) { + if (!isPathMatchPattern(pair.k, pattern)) { continue; } // get columns by tag filter From aa69181c1dc82d93ef9a942167e8a61ec8803fc6 Mon Sep 17 00:00:00 2001 From: RemHero <1104304963@qq.com> Date: Thu, 6 Jun 2024 15:57:35 +0800 Subject: [PATCH 009/138] format --- .github/workflows/DB-CE.yml | 2 +- .github/workflows/standard-test-suite.yml | 40 +++++------ .../execute/StoragePhysicalTaskExecutor.java | 5 +- .../iginx/filesystem/exec/LocalExecutor.java | 14 ++-- .../iginx/parquet/ParquetStorage.java | 4 +- .../iginx/relational/RelationalStorage.java | 3 +- .../expansion/BaseCapacityExpansionIT.java | 70 +++++++++---------- 7 files changed, 67 insertions(+), 71 deletions(-) diff --git a/.github/workflows/DB-CE.yml b/.github/workflows/DB-CE.yml index c331810ec8..a6a941df54 100644 --- a/.github/workflows/DB-CE.yml +++ b/.github/workflows/DB-CE.yml @@ -27,7 +27,7 @@ on: description: "The database to run the test on" type: string required: false - default: '["FileSystem", "IoTDB12"]' + default: '["FileSystem", "IoTDB12", "InfluxDB", "PostgreSQL", "Redis", "MongoDB", "Parquet", "MySQL"]' env: VERSION: 0.6.0-SNAPSHOT diff --git a/.github/workflows/standard-test-suite.yml b/.github/workflows/standard-test-suite.yml index f5b7a22f3b..a4f8234894 100644 --- a/.github/workflows/standard-test-suite.yml +++ b/.github/workflows/standard-test-suite.yml @@ -11,27 +11,27 @@ concurrency: cancel-in-progress: true jobs: -# unit-test: -# uses: ./.github/workflows/unit-test.yml -# unit-mds: -# uses: ./.github/workflows/unit-mds.yml -# case-regression: -# uses: ./.github/workflows/case-regression.yml -# with: -# metadata-matrix: '["zookeeper"]' -# standalone-test: -# uses: ./.github/workflows/standalone-test.yml -# with: -# metadata-matrix: '["zookeeper"]' -# standalone-test-pushdown: -# uses: ./.github/workflows/standalone-test-pushdown.yml -# with: -# metadata-matrix: '["zookeeper"]' + unit-test: + uses: ./.github/workflows/unit-test.yml + unit-mds: + uses: ./.github/workflows/unit-mds.yml + case-regression: + uses: ./.github/workflows/case-regression.yml + with: + metadata-matrix: '["zookeeper"]' + standalone-test: + uses: ./.github/workflows/standalone-test.yml + with: + metadata-matrix: '["zookeeper"]' + standalone-test-pushdown: + uses: ./.github/workflows/standalone-test-pushdown.yml + with: + metadata-matrix: '["zookeeper"]' db-ce: uses: ./.github/workflows/DB-CE.yml with: metadata-matrix: '["zookeeper"]' -# remote-test: -# uses: ./.github/workflows/remote-test.yml -# with: -# metadata-matrix: '["zookeeper"]' + remote-test: + uses: ./.github/workflows/remote-test.yml + with: + metadata-matrix: '["zookeeper"]' diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java index fc7b6314b1..917a55ceee 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java @@ -53,6 +53,7 @@ import cn.edu.tsinghua.iginx.monitor.HotSpotMonitor; import cn.edu.tsinghua.iginx.monitor.RequestsMonitor; import cn.edu.tsinghua.iginx.utils.Pair; +import cn.edu.tsinghua.iginx.utils.StringUtils; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; @@ -60,8 +61,6 @@ import java.util.concurrent.ThreadPoolExecutor; import java.util.regex.Pattern; import java.util.stream.Collectors; - -import cn.edu.tsinghua.iginx.utils.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -343,7 +342,7 @@ public TaskExecuteResult executeShowColumns(ShowColumns showColumns) { boolean isMatch = false; for (String pathRegex : patternSet) { if (Pattern.matches(StringUtils.reformatPath(pathRegex), column.getPath())) { - isMatch=true; + isMatch = true; break; } } diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java index 85c7e3bcc2..d7f2160a2a 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java @@ -341,7 +341,7 @@ public List getColumnsOfStorageUnit( file.getAbsolutePath())); } // get columns by pattern - if(!isPathMatchPattern(columnPath, pattern)) { + if (!isPathMatchPattern(columnPath, pattern)) { continue; } // get columns by tag filter @@ -354,16 +354,12 @@ public List getColumnsOfStorageUnit( // get columns from dummy storage unit if (hasData && dummyRoot != null && tagFilter == null) { for (File file : fileSystemManager.getAllFiles(new File(realDummyRoot), true)) { - String dummyPath = FilePathUtils.convertAbsolutePathToPath(dummyRoot, file.getAbsolutePath(), storageUnit); - if(!isPathMatchPattern(dummyPath, pattern)) { + String dummyPath = + FilePathUtils.convertAbsolutePathToPath(dummyRoot, file.getAbsolutePath(), storageUnit); + if (!isPathMatchPattern(dummyPath, pattern)) { continue; } - columns.add( - new Column( - dummyPath, - DataType.BINARY, - null, - true)); + columns.add(new Column(dummyPath, DataType.BINARY, null, true)); } } return columns; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/ParquetStorage.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/ParquetStorage.java index 12c69e5149..c2bc012f09 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/ParquetStorage.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/ParquetStorage.java @@ -46,7 +46,6 @@ import java.util.List; import java.util.Map; import java.util.Set; - import org.apache.thrift.transport.TTransportException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -177,7 +176,8 @@ public TaskExecuteResult executeInsert(Insert insert, DataArea dataArea) { } @Override - public List getColumns(Set pattern, TagFilter tagFilter) throws PhysicalException { + public List getColumns(Set pattern, TagFilter tagFilter) + throws PhysicalException { return executor.getColumnsOfStorageUnit("*"); } diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java index 072723874b..1084b6e69c 100644 --- a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java +++ b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java @@ -335,7 +335,8 @@ private boolean filterContainsType(List types, Filter filter) { } @Override - public List getColumns(Set pattern, TagFilter tagFilter) throws RelationalTaskExecuteFailureException { + public List getColumns(Set pattern, TagFilter tagFilter) + throws RelationalTaskExecuteFailureException { List columns = new ArrayList<>(); Map extraParams = meta.getExtraParams(); try { diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java index a2959c9e1e..676ebc3e30 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java @@ -24,7 +24,6 @@ import java.util.Collections; import java.util.List; import java.util.stream.Collectors; - import org.junit.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -328,14 +327,14 @@ protected void queryExtendedKeyDummy() { session, statement, READ_ONLY_PATH_LIST, READ_ONLY_EXTEND_VALUES_LIST); // test show columns - testShowColumns(Arrays.asList( - new Column("mn.wf01.wt01.temperature", DataType.DOUBLE), - new Column("mn.wf01.wt01.status", DataType.LONG), - new Column("nt.wf03.wt01.status2", DataType.LONG), - new Column("nt.wf04.wt01.temperature", DataType.DOUBLE), - new Column("tm.wf05.wt01.status", DataType.LONG), - new Column("tm.wf05.wt01.temperature", DataType.DOUBLE) - )); + testShowColumns( + Arrays.asList( + new Column("mn.wf01.wt01.temperature", DataType.DOUBLE), + new Column("mn.wf01.wt01.status", DataType.LONG), + new Column("nt.wf03.wt01.status2", DataType.LONG), + new Column("nt.wf04.wt01.temperature", DataType.DOUBLE), + new Column("tm.wf05.wt01.status", DataType.LONG), + new Column("tm.wf05.wt01.temperature", DataType.DOUBLE))); } protected void queryExtendedColDummy() { @@ -474,15 +473,11 @@ private void testShowColumns(List expectColumns) { LOGGER.info("show columns: {}", columns); // 对期望列表和实际列表中的Column对象按路径排序 - List sortedExpectPaths = expectColumns.stream() - .map(Column::getPath) - .sorted() - .collect(Collectors.toList()); + List sortedExpectPaths = + expectColumns.stream().map(Column::getPath).sorted().collect(Collectors.toList()); - List sortedActualPaths = columns.stream() - .map(Column::getPath) - .sorted() - .collect(Collectors.toList()); + List sortedActualPaths = + columns.stream().map(Column::getPath).sorted().collect(Collectors.toList()); // 检查排序后的路径列表是否相同 assertArrayEquals(sortedExpectPaths.toArray(), sortedActualPaths.toArray()); @@ -501,26 +496,31 @@ private void testAddAndRemoveStorageEngineWithPrefix() { List> valuesList = EXP_VALUES_LIST1; - testShowColumns(Arrays.asList( - new Column("b.b.b", DataType.LONG), - new Column("ln.wf02.status", DataType.BOOLEAN), - new Column("ln.wf02.version", DataType.BINARY), - new Column("nt.wf03.wt01.status2", DataType.LONG), - new Column("nt.wf04.wt01.temperature", DataType.DOUBLE), - new Column("zzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzzzz", DataType.LONG) - )); + testShowColumns( + Arrays.asList( + new Column("b.b.b", DataType.LONG), + new Column("ln.wf02.status", DataType.BOOLEAN), + new Column("ln.wf02.version", DataType.BINARY), + new Column("nt.wf03.wt01.status2", DataType.LONG), + new Column("nt.wf04.wt01.temperature", DataType.DOUBLE), + new Column( + "zzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzzzz", + DataType.LONG))); // 添加不同 schemaPrefix,相同 dataPrefix addStorageEngine(expPort, true, true, dataPrefix1, schemaPrefix1, extraParams); - testShowColumns(Arrays.asList( - new Column("b.b.b", DataType.LONG), - new Column("ln.wf02.status", DataType.BOOLEAN), - new Column("ln.wf02.version", DataType.BINARY), - new Column("nt.wf03.wt01.status2", DataType.LONG),new Column("p1.nt.wf03.wt01.status2", DataType.LONG), - new Column("nt.wf04.wt01.temperature", DataType.DOUBLE), - new Column("zzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzzzz", DataType.LONG) - )); + testShowColumns( + Arrays.asList( + new Column("b.b.b", DataType.LONG), + new Column("ln.wf02.status", DataType.BOOLEAN), + new Column("ln.wf02.version", DataType.BINARY), + new Column("nt.wf03.wt01.status2", DataType.LONG), + new Column("p1.nt.wf03.wt01.status2", DataType.LONG), + new Column("nt.wf04.wt01.temperature", DataType.DOUBLE), + new Column( + "zzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzzzz", + DataType.LONG))); // 添加节点 dataPrefix = dataPrefix1 && schemaPrefix = p1 后查询 String statement = "select status2 from *;"; @@ -734,8 +734,8 @@ private void testSameKeyWarning() { QueryDataSet res = session.executeQuery(statement); if ((res.getWarningMsg() == null - || res.getWarningMsg().isEmpty() - || !res.getWarningMsg().contains("The query results contain overlapped keys.")) + || res.getWarningMsg().isEmpty() + || !res.getWarningMsg().contains("The query results contain overlapped keys.")) && SUPPORT_KEY.get(testConf.getStorageType())) { LOGGER.error("未抛出重叠key的警告"); fail(); From 4c73402cc3058622c44bca98f7451667b8ba2227 Mon Sep 17 00:00:00 2001 From: RemHero <1104304963@qq.com> Date: Fri, 7 Jun 2024 16:14:52 +0800 Subject: [PATCH 010/138] add test --- .../storage/execute/StoragePhysicalTaskExecutor.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java index 917a55ceee..658e615973 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java @@ -315,7 +315,6 @@ public TaskExecuteResult executeGlobalTask(GlobalPhysicalTask task) { public TaskExecuteResult executeShowColumns(ShowColumns showColumns) { List storageList = metaManager.getStorageEngineList(); - Set columnSet = new HashSet<>(); TreeSet columnSetAfterFilter = new TreeSet<>(Comparator.comparing(Column::getPhysicalPath)); for (StorageEngineMeta storage : storageList) { @@ -332,14 +331,14 @@ public TaskExecuteResult executeShowColumns(ShowColumns showColumns) { // fix the schemaPrefix and dataPrefix String schemaPrefix = storage.getSchemaPrefix(); - String dataPrefixRegex = StringUtils.reformatPath(storage.getDataPrefix() + ".*"); + String dataPrefixRegex = storage.getDataPrefix() == null ? null : StringUtils.reformatPath(storage.getDataPrefix() + ".*"); if (tagFilter == null) { for (Column column : columnList) { if (column.isDummy()) { - if (Pattern.matches(dataPrefixRegex, column.getPath())) { + if (dataPrefixRegex == null || Pattern.matches(dataPrefixRegex, column.getPath())) { if (schemaPrefix != null) { column.setPath(schemaPrefix + "." + column.getPath()); - boolean isMatch = false; + boolean isMatch = patternSet.isEmpty(); for (String pathRegex : patternSet) { if (Pattern.matches(StringUtils.reformatPath(pathRegex), column.getPath())) { isMatch = true; @@ -349,16 +348,17 @@ public TaskExecuteResult executeShowColumns(ShowColumns showColumns) { if (isMatch) { columnSetAfterFilter.add(column); } + } else { + columnSetAfterFilter.add(column); } } } else { - columnSetAfterFilter.addAll(columnList); + columnSetAfterFilter.add(column); } } } else { columnSetAfterFilter.addAll(columnList); } - columnSet.addAll(columnList); } catch (PhysicalException e) { return new TaskExecuteResult(e); } From 7acf6a8788cfeaafe57650075550d7e18fb9270a Mon Sep 17 00:00:00 2001 From: RemHero <1104304963@qq.com> Date: Fri, 7 Jun 2024 16:43:57 +0800 Subject: [PATCH 011/138] remove test --- .../integration/expansion/BaseCapacityExpansionIT.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java index 676ebc3e30..9af9fa87f0 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java @@ -325,16 +325,6 @@ protected void queryExtendedKeyDummy() { statement = "select wf05.wt01.status, wf05.wt01.temperature from tm;"; SQLTestTools.executeAndContainValue( session, statement, READ_ONLY_PATH_LIST, READ_ONLY_EXTEND_VALUES_LIST); - - // test show columns - testShowColumns( - Arrays.asList( - new Column("mn.wf01.wt01.temperature", DataType.DOUBLE), - new Column("mn.wf01.wt01.status", DataType.LONG), - new Column("nt.wf03.wt01.status2", DataType.LONG), - new Column("nt.wf04.wt01.temperature", DataType.DOUBLE), - new Column("tm.wf05.wt01.status", DataType.LONG), - new Column("tm.wf05.wt01.temperature", DataType.DOUBLE))); } protected void queryExtendedColDummy() { From aa3b1032d1963b217e7eef47ed27473bb275e04e Mon Sep 17 00:00:00 2001 From: An Qi Date: Fri, 7 Jun 2024 17:06:02 +0800 Subject: [PATCH 012/138] feat(redis): show columns with pattern and tagFilter --- .../tsinghua/iginx/redis/RedisStorage.java | 88 +++++++++++-------- .../iginx/redis/tools/TagKVUtils.java | 6 +- 2 files changed, 57 insertions(+), 37 deletions(-) diff --git a/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java b/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java index 37ecff2dc2..abd7d16e78 100644 --- a/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java +++ b/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java @@ -468,49 +468,65 @@ public TaskExecuteResult executeInsert(Insert insert, DataArea dataArea) { @Override public List getColumns(Set pattern, TagFilter tagFilter) { - List ret = new ArrayList<>(); - getIginxColumns(ret::add); - getDummyColumns(ret::add); - return ret; + try { + List ret = new ArrayList<>(); + getIginxColumns(ret::add, pattern, tagFilter); + getDummyColumns(ret::add, pattern); + return ret; + } catch (PhysicalException e) { + throw new IllegalStateException("get columns error", e); + } } - private void getIginxColumns(Consumer ret) { + private void getIginxColumns(Consumer ret, Set pattern, TagFilter tagFilter) + throws PhysicalException { + List patternList = new ArrayList<>(pattern); + if (patternList.isEmpty()) { + patternList.add("*"); + } + List allPaths = determinePathList("*", patternList, tagFilter); try (Jedis jedis = getDataConnection()) { - Map pathsAndTypes = jedis.hgetAll(KEY_DATA_TYPE); - pathsAndTypes.forEach( - (k, v) -> { - DataType type = DataTransformer.fromStringDataType(v); - Pair> pair = TagKVUtils.splitFullName(k); - ret.accept(new Column(pair.k, type, pair.v)); - }); + for (String path : allPaths) { + String typeStr = jedis.hget(KEY_DATA_TYPE, path); + if (typeStr == null) { + continue; + } + DataType type = DataTransformer.fromStringDataType(typeStr); + Pair> pair = TagKVUtils.splitFullName(path); + ret.accept(new Column(pair.k, type, pair.v)); + } } } - private void getDummyColumns(Consumer ret) { + private void getDummyColumns(Consumer ret, Set patterns) { + List patternList = new ArrayList<>(patterns); + if (patternList.isEmpty()) { + patternList.add("*"); + } try (Jedis jedis = getDummyConnection()) { - String pattern = STAR; - if (dataPrefix != null) { - pattern = dataPrefix + "." + pattern; - } - Set keys = jedis.keys(pattern); - for (String key : keys) { - String type = jedis.type(key); - switch (type) { - case "string": - case "list": - case "set": - case "zset": - ret.accept(new Column(key, DataType.BINARY, Collections.emptyMap(), true)); - break; - case "hash": - ret.accept(new Column(key + SUFFIX_KEY, DataType.BINARY, Collections.emptyMap(), true)); - ret.accept( - new Column(key + SUFFIX_VALUE, DataType.BINARY, Collections.emptyMap(), true)); - break; - case "none": - LOGGER.warn("key {} not exists", key); - default: - LOGGER.warn("unknown key type, type={}", type); + for (String pattern : patternList) { + String redisPattern = TagKVUtils.escapeRedisSpecialCharInPattern(pattern); + Set keys = jedis.keys(redisPattern); + for (String key : keys) { + String type = jedis.type(key); + switch (type) { + case "string": + case "list": + case "set": + case "zset": + ret.accept(new Column(key, DataType.BINARY, Collections.emptyMap(), true)); + break; + case "hash": + ret.accept( + new Column(key + SUFFIX_KEY, DataType.BINARY, Collections.emptyMap(), true)); + ret.accept( + new Column(key + SUFFIX_VALUE, DataType.BINARY, Collections.emptyMap(), true)); + break; + case "none": + LOGGER.warn("key {} not exists", key); + default: + LOGGER.warn("unknown key type, type={}", type); + } } } } diff --git a/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/TagKVUtils.java b/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/TagKVUtils.java index c42ffba5d3..d1ac9055e5 100644 --- a/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/TagKVUtils.java +++ b/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/TagKVUtils.java @@ -67,7 +67,11 @@ public static Pair> splitFullName(String fullName) { public static String getPattern(String name) { String escaped = COLUMN_KEY_TRANSLATOR.getEscaper().escape(name); - return escaped.replaceAll("[?^{}\\[\\]\\\\]", "\\\\$0"); + return escapeRedisSpecialCharInPattern(escaped); + } + + public static String escapeRedisSpecialCharInPattern(String name) { + return name.replaceAll("[?^{}\\[\\]\\\\]", "\\\\$0"); } public static boolean match(Map tags, TagFilter tagFilter) { From 4c08d43839acba537063ae6593600cbfa5dbd222 Mon Sep 17 00:00:00 2001 From: An Qi Date: Fri, 7 Jun 2024 20:51:21 +0800 Subject: [PATCH 013/138] feat(mongodb): show columns with pattern and tagFilter --- .../iginx/mongodb/MongoDBStorage.java | 12 ++++++++-- .../iginx/mongodb/tools/NameUtils.java | 23 ++++++++++++------- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java index ca8b450d6b..4178ea2fab 100644 --- a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java +++ b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java @@ -296,6 +296,10 @@ private static long getDuplicateKey(WriteError error) { @Override public List getColumns(Set pattern, TagFilter tagFilter) { + List patternList = new ArrayList<>(pattern); + if (patternList.isEmpty()) { + patternList.add("*"); + } List columns = new ArrayList<>(); for (String dbName : getDatabaseNames(this.client)) { MongoDatabase db = this.client.getDatabase(dbName); @@ -303,7 +307,9 @@ public List getColumns(Set pattern, TagFilter tagFilter) { try { if (dbName.startsWith("unit")) { Field field = NameUtils.parseCollectionName(collectionName); - columns.add(new Column(field.getName(), field.getType(), field.getTags(), false)); + if (NameUtils.match(field.getName(), field.getTags(), patternList, tagFilter)) { + columns.add(new Column(field.getName(), field.getType(), field.getTags(), false)); + } continue; } } catch (Exception ignored) { @@ -315,7 +321,9 @@ public List getColumns(Set pattern, TagFilter tagFilter) { Map sampleSchema = new SchemaSample(schemaSampleSize).query(collection, true); for (Map.Entry entry : sampleSchema.entrySet()) { - columns.add(new Column(entry.getKey(), entry.getValue(), null, true)); + if (NameUtils.match(entry.getKey(), Collections.emptyMap(), patternList, null)) { + columns.add(new Column(entry.getKey(), entry.getValue(), null, true)); + } } continue; } diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/tools/NameUtils.java b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/tools/NameUtils.java index 5871b82b20..14c9901eb9 100644 --- a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/tools/NameUtils.java +++ b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/tools/NameUtils.java @@ -63,19 +63,26 @@ public static List match( Iterable fieldList, Iterable patterns, TagFilter tagFilter) { List fields = new ArrayList<>(); for (Field field : fieldList) { - if (tagFilter != null && !TagKVUtils.match(field.getTags(), tagFilter)) { - continue; - } - for (String pattern : patterns) { - if (Pattern.matches(StringUtils.reformatPath(pattern), field.getName())) { - fields.add(field); - break; - } + if (match(field.getName(), field.getTags(), patterns, tagFilter)) { + fields.add(field); } } return fields; } + public static boolean match( + String columnName, Map tags, Iterable patterns, TagFilter tagFilter) { + if (tagFilter != null && !TagKVUtils.match(tags, tagFilter)) { + return false; + } + for (String pattern : patterns) { + if (Pattern.matches(StringUtils.reformatPath(pattern), columnName)) { + return true; + } + } + return false; + } + public static boolean isWildcard(String node) { return node.contains("*"); } From f2bf124fa89737fe4c725d9f2358cb1272c6d0a2 Mon Sep 17 00:00:00 2001 From: An Qi Date: Fri, 7 Jun 2024 20:58:56 +0800 Subject: [PATCH 014/138] build: convenient version switching (#349) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 使项目版本切换更便捷。 移除了下面模块对特定版本的依赖 a. 测试 @RemHero b. docker 添加了一个 github workflow 用来切换版本 --- .../capacityExpansionUnionTest/action.yml | 7 -- .github/actions/context/action.yml | 1 - .github/actions/dependence/action.yml | 9 +++ .github/actions/iginxRunner/action.yml | 4 -- .github/actions/project/action.yml | 23 ++++++ .github/workflows/DB-CE.yml | 6 -- .github/workflows/case-regression.yml | 3 - .github/workflows/remote-test.yml | 3 - .../workflows/standalone-test-pushdown.yml | 3 - .github/workflows/standalone-test.yml | 4 -- .github/workflows/unit-test.yml | 3 - .github/workflows/update-project-version.yml | 70 +++++++++++++++++++ antlr/pom.xml | 1 - client/pom.xml | 1 - .../tsinghua/iginx/client/IginxClient.java | 29 +++++--- core/pom.xml | 1 - docker/client/build-no-maven.bat | 2 +- docker/client/build-no-maven.sh | 2 +- docker/client/build.bat | 2 +- docker/client/build.sh | 2 +- docker/client/run_docker.bat | 2 +- docker/client/run_docker.sh | 2 +- .../onlyIginx-parquet/build_iginx_docker.bat | 2 +- .../onlyIginx-parquet/build_iginx_docker.sh | 2 +- docker/onlyIginx-parquet/run_iginx_docker.bat | 2 +- docker/onlyIginx-parquet/run_iginx_docker.sh | 2 +- docker/onlyIginx/build_iginx_docker.bat | 2 +- docker/onlyIginx/build_iginx_docker.sh | 2 +- docker/onlyIginx/run_iginx_docker.bat | 2 +- docker/onlyIginx/run_iginx_docker.sh | 2 +- example/pom.xml | 1 - jdbc/pom.xml | 1 - pom.xml | 2 +- test/pom.xml | 1 - .../func/session/NewSessionIT.java | 5 +- thrift/pom.xml | 1 - 36 files changed, 141 insertions(+), 66 deletions(-) create mode 100644 .github/actions/project/action.yml create mode 100644 .github/workflows/update-project-version.yml diff --git a/.github/actions/capacityExpansionUnionTest/action.yml b/.github/actions/capacityExpansionUnionTest/action.yml index 6096601a35..ffe31ada33 100644 --- a/.github/actions/capacityExpansionUnionTest/action.yml +++ b/.github/actions/capacityExpansionUnionTest/action.yml @@ -1,10 +1,6 @@ name: "CapExp-Union-Test" description: "steps to test the capacity expansion" inputs: - version: - description: "iginx runner version" - required: false - default: 0.6.0-SNAPSHOT DB-name: description: "DB name" required: false @@ -34,7 +30,6 @@ runs: - name: Stop IGinX uses: ./.github/actions/iginxRunner with: - version: ${{ inputs.version }} if-stop: true - name: Stop and clear Metadata @@ -66,5 +61,3 @@ runs: - name: Start IGinX uses: ./.github/actions/iginxRunner - with: - version: ${{ inputs.version }} diff --git a/.github/actions/context/action.yml b/.github/actions/context/action.yml index 755c7cfd02..fb8a4bc509 100644 --- a/.github/actions/context/action.yml +++ b/.github/actions/context/action.yml @@ -25,7 +25,6 @@ runs: name: Stop IGinX uses: ./.github/actions/iginxRunner with: - version: ${VERSION} if-stop: true - if: inputs.work-name=='stop-iginx-meta' || inputs.work-name=='restart-iginx-meta' diff --git a/.github/actions/dependence/action.yml b/.github/actions/dependence/action.yml index 3491e64b2b..97ab7dde48 100644 --- a/.github/actions/dependence/action.yml +++ b/.github/actions/dependence/action.yml @@ -60,3 +60,12 @@ runs: java-version: ${{ inputs.java }} distribution: "temurin" cache: "maven" + + - name: Get project info + id: project + uses: ./.github/actions/project + + - name: Set up environment variable + shell: bash + run: | + echo "VERSION=${{ steps.project.outputs.version }}" >> $GITHUB_ENV diff --git a/.github/actions/iginxRunner/action.yml b/.github/actions/iginxRunner/action.yml index 1e02011434..859354faf2 100644 --- a/.github/actions/iginxRunner/action.yml +++ b/.github/actions/iginxRunner/action.yml @@ -1,10 +1,6 @@ name: "iginx-runner" description: "iginx runner" inputs: - version: - description: "iginx runner version" - required: false - default: 0.6.0-SNAPSHOT if-stop: description: "to stop the iginx" required: false diff --git a/.github/actions/project/action.yml b/.github/actions/project/action.yml new file mode 100644 index 0000000000..fed7041df2 --- /dev/null +++ b/.github/actions/project/action.yml @@ -0,0 +1,23 @@ +name: "project" +description: "use maven to get project information in pom.xml" +inputs: + workspace: + description: "file paths delimited by space" + required: false + default: ${{ github.workspace }} + +outputs: + version: + description: "project version" + value: ${{ steps.info.outputs.version }} + +runs: + using: "composite" + steps: + - name: "information" + id: info + shell: bash + working-directory: ${{ inputs.workspace }} + run: | + VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout) + echo "version=$VERSION" >> $GITHUB_OUTPUT diff --git a/.github/workflows/DB-CE.yml b/.github/workflows/DB-CE.yml index a6a941df54..2d86315200 100644 --- a/.github/workflows/DB-CE.yml +++ b/.github/workflows/DB-CE.yml @@ -30,7 +30,6 @@ on: default: '["FileSystem", "IoTDB12", "InfluxDB", "PostgreSQL", "Redis", "MongoDB", "Parquet", "MySQL"]' env: - VERSION: 0.6.0-SNAPSHOT FUNCTEST: NewSessionIT,SQLCompareIT,TagIT,RestIT,TransformIT,UDFIT,RestAnnotationIT,SQLSessionIT,SQLSessionPoolIT,SessionV2IT,SessionIT,SessionPoolIT,CompactionIT,TimePrecisionIT,PySessionIT jobs: @@ -74,7 +73,6 @@ jobs: - name: Prepare CapExp environment oriHasDataExpHasData uses: ./.github/actions/capacityExpansionUnionTest with: - version: ${VERSION} DB-name: ${{ matrix.DB-name }} Test-Way: oriHasDataExpHasData @@ -98,7 +96,6 @@ jobs: - name: Prepare CapExp environment oriNoDataExpNoData uses: ./.github/actions/capacityExpansionUnionTest with: - version: ${VERSION} DB-name: ${{ matrix.DB-name }} Test-Way: oriNoDataExpNoData @@ -122,7 +119,6 @@ jobs: - name: Prepare CapExp environment oriHasDataExpNoData uses: ./.github/actions/capacityExpansionUnionTest with: - version: ${VERSION} DB-name: ${{ matrix.DB-name }} Test-Way: oriHasDataExpNoData @@ -146,7 +142,6 @@ jobs: - name: Prepare CapExp environment oriNoDataExpHasData uses: ./.github/actions/capacityExpansionUnionTest with: - version: ${VERSION} DB-name: ${{ matrix.DB-name }} Test-Way: oriNoDataExpHasData @@ -170,7 +165,6 @@ jobs: - name: Prepare CapExp environment for testReadOnly uses: ./.github/actions/capacityExpansionUnionTest with: - version: ${VERSION} DB-name: ${{ matrix.DB-name }} Test-Way: oriHasDataExpHasData Read-Only: true diff --git a/.github/workflows/case-regression.yml b/.github/workflows/case-regression.yml index 8015c3165e..f923406da3 100644 --- a/.github/workflows/case-regression.yml +++ b/.github/workflows/case-regression.yml @@ -24,9 +24,6 @@ on: required: false default: '["zookeeper", "etcd"]' -env: - VERSION: 0.6.0-SNAPSHOT - jobs: MixCluster-ShowTimeseries: timeout-minutes: 15 diff --git a/.github/workflows/remote-test.yml b/.github/workflows/remote-test.yml index 0f73210f4c..a0772504bb 100644 --- a/.github/workflows/remote-test.yml +++ b/.github/workflows/remote-test.yml @@ -29,7 +29,6 @@ on: default: '["IoTDB12", "Parquet"]' env: - VERSION: 0.6.0-SNAPSHOT FUNCTEST: RemoteUDFIT jobs: @@ -106,8 +105,6 @@ jobs: - name: Start IGinX uses: ./.github/actions/iginxRunner - with: - version: ${VERSION} - name: Register Remote UDFs shell: bash diff --git a/.github/workflows/standalone-test-pushdown.yml b/.github/workflows/standalone-test-pushdown.yml index c4116604e3..049d7dce42 100644 --- a/.github/workflows/standalone-test-pushdown.yml +++ b/.github/workflows/standalone-test-pushdown.yml @@ -29,9 +29,6 @@ on: required: false default: '["FileSystem", "IoTDB12", "InfluxDB", "PostgreSQL", "Redis", "MongoDB", "Parquet", "MySQL"]' -env: - VERSION: 0.6.0-SNAPSHOT - jobs: Union-DB-Test-Push_Down: timeout-minutes: 35 diff --git a/.github/workflows/standalone-test.yml b/.github/workflows/standalone-test.yml index e9f202c6e3..4e5d291fc9 100644 --- a/.github/workflows/standalone-test.yml +++ b/.github/workflows/standalone-test.yml @@ -29,9 +29,6 @@ on: required: false default: '["FileSystem", "IoTDB12", "InfluxDB", "PostgreSQL", "Redis", "MongoDB", "Parquet", "MySQL"]' -env: - VERSION: 0.6.0-SNAPSHOT - jobs: Union-DB-Test: timeout-minutes: 40 @@ -78,7 +75,6 @@ jobs: - name: Start IGinX uses: ./.github/actions/iginxRunner with: - version: ${VERSION} if-test-udf: "true" - name: Run UDF path test diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index a8a2270036..2c12c12252 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -19,9 +19,6 @@ on: required: false default: '["ubuntu-latest", "macos-13", "windows-latest"]' -env: - VERSION: 0.6.0-SNAPSHOT - jobs: Unit-Test: strategy: diff --git a/.github/workflows/update-project-version.yml b/.github/workflows/update-project-version.yml new file mode 100644 index 0000000000..1925efee46 --- /dev/null +++ b/.github/workflows/update-project-version.yml @@ -0,0 +1,70 @@ +name: Update Project Version + +on: + workflow_dispatch: + inputs: + major: + description: "Major version" + required: true + type: number + minor: + description: "Minor version" + required: true + type: number + patch: + description: "Patch version" + required: true + type: number + snapshot: + description: "Snapshot version" + required: true + type: boolean + +jobs: + update-project-version: + name: Update Project Version + runs-on: ubuntu-latest + permissions: + pull-requests: write + contents: write + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 + with: + java-version: "8" + distribution: "temurin" + cache: "maven" + - id: new-version + name: Get project version from inputs + shell: bash + run: | + NEWVERSION=${{ inputs.major }}.${{ inputs.minor }}.${{ inputs.patch }} + if ${{ inputs.snapshot }}; then + NEWVERSION=${NEWVERSION}-SNAPSHOT + fi + echo "version=${NEWVERSION}" >> $GITHUB_OUTPUT + - id: old-version + name: Get old project version from pom.xml + uses: ./.github/actions/project + - name: Update project version + shell: bash + run: mvn versions:set-property -Dproperty=revision -DnewVersion="${{ steps.new-version.outputs.version }}" + - name: update verison in docker directory + shell: bash + run: | + find docker -type f -exec sed -i "s/${{ steps.old-version.outputs.version }}/${{ steps.new-version.outputs.version }}/g" {} \; + - name: update version in docs + shell: bash + run: | + find docs -type f -exec sed -i "s/${{ steps.old-version.outputs.version }}/${{ steps.new-version.outputs.version }}/g" {} \; + - name: create pull request + uses: peter-evans/create-pull-request@v6 + with: + add-paths: | + pom.xml + docker + docs + branch: version-bot/${{ steps.new-version.outputs.version }} + delete-branch: true + commit-message: "build: update project version to ${{ steps.new-version.outputs.version }}" + title: "build: update project version to ${{ steps.new-version.outputs.version }}" diff --git a/antlr/pom.xml b/antlr/pom.xml index 582b4f916d..21fc4db912 100644 --- a/antlr/pom.xml +++ b/antlr/pom.xml @@ -7,7 +7,6 @@ cn.edu.tsinghua iginx ${revision} - ../pom.xml iginx-antlr diff --git a/client/pom.xml b/client/pom.xml index c2dadeeb21..65d70bbe39 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -7,7 +7,6 @@ cn.edu.tsinghua iginx ${revision} - ../pom.xml iginx-client diff --git a/client/src/main/java/cn/edu/tsinghua/iginx/client/IginxClient.java b/client/src/main/java/cn/edu/tsinghua/iginx/client/IginxClient.java index b6fedba735..a20cad8c27 100644 --- a/client/src/main/java/cn/edu/tsinghua/iginx/client/IginxClient.java +++ b/client/src/main/java/cn/edu/tsinghua/iginx/client/IginxClient.java @@ -35,18 +35,12 @@ import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; +import java.net.URL; import java.nio.ByteBuffer; import java.nio.file.Files; import java.nio.file.Paths; import java.security.InvalidParameterException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import org.apache.commons.cli.*; import org.apache.commons.csv.CSVPrinter; import org.apache.commons.io.FileUtils; @@ -217,7 +211,7 @@ private static void serve(String[] args) { if (execute.equals("")) { echoStarting(); - displayLogo("0.6.0-SNAPSHOT"); + displayLogo(loadClientVersion()); String command; while (true) { @@ -251,6 +245,23 @@ private static void serve(String[] args) { } } + private static String loadClientVersion() { + URL url = + IginxClient.class.getResource( + "/META-INF/maven/cn.edu.tsinghua/iginx-client/pom.properties"); + if (url != null) { + Properties properties = new Properties(); + try { + properties.load(url.openStream()); + return properties.getProperty("version"); + } catch (Exception e) { + System.err.println("Failed to load version: " + e); + } + } + + return "unknown"; + } + private static boolean processCommand(String command) throws SessionException, IOException { if (command == null || command.trim().isEmpty()) { return true; diff --git a/core/pom.xml b/core/pom.xml index 4c3389c57c..bc1b4e11fa 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -7,7 +7,6 @@ cn.edu.tsinghua iginx ${revision} - ../pom.xml iginx-core IGinX Core diff --git a/docker/client/build-no-maven.bat b/docker/client/build-no-maven.bat index 02015e96a7..e36c178c94 100644 --- a/docker/client/build-no-maven.bat +++ b/docker/client/build-no-maven.bat @@ -1 +1 @@ -docker build --file Dockerfile-no-maven-windows -t iginx-client:0.6.0 ../../client \ No newline at end of file +docker build --file Dockerfile-no-maven-windows -t iginx-client:0.6.0-SNAPSHOT ../../client \ No newline at end of file diff --git a/docker/client/build-no-maven.sh b/docker/client/build-no-maven.sh index 961ecc07e8..810565fb7a 100644 --- a/docker/client/build-no-maven.sh +++ b/docker/client/build-no-maven.sh @@ -1,2 +1,2 @@ #!/bin/bash -docker build --file Dockerfile-no-maven -t iginx-client:0.6.0 ../../client \ No newline at end of file +docker build --file Dockerfile-no-maven -t iginx-client:0.6.0-SNAPSHOT ../../client \ No newline at end of file diff --git a/docker/client/build.bat b/docker/client/build.bat index 2861d26462..2a056ac99b 100644 --- a/docker/client/build.bat +++ b/docker/client/build.bat @@ -1 +1 @@ -docker build --file Dockerfile -t iginx-client:0.6.0 ../../client \ No newline at end of file +docker build --file Dockerfile -t iginx-client:0.6.0-SNAPSHOT ../../client \ No newline at end of file diff --git a/docker/client/build.sh b/docker/client/build.sh index 9f0a707b1a..ac16f75ef5 100644 --- a/docker/client/build.sh +++ b/docker/client/build.sh @@ -1,2 +1,2 @@ #!/bin/bash -docker build --file Dockerfile -t iginx-client:0.6.0 ../../client \ No newline at end of file +docker build --file Dockerfile -t iginx-client:0.6.0-SNAPSHOT ../../client \ No newline at end of file diff --git a/docker/client/run_docker.bat b/docker/client/run_docker.bat index ea633324b5..4cec937600 100644 --- a/docker/client/run_docker.bat +++ b/docker/client/run_docker.bat @@ -34,7 +34,7 @@ if not exist "%datadir%" ( mkdir "%datadir%" ) -set command=docker run --name="%name%" -dit --add-host=host.docker.internal:host-gateway --mount type=bind,source=!datadir!,target=C:/iginx_client/data iginx-client:0.6.0 +set command=docker run --name="%name%" -dit --add-host=host.docker.internal:host-gateway --mount type=bind,source=!datadir!,target=C:/iginx_client/data iginx-client:0.6.0-SNAPSHOT echo %command% %command% diff --git a/docker/client/run_docker.sh b/docker/client/run_docker.sh index 5384ea95c4..3b6af08f21 100644 --- a/docker/client/run_docker.sh +++ b/docker/client/run_docker.sh @@ -21,6 +21,6 @@ done [ -d "$datadir" ] || mkdir -p "$datadir" -command="docker run --name=\"$name\" --privileged -dit --add-host=host.docker.internal:host-gateway --mount type=bind,source=${datadir},target=/iginx_client/data iginx-client:0.6.0" +command="docker run --name=\"$name\" --privileged -dit --add-host=host.docker.internal:host-gateway --mount type=bind,source=${datadir},target=/iginx_client/data iginx-client:0.6.0-SNAPSHOT" echo $command eval $command diff --git a/docker/onlyIginx-parquet/build_iginx_docker.bat b/docker/onlyIginx-parquet/build_iginx_docker.bat index fb3c1f43d5..196e9d6114 100644 --- a/docker/onlyIginx-parquet/build_iginx_docker.bat +++ b/docker/onlyIginx-parquet/build_iginx_docker.bat @@ -1 +1 @@ -docker build --file Dockerfile-iginx -t iginx:0.6.0 ../.. \ No newline at end of file +docker build --file Dockerfile-iginx -t iginx:0.6.0-SNAPSHOT ../.. \ No newline at end of file diff --git a/docker/onlyIginx-parquet/build_iginx_docker.sh b/docker/onlyIginx-parquet/build_iginx_docker.sh index 9d66c60f9d..b99c88eb2f 100644 --- a/docker/onlyIginx-parquet/build_iginx_docker.sh +++ b/docker/onlyIginx-parquet/build_iginx_docker.sh @@ -1,2 +1,2 @@ #!/bin/bash -docker build --file Dockerfile-iginx -t iginx:0.6.0 ../.. \ No newline at end of file +docker build --file Dockerfile-iginx -t iginx:0.6.0-SNAPSHOT ../.. \ No newline at end of file diff --git a/docker/onlyIginx-parquet/run_iginx_docker.bat b/docker/onlyIginx-parquet/run_iginx_docker.bat index 98aabd3787..7db3105cc4 100644 --- a/docker/onlyIginx-parquet/run_iginx_docker.bat +++ b/docker/onlyIginx-parquet/run_iginx_docker.bat @@ -162,7 +162,7 @@ if "!network!" neq "null" ( set "configFileConfig=-v !localConfigFile!:/iginx/conf " @REM -set command=docker run --name="%name%" !network!!localIPConfig!!configFileConfig!--privileged -dit -e host_iginx_port=%hostPort% -p %hostPort%:!port! !engineCast!iginx:0.6.0 +set command=docker run --name="%name%" !network!!localIPConfig!!configFileConfig!--privileged -dit -e host_iginx_port=%hostPort% -p %hostPort%:!port! !engineCast!iginx:0.6.0-SNAPSHOT echo %command% %command% diff --git a/docker/onlyIginx-parquet/run_iginx_docker.sh b/docker/onlyIginx-parquet/run_iginx_docker.sh index 5db6a6e0da..d07ca1308a 100644 --- a/docker/onlyIginx-parquet/run_iginx_docker.sh +++ b/docker/onlyIginx-parquet/run_iginx_docker.sh @@ -121,6 +121,6 @@ fi configFileConfig="-v ${localConfigFile}:/iginx/conf/config.properties " -command="docker run --name=${name} ${localIPConfig}${configFileConfig}--add-host=host.docker.internal:host-gateway ${network}--privileged -dit -e host_iginx_port=${hostPort}${portCastParams} iginx:0.6.0" +command="docker run --name=${name} ${localIPConfig}${configFileConfig}--add-host=host.docker.internal:host-gateway ${network}--privileged -dit -e host_iginx_port=${hostPort}${portCastParams} iginx:0.6.0-SNAPSHOT" echo "RUNNING ${command}" # ${command} \ No newline at end of file diff --git a/docker/onlyIginx/build_iginx_docker.bat b/docker/onlyIginx/build_iginx_docker.bat index fb3c1f43d5..196e9d6114 100644 --- a/docker/onlyIginx/build_iginx_docker.bat +++ b/docker/onlyIginx/build_iginx_docker.bat @@ -1 +1 @@ -docker build --file Dockerfile-iginx -t iginx:0.6.0 ../.. \ No newline at end of file +docker build --file Dockerfile-iginx -t iginx:0.6.0-SNAPSHOT ../.. \ No newline at end of file diff --git a/docker/onlyIginx/build_iginx_docker.sh b/docker/onlyIginx/build_iginx_docker.sh index fb3c1f43d5..196e9d6114 100755 --- a/docker/onlyIginx/build_iginx_docker.sh +++ b/docker/onlyIginx/build_iginx_docker.sh @@ -1 +1 @@ -docker build --file Dockerfile-iginx -t iginx:0.6.0 ../.. \ No newline at end of file +docker build --file Dockerfile-iginx -t iginx:0.6.0-SNAPSHOT ../.. \ No newline at end of file diff --git a/docker/onlyIginx/run_iginx_docker.bat b/docker/onlyIginx/run_iginx_docker.bat index 6e275635fd..0a4d7bd8e4 100644 --- a/docker/onlyIginx/run_iginx_docker.bat +++ b/docker/onlyIginx/run_iginx_docker.bat @@ -11,4 +11,4 @@ set ip=%1 set name=%2 set port=%3 mkdir -p logs/docker_logs -docker run --name="%name%" --privileged -dit --net docker-cluster-iginx --ip %ip% --add-host=host.docker.internal:host-gateway -v %logdir%:/iginx/logs/ -p %port%:6888 iginx:0.6.0 \ No newline at end of file +docker run --name="%name%" --privileged -dit --net docker-cluster-iginx --ip %ip% --add-host=host.docker.internal:host-gateway -v %logdir%:/iginx/logs/ -p %port%:6888 iginx:0.6.0-SNAPSHOT \ No newline at end of file diff --git a/docker/onlyIginx/run_iginx_docker.sh b/docker/onlyIginx/run_iginx_docker.sh index c22cdebe2f..e32b94f654 100755 --- a/docker/onlyIginx/run_iginx_docker.sh +++ b/docker/onlyIginx/run_iginx_docker.sh @@ -3,4 +3,4 @@ name=$2 port=$3 logdir="$(pwd)/../../logs/docker_logs" mkdir -p $logdir -docker run --name="${name}" --privileged -dit --net docker-cluster-iginx --ip ${ip} --add-host=host.docker.internal:host-gateway -v ${logdir}:/iginx/logs/ -p ${port}:6888 iginx:0.6.0 \ No newline at end of file +docker run --name="${name}" --privileged -dit --net docker-cluster-iginx --ip ${ip} --add-host=host.docker.internal:host-gateway -v ${logdir}:/iginx/logs/ -p ${port}:6888 iginx:0.6.0-SNAPSHOT \ No newline at end of file diff --git a/example/pom.xml b/example/pom.xml index 44ca4adf64..b9e5390575 100644 --- a/example/pom.xml +++ b/example/pom.xml @@ -7,7 +7,6 @@ cn.edu.tsinghua iginx ${revision} - ../pom.xml iginx-example diff --git a/jdbc/pom.xml b/jdbc/pom.xml index 7daf87ceed..1c401d176b 100644 --- a/jdbc/pom.xml +++ b/jdbc/pom.xml @@ -6,7 +6,6 @@ cn.edu.tsinghua iginx ${revision} - ../pom.xml iginx-jdbc diff --git a/pom.xml b/pom.xml index 034c86e16c..a3ca9b1319 100644 --- a/pom.xml +++ b/pom.xml @@ -104,7 +104,7 @@ cn.edu.tsinghua relational - 0.6.0-SNAPSHOT + ${project.version} cn.edu.tsinghua diff --git a/test/pom.xml b/test/pom.xml index d2d0c8dc6c..898c7a0447 100644 --- a/test/pom.xml +++ b/test/pom.xml @@ -7,7 +7,6 @@ cn.edu.tsinghua iginx ${revision} - ../pom.xml test diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/NewSessionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/NewSessionIT.java index 45aaa44c2e..8b16ad9f40 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/NewSessionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/NewSessionIT.java @@ -399,6 +399,7 @@ public void testCancelSession() { public void testCancelClient() { File clientDir = new File("../client/target/"); File[] matchingFiles = clientDir.listFiles((dir, name) -> name.startsWith("iginx-client-")); + matchingFiles = Arrays.stream(matchingFiles).filter(File::isDirectory).toArray(File[]::new); String version = matchingFiles[0].getName(); version = version.contains(".jar") ? version.substring(0, version.lastIndexOf(".")) : version; // use .sh on unix & .bat on windows(absolute path) @@ -420,7 +421,9 @@ public void testCancelClient() { if (ShellRunner.isOnWin()) { pb.command(clientWinPath); } else { - Runtime.getRuntime().exec(new String[] {"chmod", "+x", clientUnixPath}); + Process before = Runtime.getRuntime().exec(new String[] {"chmod", "+x", clientUnixPath}); + before.waitFor(); + LOGGER.info("before start a client, exit value: {}", before.exitValue()); pb.command("bash", "-c", clientUnixPath); } Process p = pb.start(); diff --git a/thrift/pom.xml b/thrift/pom.xml index 061de88fff..90790c9bed 100644 --- a/thrift/pom.xml +++ b/thrift/pom.xml @@ -7,7 +7,6 @@ cn.edu.tsinghua iginx ${revision} - ../pom.xml iginx-thrift From 54ae6815d4baee286527681b7c285bb67dfda5e8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 7 Jun 2024 21:02:01 +0800 Subject: [PATCH 015/138] build: update project version to 0.7.0-SNAPSHOT (#354) Co-authored-by: zhuyuqing <8178047+zhuyuqing@users.noreply.github.com> --- docker/client/Dockerfile | 2 +- docker/client/Dockerfile-no-maven | 2 +- docker/client/Dockerfile-no-maven-windows | 2 +- docker/client/build-no-maven.bat | 2 +- docker/client/build-no-maven.sh | 2 +- docker/client/build.bat | 2 +- docker/client/build.sh | 2 +- docker/client/run_docker.bat | 2 +- docker/client/run_docker.sh | 2 +- docker/onlyIginx-parquet/Dockerfile-iginx | 2 +- docker/onlyIginx-parquet/build_iginx_docker.bat | 2 +- docker/onlyIginx-parquet/build_iginx_docker.sh | 2 +- docker/onlyIginx-parquet/run_iginx_docker.bat | 2 +- docker/onlyIginx-parquet/run_iginx_docker.sh | 2 +- docker/onlyIginx/Dockerfile-iginx | 2 +- docker/onlyIginx/build_iginx_docker.bat | 2 +- docker/onlyIginx/build_iginx_docker.sh | 2 +- docker/onlyIginx/run_iginx_docker.bat | 2 +- docker/onlyIginx/run_iginx_docker.sh | 2 +- docs/quickStarts/IGinXByDocker-EnglishVersion.md | 2 +- docs/quickStarts/IGinXByDocker.md | 2 +- docs/quickStarts/IGinXBySource-EnglishVersion.md | 4 ++-- docs/quickStarts/IGinXBySource.md | 6 +++--- docs/quickStarts/IGinXCluster-EnglishVersion.md | 2 +- docs/quickStarts/IGinXCluster.md | 2 +- docs/quickStarts/IGinXInOneShot-EnglishVersion.md | 2 +- docs/quickStarts/IGinXInOneShot.md | 2 +- docs/quickStarts/IGinXManual-EnglishVersion.md | 2 +- docs/quickStarts/IGinXManual.md | 2 +- docs/quickStarts/IGinXZeppelin-EnglishVersion.md | 6 +++--- docs/quickStarts/IGinXZeppelin.md | 6 +++--- docs/quickStarts_Parquet/IGinXByDocker-EnglishVersion.md | 2 +- docs/quickStarts_Parquet/IGinXByDocker.md | 2 +- docs/quickStarts_Parquet/IGinXBySource-EnglishVersion.md | 4 ++-- docs/quickStarts_Parquet/IGinXBySource.md | 6 +++--- docs/quickStarts_Parquet/IGinXCluster-EnglishVersion.md | 2 +- docs/quickStarts_Parquet/IGinXCluster.md | 2 +- docs/quickStarts_Parquet/IGinXInOneShot-EnglishVersion.md | 2 +- docs/quickStarts_Parquet/IGinXInOneShot.md | 2 +- pom.xml | 2 +- 40 files changed, 50 insertions(+), 50 deletions(-) diff --git a/docker/client/Dockerfile b/docker/client/Dockerfile index 98c47d9b62..903ce7dc9a 100644 --- a/docker/client/Dockerfile +++ b/docker/client/Dockerfile @@ -4,7 +4,7 @@ WORKDIR /root/iginx RUN mvn clean package -pl client -am -Dmaven.test.skip=true -P-format -e FROM openjdk:11-jre-slim -COPY --from=builder /root/iginx/client/target/iginx-client-0.6.0-SNAPSHOT/ /iginx_client/ +COPY --from=builder /root/iginx/client/target/iginx-client-0.7.0-SNAPSHOT/ /iginx_client/ RUN mkdir -p /iginx_client/logs RUN mkdir -p /iginx_client/data diff --git a/docker/client/Dockerfile-no-maven b/docker/client/Dockerfile-no-maven index af0681b03d..e5a9ea1908 100644 --- a/docker/client/Dockerfile-no-maven +++ b/docker/client/Dockerfile-no-maven @@ -1,5 +1,5 @@ FROM openjdk:11-jre-slim -COPY ./target/iginx-client-0.6.0-SNAPSHOT/ /iginx_client/ +COPY ./target/iginx-client-0.7.0-SNAPSHOT/ /iginx_client/ RUN mkdir -p /iginx_client/logs RUN mkdir -p /iginx_client/data diff --git a/docker/client/Dockerfile-no-maven-windows b/docker/client/Dockerfile-no-maven-windows index 251678cf37..2cc4c8e59c 100644 --- a/docker/client/Dockerfile-no-maven-windows +++ b/docker/client/Dockerfile-no-maven-windows @@ -2,7 +2,7 @@ FROM mcr.microsoft.com/windows/servercore:ltsc2022 COPY . C:/iginx WORKDIR C:/iginx -COPY ./target/iginx-client-0.6.0-SNAPSHOT/ C:/iginx_client +COPY ./target/iginx-client-0.7.0-SNAPSHOT/ C:/iginx_client # 设置环境变量 USER ContainerAdministrator diff --git a/docker/client/build-no-maven.bat b/docker/client/build-no-maven.bat index e36c178c94..497ce80c6e 100644 --- a/docker/client/build-no-maven.bat +++ b/docker/client/build-no-maven.bat @@ -1 +1 @@ -docker build --file Dockerfile-no-maven-windows -t iginx-client:0.6.0-SNAPSHOT ../../client \ No newline at end of file +docker build --file Dockerfile-no-maven-windows -t iginx-client:0.7.0-SNAPSHOT ../../client \ No newline at end of file diff --git a/docker/client/build-no-maven.sh b/docker/client/build-no-maven.sh index 810565fb7a..9e4f8c1829 100644 --- a/docker/client/build-no-maven.sh +++ b/docker/client/build-no-maven.sh @@ -1,2 +1,2 @@ #!/bin/bash -docker build --file Dockerfile-no-maven -t iginx-client:0.6.0-SNAPSHOT ../../client \ No newline at end of file +docker build --file Dockerfile-no-maven -t iginx-client:0.7.0-SNAPSHOT ../../client \ No newline at end of file diff --git a/docker/client/build.bat b/docker/client/build.bat index 2a056ac99b..b3220791a7 100644 --- a/docker/client/build.bat +++ b/docker/client/build.bat @@ -1 +1 @@ -docker build --file Dockerfile -t iginx-client:0.6.0-SNAPSHOT ../../client \ No newline at end of file +docker build --file Dockerfile -t iginx-client:0.7.0-SNAPSHOT ../../client \ No newline at end of file diff --git a/docker/client/build.sh b/docker/client/build.sh index ac16f75ef5..7e39502357 100644 --- a/docker/client/build.sh +++ b/docker/client/build.sh @@ -1,2 +1,2 @@ #!/bin/bash -docker build --file Dockerfile -t iginx-client:0.6.0-SNAPSHOT ../../client \ No newline at end of file +docker build --file Dockerfile -t iginx-client:0.7.0-SNAPSHOT ../../client \ No newline at end of file diff --git a/docker/client/run_docker.bat b/docker/client/run_docker.bat index 4cec937600..c96c3488e7 100644 --- a/docker/client/run_docker.bat +++ b/docker/client/run_docker.bat @@ -34,7 +34,7 @@ if not exist "%datadir%" ( mkdir "%datadir%" ) -set command=docker run --name="%name%" -dit --add-host=host.docker.internal:host-gateway --mount type=bind,source=!datadir!,target=C:/iginx_client/data iginx-client:0.6.0-SNAPSHOT +set command=docker run --name="%name%" -dit --add-host=host.docker.internal:host-gateway --mount type=bind,source=!datadir!,target=C:/iginx_client/data iginx-client:0.7.0-SNAPSHOT echo %command% %command% diff --git a/docker/client/run_docker.sh b/docker/client/run_docker.sh index 3b6af08f21..26af3060d2 100644 --- a/docker/client/run_docker.sh +++ b/docker/client/run_docker.sh @@ -21,6 +21,6 @@ done [ -d "$datadir" ] || mkdir -p "$datadir" -command="docker run --name=\"$name\" --privileged -dit --add-host=host.docker.internal:host-gateway --mount type=bind,source=${datadir},target=/iginx_client/data iginx-client:0.6.0-SNAPSHOT" +command="docker run --name=\"$name\" --privileged -dit --add-host=host.docker.internal:host-gateway --mount type=bind,source=${datadir},target=/iginx_client/data iginx-client:0.7.0-SNAPSHOT" echo $command eval $command diff --git a/docker/onlyIginx-parquet/Dockerfile-iginx b/docker/onlyIginx-parquet/Dockerfile-iginx index df05c79099..9bdd06f46b 100644 --- a/docker/onlyIginx-parquet/Dockerfile-iginx +++ b/docker/onlyIginx-parquet/Dockerfile-iginx @@ -4,7 +4,7 @@ WORKDIR /root/iginx RUN mvn clean package -DskipTests -P-format -e FROM openjdk:11-jre-slim -COPY --from=builder /root/iginx/core/target/iginx-core-0.6.0-SNAPSHOT /iginx +COPY --from=builder /root/iginx/core/target/iginx-core-0.7.0-SNAPSHOT /iginx # ports will be cast in run.bat diff --git a/docker/onlyIginx-parquet/build_iginx_docker.bat b/docker/onlyIginx-parquet/build_iginx_docker.bat index 196e9d6114..d08f72dac8 100644 --- a/docker/onlyIginx-parquet/build_iginx_docker.bat +++ b/docker/onlyIginx-parquet/build_iginx_docker.bat @@ -1 +1 @@ -docker build --file Dockerfile-iginx -t iginx:0.6.0-SNAPSHOT ../.. \ No newline at end of file +docker build --file Dockerfile-iginx -t iginx:0.7.0-SNAPSHOT ../.. \ No newline at end of file diff --git a/docker/onlyIginx-parquet/build_iginx_docker.sh b/docker/onlyIginx-parquet/build_iginx_docker.sh index b99c88eb2f..46acb2af5a 100644 --- a/docker/onlyIginx-parquet/build_iginx_docker.sh +++ b/docker/onlyIginx-parquet/build_iginx_docker.sh @@ -1,2 +1,2 @@ #!/bin/bash -docker build --file Dockerfile-iginx -t iginx:0.6.0-SNAPSHOT ../.. \ No newline at end of file +docker build --file Dockerfile-iginx -t iginx:0.7.0-SNAPSHOT ../.. \ No newline at end of file diff --git a/docker/onlyIginx-parquet/run_iginx_docker.bat b/docker/onlyIginx-parquet/run_iginx_docker.bat index 7db3105cc4..173b980e57 100644 --- a/docker/onlyIginx-parquet/run_iginx_docker.bat +++ b/docker/onlyIginx-parquet/run_iginx_docker.bat @@ -162,7 +162,7 @@ if "!network!" neq "null" ( set "configFileConfig=-v !localConfigFile!:/iginx/conf " @REM -set command=docker run --name="%name%" !network!!localIPConfig!!configFileConfig!--privileged -dit -e host_iginx_port=%hostPort% -p %hostPort%:!port! !engineCast!iginx:0.6.0-SNAPSHOT +set command=docker run --name="%name%" !network!!localIPConfig!!configFileConfig!--privileged -dit -e host_iginx_port=%hostPort% -p %hostPort%:!port! !engineCast!iginx:0.7.0-SNAPSHOT echo %command% %command% diff --git a/docker/onlyIginx-parquet/run_iginx_docker.sh b/docker/onlyIginx-parquet/run_iginx_docker.sh index d07ca1308a..8b54fb4e87 100644 --- a/docker/onlyIginx-parquet/run_iginx_docker.sh +++ b/docker/onlyIginx-parquet/run_iginx_docker.sh @@ -121,6 +121,6 @@ fi configFileConfig="-v ${localConfigFile}:/iginx/conf/config.properties " -command="docker run --name=${name} ${localIPConfig}${configFileConfig}--add-host=host.docker.internal:host-gateway ${network}--privileged -dit -e host_iginx_port=${hostPort}${portCastParams} iginx:0.6.0-SNAPSHOT" +command="docker run --name=${name} ${localIPConfig}${configFileConfig}--add-host=host.docker.internal:host-gateway ${network}--privileged -dit -e host_iginx_port=${hostPort}${portCastParams} iginx:0.7.0-SNAPSHOT" echo "RUNNING ${command}" # ${command} \ No newline at end of file diff --git a/docker/onlyIginx/Dockerfile-iginx b/docker/onlyIginx/Dockerfile-iginx index 6c37adca7c..f5bace0822 100644 --- a/docker/onlyIginx/Dockerfile-iginx +++ b/docker/onlyIginx/Dockerfile-iginx @@ -4,7 +4,7 @@ WORKDIR /root/iginx RUN mvn clean package -DskipTests -P-format FROM openjdk:11-jre-slim -COPY --from=builder /root/iginx/core/target/iginx-core-0.6.0-SNAPSHOT /iginx +COPY --from=builder /root/iginx/core/target/iginx-core-0.7.0-SNAPSHOT /iginx # 安装 Python 3.8, pip 并安装所需的 Python 包 RUN apt-get update && \ diff --git a/docker/onlyIginx/build_iginx_docker.bat b/docker/onlyIginx/build_iginx_docker.bat index 196e9d6114..d08f72dac8 100644 --- a/docker/onlyIginx/build_iginx_docker.bat +++ b/docker/onlyIginx/build_iginx_docker.bat @@ -1 +1 @@ -docker build --file Dockerfile-iginx -t iginx:0.6.0-SNAPSHOT ../.. \ No newline at end of file +docker build --file Dockerfile-iginx -t iginx:0.7.0-SNAPSHOT ../.. \ No newline at end of file diff --git a/docker/onlyIginx/build_iginx_docker.sh b/docker/onlyIginx/build_iginx_docker.sh index 196e9d6114..d08f72dac8 100755 --- a/docker/onlyIginx/build_iginx_docker.sh +++ b/docker/onlyIginx/build_iginx_docker.sh @@ -1 +1 @@ -docker build --file Dockerfile-iginx -t iginx:0.6.0-SNAPSHOT ../.. \ No newline at end of file +docker build --file Dockerfile-iginx -t iginx:0.7.0-SNAPSHOT ../.. \ No newline at end of file diff --git a/docker/onlyIginx/run_iginx_docker.bat b/docker/onlyIginx/run_iginx_docker.bat index 0a4d7bd8e4..3ca78a712c 100644 --- a/docker/onlyIginx/run_iginx_docker.bat +++ b/docker/onlyIginx/run_iginx_docker.bat @@ -11,4 +11,4 @@ set ip=%1 set name=%2 set port=%3 mkdir -p logs/docker_logs -docker run --name="%name%" --privileged -dit --net docker-cluster-iginx --ip %ip% --add-host=host.docker.internal:host-gateway -v %logdir%:/iginx/logs/ -p %port%:6888 iginx:0.6.0-SNAPSHOT \ No newline at end of file +docker run --name="%name%" --privileged -dit --net docker-cluster-iginx --ip %ip% --add-host=host.docker.internal:host-gateway -v %logdir%:/iginx/logs/ -p %port%:6888 iginx:0.7.0-SNAPSHOT \ No newline at end of file diff --git a/docker/onlyIginx/run_iginx_docker.sh b/docker/onlyIginx/run_iginx_docker.sh index e32b94f654..30b7eb8546 100755 --- a/docker/onlyIginx/run_iginx_docker.sh +++ b/docker/onlyIginx/run_iginx_docker.sh @@ -3,4 +3,4 @@ name=$2 port=$3 logdir="$(pwd)/../../logs/docker_logs" mkdir -p $logdir -docker run --name="${name}" --privileged -dit --net docker-cluster-iginx --ip ${ip} --add-host=host.docker.internal:host-gateway -v ${logdir}:/iginx/logs/ -p ${port}:6888 iginx:0.6.0-SNAPSHOT \ No newline at end of file +docker run --name="${name}" --privileged -dit --net docker-cluster-iginx --ip ${ip} --add-host=host.docker.internal:host-gateway -v ${logdir}:/iginx/logs/ -p ${port}:6888 iginx:0.7.0-SNAPSHOT \ No newline at end of file diff --git a/docs/quickStarts/IGinXByDocker-EnglishVersion.md b/docs/quickStarts/IGinXByDocker-EnglishVersion.md index d72b72f56d..7d1c4a3b4c 100644 --- a/docs/quickStarts/IGinXByDocker-EnglishVersion.md +++ b/docs/quickStarts/IGinXByDocker-EnglishVersion.md @@ -255,7 +255,7 @@ The following words are displayed to indicate that the image was built successfu => [builder 2/4] COPY . /root/iginx 1.3s => [builder 3/4] WORKDIR /root/iginx 0.1s => [builder 4/4] RUN mvn clean package -DskipTests -P-format 876.3s -=> [stage-1 2/2] COPY --from=builder /root/iginx/core/target/iginx-core-0.6.0-SNAPSHOT /iginx 0.2s +=> [stage-1 2/2] COPY --from=builder /root/iginx/core/target/iginx-core-0.7.0-SNAPSHOT /iginx 0.2s => exporting to image 0.5s => => exporting layers 0.5s => => writing image sha256:e738348598c9db601dbf39c7a8ca9e1396c5ff51769afeb0fe3da12e2fdcd73a 0.0s diff --git a/docs/quickStarts/IGinXByDocker.md b/docs/quickStarts/IGinXByDocker.md index 2fbf30eb82..110405dff5 100644 --- a/docs/quickStarts/IGinXByDocker.md +++ b/docs/quickStarts/IGinXByDocker.md @@ -254,7 +254,7 @@ $ ./build_iginx_docker.sh => [builder 2/4] COPY . /root/iginx 1.3s => [builder 3/4] WORKDIR /root/iginx 0.1s => [builder 4/4] RUN mvn clean package -DskipTests -P-format 876.3s -=> [stage-1 2/2] COPY --from=builder /root/iginx/core/target/iginx-core-0.6.0-SNAPSHOT /iginx 0.2s +=> [stage-1 2/2] COPY --from=builder /root/iginx/core/target/iginx-core-0.7.0-SNAPSHOT /iginx 0.2s => exporting to image 0.5s => => exporting layers 0.5s => => writing image sha256:e738348598c9db601dbf39c7a8ca9e1396c5ff51769afeb0fe3da12e2fdcd73a 0.0s diff --git a/docs/quickStarts/IGinXBySource-EnglishVersion.md b/docs/quickStarts/IGinXBySource-EnglishVersion.md index 083c52eca1..12bd746533 100644 --- a/docs/quickStarts/IGinXBySource-EnglishVersion.md +++ b/docs/quickStarts/IGinXBySource-EnglishVersion.md @@ -180,7 +180,7 @@ The following words are displayed, indicating that the IGinX build is successful ```shell [INFO] ------------------------------------------------------------------------ -[INFO] Reactor Summary for IGinX 0.6.0-SNAPSHOT: +[INFO] Reactor Summary for IGinX 0.7.0-SNAPSHOT: [INFO] [INFO] IGinX .............................................. SUCCESS [ 20.674 s] [INFO] IGinX Thrift ....................................... SUCCESS [01:18 min] @@ -445,7 +445,7 @@ Specifically, when using it, you only need to introduce the following dependenci cn.edu.tsinghua iginx-core - 0.6.0-SNAPSHOT + 0.7.0-SNAPSHOT ``` diff --git a/docs/quickStarts/IGinXBySource.md b/docs/quickStarts/IGinXBySource.md index 0849bd2ab3..4202a91f2a 100644 --- a/docs/quickStarts/IGinXBySource.md +++ b/docs/quickStarts/IGinXBySource.md @@ -180,7 +180,7 @@ $ mvn clean install -Dmaven.test.skip=true ```shell [INFO] ------------------------------------------------------------------------ -[INFO] Reactor Summary for IGinX 0.6.0-SNAPSHOT: +[INFO] Reactor Summary for IGinX 0.7.0-SNAPSHOT: [INFO] [INFO] IGinX .............................................. SUCCESS [ 20.674 s] [INFO] IGinX Thrift ....................................... SUCCESS [01:18 min] @@ -257,7 +257,7 @@ Starting zookeeper ... STARTED ```shell $ cd ~ -$ cd IGinX/core/target/iginx-core-0.6.0-SNAPSHOT +$ cd IGinX/core/target/iginx-core-0.7.0-SNAPSHOT $ chmod +x sbin/start_iginx.sh # 为启动脚本添加启动权限 $ ./sbin/start_iginx.sh ``` @@ -440,7 +440,7 @@ $ mvn clean install -DskipTests cn.edu.tsinghua iginx-core - 0.6.0-SNAPSHOT + 0.7.0-SNAPSHOT ``` diff --git a/docs/quickStarts/IGinXCluster-EnglishVersion.md b/docs/quickStarts/IGinXCluster-EnglishVersion.md index 8496bbb1b6..d73ebc7676 100644 --- a/docs/quickStarts/IGinXCluster-EnglishVersion.md +++ b/docs/quickStarts/IGinXCluster-EnglishVersion.md @@ -356,7 +356,7 @@ Only when you are using it, you need to introduce the following dependencies in cn.edu.tsinghua iginx-core - 0.6.0-SNAPSHOT + 0.7.0-SNAPSHOT ``` diff --git a/docs/quickStarts/IGinXCluster.md b/docs/quickStarts/IGinXCluster.md index eb3788c68c..bf936b0843 100644 --- a/docs/quickStarts/IGinXCluster.md +++ b/docs/quickStarts/IGinXCluster.md @@ -363,7 +363,7 @@ $ mvn clean install -DskipTests cn.edu.tsinghua iginx-core - 0.6.0-SNAPSHOT + 0.7.0-SNAPSHOT ``` diff --git a/docs/quickStarts/IGinXInOneShot-EnglishVersion.md b/docs/quickStarts/IGinXInOneShot-EnglishVersion.md index 3151c4f49f..2c02151d3a 100644 --- a/docs/quickStarts/IGinXInOneShot-EnglishVersion.md +++ b/docs/quickStarts/IGinXInOneShot-EnglishVersion.md @@ -272,7 +272,7 @@ Specifically, when using it, you only need to introduce the following dependenci cn.edu.tsinghua iginx-core - 0.6.0-SNAPSHOT + 0.7.0-SNAPSHOT ``` diff --git a/docs/quickStarts/IGinXInOneShot.md b/docs/quickStarts/IGinXInOneShot.md index fb39310c8a..cf8b7d93d1 100644 --- a/docs/quickStarts/IGinXInOneShot.md +++ b/docs/quickStarts/IGinXInOneShot.md @@ -266,7 +266,7 @@ $ mvn clean install -DskipTests cn.edu.tsinghua iginx-core - 0.6.0-SNAPSHOT + 0.7.0-SNAPSHOT ``` diff --git a/docs/quickStarts/IGinXManual-EnglishVersion.md b/docs/quickStarts/IGinXManual-EnglishVersion.md index 56b3ebfbfd..02bcfc1dd8 100644 --- a/docs/quickStarts/IGinXManual-EnglishVersion.md +++ b/docs/quickStarts/IGinXManual-EnglishVersion.md @@ -503,7 +503,7 @@ Only when you are using it, you need to introduce the following dependencies in cn.edu.tsinghua iginx-core - 0.6.0-SNAPSHOT + 0.7.0-SNAPSHOT ``` diff --git a/docs/quickStarts/IGinXManual.md b/docs/quickStarts/IGinXManual.md index 12eeab3b7d..3db0884adf 100644 --- a/docs/quickStarts/IGinXManual.md +++ b/docs/quickStarts/IGinXManual.md @@ -504,7 +504,7 @@ $ mvn clean install -DskipTests cn.edu.tsinghua iginx-core - 0.6.0-SNAPSHOT + 0.7.0-SNAPSHOT ``` diff --git a/docs/quickStarts/IGinXZeppelin-EnglishVersion.md b/docs/quickStarts/IGinXZeppelin-EnglishVersion.md index b1d34754e1..9d2b6e976b 100644 --- a/docs/quickStarts/IGinXZeppelin-EnglishVersion.md +++ b/docs/quickStarts/IGinXZeppelin-EnglishVersion.md @@ -10,7 +10,7 @@ Navigate to the IGinX directory and execute the following command to build the I mvn clean package -DskipTests -P get-jar-with-dependencies ``` -Upon successful compilation, you will find the `zeppelin-iginx-0.6.0-SNAPSHOT-jar-with-dependencies.jar` package in the `IGinX/zeppelin-interpreter/target/` directory. We will need this package for the next steps of deploying Zeppelin. +Upon successful compilation, you will find the `zeppelin-iginx-0.7.0-SNAPSHOT-jar-with-dependencies.jar` package in the `IGinX/zeppelin-interpreter/target/` directory. We will need this package for the next steps of deploying Zeppelin. ## Deploying Zeppelin @@ -56,7 +56,7 @@ export JAVA_HOME= #### Integrating IGinX Zeppelin Interpreter -In the `zeppelin-0.10.1-bin-netinst/interpreter/` folder, create a new folder named `IGinX`. Place the compiled `zeppelin-iginx-0.6.0-SNAPSHOT-jar-with-dependencies.jar` package inside this folder. +In the `zeppelin-0.10.1-bin-netinst/interpreter/` folder, create a new folder named `IGinX`. Place the compiled `zeppelin-iginx-0.7.0-SNAPSHOT-jar-with-dependencies.jar` package inside this folder. #### Starting IGinX @@ -86,7 +86,7 @@ Before deploying Zeppelin, start IGinX. Prepare a folder to place the IGinX Zeppelin Interpreter. For example, let's name the folder `zeppelin-interpreter` with the absolute path `~/code/zeppelin-interpreter/`. -Place the `zeppelin-iginx-0.6.0-SNAPSHOT-jar-with-dependencies.jar` package inside this prepared `zeppelin-interpreter` folder. +Place the `zeppelin-iginx-0.7.0-SNAPSHOT-jar-with-dependencies.jar` package inside this prepared `zeppelin-interpreter` folder. #### Starting Docker Container Using Commands diff --git a/docs/quickStarts/IGinXZeppelin.md b/docs/quickStarts/IGinXZeppelin.md index 542f93d0ad..f2e0e6f58d 100644 --- a/docs/quickStarts/IGinXZeppelin.md +++ b/docs/quickStarts/IGinXZeppelin.md @@ -10,7 +10,7 @@ mvn clean package -DskipTests -P get-jar-with-dependencies ``` -构建成功后,在`IGinX/zeppelin-interpreter/target/`路径下找到`zeppelin-iginx-0.6.0-SNAPSHOT-jar-with-dependencies.jar`包。 +构建成功后,在`IGinX/zeppelin-interpreter/target/`路径下找到`zeppelin-iginx-0.7.0-SNAPSHOT-jar-with-dependencies.jar`包。 在下一步部署Zeppelin时我们需要用到这个包。 @@ -60,7 +60,7 @@ export JAVA_HOME= #### 接入IGinX Zeppelin Interpreter -在`zeppelin-0.10.1-bin-netinst/interpreter/`文件夹下新建一个文件夹`IGinX`,将构建好的`zeppelin-iginx-0.6.0-SNAPSHOT-jar-with-dependencies.jar`包放入其中即可。 +在`zeppelin-0.10.1-bin-netinst/interpreter/`文件夹下新建一个文件夹`IGinX`,将构建好的`zeppelin-iginx-0.7.0-SNAPSHOT-jar-with-dependencies.jar`包放入其中即可。 #### 启动IGinX @@ -90,7 +90,7 @@ export JAVA_HOME= 我们需要准备一个文件夹,用于放置IGinX Zeppelin Interpreter。例如我们准备一个文件夹名为`zeppelin-interpreter`,其绝对路径为`~/code/zeppelin-interpreter/`。 -将`zeppelin-iginx-0.6.0-SNAPSHOT-jar-with-dependencies.jar`包放入我们准备好的`zeppelin-interpreter`文件夹内即可。 +将`zeppelin-iginx-0.7.0-SNAPSHOT-jar-with-dependencies.jar`包放入我们准备好的`zeppelin-interpreter`文件夹内即可。 #### 使用命令启动Docker容器 diff --git a/docs/quickStarts_Parquet/IGinXByDocker-EnglishVersion.md b/docs/quickStarts_Parquet/IGinXByDocker-EnglishVersion.md index 555f039d90..de88978e2e 100644 --- a/docs/quickStarts_Parquet/IGinXByDocker-EnglishVersion.md +++ b/docs/quickStarts_Parquet/IGinXByDocker-EnglishVersion.md @@ -250,7 +250,7 @@ The following words are displayed to indicate that the image was built successfu => [builder 2/4] COPY . /root/iginx 1.3s => [builder 3/4] WORKDIR /root/iginx 0.1s => [builder 4/4] RUN mvn clean package -DskipTests -P passFormat 876.3s -=> [stage-1 2/2] COPY --from=builder /root/iginx/core/target/iginx-core-0.6.0-SNAPSHOT /iginx 0.2s +=> [stage-1 2/2] COPY --from=builder /root/iginx/core/target/iginx-core-0.7.0-SNAPSHOT /iginx 0.2s => exporting to image 0.5s => => exporting layers 0.5s => => writing image sha256:e738348598c9db601dbf39c7a8ca9e1396c5ff51769afeb0fe3da12e2fdcd73a 0.0s diff --git a/docs/quickStarts_Parquet/IGinXByDocker.md b/docs/quickStarts_Parquet/IGinXByDocker.md index e8c0dffa31..acc9420336 100644 --- a/docs/quickStarts_Parquet/IGinXByDocker.md +++ b/docs/quickStarts_Parquet/IGinXByDocker.md @@ -249,7 +249,7 @@ $ ./build_iginx_docker.sh => [builder 2/4] COPY . /root/iginx 1.3s => [builder 3/4] WORKDIR /root/iginx 0.1s => [builder 4/4] RUN mvn clean package -DskipTests -P passFormat 876.3s -=> [stage-1 2/2] COPY --from=builder /root/iginx/core/target/iginx-core-0.6.0-SNAPSHOT /iginx 0.2s +=> [stage-1 2/2] COPY --from=builder /root/iginx/core/target/iginx-core-0.7.0-SNAPSHOT /iginx 0.2s => exporting to image 0.5s => => exporting layers 0.5s => => writing image sha256:e738348598c9db601dbf39c7a8ca9e1396c5ff51769afeb0fe3da12e2fdcd73a 0.0s diff --git a/docs/quickStarts_Parquet/IGinXBySource-EnglishVersion.md b/docs/quickStarts_Parquet/IGinXBySource-EnglishVersion.md index 90266f51b1..5eb2b6053b 100644 --- a/docs/quickStarts_Parquet/IGinXBySource-EnglishVersion.md +++ b/docs/quickStarts_Parquet/IGinXBySource-EnglishVersion.md @@ -168,7 +168,7 @@ The following words are displayed, indicating that the IGinX build is successful ```shell [INFO] ------------------------------------------------------------------------ -[INFO] Reactor Summary for IGinX 0.6.0-SNAPSHOT: +[INFO] Reactor Summary for IGinX 0.7.0-SNAPSHOT: [INFO] [INFO] IGinX .............................................. SUCCESS [ 20.674 s] [INFO] IGinX Thrift ....................................... SUCCESS [01:18 min] @@ -417,7 +417,7 @@ Specifically, when using it, you only need to introduce the following dependenci cn.edu.tsinghua iginx-core - 0.6.0-SNAPSHOT + 0.7.0-SNAPSHOT ``` diff --git a/docs/quickStarts_Parquet/IGinXBySource.md b/docs/quickStarts_Parquet/IGinXBySource.md index 67e272ff85..e55cc7fcee 100644 --- a/docs/quickStarts_Parquet/IGinXBySource.md +++ b/docs/quickStarts_Parquet/IGinXBySource.md @@ -170,7 +170,7 @@ $ mvn clean install -Dmaven.test.skip=true ```shell [INFO] ------------------------------------------------------------------------ -[INFO] Reactor Summary for IGinX 0.6.0-SNAPSHOT: +[INFO] Reactor Summary for IGinX 0.7.0-SNAPSHOT: [INFO] [INFO] IGinX .............................................. SUCCESS [ 20.674 s] [INFO] IGinX Thrift ....................................... SUCCESS [01:18 min] @@ -232,7 +232,7 @@ storageEngineList=127.0.0.1#6667#parquet#dir=parquetData#has_data=false#is_read_ ```shell $ cd ~ -$ cd IGinX/core/target/iginx-core-0.6.0-SNAPSHOT +$ cd IGinX/core/target/iginx-core-0.7.0-SNAPSHOT $ chmod +x sbin/start_iginx.sh # 为启动脚本添加启动权限 $ ./sbin/start_iginx.sh ``` @@ -414,7 +414,7 @@ $ mvn clean install -DskipTests cn.edu.tsinghua iginx-core - 0.6.0-SNAPSHOT + 0.7.0-SNAPSHOT ``` diff --git a/docs/quickStarts_Parquet/IGinXCluster-EnglishVersion.md b/docs/quickStarts_Parquet/IGinXCluster-EnglishVersion.md index 12bbcd0158..c32c716950 100644 --- a/docs/quickStarts_Parquet/IGinXCluster-EnglishVersion.md +++ b/docs/quickStarts_Parquet/IGinXCluster-EnglishVersion.md @@ -322,7 +322,7 @@ Only when you are using it, you need to introduce the following dependencies in cn.edu.tsinghua iginx-core - 0.6.0-SNAPSHOT + 0.7.0-SNAPSHOT ``` diff --git a/docs/quickStarts_Parquet/IGinXCluster.md b/docs/quickStarts_Parquet/IGinXCluster.md index 57713afa2a..6fc5d56891 100644 --- a/docs/quickStarts_Parquet/IGinXCluster.md +++ b/docs/quickStarts_Parquet/IGinXCluster.md @@ -325,7 +325,7 @@ $ mvn clean install -DskipTests cn.edu.tsinghua iginx-core - 0.6.0-SNAPSHOT + 0.7.0-SNAPSHOT ``` diff --git a/docs/quickStarts_Parquet/IGinXInOneShot-EnglishVersion.md b/docs/quickStarts_Parquet/IGinXInOneShot-EnglishVersion.md index 68954fac37..cb785b4282 100644 --- a/docs/quickStarts_Parquet/IGinXInOneShot-EnglishVersion.md +++ b/docs/quickStarts_Parquet/IGinXInOneShot-EnglishVersion.md @@ -254,7 +254,7 @@ Specifically, when using it, you only need to introduce the following dependenci cn.edu.tsinghua iginx-core - 0.6.0-SNAPSHOT + 0.7.0-SNAPSHOT ``` diff --git a/docs/quickStarts_Parquet/IGinXInOneShot.md b/docs/quickStarts_Parquet/IGinXInOneShot.md index ce08c36de7..02ccdbd77e 100644 --- a/docs/quickStarts_Parquet/IGinXInOneShot.md +++ b/docs/quickStarts_Parquet/IGinXInOneShot.md @@ -247,7 +247,7 @@ $ mvn clean install -DskipTests cn.edu.tsinghua iginx-core - 0.6.0-SNAPSHOT + 0.7.0-SNAPSHOT ``` diff --git a/pom.xml b/pom.xml index a3ca9b1319..85ca2f59f4 100644 --- a/pom.xml +++ b/pom.xml @@ -41,7 +41,7 @@ ${project.basedir} UTF-8 UTF-8 - 0.6.0-SNAPSHOT + 0.7.0-SNAPSHOT From d018ef08a375162170afcb15b9c19ddf3fc22188 Mon Sep 17 00:00:00 2001 From: ZM <12236590+shinyano@users.noreply.github.com> Date: Fri, 7 Jun 2024 21:18:07 +0800 Subject: [PATCH 016/138] feat(query): adjust downsample query (#347) The key column in previous downsample query result is confusing. It refers to the start of a window in such results, while user would assume it is a key for a record. Also, user should be able to slice windows based on queried data, instead of specifying key range. fix Add two columns: window_start and window_end to avoid misunderstanding. Adjust downsample sql statement SQL adjust Allow user to use: SELECT (, )* FROM prefixPath ? ? : OVER WINDOW LEFT_BRACKET SIZE DURATION (IN )? (SLIDE DURATION)? RIGHT_BRACKET; to generate windows according to queried data. doc:https://oxlh5mrwi0.feishu.cn/wiki/BUerw0yvQiGBgOkz6YjcfbXInvd --- .github/actions/dependence/action.yml | 6 +- .github/workflows/remote-test.yml | 1 + .../antlr4/cn/edu/tsinghua/iginx/sql/Sql.g4 | 17 +- .../naive/NaiveOperatorMemoryExecutor.java | 52 +- .../execute/stream/DownsampleLazyStream.java | 25 +- .../iginx/engine/shared/Constants.java | 11 + .../iginx/engine/shared/data/read/Header.java | 11 + .../engine/shared/operator/Downsample.java | 7 + .../iginx/metadata/entity/KeyInterval.java | 5 +- .../tsinghua/iginx/rest/bean/QueryResult.java | 12 +- .../tsinghua/iginx/sql/IginXSqlVisitor.java | 22 +- .../AbstractOperatorMemoryExecutorTest.java | 12 +- .../cn/edu/tsinghua/iginx/sql/ParseTest.java | 10 +- .../edu/tsinghua/iginx/pool/SessionPool.java | 9 + .../session_v2/query/DownsampleQuery.java | 9 +- session_py/iginx/iginx_pyclient/dataset.py | 16 +- session_py/iginx/iginx_pyclient/session.py | 9 + .../iginx_pyclient/thrift/rpc/IService-remote | 21 + .../iginx_pyclient/thrift/rpc/IService.py | 567 +++++++++ .../iginx/iginx_pyclient/thrift/rpc/ttypes.py | 1095 +++++++++++++---- .../iginx/constant/GlobalConstant.java | 4 + .../iginx/integration/func/rest/RestIT.java | 14 +- .../func/session/NewSessionIT.java | 265 +++- .../integration/func/session/PySessionIT.java | 36 +- .../integration/func/session/SessionIT.java | 6 +- .../integration/func/session/SessionV2IT.java | 23 +- .../integration/func/sql/SQLSessionIT.java | 1007 ++++++++------- .../iginx/integration/func/udf/UDFIT.java | 2 +- .../integration/tool/MultiConnection.java | 9 +- test/src/test/resources/pySessionIT/tests.py | 16 + 30 files changed, 2490 insertions(+), 809 deletions(-) diff --git a/.github/actions/dependence/action.yml b/.github/actions/dependence/action.yml index 97ab7dde48..5e8c150a40 100644 --- a/.github/actions/dependence/action.yml +++ b/.github/actions/dependence/action.yml @@ -18,6 +18,10 @@ inputs: required: false default: all # all: setup all + docker-required: + description: "is docker needed in this test" + required: false + default: "false" runs: using: "composite" @@ -30,7 +34,7 @@ runs: tzutil /s "China Standard Time" echo "JAVA_OPTS=-Xmx4g -Xms2g" >> %GITHUB_ENV% - - if: runner.os == 'macOS' + - if: runner.os == 'macOS' && inputs.docker-required=='true' name: Install Docker on MacOS shell: bash run: | diff --git a/.github/workflows/remote-test.yml b/.github/workflows/remote-test.yml index a0772504bb..a614fa402f 100644 --- a/.github/workflows/remote-test.yml +++ b/.github/workflows/remote-test.yml @@ -50,6 +50,7 @@ jobs: with: python-version: ${{ matrix.python-version }} java: ${{ matrix.java }} + docker-required: true - if: runner.os == 'Windows' name: Set up Docker Firewall on Windows diff --git a/antlr/src/main/antlr4/cn/edu/tsinghua/iginx/sql/Sql.g4 b/antlr/src/main/antlr4/cn/edu/tsinghua/iginx/sql/Sql.g4 index 8155a47c3d..53354ae04b 100644 --- a/antlr/src/main/antlr4/cn/edu/tsinghua/iginx/sql/Sql.g4 +++ b/antlr/src/main/antlr4/cn/edu/tsinghua/iginx/sql/Sql.g4 @@ -255,7 +255,7 @@ orderByClause ; downsampleClause - : OVER LR_BRACKET RANGE aggLen IN timeInterval (STEP aggLen)? RR_BRACKET + : OVER WINDOW LR_BRACKET SIZE aggLen (IN timeInterval)? (SLIDE aggLen)? RR_BRACKET ; aggLen @@ -481,6 +481,9 @@ keyWords | HEADER | LOAD | VALUE2META + | WINDOW + | SIZE + | SLIDE ; dateFormat @@ -959,6 +962,18 @@ LOAD : L O A D ; +WINDOW + : W I N D O W + ; + +SIZE + : S I Z E + ; + +SLIDE + : S L I D E + ; + VALUE2META : V A L U E INT_2 M E T A ; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/naive/NaiveOperatorMemoryExecutor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/naive/NaiveOperatorMemoryExecutor.java index c13ed3f56f..308c25043a 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/naive/NaiveOperatorMemoryExecutor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/naive/NaiveOperatorMemoryExecutor.java @@ -29,7 +29,7 @@ import static cn.edu.tsinghua.iginx.engine.physical.memory.execute.utils.RowUtils.getSamePathWithSpecificPrefix; import static cn.edu.tsinghua.iginx.engine.physical.memory.execute.utils.RowUtils.isValueEqualRow; import static cn.edu.tsinghua.iginx.engine.physical.memory.execute.utils.RowUtils.removeDuplicateRows; -import static cn.edu.tsinghua.iginx.engine.shared.Constants.KEY; +import static cn.edu.tsinghua.iginx.engine.shared.Constants.*; import static cn.edu.tsinghua.iginx.engine.shared.function.FunctionUtils.isCanUseSetQuantifierFunction; import static cn.edu.tsinghua.iginx.engine.shared.function.system.utils.ValueUtils.getHash; import static cn.edu.tsinghua.iginx.sql.SQLConstant.DOT; @@ -90,15 +90,7 @@ import cn.edu.tsinghua.iginx.utils.Pair; import cn.edu.tsinghua.iginx.utils.StringUtils; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.TreeMap; +import java.util.*; import java.util.regex.Pattern; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -276,12 +268,20 @@ private RowStream executeDownsample(Downsample downsample, Table table) throws P List rows = table.getRows(); long bias = downsample.getKeyRange().getActualBeginKey(); long endKey = downsample.getKeyRange().getActualEndKey(); + if (downsample.notSetInterval()) { + if (table.getRowSize() <= 0) { + return Table.EMPTY_TABLE; + } + bias = table.getRow(0).getKey(); + endKey = table.getRow(table.getRowSize() - 1).getKey(); + } long precision = downsample.getPrecision(); long slideDistance = downsample.getSlideDistance(); // startKey + (n - 1) * slideDistance + precision - 1 >= endKey long n = (int) (Math.ceil((double) (endKey - bias - precision + 1) / slideDistance) + 1); List tableList = new ArrayList<>(); + boolean firstCol = true; for (FunctionCall functionCall : downsample.getFunctionCallList()) { SetMappingFunction function = (SetMappingFunction) functionCall.getFunction(); FunctionParams params = functionCall.getParams(); @@ -309,10 +309,12 @@ private RowStream executeDownsample(Downsample downsample, Table table) throws P } } } - List> transformedRawRows = new ArrayList<>(); + // < row> + List, Row>> transformedRawRows = new ArrayList<>(); try { for (Map.Entry> entry : groups.entrySet()) { - long time = entry.getKey(); + long windowStartKey = entry.getKey(); + long windowEndKey = windowStartKey + precision - 1; List group = entry.getValue(); if (params.isDistinct()) { @@ -329,7 +331,7 @@ private RowStream executeDownsample(Downsample downsample, Table table) throws P Row row = function.transform(new Table(header, group), params); if (row != null) { - transformedRawRows.add(new Pair<>(time, row)); + transformedRawRows.add(new Pair<>(new Pair<>(windowStartKey, windowEndKey), row)); } } } catch (Exception e) { @@ -340,14 +342,32 @@ private RowStream executeDownsample(Downsample downsample, Table table) throws P if (transformedRawRows.size() == 0) { return Table.EMPTY_TABLE; } - Header newHeader = new Header(Field.KEY, transformedRawRows.get(0).v.getHeader().getFields()); + + // 只让第一张表保留 window_start, window_end 列,这样按key join后无需删除重复列 + List fields = transformedRawRows.get(0).v.getHeader().getFields(); + if (firstCol) { + fields.add(0, new Field(WINDOW_START_COL, DataType.LONG)); + fields.add(1, new Field(WINDOW_END_COL, DataType.LONG)); + } + Header newHeader = new Header(Field.KEY, fields); List transformedRows = new ArrayList<>(); - for (Pair pair : transformedRawRows) { - transformedRows.add(new Row(newHeader, pair.k, pair.v.getValues())); + Object[] values = new Object[transformedRawRows.get(0).v.getValues().length + 2]; + for (Pair, Row> pair : transformedRawRows) { + if (firstCol) { + values[0] = pair.k.k; + values[1] = pair.k.v; + System.arraycopy(pair.v.getValues(), 0, values, 2, pair.v.getValues().length); + transformedRows.add(new Row(newHeader, pair.k.k, values)); + } else { + transformedRows.add(new Row(newHeader, pair.k.k, pair.v.getValues())); + } + values = new Object[transformedRawRows.get(0).v.getValues().length + 2]; } tableList.add(new Table(newHeader, transformedRows)); + firstCol = false; } + // key = window_start,而每个窗口长度一样,因此多表中key相同的列就是同一个窗口的结果,可以按key join return RowUtils.joinMultipleTablesByKey(tableList); } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/DownsampleLazyStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/DownsampleLazyStream.java index 73eb34f42a..e4d00cb990 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/DownsampleLazyStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/DownsampleLazyStream.java @@ -18,6 +18,9 @@ */ package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; +import static cn.edu.tsinghua.iginx.engine.shared.Constants.WINDOW_END_COL; +import static cn.edu.tsinghua.iginx.engine.shared.Constants.WINDOW_START_COL; + import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalTaskExecuteFailureException; import cn.edu.tsinghua.iginx.engine.physical.memory.execute.Table; @@ -31,6 +34,7 @@ import cn.edu.tsinghua.iginx.engine.shared.function.FunctionParams; import cn.edu.tsinghua.iginx.engine.shared.function.SetMappingFunction; import cn.edu.tsinghua.iginx.engine.shared.operator.Downsample; +import cn.edu.tsinghua.iginx.thrift.DataType; import java.util.ArrayList; import java.util.List; @@ -82,7 +86,7 @@ private Row loadNext() throws PhysicalException { return nextTarget; } Row row = null; - long timestamp = 0; + long windowStartKey = 0; long bias = downsample.getKeyRange().getActualBeginKey(); long endKey = downsample.getKeyRange().getActualEndKey(); long precision = downsample.getPrecision(); @@ -90,9 +94,9 @@ private Row loadNext() throws PhysicalException { // startKey + (n - 1) * slideDistance + precision - 1 >= endKey int n = (int) (Math.ceil((double) (endKey - bias - precision + 1) / slideDistance) + 1); while (row == null && wrapper.hasNext()) { - timestamp = wrapper.nextTimestamp() - (wrapper.nextTimestamp() - bias) % precision; + windowStartKey = wrapper.nextTimestamp() - (wrapper.nextTimestamp() - bias) % precision; List rows = new ArrayList<>(); - while (wrapper.hasNext() && wrapper.nextTimestamp() < timestamp + precision) { + while (wrapper.hasNext() && wrapper.nextTimestamp() < windowStartKey + precision) { rows.add(wrapper.next()); } Table table = new Table(rows.get(0).getHeader(), rows); @@ -111,9 +115,18 @@ private Row loadNext() throws PhysicalException { } row = RowUtils.combineMultipleColumns(subRowList); } - return row == null - ? null - : new Row(new Header(Field.KEY, row.getHeader().getFields()), timestamp, row.getValues()); + if (row == null) { + return null; + } else { + List fields = row.getHeader().getFields(); + fields.add(0, new Field(WINDOW_START_COL, DataType.LONG)); + fields.add(1, new Field(WINDOW_END_COL, DataType.LONG)); + Object[] values = new Object[row.getValues().length + 2]; + values[0] = windowStartKey; + values[1] = windowStartKey + precision - 1; + System.arraycopy(row.getValues(), 0, values, 2, row.getValues().length); + return new Row(new Header(Field.KEY, fields), windowStartKey, values); + } } @Override diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/Constants.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/Constants.java index 1645e8f241..d9608367a0 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/Constants.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/Constants.java @@ -18,6 +18,10 @@ */ package cn.edu.tsinghua.iginx.engine.shared; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + public class Constants { public static final String KEY = "key"; @@ -29,4 +33,11 @@ public class Constants { public static final String UDF_CLASS = "t"; public static final String UDF_FUNC = "transform"; + + public static final String WINDOW_START_COL = "window_start"; + public static final String WINDOW_END_COL = "window_end"; + + // 保留列名,会在reorder时保留,并按原顺序出现在表的最前面 + public static final Set RESERVED_COLS = + new HashSet<>(Arrays.asList(WINDOW_START_COL, WINDOW_END_COL)); } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/Header.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/Header.java index 5a6614d463..f7d9f8534b 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/Header.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/Header.java @@ -18,6 +18,8 @@ */ package cn.edu.tsinghua.iginx.engine.shared.data.read; +import static cn.edu.tsinghua.iginx.engine.shared.Constants.RESERVED_COLS; + import cn.edu.tsinghua.iginx.utils.Pair; import cn.edu.tsinghua.iginx.utils.StringUtils; import java.util.*; @@ -212,6 +214,15 @@ public ReorderedHeaderWrapped reorderedHeaderWrapped( List targetFields = new ArrayList<>(); Map reorderMap = new HashMap<>(); + // 保留关键字列 + for (int i = 0; i < fields.size(); i++) { + Field field = getField(i); + if (RESERVED_COLS.contains(field.getName())) { + reorderMap.put(targetFields.size(), i); + targetFields.add(field); + } + } + for (int index = 0; index < patterns.size(); index++) { String pattern = patterns.get(index); List> matchedFields = new ArrayList<>(); diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Downsample.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Downsample.java index e1b6b6f1ac..b64040507e 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Downsample.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Downsample.java @@ -18,6 +18,9 @@ */ package cn.edu.tsinghua.iginx.engine.shared.operator; +import static cn.edu.tsinghua.iginx.constant.GlobalConstant.KEY_MAX_VAL; +import static cn.edu.tsinghua.iginx.constant.GlobalConstant.KEY_MIN_VAL; + import cn.edu.tsinghua.iginx.engine.shared.KeyRange; import cn.edu.tsinghua.iginx.engine.shared.function.FunctionCall; import cn.edu.tsinghua.iginx.engine.shared.function.MappingType; @@ -125,4 +128,8 @@ public String getInfo() { return sb.toString(); } + + public boolean notSetInterval() { + return getKeyRange().getBeginKey() == KEY_MIN_VAL && getKeyRange().getEndKey() == KEY_MAX_VAL; + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/KeyInterval.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/KeyInterval.java index d9e9d78e22..a4b9be393c 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/KeyInterval.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/KeyInterval.java @@ -18,6 +18,9 @@ */ package cn.edu.tsinghua.iginx.metadata.entity; +import static cn.edu.tsinghua.iginx.constant.GlobalConstant.KEY_MAX_VAL; +import static cn.edu.tsinghua.iginx.constant.GlobalConstant.KEY_MIN_VAL; + import java.util.Objects; public final class KeyInterval { @@ -89,6 +92,6 @@ public KeyInterval getIntersectWithLCRO(KeyInterval keyInterval) { } public static KeyInterval getDefaultKeyInterval() { - return new KeyInterval(Long.MIN_VALUE, Long.MAX_VALUE); + return new KeyInterval(KEY_MIN_VAL, KEY_MAX_VAL); } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/bean/QueryResult.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/bean/QueryResult.java index f750f151e0..c7d2357286 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/bean/QueryResult.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/bean/QueryResult.java @@ -18,6 +18,7 @@ */ package cn.edu.tsinghua.iginx.rest.bean; +import static cn.edu.tsinghua.iginx.engine.shared.Constants.*; import static cn.edu.tsinghua.iginx.rest.RestUtils.TOP_KEY; import cn.edu.tsinghua.iginx.metadata.DefaultMetaManager; @@ -146,7 +147,15 @@ private String nameToString(int pos) { if (queryAggregators.get(pos).getType() == QueryAggregatorType.SAVE_AS) { return String.format("\"name\": \"%s\"", queryAggregators.get(pos).getMetric_name()); } else { - return String.format("\"name\": \"%s\"", queryMetrics.get(pos).getName()); + // downsample query, window_start & window_end columns are attached + if (queryMetrics.get(pos).getAggregators() != null + && queryMetrics.get(pos).getAggregators().size() != 0) { + return String.format( + "\"names\": [\"%s\", \"%s\", \"%s\"]", + WINDOW_START_COL, WINDOW_END_COL, queryMetrics.get(pos).getName()); + } else { + return String.format("\"name\": \"%s\"", queryMetrics.get(pos).getName()); + } } } @@ -232,6 +241,7 @@ private String sampleSizeToString(int pos) { private Map> getTagsFromPaths(List paths) { Map> ret = new TreeMap<>(); for (String path : paths) { + if (RESERVED_COLS.contains(path)) continue; int firstBrace = path.indexOf("{"); int lastBrace = path.indexOf("}"); if (firstBrace == -1 || lastBrace == -1) { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/IginXSqlVisitor.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/IginXSqlVisitor.java index dee8b0c6e1..5bc65bf4a7 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/IginXSqlVisitor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/IginXSqlVisitor.java @@ -1,5 +1,7 @@ package cn.edu.tsinghua.iginx.sql; +import static cn.edu.tsinghua.iginx.constant.GlobalConstant.KEY_MAX_VAL; +import static cn.edu.tsinghua.iginx.constant.GlobalConstant.KEY_MIN_VAL; import static cn.edu.tsinghua.iginx.engine.shared.function.FunctionUtils.isCanUseSetQuantifierFunction; import static cn.edu.tsinghua.iginx.engine.shared.operator.MarkJoin.MARK_PREFIX; import static cn.edu.tsinghua.iginx.sql.statement.select.SelectStatement.markJoinCount; @@ -1068,27 +1070,31 @@ private void parseSpecialClause(SpecialClauseContext ctx, UnarySelectStatement s private void parseDownsampleClause( DownsampleClauseContext ctx, UnarySelectStatement selectStatement) { long precision = parseAggLen(ctx.aggLen(0)); - Pair timeInterval = parseTimeInterval(ctx.timeInterval()); - selectStatement.setStartKey(timeInterval.k); - selectStatement.setEndKey(timeInterval.v); + Pair timeInterval = + ctx.timeInterval() == null ? null : parseTimeInterval(ctx.timeInterval()); + long startKey = timeInterval == null ? KEY_MIN_VAL : timeInterval.k; + long endKey = timeInterval == null ? KEY_MAX_VAL : timeInterval.v; + selectStatement.setStartKey(startKey); + selectStatement.setEndKey(endKey); selectStatement.setPrecision(precision); selectStatement.setSlideDistance(precision); selectStatement.setHasDownsample(true); - if (ctx.STEP() != null) { + if (ctx.SLIDE() != null) { long distance = parseAggLen(ctx.aggLen(1)); selectStatement.setSlideDistance(distance); } // merge value filter and group time range filter - KeyFilter startKey = new KeyFilter(Op.GE, timeInterval.k); - KeyFilter endKey = new KeyFilter(Op.L, timeInterval.v); + KeyFilter startKeyFilter = new KeyFilter(Op.GE, startKey); + KeyFilter endKeyFilter = new KeyFilter(Op.L, endKey); Filter mergedFilter; if (selectStatement.hasValueFilter()) { mergedFilter = new AndFilter( - new ArrayList<>(Arrays.asList(selectStatement.getFilter(), startKey, endKey))); + new ArrayList<>( + Arrays.asList(selectStatement.getFilter(), startKeyFilter, endKeyFilter))); } else { - mergedFilter = new AndFilter(new ArrayList<>(Arrays.asList(startKey, endKey))); + mergedFilter = new AndFilter(new ArrayList<>(Arrays.asList(startKeyFilter, endKeyFilter))); selectStatement.setHasValueFilter(true); } selectStatement.setFilter(mergedFilter); diff --git a/core/src/test/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/AbstractOperatorMemoryExecutorTest.java b/core/src/test/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/AbstractOperatorMemoryExecutorTest.java index 4e383f69d6..c22fae8d52 100644 --- a/core/src/test/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/AbstractOperatorMemoryExecutorTest.java +++ b/core/src/test/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/AbstractOperatorMemoryExecutorTest.java @@ -18,6 +18,8 @@ */ package cn.edu.tsinghua.iginx.engine.physical.memory.execute; +import static cn.edu.tsinghua.iginx.engine.shared.Constants.WINDOW_END_COL; +import static cn.edu.tsinghua.iginx.engine.shared.Constants.WINDOW_START_COL; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -2263,9 +2265,11 @@ public void testDownsample() throws PhysicalException { Header targetHeader = stream.getHeader(); assertTrue(targetHeader.hasKey()); - assertEquals(1, targetHeader.getFields().size()); - assertEquals("avg(a.a.b)", targetHeader.getFields().get(0).getFullName()); - assertEquals(DataType.DOUBLE, targetHeader.getFields().get(0).getType()); + assertEquals(3, targetHeader.getFields().size()); + assertEquals(WINDOW_START_COL, targetHeader.getFields().get(0).getFullName()); + assertEquals(WINDOW_END_COL, targetHeader.getFields().get(1).getFullName()); + assertEquals("avg(a.a.b)", targetHeader.getFields().get(2).getFullName()); + assertEquals(DataType.DOUBLE, targetHeader.getFields().get(2).getType()); int index = 0; while (stream.hasNext()) { @@ -2276,7 +2280,7 @@ public void testDownsample() throws PhysicalException { sum += (int) table.getRow(index + cnt).getValue("a.a.b"); cnt++; } - assertEquals(sum * 1.0 / cnt, (double) targetRow.getValue(0), 0.01); + assertEquals(sum * 1.0 / cnt, (double) targetRow.getValue(2), 0.01); index += cnt; } assertEquals(table.getRowSize(), index); diff --git a/core/src/test/java/cn/edu/tsinghua/iginx/sql/ParseTest.java b/core/src/test/java/cn/edu/tsinghua/iginx/sql/ParseTest.java index 3ccbc50bc0..e8211f82e5 100644 --- a/core/src/test/java/cn/edu/tsinghua/iginx/sql/ParseTest.java +++ b/core/src/test/java/cn/edu/tsinghua/iginx/sql/ParseTest.java @@ -70,7 +70,7 @@ public void testParseInsertWithSubQuery() { @Test public void testParseSelect() { String selectStr = - "SELECT SUM(c), SUM(d), SUM(e), COUNT(f), COUNT(g) FROM a.b WHERE 100 < key and key < 1000 or d == \"abc\" or \"666\" <= c or (e < 10 and not (f < 10)) OVER (RANGE 10 IN [200, 300));"; + "SELECT SUM(c), SUM(d), SUM(e), COUNT(f), COUNT(g) FROM a.b WHERE 100 < key and key < 1000 or d == \"abc\" or \"666\" <= c or (e < 10 and not (f < 10)) OVER WINDOW (size 10 IN [200, 300));"; UnarySelectStatement statement = (UnarySelectStatement) TestUtils.buildStatement(selectStr); assertTrue(statement.hasFunc()); @@ -122,7 +122,7 @@ public void testFilter() { @Test public void testParseGroupBy() { - String selectStr = "SELECT MAX(c) FROM a.b OVER (RANGE 10 IN [100, 1000));"; + String selectStr = "SELECT MAX(c) FROM a.b OVER WINDOW (size 10 IN [100, 1000));"; UnarySelectStatement statement = (UnarySelectStatement) TestUtils.buildStatement(selectStr); assertEquals(100, statement.getStartKey()); assertEquals(1000, statement.getEndKey()); @@ -148,7 +148,7 @@ public void testParseSpecialClause() { assertEquals(5, statement.getOffset()); assertEquals(10, statement.getLimit()); - String groupBy = "SELECT max(a) FROM test OVER (RANGE 5 IN (10, 120])"; + String groupBy = "SELECT max(a) FROM test OVER WINDOW (size 5 IN (10, 120])"; statement = (UnarySelectStatement) TestUtils.buildStatement(groupBy); assertEquals(11, statement.getStartKey()); @@ -156,7 +156,7 @@ public void testParseSpecialClause() { assertEquals(5L, statement.getPrecision()); String groupByAndLimit = - "SELECT max(a) FROM test OVER (RANGE 10 IN (10, 120)) LIMIT 5 OFFSET 2;"; + "SELECT max(a) FROM test OVER WINDOW (size 10 IN (10, 120)) LIMIT 5 OFFSET 2;"; statement = (UnarySelectStatement) TestUtils.buildStatement(groupByAndLimit); assertEquals(11, statement.getStartKey()); assertEquals(120, statement.getEndKey()); @@ -273,7 +273,7 @@ public void testParseTimeWithUnit() { assertEquals(expectedTimes, insertStatement.getKeys()); String queryStr = - "SELECT AVG(c) FROM a.b WHERE c > 10 AND c < 1ms OVER (RANGE 10 IN [1s, 2s));"; + "SELECT AVG(c) FROM a.b WHERE c > 10 AND c < 1ms OVER WINDOW (size 10 IN [1s, 2s));"; UnarySelectStatement selectStatement = (UnarySelectStatement) TestUtils.buildStatement(queryStr); diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/pool/SessionPool.java b/session/src/main/java/cn/edu/tsinghua/iginx/pool/SessionPool.java index 2510d33b0d..68f6dcd133 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/pool/SessionPool.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/pool/SessionPool.java @@ -1,5 +1,7 @@ package cn.edu.tsinghua.iginx.pool; +import static cn.edu.tsinghua.iginx.constant.GlobalConstant.KEY_MAX_VAL; +import static cn.edu.tsinghua.iginx.constant.GlobalConstant.KEY_MIN_VAL; import static java.lang.Math.max; import cn.edu.tsinghua.iginx.exception.SessionException; @@ -985,6 +987,13 @@ public SessionAggregateQueryDataSet aggregateQuery( return sessionAggregateQueryDataSet; } + // downsample query without time interval + public SessionQueryDataSet downsampleQuery( + List paths, AggregateType aggregateType, long precision) throws SessionException { + return downsampleQuery(paths, KEY_MIN_VAL, KEY_MAX_VAL, aggregateType, precision); + } + + // downsample query with time interval public SessionQueryDataSet downsampleQuery( List paths, long startKey, long endKey, AggregateType aggregateType, long precision) throws SessionException { diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/DownsampleQuery.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/DownsampleQuery.java index ddfad4fdbf..359a085b55 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/DownsampleQuery.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/DownsampleQuery.java @@ -18,6 +18,9 @@ */ package cn.edu.tsinghua.iginx.session_v2.query; +import static cn.edu.tsinghua.iginx.constant.GlobalConstant.KEY_MAX_VAL; +import static cn.edu.tsinghua.iginx.constant.GlobalConstant.KEY_MIN_VAL; + import cn.edu.tsinghua.iginx.session_v2.Arguments; import cn.edu.tsinghua.iginx.thrift.AggregateType; import java.util.*; @@ -108,8 +111,8 @@ public static class Builder { private Builder() { this.measurements = new HashSet<>(); this.tagsList = new ArrayList<>(); - this.startKey = 0L; - this.endKey = Long.MAX_VALUE; + this.startKey = KEY_MIN_VAL; + this.endKey = KEY_MAX_VAL; this.precision = 0L; this.timePrecision = null; } @@ -150,7 +153,7 @@ public DownsampleQuery.Builder startKey(long startKey) { public DownsampleQuery.Builder endKey(long endKey) { if (endKey < 0) { - throw new IllegalArgumentException("endKey mush greater than zero."); + throw new IllegalArgumentException("endKey must greater than zero."); } if (endKey <= startKey) { throw new IllegalArgumentException("endKey must greater than startKey."); diff --git a/session_py/iginx/iginx_pyclient/dataset.py b/session_py/iginx/iginx_pyclient/dataset.py index d6e08cfdf9..11879a7c16 100644 --- a/session_py/iginx/iginx_pyclient/dataset.py +++ b/session_py/iginx/iginx_pyclient/dataset.py @@ -99,15 +99,21 @@ def __str__(self): return value def to_df(self): - columns = ["key"] + has_key = self.__timestamps != [] + print(has_key) + columns = ["key"] if has_key else [] for column in self.__paths: columns.append(str(column)) value_matrix = [] - for i in range(len(self.__timestamps)): - value = [self.__timestamps[i]] - value.extend(self.__values[i]) - value_matrix.append(value) + if has_key: + for i in range(len(self.__timestamps)): + value = [self.__timestamps[i]] + value.extend(self.__values[i]) + value_matrix.append(value) + else: + for i in range(len(self.__values)): + value_matrix.append(self.__values[i]) return pd.DataFrame(value_matrix, columns=columns) diff --git a/session_py/iginx/iginx_pyclient/session.py b/session_py/iginx/iginx_pyclient/session.py index 25068a73d8..1a812f5519 100644 --- a/session_py/iginx/iginx_pyclient/session.py +++ b/session_py/iginx/iginx_pyclient/session.py @@ -62,6 +62,11 @@ logger = logging.getLogger("IginX") +# key value boundary for IGinX(defined in shared.GlobalConstant) +MAX_KEY = 9223372036854775807 +MIN_KEY = -9223372036854775807 + + def isPyReg(statement:str): statement = statement.strip().lower() return statement.startswith("create") and ("function" in statement) @@ -424,6 +429,10 @@ def last_query(self, paths, start_time=0, timePrecision=None): return QueryDataSet(paths, data_types, raw_data_set.keys, raw_data_set.valuesList, raw_data_set.bitmapList) + def downsample_query_no_interval(self, paths, type, precision, timePrecision=None): + return self.downsample_query(paths, MIN_KEY, MAX_KEY, type, precision, timePrecision) + + def downsample_query(self, paths, start_time, end_time, type, precision, timePrecision=None): req = DownsampleQueryReq(sessionId=self.__session_id, paths=paths, startKey=start_time, endKey=end_time, aggregateType=type, diff --git a/session_py/iginx/iginx_pyclient/thrift/rpc/IService-remote b/session_py/iginx/iginx_pyclient/thrift/rpc/IService-remote index d59dd67032..19c3f274b3 100644 --- a/session_py/iginx/iginx_pyclient/thrift/rpc/IService-remote +++ b/session_py/iginx/iginx_pyclient/thrift/rpc/IService-remote @@ -49,6 +49,7 @@ if len(sys.argv) <= 1 or sys.argv[1] == '--help': print(' ExecuteStatementResp executeStatement(ExecuteStatementReq req)') print(' FetchResultsResp fetchResults(FetchResultsReq req)') print(' LoadCSVResp loadCSV(LoadCSVReq req)') + print(' LoadUDFResp loadUDF(LoadUDFReq req)') print(' Status closeStatement(CloseStatementReq req)') print(' CommitTransformJobResp commitTransformJob(CommitTransformJobReq req)') print(' QueryTransformJobStatusResp queryTransformJobStatus(QueryTransformJobStatusReq req)') @@ -60,6 +61,8 @@ if len(sys.argv) <= 1 or sys.argv[1] == '--help': print(' CurveMatchResp curveMatch(CurveMatchReq req)') print(' DebugInfoResp debugInfo(DebugInfoReq req)') print(' ShowSessionIDResp showSessionID(ShowSessionIDReq req)') + print(' ShowRulesResp showRules(ShowRulesReq req)') + print(' Status setRules(SetRulesReq req)') print('') sys.exit(0) @@ -289,6 +292,12 @@ elif cmd == 'loadCSV': sys.exit(1) pp.pprint(client.loadCSV(eval(args[0]),)) +elif cmd == 'loadUDF': + if len(args) != 1: + print('loadUDF requires 1 args') + sys.exit(1) + pp.pprint(client.loadUDF(eval(args[0]),)) + elif cmd == 'closeStatement': if len(args) != 1: print('closeStatement requires 1 args') @@ -355,6 +364,18 @@ elif cmd == 'showSessionID': sys.exit(1) pp.pprint(client.showSessionID(eval(args[0]),)) +elif cmd == 'showRules': + if len(args) != 1: + print('showRules requires 1 args') + sys.exit(1) + pp.pprint(client.showRules(eval(args[0]),)) + +elif cmd == 'setRules': + if len(args) != 1: + print('setRules requires 1 args') + sys.exit(1) + pp.pprint(client.setRules(eval(args[0]),)) + else: print('Unrecognized method %s' % cmd) sys.exit(1) diff --git a/session_py/iginx/iginx_pyclient/thrift/rpc/IService.py b/session_py/iginx/iginx_pyclient/thrift/rpc/IService.py index 7af0b1502d..d19e949dde 100644 --- a/session_py/iginx/iginx_pyclient/thrift/rpc/IService.py +++ b/session_py/iginx/iginx_pyclient/thrift/rpc/IService.py @@ -219,6 +219,14 @@ def loadCSV(self, req): """ pass + def loadUDF(self, req): + """ + Parameters: + - req + + """ + pass + def closeStatement(self, req): """ Parameters: @@ -307,6 +315,22 @@ def showSessionID(self, req): """ pass + def showRules(self, req): + """ + Parameters: + - req + + """ + pass + + def setRules(self, req): + """ + Parameters: + - req + + """ + pass + class Client(Iface): def __init__(self, iprot, oprot=None): @@ -1115,6 +1139,38 @@ def recv_loadCSV(self): return result.success raise TApplicationException(TApplicationException.MISSING_RESULT, "loadCSV failed: unknown result") + def loadUDF(self, req): + """ + Parameters: + - req + + """ + self.send_loadUDF(req) + return self.recv_loadUDF() + + def send_loadUDF(self, req): + self._oprot.writeMessageBegin('loadUDF', TMessageType.CALL, self._seqid) + args = loadUDF_args() + args.req = req + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_loadUDF(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = loadUDF_result() + result.read(iprot) + iprot.readMessageEnd() + if result.success is not None: + return result.success + raise TApplicationException(TApplicationException.MISSING_RESULT, "loadUDF failed: unknown result") + def closeStatement(self, req): """ Parameters: @@ -1467,6 +1523,70 @@ def recv_showSessionID(self): return result.success raise TApplicationException(TApplicationException.MISSING_RESULT, "showSessionID failed: unknown result") + def showRules(self, req): + """ + Parameters: + - req + + """ + self.send_showRules(req) + return self.recv_showRules() + + def send_showRules(self, req): + self._oprot.writeMessageBegin('showRules', TMessageType.CALL, self._seqid) + args = showRules_args() + args.req = req + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_showRules(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = showRules_result() + result.read(iprot) + iprot.readMessageEnd() + if result.success is not None: + return result.success + raise TApplicationException(TApplicationException.MISSING_RESULT, "showRules failed: unknown result") + + def setRules(self, req): + """ + Parameters: + - req + + """ + self.send_setRules(req) + return self.recv_setRules() + + def send_setRules(self, req): + self._oprot.writeMessageBegin('setRules', TMessageType.CALL, self._seqid) + args = setRules_args() + args.req = req + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_setRules(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = setRules_result() + result.read(iprot) + iprot.readMessageEnd() + if result.success is not None: + return result.success + raise TApplicationException(TApplicationException.MISSING_RESULT, "setRules failed: unknown result") + class Processor(Iface, TProcessor): def __init__(self, handler): @@ -1497,6 +1617,7 @@ def __init__(self, handler): self._processMap["executeStatement"] = Processor.process_executeStatement self._processMap["fetchResults"] = Processor.process_fetchResults self._processMap["loadCSV"] = Processor.process_loadCSV + self._processMap["loadUDF"] = Processor.process_loadUDF self._processMap["closeStatement"] = Processor.process_closeStatement self._processMap["commitTransformJob"] = Processor.process_commitTransformJob self._processMap["queryTransformJobStatus"] = Processor.process_queryTransformJobStatus @@ -1508,6 +1629,8 @@ def __init__(self, handler): self._processMap["curveMatch"] = Processor.process_curveMatch self._processMap["debugInfo"] = Processor.process_debugInfo self._processMap["showSessionID"] = Processor.process_showSessionID + self._processMap["showRules"] = Processor.process_showRules + self._processMap["setRules"] = Processor.process_setRules self._on_message_begin = None def on_message_begin(self, func): @@ -2105,6 +2228,29 @@ def process_loadCSV(self, seqid, iprot, oprot): oprot.writeMessageEnd() oprot.trans.flush() + def process_loadUDF(self, seqid, iprot, oprot): + args = loadUDF_args() + args.read(iprot) + iprot.readMessageEnd() + result = loadUDF_result() + try: + result.success = self._handler.loadUDF(args.req) + msg_type = TMessageType.REPLY + except TTransport.TTransportException: + raise + except TApplicationException as ex: + logging.exception('TApplication exception in handler') + msg_type = TMessageType.EXCEPTION + result = ex + except Exception: + logging.exception('Unexpected exception in handler') + msg_type = TMessageType.EXCEPTION + result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error') + oprot.writeMessageBegin("loadUDF", msg_type, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + def process_closeStatement(self, seqid, iprot, oprot): args = closeStatement_args() args.read(iprot) @@ -2358,6 +2504,52 @@ def process_showSessionID(self, seqid, iprot, oprot): oprot.writeMessageEnd() oprot.trans.flush() + def process_showRules(self, seqid, iprot, oprot): + args = showRules_args() + args.read(iprot) + iprot.readMessageEnd() + result = showRules_result() + try: + result.success = self._handler.showRules(args.req) + msg_type = TMessageType.REPLY + except TTransport.TTransportException: + raise + except TApplicationException as ex: + logging.exception('TApplication exception in handler') + msg_type = TMessageType.EXCEPTION + result = ex + except Exception: + logging.exception('Unexpected exception in handler') + msg_type = TMessageType.EXCEPTION + result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error') + oprot.writeMessageBegin("showRules", msg_type, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_setRules(self, seqid, iprot, oprot): + args = setRules_args() + args.read(iprot) + iprot.readMessageEnd() + result = setRules_result() + try: + result.success = self._handler.setRules(args.req) + msg_type = TMessageType.REPLY + except TTransport.TTransportException: + raise + except TApplicationException as ex: + logging.exception('TApplication exception in handler') + msg_type = TMessageType.EXCEPTION + result = ex + except Exception: + logging.exception('Unexpected exception in handler') + msg_type = TMessageType.EXCEPTION + result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error') + oprot.writeMessageBegin("setRules", msg_type, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + # HELPER FUNCTIONS AND STRUCTURES @@ -5486,6 +5678,131 @@ def __ne__(self, other): ) +class loadUDF_args(object): + """ + Attributes: + - req + + """ + + + def __init__(self, req=None,): + self.req = req + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec]) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.STRUCT: + self.req = LoadUDFReq() + self.req.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec])) + return + oprot.writeStructBegin('loadUDF_args') + if self.req is not None: + oprot.writeFieldBegin('req', TType.STRUCT, 1) + self.req.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) +all_structs.append(loadUDF_args) +loadUDF_args.thrift_spec = ( + None, # 0 + (1, TType.STRUCT, 'req', [LoadUDFReq, None], None, ), # 1 +) + + +class loadUDF_result(object): + """ + Attributes: + - success + + """ + + + def __init__(self, success=None,): + self.success = success + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec]) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.STRUCT: + self.success = LoadUDFResp() + self.success.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec])) + return + oprot.writeStructBegin('loadUDF_result') + if self.success is not None: + oprot.writeFieldBegin('success', TType.STRUCT, 0) + self.success.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) +all_structs.append(loadUDF_result) +loadUDF_result.thrift_spec = ( + (0, TType.STRUCT, 'success', [LoadUDFResp, None], None, ), # 0 +) + + class closeStatement_args(object): """ Attributes: @@ -6859,5 +7176,255 @@ def __ne__(self, other): showSessionID_result.thrift_spec = ( (0, TType.STRUCT, 'success', [ShowSessionIDResp, None], None, ), # 0 ) + + +class showRules_args(object): + """ + Attributes: + - req + + """ + + + def __init__(self, req=None,): + self.req = req + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec]) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.STRUCT: + self.req = ShowRulesReq() + self.req.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec])) + return + oprot.writeStructBegin('showRules_args') + if self.req is not None: + oprot.writeFieldBegin('req', TType.STRUCT, 1) + self.req.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) +all_structs.append(showRules_args) +showRules_args.thrift_spec = ( + None, # 0 + (1, TType.STRUCT, 'req', [ShowRulesReq, None], None, ), # 1 +) + + +class showRules_result(object): + """ + Attributes: + - success + + """ + + + def __init__(self, success=None,): + self.success = success + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec]) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.STRUCT: + self.success = ShowRulesResp() + self.success.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec])) + return + oprot.writeStructBegin('showRules_result') + if self.success is not None: + oprot.writeFieldBegin('success', TType.STRUCT, 0) + self.success.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) +all_structs.append(showRules_result) +showRules_result.thrift_spec = ( + (0, TType.STRUCT, 'success', [ShowRulesResp, None], None, ), # 0 +) + + +class setRules_args(object): + """ + Attributes: + - req + + """ + + + def __init__(self, req=None,): + self.req = req + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec]) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.STRUCT: + self.req = SetRulesReq() + self.req.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec])) + return + oprot.writeStructBegin('setRules_args') + if self.req is not None: + oprot.writeFieldBegin('req', TType.STRUCT, 1) + self.req.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) +all_structs.append(setRules_args) +setRules_args.thrift_spec = ( + None, # 0 + (1, TType.STRUCT, 'req', [SetRulesReq, None], None, ), # 1 +) + + +class setRules_result(object): + """ + Attributes: + - success + + """ + + + def __init__(self, success=None,): + self.success = success + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec]) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.STRUCT: + self.success = Status() + self.success.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec])) + return + oprot.writeStructBegin('setRules_result') + if self.success is not None: + oprot.writeFieldBegin('success', TType.STRUCT, 0) + self.success.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) +all_structs.append(setRules_result) +setRules_result.thrift_spec = ( + (0, TType.STRUCT, 'success', [Status, None], None, ), # 0 +) fix_spec(all_structs) del all_structs diff --git a/session_py/iginx/iginx_pyclient/thrift/rpc/ttypes.py b/session_py/iginx/iginx_pyclient/thrift/rpc/ttypes.py index ab63b9837f..0e820c0567 100644 --- a/session_py/iginx/iginx_pyclient/thrift/rpc/ttypes.py +++ b/session_py/iginx/iginx_pyclient/thrift/rpc/ttypes.py @@ -47,7 +47,7 @@ class StorageEngineType(object): iotdb12 = 0 influxdb = 1 parquet = 2 - postgresql = 3 + relational = 3 mongodb = 4 redis = 5 filesystem = 6 @@ -59,7 +59,7 @@ class StorageEngineType(object): 0: "iotdb12", 1: "influxdb", 2: "parquet", - 3: "postgresql", + 3: "relational", 4: "mongodb", 5: "redis", 6: "filesystem", @@ -72,7 +72,7 @@ class StorageEngineType(object): "iotdb12": 0, "influxdb": 1, "parquet": 2, - "postgresql": 3, + "relational": 3, "mongodb": 4, "redis": 5, "filesystem": 6, @@ -145,6 +145,8 @@ class SqlType(object): ExportStream = 23 LoadCsv = 24 ShowSessionID = 25 + ShowRules = 26 + SetRules = 27 _VALUES_TO_NAMES = { 0: "Unknown", @@ -173,6 +175,8 @@ class SqlType(object): 23: "ExportStream", 24: "LoadCsv", 25: "ShowSessionID", + 26: "ShowRules", + 27: "SetRules", } _NAMES_TO_VALUES = { @@ -202,6 +206,8 @@ class SqlType(object): "ExportStream": 23, "LoadCsv": 24, "ShowSessionID": 25, + "ShowRules": 26, + "SetRules": 27, } @@ -511,6 +517,78 @@ def __ne__(self, other): return not (self == other) +class UDFClassPair(object): + """ + Attributes: + - name + - classPath + + """ + + + def __init__(self, name=None, classPath=None,): + self.name = name + self.classPath = classPath + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec]) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.STRING: + self.name = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 2: + if ftype == TType.STRING: + self.classPath = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec])) + return + oprot.writeStructBegin('UDFClassPair') + if self.name is not None: + oprot.writeFieldBegin('name', TType.STRING, 1) + oprot.writeString(self.name.encode('utf-8') if sys.version_info[0] == 2 else self.name) + oprot.writeFieldEnd() + if self.classPath is not None: + oprot.writeFieldBegin('classPath', TType.STRING, 2) + oprot.writeString(self.classPath.encode('utf-8') if sys.version_info[0] == 2 else self.classPath) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + if self.name is None: + raise TProtocolException(message='Required field name is unset!') + if self.classPath is None: + raise TProtocolException(message='Required field classPath is unset!') + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + class OpenSessionReq(object): """ Attributes: @@ -3743,14 +3821,16 @@ class ExecuteSqlResp(object): - jobId - jobState - jobIdList - - configValue + - configs - loadCsvPath - sessionIDList + - rules + - UDFModulePath """ - def __init__(self, status=None, type=None, paths=None, tagsList=None, dataTypeList=None, queryDataSet=None, keys=None, valuesList=None, replicaNum=None, pointsNum=None, aggregateType=None, parseErrorMsg=None, limit=None, offset=None, orderByPath=None, ascending=None, iginxInfos=None, storageEngineInfos=None, metaStorageInfos=None, localMetaStorageInfo=None, registerTaskInfos=None, jobId=None, jobState=None, jobIdList=None, configValue=None, loadCsvPath=None, sessionIDList=None,): + def __init__(self, status=None, type=None, paths=None, tagsList=None, dataTypeList=None, queryDataSet=None, keys=None, valuesList=None, replicaNum=None, pointsNum=None, aggregateType=None, parseErrorMsg=None, limit=None, offset=None, orderByPath=None, ascending=None, iginxInfos=None, storageEngineInfos=None, metaStorageInfos=None, localMetaStorageInfo=None, registerTaskInfos=None, jobId=None, jobState=None, jobIdList=None, configs=None, loadCsvPath=None, sessionIDList=None, rules=None, UDFModulePath=None,): self.status = status self.type = type self.paths = paths @@ -3775,9 +3855,11 @@ def __init__(self, status=None, type=None, paths=None, tagsList=None, dataTypeLi self.jobId = jobId self.jobState = jobState self.jobIdList = jobIdList - self.configValue = configValue + self.configs = configs self.loadCsvPath = loadCsvPath self.sessionIDList = sessionIDList + self.rules = rules + self.UDFModulePath = UDFModulePath def read(self, iprot): if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: @@ -3962,8 +4044,14 @@ def read(self, iprot): else: iprot.skip(ftype) elif fid == 25: - if ftype == TType.STRING: - self.configValue = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString() + if ftype == TType.MAP: + self.configs = {} + (_ktype599, _vtype600, _size598) = iprot.readMapBegin() + for _i602 in range(_size598): + _key603 = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString() + _val604 = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString() + self.configs[_key603] = _val604 + iprot.readMapEnd() else: iprot.skip(ftype) elif fid == 26: @@ -3974,13 +4062,29 @@ def read(self, iprot): elif fid == 27: if ftype == TType.LIST: self.sessionIDList = [] - (_etype601, _size598) = iprot.readListBegin() - for _i602 in range(_size598): - _elem603 = iprot.readI64() - self.sessionIDList.append(_elem603) + (_etype608, _size605) = iprot.readListBegin() + for _i609 in range(_size605): + _elem610 = iprot.readI64() + self.sessionIDList.append(_elem610) iprot.readListEnd() else: iprot.skip(ftype) + elif fid == 28: + if ftype == TType.MAP: + self.rules = {} + (_ktype612, _vtype613, _size611) = iprot.readMapBegin() + for _i615 in range(_size611): + _key616 = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString() + _val617 = iprot.readBool() + self.rules[_key616] = _val617 + iprot.readMapEnd() + else: + iprot.skip(ftype) + elif fid == 29: + if ftype == TType.STRING: + self.UDFModulePath = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) else: iprot.skip(ftype) iprot.readFieldEnd() @@ -4002,26 +4106,26 @@ def write(self, oprot): if self.paths is not None: oprot.writeFieldBegin('paths', TType.LIST, 3) oprot.writeListBegin(TType.STRING, len(self.paths)) - for iter604 in self.paths: - oprot.writeString(iter604.encode('utf-8') if sys.version_info[0] == 2 else iter604) + for iter618 in self.paths: + oprot.writeString(iter618.encode('utf-8') if sys.version_info[0] == 2 else iter618) oprot.writeListEnd() oprot.writeFieldEnd() if self.tagsList is not None: oprot.writeFieldBegin('tagsList', TType.LIST, 4) oprot.writeListBegin(TType.MAP, len(self.tagsList)) - for iter605 in self.tagsList: - oprot.writeMapBegin(TType.STRING, TType.STRING, len(iter605)) - for kiter606, viter607 in iter605.items(): - oprot.writeString(kiter606.encode('utf-8') if sys.version_info[0] == 2 else kiter606) - oprot.writeString(viter607.encode('utf-8') if sys.version_info[0] == 2 else viter607) + for iter619 in self.tagsList: + oprot.writeMapBegin(TType.STRING, TType.STRING, len(iter619)) + for kiter620, viter621 in iter619.items(): + oprot.writeString(kiter620.encode('utf-8') if sys.version_info[0] == 2 else kiter620) + oprot.writeString(viter621.encode('utf-8') if sys.version_info[0] == 2 else viter621) oprot.writeMapEnd() oprot.writeListEnd() oprot.writeFieldEnd() if self.dataTypeList is not None: oprot.writeFieldBegin('dataTypeList', TType.LIST, 5) oprot.writeListBegin(TType.I32, len(self.dataTypeList)) - for iter608 in self.dataTypeList: - oprot.writeI32(iter608) + for iter622 in self.dataTypeList: + oprot.writeI32(iter622) oprot.writeListEnd() oprot.writeFieldEnd() if self.queryDataSet is not None: @@ -4071,22 +4175,22 @@ def write(self, oprot): if self.iginxInfos is not None: oprot.writeFieldBegin('iginxInfos', TType.LIST, 17) oprot.writeListBegin(TType.STRUCT, len(self.iginxInfos)) - for iter609 in self.iginxInfos: - iter609.write(oprot) + for iter623 in self.iginxInfos: + iter623.write(oprot) oprot.writeListEnd() oprot.writeFieldEnd() if self.storageEngineInfos is not None: oprot.writeFieldBegin('storageEngineInfos', TType.LIST, 18) oprot.writeListBegin(TType.STRUCT, len(self.storageEngineInfos)) - for iter610 in self.storageEngineInfos: - iter610.write(oprot) + for iter624 in self.storageEngineInfos: + iter624.write(oprot) oprot.writeListEnd() oprot.writeFieldEnd() if self.metaStorageInfos is not None: oprot.writeFieldBegin('metaStorageInfos', TType.LIST, 19) oprot.writeListBegin(TType.STRUCT, len(self.metaStorageInfos)) - for iter611 in self.metaStorageInfos: - iter611.write(oprot) + for iter625 in self.metaStorageInfos: + iter625.write(oprot) oprot.writeListEnd() oprot.writeFieldEnd() if self.localMetaStorageInfo is not None: @@ -4096,8 +4200,8 @@ def write(self, oprot): if self.registerTaskInfos is not None: oprot.writeFieldBegin('registerTaskInfos', TType.LIST, 21) oprot.writeListBegin(TType.STRUCT, len(self.registerTaskInfos)) - for iter612 in self.registerTaskInfos: - iter612.write(oprot) + for iter626 in self.registerTaskInfos: + iter626.write(oprot) oprot.writeListEnd() oprot.writeFieldEnd() if self.jobId is not None: @@ -4111,13 +4215,17 @@ def write(self, oprot): if self.jobIdList is not None: oprot.writeFieldBegin('jobIdList', TType.LIST, 24) oprot.writeListBegin(TType.I64, len(self.jobIdList)) - for iter613 in self.jobIdList: - oprot.writeI64(iter613) + for iter627 in self.jobIdList: + oprot.writeI64(iter627) oprot.writeListEnd() oprot.writeFieldEnd() - if self.configValue is not None: - oprot.writeFieldBegin('configValue', TType.STRING, 25) - oprot.writeString(self.configValue.encode('utf-8') if sys.version_info[0] == 2 else self.configValue) + if self.configs is not None: + oprot.writeFieldBegin('configs', TType.MAP, 25) + oprot.writeMapBegin(TType.STRING, TType.STRING, len(self.configs)) + for kiter628, viter629 in self.configs.items(): + oprot.writeString(kiter628.encode('utf-8') if sys.version_info[0] == 2 else kiter628) + oprot.writeString(viter629.encode('utf-8') if sys.version_info[0] == 2 else viter629) + oprot.writeMapEnd() oprot.writeFieldEnd() if self.loadCsvPath is not None: oprot.writeFieldBegin('loadCsvPath', TType.STRING, 26) @@ -4126,10 +4234,22 @@ def write(self, oprot): if self.sessionIDList is not None: oprot.writeFieldBegin('sessionIDList', TType.LIST, 27) oprot.writeListBegin(TType.I64, len(self.sessionIDList)) - for iter614 in self.sessionIDList: - oprot.writeI64(iter614) + for iter630 in self.sessionIDList: + oprot.writeI64(iter630) oprot.writeListEnd() oprot.writeFieldEnd() + if self.rules is not None: + oprot.writeFieldBegin('rules', TType.MAP, 28) + oprot.writeMapBegin(TType.STRING, TType.BOOL, len(self.rules)) + for kiter631, viter632 in self.rules.items(): + oprot.writeString(kiter631.encode('utf-8') if sys.version_info[0] == 2 else kiter631) + oprot.writeBool(viter632) + oprot.writeMapEnd() + oprot.writeFieldEnd() + if self.UDFModulePath is not None: + oprot.writeFieldBegin('UDFModulePath', TType.STRING, 29) + oprot.writeString(self.UDFModulePath.encode('utf-8') if sys.version_info[0] == 2 else self.UDFModulePath) + oprot.writeFieldEnd() oprot.writeFieldStop() oprot.writeStructEnd() @@ -4196,10 +4316,10 @@ def read(self, iprot): elif fid == 4: if ftype == TType.SET: self.auths = set() - (_etype618, _size615) = iprot.readSetBegin() - for _i619 in range(_size615): - _elem620 = iprot.readI32() - self.auths.add(_elem620) + (_etype636, _size633) = iprot.readSetBegin() + for _i637 in range(_size633): + _elem638 = iprot.readI32() + self.auths.add(_elem638) iprot.readSetEnd() else: iprot.skip(ftype) @@ -4228,8 +4348,8 @@ def write(self, oprot): if self.auths is not None: oprot.writeFieldBegin('auths', TType.SET, 4) oprot.writeSetBegin(TType.I32, len(self.auths)) - for iter621 in self.auths: - oprot.writeI32(iter621) + for iter639 in self.auths: + oprot.writeI32(iter639) oprot.writeSetEnd() oprot.writeFieldEnd() oprot.writeFieldStop() @@ -4298,10 +4418,10 @@ def read(self, iprot): elif fid == 4: if ftype == TType.SET: self.auths = set() - (_etype625, _size622) = iprot.readSetBegin() - for _i626 in range(_size622): - _elem627 = iprot.readI32() - self.auths.add(_elem627) + (_etype643, _size640) = iprot.readSetBegin() + for _i644 in range(_size640): + _elem645 = iprot.readI32() + self.auths.add(_elem645) iprot.readSetEnd() else: iprot.skip(ftype) @@ -4330,8 +4450,8 @@ def write(self, oprot): if self.auths is not None: oprot.writeFieldBegin('auths', TType.SET, 4) oprot.writeSetBegin(TType.I32, len(self.auths)) - for iter628 in self.auths: - oprot.writeI32(iter628) + for iter646 in self.auths: + oprot.writeI32(iter646) oprot.writeSetEnd() oprot.writeFieldEnd() oprot.writeFieldStop() @@ -4462,10 +4582,10 @@ def read(self, iprot): elif fid == 2: if ftype == TType.LIST: self.usernames = [] - (_etype632, _size629) = iprot.readListBegin() - for _i633 in range(_size629): - _elem634 = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString() - self.usernames.append(_elem634) + (_etype650, _size647) = iprot.readListBegin() + for _i651 in range(_size647): + _elem652 = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString() + self.usernames.append(_elem652) iprot.readListEnd() else: iprot.skip(ftype) @@ -4486,8 +4606,8 @@ def write(self, oprot): if self.usernames is not None: oprot.writeFieldBegin('usernames', TType.LIST, 2) oprot.writeListBegin(TType.STRING, len(self.usernames)) - for iter635 in self.usernames: - oprot.writeString(iter635.encode('utf-8') if sys.version_info[0] == 2 else iter635) + for iter653 in self.usernames: + oprot.writeString(iter653.encode('utf-8') if sys.version_info[0] == 2 else iter653) oprot.writeListEnd() oprot.writeFieldEnd() oprot.writeFieldStop() @@ -4545,35 +4665,35 @@ def read(self, iprot): elif fid == 2: if ftype == TType.LIST: self.usernames = [] - (_etype639, _size636) = iprot.readListBegin() - for _i640 in range(_size636): - _elem641 = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString() - self.usernames.append(_elem641) + (_etype657, _size654) = iprot.readListBegin() + for _i658 in range(_size654): + _elem659 = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString() + self.usernames.append(_elem659) iprot.readListEnd() else: iprot.skip(ftype) elif fid == 3: if ftype == TType.LIST: self.userTypes = [] - (_etype645, _size642) = iprot.readListBegin() - for _i646 in range(_size642): - _elem647 = iprot.readI32() - self.userTypes.append(_elem647) + (_etype663, _size660) = iprot.readListBegin() + for _i664 in range(_size660): + _elem665 = iprot.readI32() + self.userTypes.append(_elem665) iprot.readListEnd() else: iprot.skip(ftype) elif fid == 4: if ftype == TType.LIST: self.auths = [] - (_etype651, _size648) = iprot.readListBegin() - for _i652 in range(_size648): - _elem653 = set() - (_etype657, _size654) = iprot.readSetBegin() - for _i658 in range(_size654): - _elem659 = iprot.readI32() - _elem653.add(_elem659) + (_etype669, _size666) = iprot.readListBegin() + for _i670 in range(_size666): + _elem671 = set() + (_etype675, _size672) = iprot.readSetBegin() + for _i676 in range(_size672): + _elem677 = iprot.readI32() + _elem671.add(_elem677) iprot.readSetEnd() - self.auths.append(_elem653) + self.auths.append(_elem671) iprot.readListEnd() else: iprot.skip(ftype) @@ -4594,24 +4714,24 @@ def write(self, oprot): if self.usernames is not None: oprot.writeFieldBegin('usernames', TType.LIST, 2) oprot.writeListBegin(TType.STRING, len(self.usernames)) - for iter660 in self.usernames: - oprot.writeString(iter660.encode('utf-8') if sys.version_info[0] == 2 else iter660) + for iter678 in self.usernames: + oprot.writeString(iter678.encode('utf-8') if sys.version_info[0] == 2 else iter678) oprot.writeListEnd() oprot.writeFieldEnd() if self.userTypes is not None: oprot.writeFieldBegin('userTypes', TType.LIST, 3) oprot.writeListBegin(TType.I32, len(self.userTypes)) - for iter661 in self.userTypes: - oprot.writeI32(iter661) + for iter679 in self.userTypes: + oprot.writeI32(iter679) oprot.writeListEnd() oprot.writeFieldEnd() if self.auths is not None: oprot.writeFieldBegin('auths', TType.LIST, 4) oprot.writeListBegin(TType.SET, len(self.auths)) - for iter662 in self.auths: - oprot.writeSetBegin(TType.I32, len(iter662)) - for iter663 in iter662: - oprot.writeI32(iter663) + for iter680 in self.auths: + oprot.writeSetBegin(TType.I32, len(iter680)) + for iter681 in iter680: + oprot.writeI32(iter681) oprot.writeSetEnd() oprot.writeListEnd() oprot.writeFieldEnd() @@ -5080,33 +5200,33 @@ def read(self, iprot): elif fid == 2: if ftype == TType.LIST: self.iginxInfos = [] - (_etype667, _size664) = iprot.readListBegin() - for _i668 in range(_size664): - _elem669 = IginxInfo() - _elem669.read(iprot) - self.iginxInfos.append(_elem669) + (_etype685, _size682) = iprot.readListBegin() + for _i686 in range(_size682): + _elem687 = IginxInfo() + _elem687.read(iprot) + self.iginxInfos.append(_elem687) iprot.readListEnd() else: iprot.skip(ftype) elif fid == 3: if ftype == TType.LIST: self.storageEngineInfos = [] - (_etype673, _size670) = iprot.readListBegin() - for _i674 in range(_size670): - _elem675 = StorageEngineInfo() - _elem675.read(iprot) - self.storageEngineInfos.append(_elem675) + (_etype691, _size688) = iprot.readListBegin() + for _i692 in range(_size688): + _elem693 = StorageEngineInfo() + _elem693.read(iprot) + self.storageEngineInfos.append(_elem693) iprot.readListEnd() else: iprot.skip(ftype) elif fid == 4: if ftype == TType.LIST: self.metaStorageInfos = [] - (_etype679, _size676) = iprot.readListBegin() - for _i680 in range(_size676): - _elem681 = MetaStorageInfo() - _elem681.read(iprot) - self.metaStorageInfos.append(_elem681) + (_etype697, _size694) = iprot.readListBegin() + for _i698 in range(_size694): + _elem699 = MetaStorageInfo() + _elem699.read(iprot) + self.metaStorageInfos.append(_elem699) iprot.readListEnd() else: iprot.skip(ftype) @@ -5133,22 +5253,22 @@ def write(self, oprot): if self.iginxInfos is not None: oprot.writeFieldBegin('iginxInfos', TType.LIST, 2) oprot.writeListBegin(TType.STRUCT, len(self.iginxInfos)) - for iter682 in self.iginxInfos: - iter682.write(oprot) + for iter700 in self.iginxInfos: + iter700.write(oprot) oprot.writeListEnd() oprot.writeFieldEnd() if self.storageEngineInfos is not None: oprot.writeFieldBegin('storageEngineInfos', TType.LIST, 3) oprot.writeListBegin(TType.STRUCT, len(self.storageEngineInfos)) - for iter683 in self.storageEngineInfos: - iter683.write(oprot) + for iter701 in self.storageEngineInfos: + iter701.write(oprot) oprot.writeListEnd() oprot.writeFieldEnd() if self.metaStorageInfos is not None: oprot.writeFieldBegin('metaStorageInfos', TType.LIST, 4) oprot.writeListBegin(TType.STRUCT, len(self.metaStorageInfos)) - for iter684 in self.metaStorageInfos: - iter684.write(oprot) + for iter702 in self.metaStorageInfos: + iter702.write(oprot) oprot.writeListEnd() oprot.writeFieldEnd() if self.localMetaStorageInfo is not None: @@ -5326,36 +5446,36 @@ def read(self, iprot): elif fid == 4: if ftype == TType.LIST: self.columns = [] - (_etype688, _size685) = iprot.readListBegin() - for _i689 in range(_size685): - _elem690 = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString() - self.columns.append(_elem690) + (_etype706, _size703) = iprot.readListBegin() + for _i707 in range(_size703): + _elem708 = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString() + self.columns.append(_elem708) iprot.readListEnd() else: iprot.skip(ftype) elif fid == 5: if ftype == TType.LIST: self.tagsList = [] - (_etype694, _size691) = iprot.readListBegin() - for _i695 in range(_size691): - _elem696 = {} - (_ktype698, _vtype699, _size697) = iprot.readMapBegin() - for _i701 in range(_size697): - _key702 = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString() - _val703 = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString() - _elem696[_key702] = _val703 + (_etype712, _size709) = iprot.readListBegin() + for _i713 in range(_size709): + _elem714 = {} + (_ktype716, _vtype717, _size715) = iprot.readMapBegin() + for _i719 in range(_size715): + _key720 = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString() + _val721 = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString() + _elem714[_key720] = _val721 iprot.readMapEnd() - self.tagsList.append(_elem696) + self.tagsList.append(_elem714) iprot.readListEnd() else: iprot.skip(ftype) elif fid == 6: if ftype == TType.LIST: self.dataTypeList = [] - (_etype707, _size704) = iprot.readListBegin() - for _i708 in range(_size704): - _elem709 = iprot.readI32() - self.dataTypeList.append(_elem709) + (_etype725, _size722) = iprot.readListBegin() + for _i726 in range(_size722): + _elem727 = iprot.readI32() + self.dataTypeList.append(_elem727) iprot.readListEnd() else: iprot.skip(ftype) @@ -5406,26 +5526,26 @@ def write(self, oprot): if self.columns is not None: oprot.writeFieldBegin('columns', TType.LIST, 4) oprot.writeListBegin(TType.STRING, len(self.columns)) - for iter710 in self.columns: - oprot.writeString(iter710.encode('utf-8') if sys.version_info[0] == 2 else iter710) + for iter728 in self.columns: + oprot.writeString(iter728.encode('utf-8') if sys.version_info[0] == 2 else iter728) oprot.writeListEnd() oprot.writeFieldEnd() if self.tagsList is not None: oprot.writeFieldBegin('tagsList', TType.LIST, 5) oprot.writeListBegin(TType.MAP, len(self.tagsList)) - for iter711 in self.tagsList: - oprot.writeMapBegin(TType.STRING, TType.STRING, len(iter711)) - for kiter712, viter713 in iter711.items(): - oprot.writeString(kiter712.encode('utf-8') if sys.version_info[0] == 2 else kiter712) - oprot.writeString(viter713.encode('utf-8') if sys.version_info[0] == 2 else viter713) + for iter729 in self.tagsList: + oprot.writeMapBegin(TType.STRING, TType.STRING, len(iter729)) + for kiter730, viter731 in iter729.items(): + oprot.writeString(kiter730.encode('utf-8') if sys.version_info[0] == 2 else kiter730) + oprot.writeString(viter731.encode('utf-8') if sys.version_info[0] == 2 else viter731) oprot.writeMapEnd() oprot.writeListEnd() oprot.writeFieldEnd() if self.dataTypeList is not None: oprot.writeFieldBegin('dataTypeList', TType.LIST, 6) oprot.writeListBegin(TType.I32, len(self.dataTypeList)) - for iter714 in self.dataTypeList: - oprot.writeI32(iter714) + for iter732 in self.dataTypeList: + oprot.writeI32(iter732) oprot.writeListEnd() oprot.writeFieldEnd() if self.queryDataSet is not None: @@ -5628,20 +5748,20 @@ def read(self, iprot): if fid == 1: if ftype == TType.LIST: self.valuesList = [] - (_etype718, _size715) = iprot.readListBegin() - for _i719 in range(_size715): - _elem720 = iprot.readBinary() - self.valuesList.append(_elem720) + (_etype736, _size733) = iprot.readListBegin() + for _i737 in range(_size733): + _elem738 = iprot.readBinary() + self.valuesList.append(_elem738) iprot.readListEnd() else: iprot.skip(ftype) elif fid == 2: if ftype == TType.LIST: self.bitmapList = [] - (_etype724, _size721) = iprot.readListBegin() - for _i725 in range(_size721): - _elem726 = iprot.readBinary() - self.bitmapList.append(_elem726) + (_etype742, _size739) = iprot.readListBegin() + for _i743 in range(_size739): + _elem744 = iprot.readBinary() + self.bitmapList.append(_elem744) iprot.readListEnd() else: iprot.skip(ftype) @@ -5658,15 +5778,15 @@ def write(self, oprot): if self.valuesList is not None: oprot.writeFieldBegin('valuesList', TType.LIST, 1) oprot.writeListBegin(TType.STRING, len(self.valuesList)) - for iter727 in self.valuesList: - oprot.writeBinary(iter727) + for iter745 in self.valuesList: + oprot.writeBinary(iter745) oprot.writeListEnd() oprot.writeFieldEnd() if self.bitmapList is not None: oprot.writeFieldBegin('bitmapList', TType.LIST, 2) oprot.writeListBegin(TType.STRING, len(self.bitmapList)) - for iter728 in self.bitmapList: - oprot.writeBinary(iter728) + for iter746 in self.bitmapList: + oprot.writeBinary(iter746) oprot.writeListEnd() oprot.writeFieldEnd() oprot.writeFieldStop() @@ -6062,10 +6182,10 @@ def read(self, iprot): elif fid == 2: if ftype == TType.LIST: self.columns = [] - (_etype732, _size729) = iprot.readListBegin() - for _i733 in range(_size729): - _elem734 = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString() - self.columns.append(_elem734) + (_etype750, _size747) = iprot.readListBegin() + for _i751 in range(_size747): + _elem752 = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString() + self.columns.append(_elem752) iprot.readListEnd() else: iprot.skip(ftype) @@ -6096,8 +6216,8 @@ def write(self, oprot): if self.columns is not None: oprot.writeFieldBegin('columns', TType.LIST, 2) oprot.writeListBegin(TType.STRING, len(self.columns)) - for iter735 in self.columns: - oprot.writeString(iter735.encode('utf-8') if sys.version_info[0] == 2 else iter735) + for iter753 in self.columns: + oprot.writeString(iter753.encode('utf-8') if sys.version_info[0] == 2 else iter753) oprot.writeListEnd() oprot.writeFieldEnd() if self.recordsNum is not None: @@ -6128,6 +6248,184 @@ def __ne__(self, other): return not (self == other) +class LoadUDFReq(object): + """ + Attributes: + - sessionId + - statement + - udfFile + - isRemote + + """ + + + def __init__(self, sessionId=None, statement=None, udfFile=None, isRemote=None,): + self.sessionId = sessionId + self.statement = statement + self.udfFile = udfFile + self.isRemote = isRemote + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec]) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.I64: + self.sessionId = iprot.readI64() + else: + iprot.skip(ftype) + elif fid == 2: + if ftype == TType.STRING: + self.statement = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 3: + if ftype == TType.STRING: + self.udfFile = iprot.readBinary() + else: + iprot.skip(ftype) + elif fid == 4: + if ftype == TType.BOOL: + self.isRemote = iprot.readBool() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec])) + return + oprot.writeStructBegin('LoadUDFReq') + if self.sessionId is not None: + oprot.writeFieldBegin('sessionId', TType.I64, 1) + oprot.writeI64(self.sessionId) + oprot.writeFieldEnd() + if self.statement is not None: + oprot.writeFieldBegin('statement', TType.STRING, 2) + oprot.writeString(self.statement.encode('utf-8') if sys.version_info[0] == 2 else self.statement) + oprot.writeFieldEnd() + if self.udfFile is not None: + oprot.writeFieldBegin('udfFile', TType.STRING, 3) + oprot.writeBinary(self.udfFile) + oprot.writeFieldEnd() + if self.isRemote is not None: + oprot.writeFieldBegin('isRemote', TType.BOOL, 4) + oprot.writeBool(self.isRemote) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + if self.sessionId is None: + raise TProtocolException(message='Required field sessionId is unset!') + if self.statement is None: + raise TProtocolException(message='Required field statement is unset!') + if self.isRemote is None: + raise TProtocolException(message='Required field isRemote is unset!') + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class LoadUDFResp(object): + """ + Attributes: + - status + - parseErrorMsg + - UDFModulePath + + """ + + + def __init__(self, status=None, parseErrorMsg=None, UDFModulePath=None,): + self.status = status + self.parseErrorMsg = parseErrorMsg + self.UDFModulePath = UDFModulePath + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec]) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.STRUCT: + self.status = Status() + self.status.read(iprot) + else: + iprot.skip(ftype) + elif fid == 2: + if ftype == TType.STRING: + self.parseErrorMsg = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 3: + if ftype == TType.STRING: + self.UDFModulePath = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec])) + return + oprot.writeStructBegin('LoadUDFResp') + if self.status is not None: + oprot.writeFieldBegin('status', TType.STRUCT, 1) + self.status.write(oprot) + oprot.writeFieldEnd() + if self.parseErrorMsg is not None: + oprot.writeFieldBegin('parseErrorMsg', TType.STRING, 2) + oprot.writeString(self.parseErrorMsg.encode('utf-8') if sys.version_info[0] == 2 else self.parseErrorMsg) + oprot.writeFieldEnd() + if self.UDFModulePath is not None: + oprot.writeFieldBegin('UDFModulePath', TType.STRING, 3) + oprot.writeString(self.UDFModulePath.encode('utf-8') if sys.version_info[0] == 2 else self.UDFModulePath) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + if self.status is None: + raise TProtocolException(message='Required field status is unset!') + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + class TaskInfo(object): """ Attributes: @@ -6174,10 +6472,10 @@ def read(self, iprot): elif fid == 4: if ftype == TType.LIST: self.sqlList = [] - (_etype739, _size736) = iprot.readListBegin() - for _i740 in range(_size736): - _elem741 = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString() - self.sqlList.append(_elem741) + (_etype757, _size754) = iprot.readListBegin() + for _i758 in range(_size754): + _elem759 = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString() + self.sqlList.append(_elem759) iprot.readListEnd() else: iprot.skip(ftype) @@ -6211,8 +6509,8 @@ def write(self, oprot): if self.sqlList is not None: oprot.writeFieldBegin('sqlList', TType.LIST, 4) oprot.writeListBegin(TType.STRING, len(self.sqlList)) - for iter742 in self.sqlList: - oprot.writeString(iter742.encode('utf-8') if sys.version_info[0] == 2 else iter742) + for iter760 in self.sqlList: + oprot.writeString(iter760.encode('utf-8') if sys.version_info[0] == 2 else iter760) oprot.writeListEnd() oprot.writeFieldEnd() if self.pyTaskName is not None: @@ -6275,11 +6573,11 @@ def read(self, iprot): elif fid == 2: if ftype == TType.LIST: self.taskList = [] - (_etype746, _size743) = iprot.readListBegin() - for _i747 in range(_size743): - _elem748 = TaskInfo() - _elem748.read(iprot) - self.taskList.append(_elem748) + (_etype764, _size761) = iprot.readListBegin() + for _i765 in range(_size761): + _elem766 = TaskInfo() + _elem766.read(iprot) + self.taskList.append(_elem766) iprot.readListEnd() else: iprot.skip(ftype) @@ -6310,8 +6608,8 @@ def write(self, oprot): if self.taskList is not None: oprot.writeFieldBegin('taskList', TType.LIST, 2) oprot.writeListBegin(TType.STRUCT, len(self.taskList)) - for iter749 in self.taskList: - iter749.write(oprot) + for iter767 in self.taskList: + iter767.write(oprot) oprot.writeListEnd() oprot.writeFieldEnd() if self.exportType is not None: @@ -6667,10 +6965,10 @@ def read(self, iprot): elif fid == 2: if ftype == TType.LIST: self.jobIdList = [] - (_etype753, _size750) = iprot.readListBegin() - for _i754 in range(_size750): - _elem755 = iprot.readI64() - self.jobIdList.append(_elem755) + (_etype771, _size768) = iprot.readListBegin() + for _i772 in range(_size768): + _elem773 = iprot.readI64() + self.jobIdList.append(_elem773) iprot.readListEnd() else: iprot.skip(ftype) @@ -6691,8 +6989,8 @@ def write(self, oprot): if self.jobIdList is not None: oprot.writeFieldBegin('jobIdList', TType.LIST, 2) oprot.writeListBegin(TType.I64, len(self.jobIdList)) - for iter756 in self.jobIdList: - oprot.writeI64(iter756) + for iter774 in self.jobIdList: + oprot.writeI64(iter774) oprot.writeListEnd() oprot.writeFieldEnd() oprot.writeFieldStop() @@ -6793,20 +7091,22 @@ class RegisterTaskReq(object): """ Attributes: - sessionId - - name - filePath - - className - - type + - UDFClassPairs + - types + - moduleFile + - isRemote """ - def __init__(self, sessionId=None, name=None, filePath=None, className=None, type=None,): + def __init__(self, sessionId=None, filePath=None, UDFClassPairs=None, types=None, moduleFile=None, isRemote=None,): self.sessionId = sessionId - self.name = name self.filePath = filePath - self.className = className - self.type = type + self.UDFClassPairs = UDFClassPairs + self.types = types + self.moduleFile = moduleFile + self.isRemote = isRemote def read(self, iprot): if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: @@ -6824,22 +7124,38 @@ def read(self, iprot): iprot.skip(ftype) elif fid == 2: if ftype == TType.STRING: - self.name = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString() + self.filePath = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString() else: iprot.skip(ftype) elif fid == 3: - if ftype == TType.STRING: - self.filePath = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString() + if ftype == TType.LIST: + self.UDFClassPairs = [] + (_etype778, _size775) = iprot.readListBegin() + for _i779 in range(_size775): + _elem780 = UDFClassPair() + _elem780.read(iprot) + self.UDFClassPairs.append(_elem780) + iprot.readListEnd() else: iprot.skip(ftype) elif fid == 4: - if ftype == TType.STRING: - self.className = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString() + if ftype == TType.LIST: + self.types = [] + (_etype784, _size781) = iprot.readListBegin() + for _i785 in range(_size781): + _elem786 = iprot.readI32() + self.types.append(_elem786) + iprot.readListEnd() else: iprot.skip(ftype) elif fid == 5: - if ftype == TType.I32: - self.type = iprot.readI32() + if ftype == TType.STRING: + self.moduleFile = iprot.readBinary() + else: + iprot.skip(ftype) + elif fid == 6: + if ftype == TType.BOOL: + self.isRemote = iprot.readBool() else: iprot.skip(ftype) else: @@ -6856,21 +7172,31 @@ def write(self, oprot): oprot.writeFieldBegin('sessionId', TType.I64, 1) oprot.writeI64(self.sessionId) oprot.writeFieldEnd() - if self.name is not None: - oprot.writeFieldBegin('name', TType.STRING, 2) - oprot.writeString(self.name.encode('utf-8') if sys.version_info[0] == 2 else self.name) - oprot.writeFieldEnd() if self.filePath is not None: - oprot.writeFieldBegin('filePath', TType.STRING, 3) + oprot.writeFieldBegin('filePath', TType.STRING, 2) oprot.writeString(self.filePath.encode('utf-8') if sys.version_info[0] == 2 else self.filePath) oprot.writeFieldEnd() - if self.className is not None: - oprot.writeFieldBegin('className', TType.STRING, 4) - oprot.writeString(self.className.encode('utf-8') if sys.version_info[0] == 2 else self.className) + if self.UDFClassPairs is not None: + oprot.writeFieldBegin('UDFClassPairs', TType.LIST, 3) + oprot.writeListBegin(TType.STRUCT, len(self.UDFClassPairs)) + for iter787 in self.UDFClassPairs: + iter787.write(oprot) + oprot.writeListEnd() oprot.writeFieldEnd() - if self.type is not None: - oprot.writeFieldBegin('type', TType.I32, 5) - oprot.writeI32(self.type) + if self.types is not None: + oprot.writeFieldBegin('types', TType.LIST, 4) + oprot.writeListBegin(TType.I32, len(self.types)) + for iter788 in self.types: + oprot.writeI32(iter788) + oprot.writeListEnd() + oprot.writeFieldEnd() + if self.moduleFile is not None: + oprot.writeFieldBegin('moduleFile', TType.STRING, 5) + oprot.writeBinary(self.moduleFile) + oprot.writeFieldEnd() + if self.isRemote is not None: + oprot.writeFieldBegin('isRemote', TType.BOOL, 6) + oprot.writeBool(self.isRemote) oprot.writeFieldEnd() oprot.writeFieldStop() oprot.writeStructEnd() @@ -6878,14 +7204,16 @@ def write(self, oprot): def validate(self): if self.sessionId is None: raise TProtocolException(message='Required field sessionId is unset!') - if self.name is None: - raise TProtocolException(message='Required field name is unset!') if self.filePath is None: raise TProtocolException(message='Required field filePath is unset!') - if self.className is None: - raise TProtocolException(message='Required field className is unset!') - if self.type is None: - raise TProtocolException(message='Required field type is unset!') + if self.UDFClassPairs is None: + raise TProtocolException(message='Required field UDFClassPairs is unset!') + if self.types is None: + raise TProtocolException(message='Required field types is unset!') + if self.moduleFile is None: + raise TProtocolException(message='Required field moduleFile is unset!') + if self.isRemote is None: + raise TProtocolException(message='Required field isRemote is unset!') return def __repr__(self): @@ -7173,11 +7501,11 @@ def read(self, iprot): elif fid == 2: if ftype == TType.LIST: self.registerTaskInfoList = [] - (_etype760, _size757) = iprot.readListBegin() - for _i761 in range(_size757): - _elem762 = RegisterTaskInfo() - _elem762.read(iprot) - self.registerTaskInfoList.append(_elem762) + (_etype792, _size789) = iprot.readListBegin() + for _i793 in range(_size789): + _elem794 = RegisterTaskInfo() + _elem794.read(iprot) + self.registerTaskInfoList.append(_elem794) iprot.readListEnd() else: iprot.skip(ftype) @@ -7198,8 +7526,8 @@ def write(self, oprot): if self.registerTaskInfoList is not None: oprot.writeFieldBegin('registerTaskInfoList', TType.LIST, 2) oprot.writeListBegin(TType.STRUCT, len(self.registerTaskInfoList)) - for iter763 in self.registerTaskInfoList: - iter763.write(oprot) + for iter795 in self.registerTaskInfoList: + iter795.write(oprot) oprot.writeListEnd() oprot.writeFieldEnd() oprot.writeFieldStop() @@ -7260,10 +7588,10 @@ def read(self, iprot): elif fid == 2: if ftype == TType.LIST: self.paths = [] - (_etype767, _size764) = iprot.readListBegin() - for _i768 in range(_size764): - _elem769 = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString() - self.paths.append(_elem769) + (_etype799, _size796) = iprot.readListBegin() + for _i800 in range(_size796): + _elem801 = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString() + self.paths.append(_elem801) iprot.readListEnd() else: iprot.skip(ftype) @@ -7280,10 +7608,10 @@ def read(self, iprot): elif fid == 5: if ftype == TType.LIST: self.curveQuery = [] - (_etype773, _size770) = iprot.readListBegin() - for _i774 in range(_size770): - _elem775 = iprot.readDouble() - self.curveQuery.append(_elem775) + (_etype805, _size802) = iprot.readListBegin() + for _i806 in range(_size802): + _elem807 = iprot.readDouble() + self.curveQuery.append(_elem807) iprot.readListEnd() else: iprot.skip(ftype) @@ -7309,8 +7637,8 @@ def write(self, oprot): if self.paths is not None: oprot.writeFieldBegin('paths', TType.LIST, 2) oprot.writeListBegin(TType.STRING, len(self.paths)) - for iter776 in self.paths: - oprot.writeString(iter776.encode('utf-8') if sys.version_info[0] == 2 else iter776) + for iter808 in self.paths: + oprot.writeString(iter808.encode('utf-8') if sys.version_info[0] == 2 else iter808) oprot.writeListEnd() oprot.writeFieldEnd() if self.startKey is not None: @@ -7324,8 +7652,8 @@ def write(self, oprot): if self.curveQuery is not None: oprot.writeFieldBegin('curveQuery', TType.LIST, 5) oprot.writeListBegin(TType.DOUBLE, len(self.curveQuery)) - for iter777 in self.curveQuery: - oprot.writeDouble(iter777) + for iter809 in self.curveQuery: + oprot.writeDouble(iter809) oprot.writeListEnd() oprot.writeFieldEnd() if self.curveUnit is not None: @@ -7824,33 +8152,33 @@ def read(self, iprot): if fid == 1: if ftype == TType.LIST: self.fragments = [] - (_etype781, _size778) = iprot.readListBegin() - for _i782 in range(_size778): - _elem783 = Fragment() - _elem783.read(iprot) - self.fragments.append(_elem783) + (_etype813, _size810) = iprot.readListBegin() + for _i814 in range(_size810): + _elem815 = Fragment() + _elem815.read(iprot) + self.fragments.append(_elem815) iprot.readListEnd() else: iprot.skip(ftype) elif fid == 2: if ftype == TType.LIST: self.storages = [] - (_etype787, _size784) = iprot.readListBegin() - for _i788 in range(_size784): - _elem789 = Storage() - _elem789.read(iprot) - self.storages.append(_elem789) + (_etype819, _size816) = iprot.readListBegin() + for _i820 in range(_size816): + _elem821 = Storage() + _elem821.read(iprot) + self.storages.append(_elem821) iprot.readListEnd() else: iprot.skip(ftype) elif fid == 3: if ftype == TType.LIST: self.storageUnits = [] - (_etype793, _size790) = iprot.readListBegin() - for _i794 in range(_size790): - _elem795 = StorageUnit() - _elem795.read(iprot) - self.storageUnits.append(_elem795) + (_etype825, _size822) = iprot.readListBegin() + for _i826 in range(_size822): + _elem827 = StorageUnit() + _elem827.read(iprot) + self.storageUnits.append(_elem827) iprot.readListEnd() else: iprot.skip(ftype) @@ -7867,22 +8195,22 @@ def write(self, oprot): if self.fragments is not None: oprot.writeFieldBegin('fragments', TType.LIST, 1) oprot.writeListBegin(TType.STRUCT, len(self.fragments)) - for iter796 in self.fragments: - iter796.write(oprot) + for iter828 in self.fragments: + iter828.write(oprot) oprot.writeListEnd() oprot.writeFieldEnd() if self.storages is not None: oprot.writeFieldBegin('storages', TType.LIST, 2) oprot.writeListBegin(TType.STRUCT, len(self.storages)) - for iter797 in self.storages: - iter797.write(oprot) + for iter829 in self.storages: + iter829.write(oprot) oprot.writeListEnd() oprot.writeFieldEnd() if self.storageUnits is not None: oprot.writeFieldBegin('storageUnits', TType.LIST, 3) oprot.writeListBegin(TType.STRUCT, len(self.storageUnits)) - for iter798 in self.storageUnits: - iter798.write(oprot) + for iter830 in self.storageUnits: + iter830.write(oprot) oprot.writeListEnd() oprot.writeFieldEnd() oprot.writeFieldStop() @@ -8180,11 +8508,11 @@ def read(self, iprot): elif fid == 2: if ftype == TType.LIST: self.removedStorageEngineInfoList = [] - (_etype802, _size799) = iprot.readListBegin() - for _i803 in range(_size799): - _elem804 = RemovedStorageEngineInfo() - _elem804.read(iprot) - self.removedStorageEngineInfoList.append(_elem804) + (_etype834, _size831) = iprot.readListBegin() + for _i835 in range(_size831): + _elem836 = RemovedStorageEngineInfo() + _elem836.read(iprot) + self.removedStorageEngineInfoList.append(_elem836) iprot.readListEnd() else: iprot.skip(ftype) @@ -8205,8 +8533,8 @@ def write(self, oprot): if self.removedStorageEngineInfoList is not None: oprot.writeFieldBegin('removedStorageEngineInfoList', TType.LIST, 2) oprot.writeListBegin(TType.STRUCT, len(self.removedStorageEngineInfoList)) - for iter805 in self.removedStorageEngineInfoList: - iter805.write(oprot) + for iter837 in self.removedStorageEngineInfoList: + iter837.write(oprot) oprot.writeListEnd() oprot.writeFieldEnd() oprot.writeFieldStop() @@ -8321,10 +8649,10 @@ def read(self, iprot): elif fid == 2: if ftype == TType.LIST: self.sessionIDList = [] - (_etype809, _size806) = iprot.readListBegin() - for _i810 in range(_size806): - _elem811 = iprot.readI64() - self.sessionIDList.append(_elem811) + (_etype841, _size838) = iprot.readListBegin() + for _i842 in range(_size838): + _elem843 = iprot.readI64() + self.sessionIDList.append(_elem843) iprot.readListEnd() else: iprot.skip(ftype) @@ -8345,8 +8673,8 @@ def write(self, oprot): if self.sessionIDList is not None: oprot.writeFieldBegin('sessionIDList', TType.LIST, 2) oprot.writeListBegin(TType.I64, len(self.sessionIDList)) - for iter812 in self.sessionIDList: - oprot.writeI64(iter812) + for iter844 in self.sessionIDList: + oprot.writeI64(iter844) oprot.writeListEnd() oprot.writeFieldEnd() oprot.writeFieldStop() @@ -8369,6 +8697,230 @@ def __eq__(self, other): def __ne__(self, other): return not (self == other) + + +class ShowRulesReq(object): + """ + Attributes: + - sessionId + + """ + + + def __init__(self, sessionId=None,): + self.sessionId = sessionId + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec]) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.I64: + self.sessionId = iprot.readI64() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec])) + return + oprot.writeStructBegin('ShowRulesReq') + if self.sessionId is not None: + oprot.writeFieldBegin('sessionId', TType.I64, 1) + oprot.writeI64(self.sessionId) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + if self.sessionId is None: + raise TProtocolException(message='Required field sessionId is unset!') + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class ShowRulesResp(object): + """ + Attributes: + - status + - rules + + """ + + + def __init__(self, status=None, rules=None,): + self.status = status + self.rules = rules + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec]) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.STRUCT: + self.status = Status() + self.status.read(iprot) + else: + iprot.skip(ftype) + elif fid == 2: + if ftype == TType.MAP: + self.rules = {} + (_ktype846, _vtype847, _size845) = iprot.readMapBegin() + for _i849 in range(_size845): + _key850 = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString() + _val851 = iprot.readBool() + self.rules[_key850] = _val851 + iprot.readMapEnd() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec])) + return + oprot.writeStructBegin('ShowRulesResp') + if self.status is not None: + oprot.writeFieldBegin('status', TType.STRUCT, 1) + self.status.write(oprot) + oprot.writeFieldEnd() + if self.rules is not None: + oprot.writeFieldBegin('rules', TType.MAP, 2) + oprot.writeMapBegin(TType.STRING, TType.BOOL, len(self.rules)) + for kiter852, viter853 in self.rules.items(): + oprot.writeString(kiter852.encode('utf-8') if sys.version_info[0] == 2 else kiter852) + oprot.writeBool(viter853) + oprot.writeMapEnd() + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + if self.status is None: + raise TProtocolException(message='Required field status is unset!') + if self.rules is None: + raise TProtocolException(message='Required field rules is unset!') + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class SetRulesReq(object): + """ + Attributes: + - sessionId + - rulesChange + + """ + + + def __init__(self, sessionId=None, rulesChange=None,): + self.sessionId = sessionId + self.rulesChange = rulesChange + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec]) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.I64: + self.sessionId = iprot.readI64() + else: + iprot.skip(ftype) + elif fid == 2: + if ftype == TType.MAP: + self.rulesChange = {} + (_ktype855, _vtype856, _size854) = iprot.readMapBegin() + for _i858 in range(_size854): + _key859 = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString() + _val860 = iprot.readBool() + self.rulesChange[_key859] = _val860 + iprot.readMapEnd() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec])) + return + oprot.writeStructBegin('SetRulesReq') + if self.sessionId is not None: + oprot.writeFieldBegin('sessionId', TType.I64, 1) + oprot.writeI64(self.sessionId) + oprot.writeFieldEnd() + if self.rulesChange is not None: + oprot.writeFieldBegin('rulesChange', TType.MAP, 2) + oprot.writeMapBegin(TType.STRING, TType.BOOL, len(self.rulesChange)) + for kiter861, viter862 in self.rulesChange.items(): + oprot.writeString(kiter861.encode('utf-8') if sys.version_info[0] == 2 else kiter861) + oprot.writeBool(viter862) + oprot.writeMapEnd() + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + if self.sessionId is None: + raise TProtocolException(message='Required field sessionId is unset!') + if self.rulesChange is None: + raise TProtocolException(message='Required field rulesChange is unset!') + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) all_structs.append(Status) Status.thrift_spec = ( None, # 0 @@ -8376,6 +8928,12 @@ def __ne__(self, other): (2, TType.STRING, 'message', 'UTF8', None, ), # 2 (3, TType.LIST, 'subStatus', (TType.STRUCT, [Status, None], False), None, ), # 3 ) +all_structs.append(UDFClassPair) +UDFClassPair.thrift_spec = ( + None, # 0 + (1, TType.STRING, 'name', 'UTF8', None, ), # 1 + (2, TType.STRING, 'classPath', 'UTF8', None, ), # 2 +) all_structs.append(OpenSessionReq) OpenSessionReq.thrift_spec = ( None, # 0 @@ -8621,9 +9179,11 @@ def __ne__(self, other): (22, TType.I64, 'jobId', None, None, ), # 22 (23, TType.I32, 'jobState', None, None, ), # 23 (24, TType.LIST, 'jobIdList', (TType.I64, None, False), None, ), # 24 - (25, TType.STRING, 'configValue', 'UTF8', None, ), # 25 + (25, TType.MAP, 'configs', (TType.STRING, 'UTF8', TType.STRING, 'UTF8', False), None, ), # 25 (26, TType.STRING, 'loadCsvPath', 'UTF8', None, ), # 26 (27, TType.LIST, 'sessionIDList', (TType.I64, None, False), None, ), # 27 + (28, TType.MAP, 'rules', (TType.STRING, 'UTF8', TType.BOOL, None, False), None, ), # 28 + (29, TType.STRING, 'UDFModulePath', 'UTF8', None, ), # 29 ) all_structs.append(UpdateUserReq) UpdateUserReq.thrift_spec = ( @@ -8779,6 +9339,21 @@ def __ne__(self, other): (3, TType.I64, 'recordsNum', None, None, ), # 3 (4, TType.STRING, 'parseErrorMsg', 'UTF8', None, ), # 4 ) +all_structs.append(LoadUDFReq) +LoadUDFReq.thrift_spec = ( + None, # 0 + (1, TType.I64, 'sessionId', None, None, ), # 1 + (2, TType.STRING, 'statement', 'UTF8', None, ), # 2 + (3, TType.STRING, 'udfFile', 'BINARY', None, ), # 3 + (4, TType.BOOL, 'isRemote', None, None, ), # 4 +) +all_structs.append(LoadUDFResp) +LoadUDFResp.thrift_spec = ( + None, # 0 + (1, TType.STRUCT, 'status', [Status, None], None, ), # 1 + (2, TType.STRING, 'parseErrorMsg', 'UTF8', None, ), # 2 + (3, TType.STRING, 'UDFModulePath', 'UTF8', None, ), # 3 +) all_structs.append(TaskInfo) TaskInfo.thrift_spec = ( None, # 0 @@ -8836,10 +9411,11 @@ def __ne__(self, other): RegisterTaskReq.thrift_spec = ( None, # 0 (1, TType.I64, 'sessionId', None, None, ), # 1 - (2, TType.STRING, 'name', 'UTF8', None, ), # 2 - (3, TType.STRING, 'filePath', 'UTF8', None, ), # 3 - (4, TType.STRING, 'className', 'UTF8', None, ), # 4 - (5, TType.I32, 'type', None, None, ), # 5 + (2, TType.STRING, 'filePath', 'UTF8', None, ), # 2 + (3, TType.LIST, 'UDFClassPairs', (TType.STRUCT, [UDFClassPair, None], False), None, ), # 3 + (4, TType.LIST, 'types', (TType.I32, None, False), None, ), # 4 + (5, TType.STRING, 'moduleFile', 'BINARY', None, ), # 5 + (6, TType.BOOL, 'isRemote', None, None, ), # 6 ) all_structs.append(DropTaskReq) DropTaskReq.thrift_spec = ( @@ -8957,5 +9533,22 @@ def __ne__(self, other): (1, TType.STRUCT, 'status', [Status, None], None, ), # 1 (2, TType.LIST, 'sessionIDList', (TType.I64, None, False), None, ), # 2 ) +all_structs.append(ShowRulesReq) +ShowRulesReq.thrift_spec = ( + None, # 0 + (1, TType.I64, 'sessionId', None, None, ), # 1 +) +all_structs.append(ShowRulesResp) +ShowRulesResp.thrift_spec = ( + None, # 0 + (1, TType.STRUCT, 'status', [Status, None], None, ), # 1 + (2, TType.MAP, 'rules', (TType.STRING, 'UTF8', TType.BOOL, None, False), None, ), # 2 +) +all_structs.append(SetRulesReq) +SetRulesReq.thrift_spec = ( + None, # 0 + (1, TType.I64, 'sessionId', None, None, ), # 1 + (2, TType.MAP, 'rulesChange', (TType.STRING, 'UTF8', TType.BOOL, None, False), None, ), # 2 +) fix_spec(all_structs) del all_structs diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/constant/GlobalConstant.java b/shared/src/main/java/cn/edu/tsinghua/iginx/constant/GlobalConstant.java index c3e3e0a5f0..fb9927bdfa 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/constant/GlobalConstant.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/constant/GlobalConstant.java @@ -8,4 +8,8 @@ public class GlobalConstant { public static final String CLEAR_DUMMY_DATA_CAUTION = "Unable to delete data from read-only nodes. The data of the writable nodes has been cleared."; + + public static final Long KEY_MIN_VAL = Long.MIN_VALUE + 1; + + public static final Long KEY_MAX_VAL = Long.MAX_VALUE; } diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/rest/RestIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/rest/RestIT.java index 62211e88fd..2a465ee114 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/rest/RestIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/rest/RestIT.java @@ -238,7 +238,7 @@ public void testQueryWrongTime() { public void testQueryAvg() { String json = "testQueryAvg.json"; String result = - "{\"queries\":[{\"sample_size\": 3,\"results\": [{ \"name\": \"archive.file.tracked\",\"group_by\": [{\"name\": \"type\",\"type\": \"number\"}], \"tags\": {\"dc\": [\"DC1\"],\"host\": [\"server1\"]}, \"values\": [[1359788298001,13.2],[1359788398001,123.3],[1359788408001,23.1]]}]}]}"; + "{\"queries\":[{\"sample_size\": 9,\"results\": [{ \"names\": [\"window_start\", \"window_end\", \"archive.file.tracked\"],\"group_by\": [{\"name\": \"type\",\"type\": \"number\"}], \"tags\": {\"dc\": [\"DC1\"],\"host\": [\"server1\"]}, \"values\": [[1359788298001,1359788298001],[1359788398001,1359788398001],[1359788408001,1359788408001],[1359788298001,1359788300000],[1359788398001,1359788400000],[1359788408001,1359788410000],[1359788298001,13.2],[1359788398001,123.3],[1359788408001,23.1]]}]}]}"; executeAndCompare(json, result); } @@ -246,7 +246,7 @@ public void testQueryAvg() { public void testQueryCount() { String json = "testQueryCount.json"; String result = - "{\"queries\":[{\"sample_size\": 1,\"results\": [{ \"name\": \"archive.file.tracked\",\"group_by\": [{\"name\": \"type\",\"type\": \"number\"}], \"tags\": {\"dc\": [\"DC1\"],\"host\": [\"server1\"]}, \"values\": [[1359763200001,3]]}]}]}"; + "{\"queries\":[{\"sample_size\": 3,\"results\": [{ \"names\": [\"window_start\", \"window_end\", \"archive.file.tracked\"],\"group_by\": [{\"name\": \"type\",\"type\": \"number\"}], \"tags\": {\"dc\": [\"DC1\"],\"host\": [\"server1\"]}, \"values\": [[1359763200001,1359763200001],[1359763200001,1359849600000],[1359763200001,3]]}]}]}"; executeAndCompare(json, result); } @@ -254,7 +254,7 @@ public void testQueryCount() { public void testQueryFirst() { String json = "testQueryFirst.json"; String result = - "{\"queries\":[{\"sample_size\": 1,\"results\": [{ \"name\": \"archive.file.tracked\",\"group_by\": [{\"name\": \"type\",\"type\": \"number\"}], \"tags\": {\"dc\": [\"DC1\"],\"host\": [\"server1\"]}, \"values\": [[1359763200001,13.2]]}]}]}"; + "{\"queries\":[{\"sample_size\": 3,\"results\": [{ \"names\": [\"window_start\", \"window_end\", \"archive.file.tracked\"],\"group_by\": [{\"name\": \"type\",\"type\": \"number\"}], \"tags\": {\"dc\": [\"DC1\"],\"host\": [\"server1\"]}, \"values\": [[1359763200001,1359763200001],[1359763200001,1359936000000],[1359763200001,13.2]]}]}]}"; executeAndCompare(json, result); } @@ -262,7 +262,7 @@ public void testQueryFirst() { public void testQueryLast() { String json = "testQueryLast.json"; String result = - "{\"queries\":[{\"sample_size\": 1,\"results\": [{ \"name\": \"archive.file.tracked\",\"group_by\": [{\"name\": \"type\",\"type\": \"number\"}], \"tags\": {\"dc\": [\"DC1\"],\"host\": [\"server1\"]}, \"values\": [[1359763200001,23.1]]}]}]}"; + "{\"queries\":[{\"sample_size\": 3,\"results\": [{ \"names\": [\"window_start\", \"window_end\", \"archive.file.tracked\"],\"group_by\": [{\"name\": \"type\",\"type\": \"number\"}], \"tags\": {\"dc\": [\"DC1\"],\"host\": [\"server1\"]}, \"values\": [[1359763200001,1359763200001],[1359763200001,1359936000000],[1359763200001,23.1]]}]}]}"; executeAndCompare(json, result); } @@ -270,7 +270,7 @@ public void testQueryLast() { public void testQueryMax() { String json = "testQueryMax.json"; String result = - "{\"queries\":[{\"sample_size\": 1,\"results\": [{ \"name\": \"archive.file.tracked\",\"group_by\": [{\"name\": \"type\",\"type\": \"number\"}], \"tags\": {\"dc\": [\"DC1\"],\"host\": [\"server1\"]}, \"values\": [[1359763200001,123.3]]}]}]}"; + "{\"queries\":[{\"sample_size\": 3,\"results\": [{ \"names\": [\"window_start\", \"window_end\", \"archive.file.tracked\"],\"group_by\": [{\"name\": \"type\",\"type\": \"number\"}], \"tags\": {\"dc\": [\"DC1\"],\"host\": [\"server1\"]}, \"values\": [[1359763200001,1359763200001],[1359763200001,1359936000000],[1359763200001,123.3]]}]}]}"; executeAndCompare(json, result); } @@ -278,7 +278,7 @@ public void testQueryMax() { public void testQueryMin() { String json = "testQueryMin.json"; String result = - "{\"queries\":[{\"sample_size\": 1,\"results\": [{ \"name\": \"archive.file.tracked\",\"group_by\": [{\"name\": \"type\",\"type\": \"number\"}], \"tags\": {\"dc\": [\"DC1\"],\"host\": [\"server1\"]}, \"values\": [[1359763200001,13.2]]}]}]}"; + "{\"queries\":[{\"sample_size\": 3,\"results\": [{ \"names\": [\"window_start\", \"window_end\", \"archive.file.tracked\"],\"group_by\": [{\"name\": \"type\",\"type\": \"number\"}], \"tags\": {\"dc\": [\"DC1\"],\"host\": [\"server1\"]}, \"values\": [[1359763200001,1359763200001],[1359763200001,1359936000000],[1359763200001,13.2]]}]}]}"; executeAndCompare(json, result); } @@ -286,7 +286,7 @@ public void testQueryMin() { public void testQuerySum() { String json = "testQuerySum.json"; String result = - "{\"queries\":[{\"sample_size\": 1,\"results\": [{ \"name\": \"archive.file.tracked\",\"group_by\": [{\"name\": \"type\",\"type\": \"number\"}], \"tags\": {\"dc\": [\"DC1\"],\"host\": [\"server1\"]}, \"values\": [[1359763200001,159.6]]}]}]}"; + "{\"queries\":[{\"sample_size\": 3,\"results\": [{ \"names\": [\"window_start\", \"window_end\", \"archive.file.tracked\"],\"group_by\": [{\"name\": \"type\",\"type\": \"number\"}], \"tags\": {\"dc\": [\"DC1\"],\"host\": [\"server1\"]}, \"values\": [[1359763200001,1359763200001],[1359763200001,1359936000000],[1359763200001,159.6]]}]}]}"; executeAndCompare(json, result); } diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/NewSessionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/NewSessionIT.java index 8b16ad9f40..a5a2a7b49e 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/NewSessionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/NewSessionIT.java @@ -1,5 +1,7 @@ package cn.edu.tsinghua.iginx.integration.func.session; +import static cn.edu.tsinghua.iginx.engine.shared.Constants.WINDOW_END_COL; +import static cn.edu.tsinghua.iginx.engine.shared.Constants.WINDOW_START_COL; import static cn.edu.tsinghua.iginx.integration.controller.Controller.SUPPORT_KEY; import static cn.edu.tsinghua.iginx.integration.controller.Controller.clearAllData; import static cn.edu.tsinghua.iginx.integration.func.session.InsertAPIType.*; @@ -638,6 +640,9 @@ public void testAggregateQuery() { @Test public void testDownsampleQuery() { List paths = Arrays.asList("us.d1.s2", "us.d1.s3", "us.d1.s4", "us.d1.s5"); + List resPaths = + Arrays.asList( + WINDOW_START_COL, WINDOW_END_COL, "us.d1.s2", "us.d1.s3", "us.d1.s4", "us.d1.s5"); List types = Arrays.asList(DataType.INTEGER, DataType.LONG, DataType.FLOAT, DataType.DOUBLE); List keys = Arrays.asList(0L, 4000L, 8000L, 12000L); @@ -658,72 +663,114 @@ public void testDownsampleQuery() { new TestDataSection( keys, types, - paths.stream().map(s -> "max(" + s + ")").collect(Collectors.toList()), + resPaths.stream() + .map( + s -> + s.equals(WINDOW_START_COL) || s.equals(WINDOW_END_COL) + ? s + : "max(" + s + ")") + .collect(Collectors.toList()), Arrays.asList( - Arrays.asList(3999, 3999L, 3999.1f, 3999.2d), - Arrays.asList(7999, 7999L, 7999.1f, 7999.2d), - Arrays.asList(11999, 11999L, 11999.1f, 11999.2d), - Arrays.asList(15999, 15999L, 15999.1f, 15999.2d)), + Arrays.asList(0L, 3999L, 3999, 3999L, 3999.1f, 3999.2d), + Arrays.asList(4000L, 7999L, 7999, 7999L, 7999.1f, 7999.2d), + Arrays.asList(8000L, 11999L, 11999, 11999L, 11999.1f, 11999.2d), + Arrays.asList(12000L, 15999L, 15999, 15999L, 15999.1f, 15999.2d)), baseDataSection.getTagsList()), new TestDataSection( keys, types, - paths.stream().map(s -> "min(" + s + ")").collect(Collectors.toList()), + resPaths.stream() + .map( + s -> + s.equals(WINDOW_START_COL) || s.equals(WINDOW_END_COL) + ? s + : "min(" + s + ")") + .collect(Collectors.toList()), Arrays.asList( - Arrays.asList(0, 0L, 0.1f, 0.2d), - Arrays.asList(4000, 4000L, 4000.1f, 4000.2d), - Arrays.asList(8000, 8000L, 8000.1f, 8000.2d), - Arrays.asList(12000, 12000L, 12000.1f, 12000.2d)), + Arrays.asList(0L, 3999L, 0, 0L, 0.1f, 0.2d), + Arrays.asList(4000L, 7999L, 4000, 4000L, 4000.1f, 4000.2d), + Arrays.asList(8000L, 11999L, 8000, 8000L, 8000.1f, 8000.2d), + Arrays.asList(12000L, 15999L, 12000, 12000L, 12000.1f, 12000.2d)), baseDataSection.getTagsList()), new TestDataSection( keys, types, - paths.stream().map(s -> "sum(" + s + ")").collect(Collectors.toList()), + resPaths.stream() + .map( + s -> + s.equals(WINDOW_START_COL) || s.equals(WINDOW_END_COL) + ? s + : "sum(" + s + ")") + .collect(Collectors.toList()), Arrays.asList( - Arrays.asList(7998000L, 7998000L, 7998400.0d, 7998800.0d), - Arrays.asList(23998000L, 23998000L, 23998400.0d, 23998800.0d), - Arrays.asList(39998000L, 39998000L, 39998400.0d, 39998800.0d), - Arrays.asList(55998000L, 55998000L, 55998400.0d, 55998800.0d)), + Arrays.asList(0L, 3999L, 7998000L, 7998000L, 7998400.0d, 7998800.0d), + Arrays.asList(4000L, 7999L, 23998000L, 23998000L, 23998400.0d, 23998800.0d), + Arrays.asList(8000L, 11999L, 39998000L, 39998000L, 39998400.0d, 39998800.0d), + Arrays.asList(12000L, 15999L, 55998000L, 55998000L, 55998400.0d, 55998800.0d)), baseDataSection.getTagsList()), new TestDataSection( keys, types, - paths.stream().map(s -> "count(" + s + ")").collect(Collectors.toList()), + resPaths.stream() + .map( + s -> + s.equals(WINDOW_START_COL) || s.equals(WINDOW_END_COL) + ? s + : "count(" + s + ")") + .collect(Collectors.toList()), Arrays.asList( - Arrays.asList(4000L, 4000L, 4000L, 4000L), - Arrays.asList(4000L, 4000L, 4000L, 4000L), - Arrays.asList(4000L, 4000L, 4000L, 4000L), - Arrays.asList(4000L, 4000L, 4000L, 4000L)), + Arrays.asList(0L, 3999L, 4000L, 4000L, 4000L, 4000L), + Arrays.asList(4000L, 7999L, 4000L, 4000L, 4000L, 4000L), + Arrays.asList(8000L, 11999L, 4000L, 4000L, 4000L, 4000L), + Arrays.asList(12000L, 15999L, 4000L, 4000L, 4000L, 4000L)), baseDataSection.getTagsList()), new TestDataSection( keys, types, - paths.stream().map(s -> "avg(" + s + ")").collect(Collectors.toList()), + resPaths.stream() + .map( + s -> + s.equals(WINDOW_START_COL) || s.equals(WINDOW_END_COL) + ? s + : "avg(" + s + ")") + .collect(Collectors.toList()), Arrays.asList( - Arrays.asList(1999.5d, 1999.5d, 1999.6d, 1999.7d), - Arrays.asList(5999.5d, 5999.5d, 5999.6d, 5999.7d), - Arrays.asList(9999.5d, 9999.5d, 9999.6d, 9999.7d), - Arrays.asList(13999.5d, 13999.5d, 13999.6d, 13999.7d)), + Arrays.asList(0L, 3999L, 1999.5d, 1999.5d, 1999.6d, 1999.7d), + Arrays.asList(4000L, 7999L, 5999.5d, 5999.5d, 5999.6d, 5999.7d), + Arrays.asList(8000L, 11999L, 9999.5d, 9999.5d, 9999.6d, 9999.7d), + Arrays.asList(12000L, 15999L, 13999.5d, 13999.5d, 13999.6d, 13999.7d)), baseDataSection.getTagsList()), new TestDataSection( keys, types, - paths.stream().map(s -> "first_value(" + s + ")").collect(Collectors.toList()), + resPaths.stream() + .map( + s -> + s.equals(WINDOW_START_COL) || s.equals(WINDOW_END_COL) + ? s + : "first_value(" + s + ")") + .collect(Collectors.toList()), Arrays.asList( - Arrays.asList(0, 0L, 0.1f, 0.2d), - Arrays.asList(4000, 4000L, 4000.1f, 4000.2d), - Arrays.asList(8000, 8000L, 8000.1f, 8000.2d), - Arrays.asList(12000, 12000L, 12000.1f, 12000.2d)), + Arrays.asList(0L, 3999L, 0, 0L, 0.1f, 0.2d), + Arrays.asList(4000L, 7999L, 4000, 4000L, 4000.1f, 4000.2d), + Arrays.asList(8000L, 11999L, 8000, 8000L, 8000.1f, 8000.2d), + Arrays.asList(12000L, 15999L, 12000, 12000L, 12000.1f, 12000.2d)), baseDataSection.getTagsList()), new TestDataSection( keys, types, - paths.stream().map(s -> "last_value(" + s + ")").collect(Collectors.toList()), + resPaths.stream() + .map( + s -> + s.equals(WINDOW_START_COL) || s.equals(WINDOW_END_COL) + ? s + : "last_value(" + s + ")") + .collect(Collectors.toList()), Arrays.asList( - Arrays.asList(3999, 3999L, 3999.1f, 3999.2d), - Arrays.asList(7999, 7999L, 7999.1f, 7999.2d), - Arrays.asList(11999, 11999L, 11999.1f, 11999.2d), - Arrays.asList(15999, 15999L, 15999.1f, 15999.2d)), + Arrays.asList(0L, 3999L, 3999, 3999L, 3999.1f, 3999.2d), + Arrays.asList(4000L, 7999L, 7999, 7999L, 7999.1f, 7999.2d), + Arrays.asList(8000L, 11999L, 11999, 11999L, 11999.1f, 11999.2d), + Arrays.asList(12000L, 15999L, 15999, 15999L, 15999.1f, 15999.2d)), baseDataSection.getTagsList())); for (int i = 0; i < aggregateTypes.size(); i++) { @@ -739,6 +786,154 @@ public void testDownsampleQuery() { } } + @Test + public void testDownsampleQueryNoInterval() { + List paths = Arrays.asList("us.d1.s2", "us.d1.s3", "us.d1.s4", "us.d1.s5"); + List resPaths = + Arrays.asList( + WINDOW_START_COL, WINDOW_END_COL, "us.d1.s2", "us.d1.s3", "us.d1.s4", "us.d1.s5"); + List types = + Arrays.asList(DataType.INTEGER, DataType.LONG, DataType.FLOAT, DataType.DOUBLE); + List keys = Arrays.asList(0L, 4000L, 8000L, 12000L); + + List aggregateTypes = + Arrays.asList( + AggregateType.MAX, + AggregateType.MIN, + AggregateType.SUM, + AggregateType.COUNT, + AggregateType.AVG, + AggregateType.FIRST_VALUE, + AggregateType.LAST_VALUE); + long precision = 4000; + + List expectedResults = + Arrays.asList( + new TestDataSection( + keys, + types, + resPaths.stream() + .map( + s -> + s.equals(WINDOW_START_COL) || s.equals(WINDOW_END_COL) + ? s + : "max(" + s + ")") + .collect(Collectors.toList()), + Arrays.asList( + Arrays.asList(0L, 3999L, 3999, 3999L, 3999.1f, 3999.2d), + Arrays.asList(4000L, 7999L, 7999, 7999L, 7999.1f, 7999.2d), + Arrays.asList(8000L, 11999L, 11999, 11999L, 11999.1f, 11999.2d), + Arrays.asList(12000L, 15999L, 15999, 15999L, 15999.1f, 15999.2d)), + baseDataSection.getTagsList()), + new TestDataSection( + keys, + types, + resPaths.stream() + .map( + s -> + s.equals(WINDOW_START_COL) || s.equals(WINDOW_END_COL) + ? s + : "min(" + s + ")") + .collect(Collectors.toList()), + Arrays.asList( + Arrays.asList(0L, 3999L, 0, 0L, 0.1f, 0.2d), + Arrays.asList(4000L, 7999L, 4000, 4000L, 4000.1f, 4000.2d), + Arrays.asList(8000L, 11999L, 8000, 8000L, 8000.1f, 8000.2d), + Arrays.asList(12000L, 15999L, 12000, 12000L, 12000.1f, 12000.2d)), + baseDataSection.getTagsList()), + new TestDataSection( + keys, + types, + resPaths.stream() + .map( + s -> + s.equals(WINDOW_START_COL) || s.equals(WINDOW_END_COL) + ? s + : "sum(" + s + ")") + .collect(Collectors.toList()), + Arrays.asList( + Arrays.asList(0L, 3999L, 7998000L, 7998000L, 7998400.0d, 7998800.0d), + Arrays.asList(4000L, 7999L, 23998000L, 23998000L, 23998400.0d, 23998800.0d), + Arrays.asList(8000L, 11999L, 39998000L, 39998000L, 39998400.0d, 39998800.0d), + Arrays.asList(12000L, 15999L, 55998000L, 55998000L, 55998400.0d, 55998800.0d)), + baseDataSection.getTagsList()), + new TestDataSection( + keys, + types, + resPaths.stream() + .map( + s -> + s.equals(WINDOW_START_COL) || s.equals(WINDOW_END_COL) + ? s + : "count(" + s + ")") + .collect(Collectors.toList()), + Arrays.asList( + Arrays.asList(0L, 3999L, 4000L, 4000L, 4000L, 4000L), + Arrays.asList(4000L, 7999L, 4000L, 4000L, 4000L, 4000L), + Arrays.asList(8000L, 11999L, 4000L, 4000L, 4000L, 4000L), + Arrays.asList(12000L, 15999L, 4000L, 4000L, 4000L, 4000L)), + baseDataSection.getTagsList()), + new TestDataSection( + keys, + types, + resPaths.stream() + .map( + s -> + s.equals(WINDOW_START_COL) || s.equals(WINDOW_END_COL) + ? s + : "avg(" + s + ")") + .collect(Collectors.toList()), + Arrays.asList( + Arrays.asList(0L, 3999L, 1999.5d, 1999.5d, 1999.6d, 1999.7d), + Arrays.asList(4000L, 7999L, 5999.5d, 5999.5d, 5999.6d, 5999.7d), + Arrays.asList(8000L, 11999L, 9999.5d, 9999.5d, 9999.6d, 9999.7d), + Arrays.asList(12000L, 15999L, 13999.5d, 13999.5d, 13999.6d, 13999.7d)), + baseDataSection.getTagsList()), + new TestDataSection( + keys, + types, + resPaths.stream() + .map( + s -> + s.equals(WINDOW_START_COL) || s.equals(WINDOW_END_COL) + ? s + : "first_value(" + s + ")") + .collect(Collectors.toList()), + Arrays.asList( + Arrays.asList(0L, 3999L, 0, 0L, 0.1f, 0.2d), + Arrays.asList(4000L, 7999L, 4000, 4000L, 4000.1f, 4000.2d), + Arrays.asList(8000L, 11999L, 8000, 8000L, 8000.1f, 8000.2d), + Arrays.asList(12000L, 15999L, 12000, 12000L, 12000.1f, 12000.2d)), + baseDataSection.getTagsList()), + new TestDataSection( + keys, + types, + resPaths.stream() + .map( + s -> + s.equals(WINDOW_START_COL) || s.equals(WINDOW_END_COL) + ? s + : "last_value(" + s + ")") + .collect(Collectors.toList()), + Arrays.asList( + Arrays.asList(0L, 3999L, 3999, 3999L, 3999.1f, 3999.2d), + Arrays.asList(4000L, 7999L, 7999, 7999L, 7999.1f, 7999.2d), + Arrays.asList(8000L, 11999L, 11999, 11999L, 11999.1f, 11999.2d), + Arrays.asList(12000L, 15999L, 15999, 15999L, 15999.1f, 15999.2d)), + baseDataSection.getTagsList())); + + for (int i = 0; i < aggregateTypes.size(); i++) { + AggregateType type = aggregateTypes.get(i); + try { + SessionQueryDataSet dataSet = conn.downsampleQuery(paths, type, precision); + compare(expectedResults.get(i), dataSet); + } catch (SessionException e) { + LOGGER.error("execute downsample query failed, AggType={}, Precision={}", type, precision); + fail(); + } + } + } + @Test public void testQueryAfterDelete() { if (!isAbleToDelete) return; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/PySessionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/PySessionIT.java index a38caa3f97..8b8883b258 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/PySessionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/PySessionIT.java @@ -46,7 +46,7 @@ public class PySessionIT { protected static String defaultTestPass = "root"; private static final Config config = ConfigDescriptor.getInstance().getConfig(); - private static String pythonCMD = config.getPythonCMD(); + private static String pythonCMD = "python"; private static boolean isAbleToDelete = true; private static PythonInterpreter interpreter; @@ -164,9 +164,37 @@ public void testDownSampleQuery() { } // 检查Python脚本的输出是否符合预期 String expected = - " key count(test.a.a) count(test.a.b) count(test.b.b) count(test.c.c)\n" - + "0 0 1 1 1 1\n" - + "1 3 1 1 1 1\n"; + " key window_start window_end count(test.a.a) count(test.a.b) \\\n" + + "0 0 0 2 1 1 \n" + + "1 3 3 5 1 1 \n" + + "\n" + + " count(test.b.b) count(test.c.c) \n" + + "0 1 1 \n" + + "1 1 1 \n"; + assertEquals(expected, result); + } + + @Test + public void testDownSampleQueryNoInterval() { + String result = ""; + try { + // 设置Python脚本路径 + logger.info("Test downsample query without time interval"); + result = runPythonScript("downsampleQueryNoInterval"); + logger.info(result); + } catch (IOException | InterruptedException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + // 检查Python脚本的输出是否符合预期 + String expected = + " key window_start window_end count(test.a.a) count(test.a.b) \\\n" + + "0 0 0 2 1 1 \n" + + "1 3 3 5 1 1 \n" + + "\n" + + " count(test.b.b) count(test.c.c) \n" + + "0 1 1 \n" + + "1 1 1 \n"; assertEquals(expected, result); } diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/SessionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/SessionIT.java index a83297ee1e..dc3dc2b0c9 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/SessionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/SessionIT.java @@ -522,7 +522,8 @@ public void sessionTest() throws SessionException, InterruptedException { long dsStartKey = delDsAvgDataSet.getKeys()[i]; assertEquals(START_KEY + i * PRECISION, dsStartKey); List dsResult = delDsAvgDataSet.getValues().get(i); - for (int j = 0; j < delDsResPaths.size(); j++) { + // j starts from 2 to skip WINDOW_START & WINDOW_END + for (int j = 2; j < delDsResPaths.size(); j++) { long dsEndKey = Math.min((START_KEY + (i + 1) * PRECISION - 1), END_KEY); double delDsAvg = (dsStartKey + dsEndKey) / 2.0; int pathNum = getPathNum(delDsResPaths.get(j)); @@ -636,7 +637,8 @@ public void sessionTest() throws SessionException, InterruptedException { long dsKey = dsDelDataInColSet.getKeys()[i]; assertEquals(START_KEY + i * PRECISION, dsKey); List dsResult = dsDelDataInColSet.getValues().get(i); - for (int j = 0; j < dsDelDataResPaths.size(); j++) { + // j starts from 2 to skip WINDOW_START & WINDOW_END + for (int j = 2; j < dsDelDataResPaths.size(); j++) { long maxNum = Math.min((START_KEY + (i + 1) * PRECISION - 1), END_KEY); double avg = (dsKey + maxNum) / 2.0; int pathNum = getPathNum(dsDelDataResPaths.get(j)); diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/SessionV2IT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/SessionV2IT.java index 2a3771bf83..1b3dc26691 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/SessionV2IT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/SessionV2IT.java @@ -1,5 +1,7 @@ package cn.edu.tsinghua.iginx.integration.func.session; +import static cn.edu.tsinghua.iginx.engine.shared.Constants.WINDOW_END_COL; +import static cn.edu.tsinghua.iginx.engine.shared.Constants.WINDOW_START_COL; import static cn.edu.tsinghua.iginx.integration.controller.Controller.SUPPORT_KEY; import static cn.edu.tsinghua.iginx.thrift.StorageEngineType.influxdb; import static org.junit.Assert.*; @@ -616,6 +618,22 @@ public void testDownsampleQuery() { .startKey(startKey) .endKey(endKey + (endKey - startKey)) .build(); + executeDownsampleQuery(query); + } + + @Test + public void testDownsampleQueryNoInterval() { + Query query = + DownsampleQuery.builder() + .addMeasurement("test.session.v2.long") + .addMeasurement("test.session.v2.double") + .aggregate(AggregateType.SUM) + .precision((endKey - startKey) / 10) + .build(); + executeDownsampleQuery(query); + } + + private void executeDownsampleQuery(Query query) { IginXTable table = queryClient.query(query); if (!needCompareResult) { return; @@ -624,7 +642,7 @@ public void testDownsampleQuery() { IginXHeader header = table.getHeader(); assertTrue(header.hasTimestamp()); List columns = header.getColumns(); - assertEquals(2, columns.size()); + assertEquals(4, columns.size()); for (IginXColumn column : columns) { switch (column.getName()) { case "sum(test.session.v2.long)": @@ -633,6 +651,9 @@ public void testDownsampleQuery() { case "sum(test.session.v2.double)": assertEquals(DataType.DOUBLE, column.getDataType()); break; + case WINDOW_START_COL: + case WINDOW_END_COL: + break; default: fail(); } diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/sql/SQLSessionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/sql/SQLSessionIT.java index 1c1f7ec600..27a94c7edf 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/sql/SQLSessionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/sql/SQLSessionIT.java @@ -941,34 +941,34 @@ public void testDistinct() { executor.executeAndCompare(statement, expected); statement = - "SELECT COUNT(a), AVG(a), SUM(a), MIN(a), MAX(a) FROM test OVER (RANGE 2 IN (0, 10]);"; - expected = - "ResultSets:\n" - + "+---+-------------+-----------+-----------+-----------+-----------+\n" - + "|key|count(test.a)|avg(test.a)|sum(test.a)|min(test.a)|max(test.a)|\n" - + "+---+-------------+-----------+-----------+-----------+-----------+\n" - + "| 1| 2| 1.5| 3| 1| 2|\n" - + "| 3| 2| 2.5| 5| 2| 3|\n" - + "| 5| 2| 3.0| 6| 3| 3|\n" - + "| 7| 2| 4.0| 8| 4| 4|\n" - + "| 9| 2| 4.0| 8| 4| 4|\n" - + "+---+-------------+-----------+-----------+-----------+-----------+\n" + "SELECT COUNT(a), AVG(a), SUM(a), MIN(a), MAX(a) FROM test OVER WINDOW (size 2 IN (0, 10]);"; + expected = + "ResultSets:\n" + + "+---+------------+----------+-------------+-----------+-----------+-----------+-----------+\n" + + "|key|window_start|window_end|count(test.a)|avg(test.a)|sum(test.a)|min(test.a)|max(test.a)|\n" + + "+---+------------+----------+-------------+-----------+-----------+-----------+-----------+\n" + + "| 1| 1| 2| 2| 1.5| 3| 1| 2|\n" + + "| 3| 3| 4| 2| 2.5| 5| 2| 3|\n" + + "| 5| 5| 6| 2| 3.0| 6| 3| 3|\n" + + "| 7| 7| 8| 2| 4.0| 8| 4| 4|\n" + + "| 9| 9| 10| 2| 4.0| 8| 4| 4|\n" + + "+---+------------+----------+-------------+-----------+-----------+-----------+-----------+\n" + "Total line number = 5\n"; executor.executeAndCompare(statement, expected); statement = - "SELECT COUNT(DISTINCT a), AVG(DISTINCT a), SUM(DISTINCT a), MIN(DISTINCT a), MAX(DISTINCT a) FROM test OVER (RANGE 2 IN (0, 10]);"; - expected = - "ResultSets:\n" - + "+---+----------------------+--------------------+--------------------+--------------------+--------------------+\n" - + "|key|count(distinct test.a)|avg(distinct test.a)|sum(distinct test.a)|min(distinct test.a)|max(distinct test.a)|\n" - + "+---+----------------------+--------------------+--------------------+--------------------+--------------------+\n" - + "| 1| 2| 1.5| 3| 1| 2|\n" - + "| 3| 2| 2.5| 5| 2| 3|\n" - + "| 5| 1| 3.0| 3| 3| 3|\n" - + "| 7| 1| 4.0| 4| 4| 4|\n" - + "| 9| 1| 4.0| 4| 4| 4|\n" - + "+---+----------------------+--------------------+--------------------+--------------------+--------------------+\n" + "SELECT COUNT(DISTINCT a), AVG(DISTINCT a), SUM(DISTINCT a), MIN(DISTINCT a), MAX(DISTINCT a) FROM test OVER WINDOW (size 2 IN (0, 10]);"; + expected = + "ResultSets:\n" + + "+---+------------+----------+----------------------+--------------------+--------------------+--------------------+--------------------+\n" + + "|key|window_start|window_end|count(distinct test.a)|avg(distinct test.a)|sum(distinct test.a)|min(distinct test.a)|max(distinct test.a)|\n" + + "+---+------------+----------+----------------------+--------------------+--------------------+--------------------+--------------------+\n" + + "| 1| 1| 2| 2| 1.5| 3| 1| 2|\n" + + "| 3| 3| 4| 2| 2.5| 5| 2| 3|\n" + + "| 5| 5| 6| 1| 3.0| 3| 3| 3|\n" + + "| 7| 7| 8| 1| 4.0| 4| 4| 4|\n" + + "| 9| 9| 10| 1| 4.0| 4| 4| 4|\n" + + "+---+------------+----------+----------------------+--------------------+--------------------+--------------------+--------------------+\n" + "Total line number = 5\n"; executor.executeAndCompare(statement, expected); } @@ -1427,122 +1427,122 @@ public void testAggregateQuery() { @Test public void testDownSampleQuery() { - String statement = "SELECT %s(s1), %s(s4) FROM us.d1 OVER (RANGE 100 IN (0, 1000));"; + String statement = "SELECT %s(s1), %s(s4) FROM us.d1 OVER WINDOW (size 100 IN (0, 1000));"; List funcTypeList = Arrays.asList("MAX", "MIN", "FIRST_VALUE", "LAST_VALUE", "SUM", "AVG", "COUNT"); List expectedList = Arrays.asList( "ResultSets:\n" - + "+---+-------------+-------------+\n" - + "|key|max(us.d1.s1)|max(us.d1.s4)|\n" - + "+---+-------------+-------------+\n" - + "| 1| 100| 100.1|\n" - + "|101| 200| 200.1|\n" - + "|201| 300| 300.1|\n" - + "|301| 400| 400.1|\n" - + "|401| 500| 500.1|\n" - + "|501| 600| 600.1|\n" - + "|601| 700| 700.1|\n" - + "|701| 800| 800.1|\n" - + "|801| 900| 900.1|\n" - + "|901| 999| 999.1|\n" - + "+---+-------------+-------------+\n" + + "+---+------------+----------+-------------+-------------+\n" + + "|key|window_start|window_end|max(us.d1.s1)|max(us.d1.s4)|\n" + + "+---+------------+----------+-------------+-------------+\n" + + "| 1| 1| 100| 100| 100.1|\n" + + "|101| 101| 200| 200| 200.1|\n" + + "|201| 201| 300| 300| 300.1|\n" + + "|301| 301| 400| 400| 400.1|\n" + + "|401| 401| 500| 500| 500.1|\n" + + "|501| 501| 600| 600| 600.1|\n" + + "|601| 601| 700| 700| 700.1|\n" + + "|701| 701| 800| 800| 800.1|\n" + + "|801| 801| 900| 900| 900.1|\n" + + "|901| 901| 1000| 999| 999.1|\n" + + "+---+------------+----------+-------------+-------------+\n" + "Total line number = 10\n", "ResultSets:\n" - + "+---+-------------+-------------+\n" - + "|key|min(us.d1.s1)|min(us.d1.s4)|\n" - + "+---+-------------+-------------+\n" - + "| 1| 1| 1.1|\n" - + "|101| 101| 101.1|\n" - + "|201| 201| 201.1|\n" - + "|301| 301| 301.1|\n" - + "|401| 401| 401.1|\n" - + "|501| 501| 501.1|\n" - + "|601| 601| 601.1|\n" - + "|701| 701| 701.1|\n" - + "|801| 801| 801.1|\n" - + "|901| 901| 901.1|\n" - + "+---+-------------+-------------+\n" + + "+---+------------+----------+-------------+-------------+\n" + + "|key|window_start|window_end|min(us.d1.s1)|min(us.d1.s4)|\n" + + "+---+------------+----------+-------------+-------------+\n" + + "| 1| 1| 100| 1| 1.1|\n" + + "|101| 101| 200| 101| 101.1|\n" + + "|201| 201| 300| 201| 201.1|\n" + + "|301| 301| 400| 301| 301.1|\n" + + "|401| 401| 500| 401| 401.1|\n" + + "|501| 501| 600| 501| 501.1|\n" + + "|601| 601| 700| 601| 601.1|\n" + + "|701| 701| 800| 701| 701.1|\n" + + "|801| 801| 900| 801| 801.1|\n" + + "|901| 901| 1000| 901| 901.1|\n" + + "+---+------------+----------+-------------+-------------+\n" + "Total line number = 10\n", "ResultSets:\n" - + "+---+---------------------+---------------------+\n" - + "|key|first_value(us.d1.s1)|first_value(us.d1.s4)|\n" - + "+---+---------------------+---------------------+\n" - + "| 1| 1| 1.1|\n" - + "|101| 101| 101.1|\n" - + "|201| 201| 201.1|\n" - + "|301| 301| 301.1|\n" - + "|401| 401| 401.1|\n" - + "|501| 501| 501.1|\n" - + "|601| 601| 601.1|\n" - + "|701| 701| 701.1|\n" - + "|801| 801| 801.1|\n" - + "|901| 901| 901.1|\n" - + "+---+---------------------+---------------------+\n" + + "+---+------------+----------+---------------------+---------------------+\n" + + "|key|window_start|window_end|first_value(us.d1.s1)|first_value(us.d1.s4)|\n" + + "+---+------------+----------+---------------------+---------------------+\n" + + "| 1| 1| 100| 1| 1.1|\n" + + "|101| 101| 200| 101| 101.1|\n" + + "|201| 201| 300| 201| 201.1|\n" + + "|301| 301| 400| 301| 301.1|\n" + + "|401| 401| 500| 401| 401.1|\n" + + "|501| 501| 600| 501| 501.1|\n" + + "|601| 601| 700| 601| 601.1|\n" + + "|701| 701| 800| 701| 701.1|\n" + + "|801| 801| 900| 801| 801.1|\n" + + "|901| 901| 1000| 901| 901.1|\n" + + "+---+------------+----------+---------------------+---------------------+\n" + "Total line number = 10\n", "ResultSets:\n" - + "+---+--------------------+--------------------+\n" - + "|key|last_value(us.d1.s1)|last_value(us.d1.s4)|\n" - + "+---+--------------------+--------------------+\n" - + "| 1| 100| 100.1|\n" - + "|101| 200| 200.1|\n" - + "|201| 300| 300.1|\n" - + "|301| 400| 400.1|\n" - + "|401| 500| 500.1|\n" - + "|501| 600| 600.1|\n" - + "|601| 700| 700.1|\n" - + "|701| 800| 800.1|\n" - + "|801| 900| 900.1|\n" - + "|901| 999| 999.1|\n" - + "+---+--------------------+--------------------+\n" + + "+---+------------+----------+--------------------+--------------------+\n" + + "|key|window_start|window_end|last_value(us.d1.s1)|last_value(us.d1.s4)|\n" + + "+---+------------+----------+--------------------+--------------------+\n" + + "| 1| 1| 100| 100| 100.1|\n" + + "|101| 101| 200| 200| 200.1|\n" + + "|201| 201| 300| 300| 300.1|\n" + + "|301| 301| 400| 400| 400.1|\n" + + "|401| 401| 500| 500| 500.1|\n" + + "|501| 501| 600| 600| 600.1|\n" + + "|601| 601| 700| 700| 700.1|\n" + + "|701| 701| 800| 800| 800.1|\n" + + "|801| 801| 900| 900| 900.1|\n" + + "|901| 901| 1000| 999| 999.1|\n" + + "+---+------------+----------+--------------------+--------------------+\n" + "Total line number = 10\n", "ResultSets:\n" - + "+---+-------------+------------------+\n" - + "|key|sum(us.d1.s1)| sum(us.d1.s4)|\n" - + "+---+-------------+------------------+\n" - + "| 1| 5050| 5060.0|\n" - + "|101| 15050|15060.000000000022|\n" - + "|201| 25050| 25059.99999999997|\n" - + "|301| 35050| 35059.99999999994|\n" - + "|401| 45050| 45059.99999999992|\n" - + "|501| 55050| 55059.99999999991|\n" - + "|601| 65050| 65059.9999999999|\n" - + "|701| 75050| 75059.99999999999|\n" - + "|801| 85050| 85060.00000000004|\n" - + "|901| 94050| 94059.9000000001|\n" - + "+---+-------------+------------------+\n" + + "+---+------------+----------+-------------+------------------+\n" + + "|key|window_start|window_end|sum(us.d1.s1)| sum(us.d1.s4)|\n" + + "+---+------------+----------+-------------+------------------+\n" + + "| 1| 1| 100| 5050| 5060.0|\n" + + "|101| 101| 200| 15050|15060.000000000022|\n" + + "|201| 201| 300| 25050| 25059.99999999997|\n" + + "|301| 301| 400| 35050| 35059.99999999994|\n" + + "|401| 401| 500| 45050| 45059.99999999992|\n" + + "|501| 501| 600| 55050| 55059.99999999991|\n" + + "|601| 601| 700| 65050| 65059.9999999999|\n" + + "|701| 701| 800| 75050| 75059.99999999999|\n" + + "|801| 801| 900| 85050| 85060.00000000004|\n" + + "|901| 901| 1000| 94050| 94059.9000000001|\n" + + "+---+------------+----------+-------------+------------------+\n" + "Total line number = 10\n", "ResultSets:\n" - + "+---+-------------+------------------+\n" - + "|key|avg(us.d1.s1)| avg(us.d1.s4)|\n" - + "+---+-------------+------------------+\n" - + "| 1| 50.5| 50.6|\n" - + "|101| 150.5|150.60000000000022|\n" - + "|201| 250.5| 250.5999999999997|\n" - + "|301| 350.5| 350.5999999999994|\n" - + "|401| 450.5| 450.5999999999992|\n" - + "|501| 550.5| 550.5999999999991|\n" - + "|601| 650.5| 650.599999999999|\n" - + "|701| 750.5| 750.5999999999999|\n" - + "|801| 850.5| 850.6000000000005|\n" - + "|901| 950.0| 950.1000000000009|\n" - + "+---+-------------+------------------+\n" + + "+---+------------+----------+-------------+------------------+\n" + + "|key|window_start|window_end|avg(us.d1.s1)| avg(us.d1.s4)|\n" + + "+---+------------+----------+-------------+------------------+\n" + + "| 1| 1| 100| 50.5| 50.6|\n" + + "|101| 101| 200| 150.5|150.60000000000022|\n" + + "|201| 201| 300| 250.5| 250.5999999999997|\n" + + "|301| 301| 400| 350.5| 350.5999999999994|\n" + + "|401| 401| 500| 450.5| 450.5999999999992|\n" + + "|501| 501| 600| 550.5| 550.5999999999991|\n" + + "|601| 601| 700| 650.5| 650.599999999999|\n" + + "|701| 701| 800| 750.5| 750.5999999999999|\n" + + "|801| 801| 900| 850.5| 850.6000000000005|\n" + + "|901| 901| 1000| 950.0| 950.1000000000009|\n" + + "+---+------------+----------+-------------+------------------+\n" + "Total line number = 10\n", "ResultSets:\n" - + "+---+---------------+---------------+\n" - + "|key|count(us.d1.s1)|count(us.d1.s4)|\n" - + "+---+---------------+---------------+\n" - + "| 1| 100| 100|\n" - + "|101| 100| 100|\n" - + "|201| 100| 100|\n" - + "|301| 100| 100|\n" - + "|401| 100| 100|\n" - + "|501| 100| 100|\n" - + "|601| 100| 100|\n" - + "|701| 100| 100|\n" - + "|801| 100| 100|\n" - + "|901| 99| 99|\n" - + "+---+---------------+---------------+\n" + + "+---+------------+----------+---------------+---------------+\n" + + "|key|window_start|window_end|count(us.d1.s1)|count(us.d1.s4)|\n" + + "+---+------------+----------+---------------+---------------+\n" + + "| 1| 1| 100| 100| 100|\n" + + "|101| 101| 200| 100| 100|\n" + + "|201| 201| 300| 100| 100|\n" + + "|301| 301| 400| 100| 100|\n" + + "|401| 401| 500| 100| 100|\n" + + "|501| 501| 600| 100| 100|\n" + + "|601| 601| 700| 100| 100|\n" + + "|701| 701| 800| 100| 100|\n" + + "|801| 801| 900| 100| 100|\n" + + "|901| 901| 1000| 99| 99|\n" + + "+---+------------+----------+---------------+---------------+\n" + "Total line number = 10\n"); for (int i = 0; i < funcTypeList.size(); i++) { String type = funcTypeList.get(i); @@ -1555,7 +1555,7 @@ public void testDownSampleQuery() { } statement = - "explain SELECT avg(s1), count(s4) FROM us.d1 OVER (RANGE 100 IN (0, 1000) STEP 50);"; + "explain SELECT avg(s1), count(s4) FROM us.d1 OVER WINDOW (size 100 IN (0, 1000) SLIDE 50);"; assertTrue( Arrays.stream(executor.execute(statement).split("\\n")) .anyMatch(s -> s.contains("Downsample") && s.contains("avg") && s.contains("count"))); @@ -1564,73 +1564,73 @@ public void testDownSampleQuery() { @Test public void testRangeDownSampleQuery() { String statement = - "SELECT %s(s1), %s(s4) FROM us.d1 WHERE key > 600 AND s1 <= 900 OVER (RANGE 100 IN (0, 1000));"; + "SELECT %s(s1), %s(s4) FROM us.d1 WHERE key > 600 AND s1 <= 900 OVER WINDOW (size 100 IN (0, 1000));"; List funcTypeList = Arrays.asList("MAX", "MIN", "FIRST_VALUE", "LAST_VALUE", "SUM", "AVG", "COUNT"); List expectedList = Arrays.asList( "ResultSets:\n" - + "+---+-------------+-------------+\n" - + "|key|max(us.d1.s1)|max(us.d1.s4)|\n" - + "+---+-------------+-------------+\n" - + "|601| 700| 700.1|\n" - + "|701| 800| 800.1|\n" - + "|801| 900| 900.1|\n" - + "+---+-------------+-------------+\n" + + "+---+------------+----------+-------------+-------------+\n" + + "|key|window_start|window_end|max(us.d1.s1)|max(us.d1.s4)|\n" + + "+---+------------+----------+-------------+-------------+\n" + + "|601| 601| 700| 700| 700.1|\n" + + "|701| 701| 800| 800| 800.1|\n" + + "|801| 801| 900| 900| 900.1|\n" + + "+---+------------+----------+-------------+-------------+\n" + "Total line number = 3\n", "ResultSets:\n" - + "+---+-------------+-------------+\n" - + "|key|min(us.d1.s1)|min(us.d1.s4)|\n" - + "+---+-------------+-------------+\n" - + "|601| 601| 601.1|\n" - + "|701| 701| 701.1|\n" - + "|801| 801| 801.1|\n" - + "+---+-------------+-------------+\n" + + "+---+------------+----------+-------------+-------------+\n" + + "|key|window_start|window_end|min(us.d1.s1)|min(us.d1.s4)|\n" + + "+---+------------+----------+-------------+-------------+\n" + + "|601| 601| 700| 601| 601.1|\n" + + "|701| 701| 800| 701| 701.1|\n" + + "|801| 801| 900| 801| 801.1|\n" + + "+---+------------+----------+-------------+-------------+\n" + "Total line number = 3\n", "ResultSets:\n" - + "+---+---------------------+---------------------+\n" - + "|key|first_value(us.d1.s1)|first_value(us.d1.s4)|\n" - + "+---+---------------------+---------------------+\n" - + "|601| 601| 601.1|\n" - + "|701| 701| 701.1|\n" - + "|801| 801| 801.1|\n" - + "+---+---------------------+---------------------+\n" + + "+---+------------+----------+---------------------+---------------------+\n" + + "|key|window_start|window_end|first_value(us.d1.s1)|first_value(us.d1.s4)|\n" + + "+---+------------+----------+---------------------+---------------------+\n" + + "|601| 601| 700| 601| 601.1|\n" + + "|701| 701| 800| 701| 701.1|\n" + + "|801| 801| 900| 801| 801.1|\n" + + "+---+------------+----------+---------------------+---------------------+\n" + "Total line number = 3\n", "ResultSets:\n" - + "+---+--------------------+--------------------+\n" - + "|key|last_value(us.d1.s1)|last_value(us.d1.s4)|\n" - + "+---+--------------------+--------------------+\n" - + "|601| 700| 700.1|\n" - + "|701| 800| 800.1|\n" - + "|801| 900| 900.1|\n" - + "+---+--------------------+--------------------+\n" + + "+---+------------+----------+--------------------+--------------------+\n" + + "|key|window_start|window_end|last_value(us.d1.s1)|last_value(us.d1.s4)|\n" + + "+---+------------+----------+--------------------+--------------------+\n" + + "|601| 601| 700| 700| 700.1|\n" + + "|701| 701| 800| 800| 800.1|\n" + + "|801| 801| 900| 900| 900.1|\n" + + "+---+------------+----------+--------------------+--------------------+\n" + "Total line number = 3\n", "ResultSets:\n" - + "+---+-------------+-----------------+\n" - + "|key|sum(us.d1.s1)| sum(us.d1.s4)|\n" - + "+---+-------------+-----------------+\n" - + "|601| 65050| 65059.9999999999|\n" - + "|701| 75050|75059.99999999999|\n" - + "|801| 85050|85060.00000000004|\n" - + "+---+-------------+-----------------+\n" + + "+---+------------+----------+-------------+-----------------+\n" + + "|key|window_start|window_end|sum(us.d1.s1)| sum(us.d1.s4)|\n" + + "+---+------------+----------+-------------+-----------------+\n" + + "|601| 601| 700| 65050| 65059.9999999999|\n" + + "|701| 701| 800| 75050|75059.99999999999|\n" + + "|801| 801| 900| 85050|85060.00000000004|\n" + + "+---+------------+----------+-------------+-----------------+\n" + "Total line number = 3\n", "ResultSets:\n" - + "+---+-------------+-----------------+\n" - + "|key|avg(us.d1.s1)| avg(us.d1.s4)|\n" - + "+---+-------------+-----------------+\n" - + "|601| 650.5| 650.599999999999|\n" - + "|701| 750.5|750.5999999999999|\n" - + "|801| 850.5|850.6000000000005|\n" - + "+---+-------------+-----------------+\n" + + "+---+------------+----------+-------------+-----------------+\n" + + "|key|window_start|window_end|avg(us.d1.s1)| avg(us.d1.s4)|\n" + + "+---+------------+----------+-------------+-----------------+\n" + + "|601| 601| 700| 650.5| 650.599999999999|\n" + + "|701| 701| 800| 750.5|750.5999999999999|\n" + + "|801| 801| 900| 850.5|850.6000000000005|\n" + + "+---+------------+----------+-------------+-----------------+\n" + "Total line number = 3\n", "ResultSets:\n" - + "+---+---------------+---------------+\n" - + "|key|count(us.d1.s1)|count(us.d1.s4)|\n" - + "+---+---------------+---------------+\n" - + "|601| 100| 100|\n" - + "|701| 100| 100|\n" - + "|801| 100| 100|\n" - + "+---+---------------+---------------+\n" + + "+---+------------+----------+---------------+---------------+\n" + + "|key|window_start|window_end|count(us.d1.s1)|count(us.d1.s4)|\n" + + "+---+------------+----------+---------------+---------------+\n" + + "|601| 601| 700| 100| 100|\n" + + "|701| 701| 800| 100| 100|\n" + + "|801| 801| 900| 100| 100|\n" + + "+---+------------+----------+---------------+---------------+\n" + "Total line number = 3\n"); for (int i = 0; i < funcTypeList.size(); i++) { String type = funcTypeList.get(i); @@ -1641,185 +1641,186 @@ public void testRangeDownSampleQuery() { @Test public void testSlideWindowByTimeQuery() { - String statement = "SELECT %s(s1), %s(s4) FROM us.d1 OVER (RANGE 100 IN (0, 1000) STEP 50);"; + String statement = + "SELECT %s(s1), %s(s4) FROM us.d1 OVER WINDOW (size 100 IN (0, 1000) SLIDE 50);"; List funcTypeList = Arrays.asList("MAX", "MIN", "FIRST_VALUE", "LAST_VALUE", "SUM", "AVG", "COUNT"); List expectedList = Arrays.asList( "ResultSets:\n" - + "+---+-------------+-------------+\n" - + "|key|max(us.d1.s1)|max(us.d1.s4)|\n" - + "+---+-------------+-------------+\n" - + "| 1| 100| 100.1|\n" - + "| 51| 150| 150.1|\n" - + "|101| 200| 200.1|\n" - + "|151| 250| 250.1|\n" - + "|201| 300| 300.1|\n" - + "|251| 350| 350.1|\n" - + "|301| 400| 400.1|\n" - + "|351| 450| 450.1|\n" - + "|401| 500| 500.1|\n" - + "|451| 550| 550.1|\n" - + "|501| 600| 600.1|\n" - + "|551| 650| 650.1|\n" - + "|601| 700| 700.1|\n" - + "|651| 750| 750.1|\n" - + "|701| 800| 800.1|\n" - + "|751| 850| 850.1|\n" - + "|801| 900| 900.1|\n" - + "|851| 950| 950.1|\n" - + "|901| 999| 999.1|\n" - + "+---+-------------+-------------+\n" + + "+---+------------+----------+-------------+-------------+\n" + + "|key|window_start|window_end|max(us.d1.s1)|max(us.d1.s4)|\n" + + "+---+------------+----------+-------------+-------------+\n" + + "| 1| 1| 100| 100| 100.1|\n" + + "| 51| 51| 150| 150| 150.1|\n" + + "|101| 101| 200| 200| 200.1|\n" + + "|151| 151| 250| 250| 250.1|\n" + + "|201| 201| 300| 300| 300.1|\n" + + "|251| 251| 350| 350| 350.1|\n" + + "|301| 301| 400| 400| 400.1|\n" + + "|351| 351| 450| 450| 450.1|\n" + + "|401| 401| 500| 500| 500.1|\n" + + "|451| 451| 550| 550| 550.1|\n" + + "|501| 501| 600| 600| 600.1|\n" + + "|551| 551| 650| 650| 650.1|\n" + + "|601| 601| 700| 700| 700.1|\n" + + "|651| 651| 750| 750| 750.1|\n" + + "|701| 701| 800| 800| 800.1|\n" + + "|751| 751| 850| 850| 850.1|\n" + + "|801| 801| 900| 900| 900.1|\n" + + "|851| 851| 950| 950| 950.1|\n" + + "|901| 901| 1000| 999| 999.1|\n" + + "+---+------------+----------+-------------+-------------+\n" + "Total line number = 19\n", "ResultSets:\n" - + "+---+-------------+-------------+\n" - + "|key|min(us.d1.s1)|min(us.d1.s4)|\n" - + "+---+-------------+-------------+\n" - + "| 1| 1| 1.1|\n" - + "| 51| 51| 51.1|\n" - + "|101| 101| 101.1|\n" - + "|151| 151| 151.1|\n" - + "|201| 201| 201.1|\n" - + "|251| 251| 251.1|\n" - + "|301| 301| 301.1|\n" - + "|351| 351| 351.1|\n" - + "|401| 401| 401.1|\n" - + "|451| 451| 451.1|\n" - + "|501| 501| 501.1|\n" - + "|551| 551| 551.1|\n" - + "|601| 601| 601.1|\n" - + "|651| 651| 651.1|\n" - + "|701| 701| 701.1|\n" - + "|751| 751| 751.1|\n" - + "|801| 801| 801.1|\n" - + "|851| 851| 851.1|\n" - + "|901| 901| 901.1|\n" - + "+---+-------------+-------------+\n" + + "+---+------------+----------+-------------+-------------+\n" + + "|key|window_start|window_end|min(us.d1.s1)|min(us.d1.s4)|\n" + + "+---+------------+----------+-------------+-------------+\n" + + "| 1| 1| 100| 1| 1.1|\n" + + "| 51| 51| 150| 51| 51.1|\n" + + "|101| 101| 200| 101| 101.1|\n" + + "|151| 151| 250| 151| 151.1|\n" + + "|201| 201| 300| 201| 201.1|\n" + + "|251| 251| 350| 251| 251.1|\n" + + "|301| 301| 400| 301| 301.1|\n" + + "|351| 351| 450| 351| 351.1|\n" + + "|401| 401| 500| 401| 401.1|\n" + + "|451| 451| 550| 451| 451.1|\n" + + "|501| 501| 600| 501| 501.1|\n" + + "|551| 551| 650| 551| 551.1|\n" + + "|601| 601| 700| 601| 601.1|\n" + + "|651| 651| 750| 651| 651.1|\n" + + "|701| 701| 800| 701| 701.1|\n" + + "|751| 751| 850| 751| 751.1|\n" + + "|801| 801| 900| 801| 801.1|\n" + + "|851| 851| 950| 851| 851.1|\n" + + "|901| 901| 1000| 901| 901.1|\n" + + "+---+------------+----------+-------------+-------------+\n" + "Total line number = 19\n", "ResultSets:\n" - + "+---+---------------------+---------------------+\n" - + "|key|first_value(us.d1.s1)|first_value(us.d1.s4)|\n" - + "+---+---------------------+---------------------+\n" - + "| 1| 1| 1.1|\n" - + "| 51| 51| 51.1|\n" - + "|101| 101| 101.1|\n" - + "|151| 151| 151.1|\n" - + "|201| 201| 201.1|\n" - + "|251| 251| 251.1|\n" - + "|301| 301| 301.1|\n" - + "|351| 351| 351.1|\n" - + "|401| 401| 401.1|\n" - + "|451| 451| 451.1|\n" - + "|501| 501| 501.1|\n" - + "|551| 551| 551.1|\n" - + "|601| 601| 601.1|\n" - + "|651| 651| 651.1|\n" - + "|701| 701| 701.1|\n" - + "|751| 751| 751.1|\n" - + "|801| 801| 801.1|\n" - + "|851| 851| 851.1|\n" - + "|901| 901| 901.1|\n" - + "+---+---------------------+---------------------+\n" + + "+---+------------+----------+---------------------+---------------------+\n" + + "|key|window_start|window_end|first_value(us.d1.s1)|first_value(us.d1.s4)|\n" + + "+---+------------+----------+---------------------+---------------------+\n" + + "| 1| 1| 100| 1| 1.1|\n" + + "| 51| 51| 150| 51| 51.1|\n" + + "|101| 101| 200| 101| 101.1|\n" + + "|151| 151| 250| 151| 151.1|\n" + + "|201| 201| 300| 201| 201.1|\n" + + "|251| 251| 350| 251| 251.1|\n" + + "|301| 301| 400| 301| 301.1|\n" + + "|351| 351| 450| 351| 351.1|\n" + + "|401| 401| 500| 401| 401.1|\n" + + "|451| 451| 550| 451| 451.1|\n" + + "|501| 501| 600| 501| 501.1|\n" + + "|551| 551| 650| 551| 551.1|\n" + + "|601| 601| 700| 601| 601.1|\n" + + "|651| 651| 750| 651| 651.1|\n" + + "|701| 701| 800| 701| 701.1|\n" + + "|751| 751| 850| 751| 751.1|\n" + + "|801| 801| 900| 801| 801.1|\n" + + "|851| 851| 950| 851| 851.1|\n" + + "|901| 901| 1000| 901| 901.1|\n" + + "+---+------------+----------+---------------------+---------------------+\n" + "Total line number = 19\n", "ResultSets:\n" - + "+---+--------------------+--------------------+\n" - + "|key|last_value(us.d1.s1)|last_value(us.d1.s4)|\n" - + "+---+--------------------+--------------------+\n" - + "| 1| 100| 100.1|\n" - + "| 51| 150| 150.1|\n" - + "|101| 200| 200.1|\n" - + "|151| 250| 250.1|\n" - + "|201| 300| 300.1|\n" - + "|251| 350| 350.1|\n" - + "|301| 400| 400.1|\n" - + "|351| 450| 450.1|\n" - + "|401| 500| 500.1|\n" - + "|451| 550| 550.1|\n" - + "|501| 600| 600.1|\n" - + "|551| 650| 650.1|\n" - + "|601| 700| 700.1|\n" - + "|651| 750| 750.1|\n" - + "|701| 800| 800.1|\n" - + "|751| 850| 850.1|\n" - + "|801| 900| 900.1|\n" - + "|851| 950| 950.1|\n" - + "|901| 999| 999.1|\n" - + "+---+--------------------+--------------------+\n" + + "+---+------------+----------+--------------------+--------------------+\n" + + "|key|window_start|window_end|last_value(us.d1.s1)|last_value(us.d1.s4)|\n" + + "+---+------------+----------+--------------------+--------------------+\n" + + "| 1| 1| 100| 100| 100.1|\n" + + "| 51| 51| 150| 150| 150.1|\n" + + "|101| 101| 200| 200| 200.1|\n" + + "|151| 151| 250| 250| 250.1|\n" + + "|201| 201| 300| 300| 300.1|\n" + + "|251| 251| 350| 350| 350.1|\n" + + "|301| 301| 400| 400| 400.1|\n" + + "|351| 351| 450| 450| 450.1|\n" + + "|401| 401| 500| 500| 500.1|\n" + + "|451| 451| 550| 550| 550.1|\n" + + "|501| 501| 600| 600| 600.1|\n" + + "|551| 551| 650| 650| 650.1|\n" + + "|601| 601| 700| 700| 700.1|\n" + + "|651| 651| 750| 750| 750.1|\n" + + "|701| 701| 800| 800| 800.1|\n" + + "|751| 751| 850| 850| 850.1|\n" + + "|801| 801| 900| 900| 900.1|\n" + + "|851| 851| 950| 950| 950.1|\n" + + "|901| 901| 1000| 999| 999.1|\n" + + "+---+------------+----------+--------------------+--------------------+\n" + "Total line number = 19\n", "ResultSets:\n" - + "+---+-------------+------------------+\n" - + "|key|sum(us.d1.s1)| sum(us.d1.s4)|\n" - + "+---+-------------+------------------+\n" - + "| 1| 5050| 5060.0|\n" - + "| 51| 10050|10060.000000000013|\n" - + "|101| 15050|15060.000000000022|\n" - + "|151| 20050|20059.999999999996|\n" - + "|201| 25050| 25059.99999999997|\n" - + "|251| 30050|30059.999999999953|\n" - + "|301| 35050| 35059.99999999994|\n" - + "|351| 40050| 40059.99999999993|\n" - + "|401| 45050| 45059.99999999992|\n" - + "|451| 50050| 50059.99999999992|\n" - + "|501| 55050| 55059.99999999991|\n" - + "|551| 60050|60059.999999999905|\n" - + "|601| 65050| 65059.9999999999|\n" - + "|651| 70050| 70059.99999999994|\n" - + "|701| 75050| 75059.99999999999|\n" - + "|751| 80050| 80060.00000000001|\n" - + "|801| 85050| 85060.00000000004|\n" - + "|851| 90050| 90060.00000000009|\n" - + "|901| 94050| 94059.9000000001|\n" - + "+---+-------------+------------------+\n" + + "+---+------------+----------+-------------+------------------+\n" + + "|key|window_start|window_end|sum(us.d1.s1)| sum(us.d1.s4)|\n" + + "+---+------------+----------+-------------+------------------+\n" + + "| 1| 1| 100| 5050| 5060.0|\n" + + "| 51| 51| 150| 10050|10060.000000000013|\n" + + "|101| 101| 200| 15050|15060.000000000022|\n" + + "|151| 151| 250| 20050|20059.999999999996|\n" + + "|201| 201| 300| 25050| 25059.99999999997|\n" + + "|251| 251| 350| 30050|30059.999999999953|\n" + + "|301| 301| 400| 35050| 35059.99999999994|\n" + + "|351| 351| 450| 40050| 40059.99999999993|\n" + + "|401| 401| 500| 45050| 45059.99999999992|\n" + + "|451| 451| 550| 50050| 50059.99999999992|\n" + + "|501| 501| 600| 55050| 55059.99999999991|\n" + + "|551| 551| 650| 60050|60059.999999999905|\n" + + "|601| 601| 700| 65050| 65059.9999999999|\n" + + "|651| 651| 750| 70050| 70059.99999999994|\n" + + "|701| 701| 800| 75050| 75059.99999999999|\n" + + "|751| 751| 850| 80050| 80060.00000000001|\n" + + "|801| 801| 900| 85050| 85060.00000000004|\n" + + "|851| 851| 950| 90050| 90060.00000000009|\n" + + "|901| 901| 1000| 94050| 94059.9000000001|\n" + + "+---+------------+----------+-------------+------------------+\n" + "Total line number = 19\n", "ResultSets:\n" - + "+---+-------------+------------------+\n" - + "|key|avg(us.d1.s1)| avg(us.d1.s4)|\n" - + "+---+-------------+------------------+\n" - + "| 1| 50.5| 50.6|\n" - + "| 51| 100.5|100.60000000000012|\n" - + "|101| 150.5|150.60000000000022|\n" - + "|151| 200.5|200.59999999999997|\n" - + "|201| 250.5| 250.5999999999997|\n" - + "|251| 300.5| 300.5999999999995|\n" - + "|301| 350.5| 350.5999999999994|\n" - + "|351| 400.5| 400.5999999999993|\n" - + "|401| 450.5| 450.5999999999992|\n" - + "|451| 500.5| 500.5999999999992|\n" - + "|501| 550.5| 550.5999999999991|\n" - + "|551| 600.5| 600.599999999999|\n" - + "|601| 650.5| 650.599999999999|\n" - + "|651| 700.5| 700.5999999999995|\n" - + "|701| 750.5| 750.5999999999999|\n" - + "|751| 800.5| 800.6000000000001|\n" - + "|801| 850.5| 850.6000000000005|\n" - + "|851| 900.5| 900.6000000000008|\n" - + "|901| 950.0| 950.1000000000009|\n" - + "+---+-------------+------------------+\n" + + "+---+------------+----------+-------------+------------------+\n" + + "|key|window_start|window_end|avg(us.d1.s1)| avg(us.d1.s4)|\n" + + "+---+------------+----------+-------------+------------------+\n" + + "| 1| 1| 100| 50.5| 50.6|\n" + + "| 51| 51| 150| 100.5|100.60000000000012|\n" + + "|101| 101| 200| 150.5|150.60000000000022|\n" + + "|151| 151| 250| 200.5|200.59999999999997|\n" + + "|201| 201| 300| 250.5| 250.5999999999997|\n" + + "|251| 251| 350| 300.5| 300.5999999999995|\n" + + "|301| 301| 400| 350.5| 350.5999999999994|\n" + + "|351| 351| 450| 400.5| 400.5999999999993|\n" + + "|401| 401| 500| 450.5| 450.5999999999992|\n" + + "|451| 451| 550| 500.5| 500.5999999999992|\n" + + "|501| 501| 600| 550.5| 550.5999999999991|\n" + + "|551| 551| 650| 600.5| 600.599999999999|\n" + + "|601| 601| 700| 650.5| 650.599999999999|\n" + + "|651| 651| 750| 700.5| 700.5999999999995|\n" + + "|701| 701| 800| 750.5| 750.5999999999999|\n" + + "|751| 751| 850| 800.5| 800.6000000000001|\n" + + "|801| 801| 900| 850.5| 850.6000000000005|\n" + + "|851| 851| 950| 900.5| 900.6000000000008|\n" + + "|901| 901| 1000| 950.0| 950.1000000000009|\n" + + "+---+------------+----------+-------------+------------------+\n" + "Total line number = 19\n", "ResultSets:\n" - + "+---+---------------+---------------+\n" - + "|key|count(us.d1.s1)|count(us.d1.s4)|\n" - + "+---+---------------+---------------+\n" - + "| 1| 100| 100|\n" - + "| 51| 100| 100|\n" - + "|101| 100| 100|\n" - + "|151| 100| 100|\n" - + "|201| 100| 100|\n" - + "|251| 100| 100|\n" - + "|301| 100| 100|\n" - + "|351| 100| 100|\n" - + "|401| 100| 100|\n" - + "|451| 100| 100|\n" - + "|501| 100| 100|\n" - + "|551| 100| 100|\n" - + "|601| 100| 100|\n" - + "|651| 100| 100|\n" - + "|701| 100| 100|\n" - + "|751| 100| 100|\n" - + "|801| 100| 100|\n" - + "|851| 100| 100|\n" - + "|901| 99| 99|\n" - + "+---+---------------+---------------+\n" + + "+---+------------+----------+---------------+---------------+\n" + + "|key|window_start|window_end|count(us.d1.s1)|count(us.d1.s4)|\n" + + "+---+------------+----------+---------------+---------------+\n" + + "| 1| 1| 100| 100| 100|\n" + + "| 51| 51| 150| 100| 100|\n" + + "|101| 101| 200| 100| 100|\n" + + "|151| 151| 250| 100| 100|\n" + + "|201| 201| 300| 100| 100|\n" + + "|251| 251| 350| 100| 100|\n" + + "|301| 301| 400| 100| 100|\n" + + "|351| 351| 450| 100| 100|\n" + + "|401| 401| 500| 100| 100|\n" + + "|451| 451| 550| 100| 100|\n" + + "|501| 501| 600| 100| 100|\n" + + "|551| 551| 650| 100| 100|\n" + + "|601| 601| 700| 100| 100|\n" + + "|651| 651| 750| 100| 100|\n" + + "|701| 701| 800| 100| 100|\n" + + "|751| 751| 850| 100| 100|\n" + + "|801| 801| 900| 100| 100|\n" + + "|851| 851| 950| 100| 100|\n" + + "|901| 901| 1000| 99| 99|\n" + + "+---+------------+----------+---------------+---------------+\n" + "Total line number = 19\n"); for (int i = 0; i < funcTypeList.size(); i++) { String type = funcTypeList.get(i); @@ -1831,101 +1832,101 @@ public void testSlideWindowByTimeQuery() { @Test public void testRangeSlideWindowByTimeQuery() { String statement = - "SELECT %s(s1), %s(s4) FROM us.d1 WHERE key > 300 AND s1 <= 600 OVER (RANGE 100 IN (0, 1000) STEP 50);"; + "SELECT %s(s1), %s(s4) FROM us.d1 WHERE key > 300 AND s1 <= 600 OVER WINDOW (size 100 IN (0, 1000) SLIDE 50);"; List funcTypeList = Arrays.asList("MAX", "MIN", "FIRST_VALUE", "LAST_VALUE", "SUM", "AVG", "COUNT"); List expectedList = Arrays.asList( "ResultSets:\n" - + "+---+-------------+-------------+\n" - + "|key|max(us.d1.s1)|max(us.d1.s4)|\n" - + "+---+-------------+-------------+\n" - + "|251| 350| 350.1|\n" - + "|301| 400| 400.1|\n" - + "|351| 450| 450.1|\n" - + "|401| 500| 500.1|\n" - + "|451| 550| 550.1|\n" - + "|501| 600| 600.1|\n" - + "|551| 600| 600.1|\n" - + "+---+-------------+-------------+\n" + + "+---+------------+----------+-------------+-------------+\n" + + "|key|window_start|window_end|max(us.d1.s1)|max(us.d1.s4)|\n" + + "+---+------------+----------+-------------+-------------+\n" + + "|251| 251| 350| 350| 350.1|\n" + + "|301| 301| 400| 400| 400.1|\n" + + "|351| 351| 450| 450| 450.1|\n" + + "|401| 401| 500| 500| 500.1|\n" + + "|451| 451| 550| 550| 550.1|\n" + + "|501| 501| 600| 600| 600.1|\n" + + "|551| 551| 650| 600| 600.1|\n" + + "+---+------------+----------+-------------+-------------+\n" + "Total line number = 7\n", "ResultSets:\n" - + "+---+-------------+-------------+\n" - + "|key|min(us.d1.s1)|min(us.d1.s4)|\n" - + "+---+-------------+-------------+\n" - + "|251| 301| 301.1|\n" - + "|301| 301| 301.1|\n" - + "|351| 351| 351.1|\n" - + "|401| 401| 401.1|\n" - + "|451| 451| 451.1|\n" - + "|501| 501| 501.1|\n" - + "|551| 551| 551.1|\n" - + "+---+-------------+-------------+\n" + + "+---+------------+----------+-------------+-------------+\n" + + "|key|window_start|window_end|min(us.d1.s1)|min(us.d1.s4)|\n" + + "+---+------------+----------+-------------+-------------+\n" + + "|251| 251| 350| 301| 301.1|\n" + + "|301| 301| 400| 301| 301.1|\n" + + "|351| 351| 450| 351| 351.1|\n" + + "|401| 401| 500| 401| 401.1|\n" + + "|451| 451| 550| 451| 451.1|\n" + + "|501| 501| 600| 501| 501.1|\n" + + "|551| 551| 650| 551| 551.1|\n" + + "+---+------------+----------+-------------+-------------+\n" + "Total line number = 7\n", "ResultSets:\n" - + "+---+---------------------+---------------------+\n" - + "|key|first_value(us.d1.s1)|first_value(us.d1.s4)|\n" - + "+---+---------------------+---------------------+\n" - + "|251| 301| 301.1|\n" - + "|301| 301| 301.1|\n" - + "|351| 351| 351.1|\n" - + "|401| 401| 401.1|\n" - + "|451| 451| 451.1|\n" - + "|501| 501| 501.1|\n" - + "|551| 551| 551.1|\n" - + "+---+---------------------+---------------------+\n" + + "+---+------------+----------+---------------------+---------------------+\n" + + "|key|window_start|window_end|first_value(us.d1.s1)|first_value(us.d1.s4)|\n" + + "+---+------------+----------+---------------------+---------------------+\n" + + "|251| 251| 350| 301| 301.1|\n" + + "|301| 301| 400| 301| 301.1|\n" + + "|351| 351| 450| 351| 351.1|\n" + + "|401| 401| 500| 401| 401.1|\n" + + "|451| 451| 550| 451| 451.1|\n" + + "|501| 501| 600| 501| 501.1|\n" + + "|551| 551| 650| 551| 551.1|\n" + + "+---+------------+----------+---------------------+---------------------+\n" + "Total line number = 7\n", "ResultSets:\n" - + "+---+--------------------+--------------------+\n" - + "|key|last_value(us.d1.s1)|last_value(us.d1.s4)|\n" - + "+---+--------------------+--------------------+\n" - + "|251| 350| 350.1|\n" - + "|301| 400| 400.1|\n" - + "|351| 450| 450.1|\n" - + "|401| 500| 500.1|\n" - + "|451| 550| 550.1|\n" - + "|501| 600| 600.1|\n" - + "|551| 600| 600.1|\n" - + "+---+--------------------+--------------------+\n" + + "+---+------------+----------+--------------------+--------------------+\n" + + "|key|window_start|window_end|last_value(us.d1.s1)|last_value(us.d1.s4)|\n" + + "+---+------------+----------+--------------------+--------------------+\n" + + "|251| 251| 350| 350| 350.1|\n" + + "|301| 301| 400| 400| 400.1|\n" + + "|351| 351| 450| 450| 450.1|\n" + + "|401| 401| 500| 500| 500.1|\n" + + "|451| 451| 550| 550| 550.1|\n" + + "|501| 501| 600| 600| 600.1|\n" + + "|551| 551| 650| 600| 600.1|\n" + + "+---+------------+----------+--------------------+--------------------+\n" + "Total line number = 7\n", "ResultSets:\n" - + "+---+-------------+------------------+\n" - + "|key|sum(us.d1.s1)| sum(us.d1.s4)|\n" - + "+---+-------------+------------------+\n" - + "|251| 16275|16280.000000000013|\n" - + "|301| 35050| 35059.99999999994|\n" - + "|351| 40050| 40059.99999999993|\n" - + "|401| 45050| 45059.99999999992|\n" - + "|451| 50050| 50059.99999999992|\n" - + "|501| 55050| 55059.99999999991|\n" - + "|551| 28775|28779.999999999975|\n" - + "+---+-------------+------------------+\n" + + "+---+------------+----------+-------------+------------------+\n" + + "|key|window_start|window_end|sum(us.d1.s1)| sum(us.d1.s4)|\n" + + "+---+------------+----------+-------------+------------------+\n" + + "|251| 251| 350| 16275|16280.000000000013|\n" + + "|301| 301| 400| 35050| 35059.99999999994|\n" + + "|351| 351| 450| 40050| 40059.99999999993|\n" + + "|401| 401| 500| 45050| 45059.99999999992|\n" + + "|451| 451| 550| 50050| 50059.99999999992|\n" + + "|501| 501| 600| 55050| 55059.99999999991|\n" + + "|551| 551| 650| 28775|28779.999999999975|\n" + + "+---+------------+----------+-------------+------------------+\n" + "Total line number = 7\n", "ResultSets:\n" - + "+---+-------------+------------------+\n" - + "|key|avg(us.d1.s1)| avg(us.d1.s4)|\n" - + "+---+-------------+------------------+\n" - + "|251| 325.5|325.60000000000025|\n" - + "|301| 350.5| 350.5999999999994|\n" - + "|351| 400.5| 400.5999999999993|\n" - + "|401| 450.5| 450.5999999999992|\n" - + "|451| 500.5| 500.5999999999992|\n" - + "|501| 550.5| 550.5999999999991|\n" - + "|551| 575.5| 575.5999999999995|\n" - + "+---+-------------+------------------+\n" + + "+---+------------+----------+-------------+------------------+\n" + + "|key|window_start|window_end|avg(us.d1.s1)| avg(us.d1.s4)|\n" + + "+---+------------+----------+-------------+------------------+\n" + + "|251| 251| 350| 325.5|325.60000000000025|\n" + + "|301| 301| 400| 350.5| 350.5999999999994|\n" + + "|351| 351| 450| 400.5| 400.5999999999993|\n" + + "|401| 401| 500| 450.5| 450.5999999999992|\n" + + "|451| 451| 550| 500.5| 500.5999999999992|\n" + + "|501| 501| 600| 550.5| 550.5999999999991|\n" + + "|551| 551| 650| 575.5| 575.5999999999995|\n" + + "+---+------------+----------+-------------+------------------+\n" + "Total line number = 7\n", "ResultSets:\n" - + "+---+---------------+---------------+\n" - + "|key|count(us.d1.s1)|count(us.d1.s4)|\n" - + "+---+---------------+---------------+\n" - + "|251| 50| 50|\n" - + "|301| 100| 100|\n" - + "|351| 100| 100|\n" - + "|401| 100| 100|\n" - + "|451| 100| 100|\n" - + "|501| 100| 100|\n" - + "|551| 50| 50|\n" - + "+---+---------------+---------------+\n" + + "+---+------------+----------+---------------+---------------+\n" + + "|key|window_start|window_end|count(us.d1.s1)|count(us.d1.s4)|\n" + + "+---+------------+----------+---------------+---------------+\n" + + "|251| 251| 350| 50| 50|\n" + + "|301| 301| 400| 100| 100|\n" + + "|351| 351| 450| 100| 100|\n" + + "|401| 401| 500| 100| 100|\n" + + "|451| 451| 550| 100| 100|\n" + + "|501| 501| 600| 100| 100|\n" + + "|551| 551| 650| 50| 50|\n" + + "+---+------------+----------+---------------+---------------+\n" + "Total line number = 7\n"); for (int i = 0; i < funcTypeList.size(); i++) { String type = funcTypeList.get(i); @@ -1934,6 +1935,98 @@ public void testRangeSlideWindowByTimeQuery() { } } + @Test + public void testRangeSlideWindowByTimeNoIntervalQuery() { + String statement = + "SELECT %s(s1), %s(s4) FROM us.d1 WHERE key > 300 AND s1 <= 600 OVER WINDOW (SIZE 100 SLIDE 50);"; + List funcTypeList = + Arrays.asList("MAX", "MIN", "FIRST_VALUE", "LAST_VALUE", "SUM", "AVG", "COUNT"); + List expectedList = + Arrays.asList( + "ResultSets:\n" + + "+---+------------+----------+-------------+-------------+\n" + + "|key|window_start|window_end|max(us.d1.s1)|max(us.d1.s4)|\n" + + "+---+------------+----------+-------------+-------------+\n" + + "|301| 301| 400| 400| 400.1|\n" + + "|351| 351| 450| 450| 450.1|\n" + + "|401| 401| 500| 500| 500.1|\n" + + "|451| 451| 550| 550| 550.1|\n" + + "|501| 501| 600| 600| 600.1|\n" + + "+---+------------+----------+-------------+-------------+\n" + + "Total line number = 5\n", + "ResultSets:\n" + + "+---+------------+----------+-------------+-------------+\n" + + "|key|window_start|window_end|min(us.d1.s1)|min(us.d1.s4)|\n" + + "+---+------------+----------+-------------+-------------+\n" + + "|301| 301| 400| 301| 301.1|\n" + + "|351| 351| 450| 351| 351.1|\n" + + "|401| 401| 500| 401| 401.1|\n" + + "|451| 451| 550| 451| 451.1|\n" + + "|501| 501| 600| 501| 501.1|\n" + + "+---+------------+----------+-------------+-------------+\n" + + "Total line number = 5\n", + "ResultSets:\n" + + "+---+------------+----------+---------------------+---------------------+\n" + + "|key|window_start|window_end|first_value(us.d1.s1)|first_value(us.d1.s4)|\n" + + "+---+------------+----------+---------------------+---------------------+\n" + + "|301| 301| 400| 301| 301.1|\n" + + "|351| 351| 450| 351| 351.1|\n" + + "|401| 401| 500| 401| 401.1|\n" + + "|451| 451| 550| 451| 451.1|\n" + + "|501| 501| 600| 501| 501.1|\n" + + "+---+------------+----------+---------------------+---------------------+\n" + + "Total line number = 5\n", + "ResultSets:\n" + + "+---+------------+----------+--------------------+--------------------+\n" + + "|key|window_start|window_end|last_value(us.d1.s1)|last_value(us.d1.s4)|\n" + + "+---+------------+----------+--------------------+--------------------+\n" + + "|301| 301| 400| 400| 400.1|\n" + + "|351| 351| 450| 450| 450.1|\n" + + "|401| 401| 500| 500| 500.1|\n" + + "|451| 451| 550| 550| 550.1|\n" + + "|501| 501| 600| 600| 600.1|\n" + + "+---+------------+----------+--------------------+--------------------+\n" + + "Total line number = 5\n", + "ResultSets:\n" + + "+---+------------+----------+-------------+-----------------+\n" + + "|key|window_start|window_end|sum(us.d1.s1)| sum(us.d1.s4)|\n" + + "+---+------------+----------+-------------+-----------------+\n" + + "|301| 301| 400| 35050|35059.99999999994|\n" + + "|351| 351| 450| 40050|40059.99999999993|\n" + + "|401| 401| 500| 45050|45059.99999999992|\n" + + "|451| 451| 550| 50050|50059.99999999992|\n" + + "|501| 501| 600| 55050|55059.99999999991|\n" + + "+---+------------+----------+-------------+-----------------+\n" + + "Total line number = 5\n", + "ResultSets:\n" + + "+---+------------+----------+-------------+-----------------+\n" + + "|key|window_start|window_end|avg(us.d1.s1)| avg(us.d1.s4)|\n" + + "+---+------------+----------+-------------+-----------------+\n" + + "|301| 301| 400| 350.5|350.5999999999994|\n" + + "|351| 351| 450| 400.5|400.5999999999993|\n" + + "|401| 401| 500| 450.5|450.5999999999992|\n" + + "|451| 451| 550| 500.5|500.5999999999992|\n" + + "|501| 501| 600| 550.5|550.5999999999991|\n" + + "+---+------------+----------+-------------+-----------------+\n" + + "Total line number = 5\n", + "ResultSets:\n" + + "+---+------------+----------+---------------+---------------+\n" + + "|key|window_start|window_end|count(us.d1.s1)|count(us.d1.s4)|\n" + + "+---+------------+----------+---------------+---------------+\n" + + "|301| 301| 400| 100| 100|\n" + + "|351| 351| 450| 100| 100|\n" + + "|401| 401| 500| 100| 100|\n" + + "|451| 451| 550| 100| 100|\n" + + "|501| 501| 600| 100| 100|\n" + + "+---+------------+----------+---------------+---------------+\n" + + "Total line number = 5\n"); + for (int i = 0; i < funcTypeList.size(); i++) { + String type = funcTypeList.get(i); + String expected = expectedList.get(i); + executor.executeAndCompare(String.format(statement, type, type), expected); + } + } + @Test public void testDelete() { if (!isAbleToDelete) { @@ -3144,7 +3237,7 @@ public void testAlias() { @Test public void testAggregateSubQuery() { String statement = - "SELECT %s_s1 FROM (SELECT %s(s1) AS %s_s1 FROM us.d1 OVER(RANGE 60 IN [1000, 1600)));"; + "SELECT %s_s1 FROM (SELECT %s(s1) AS %s_s1 FROM us.d1 OVER WINDOW(SIZE 60 IN [1000, 1600)));"; List funcTypeList = Arrays.asList("max", "min", "sum", "avg", "count", "first_value", "last_value"); @@ -3272,7 +3365,7 @@ public void testAggregateSubQuery() { @Test public void testSelectFromAggregate() { String statement = - "SELECT `%s(us.d1.s1)` FROM (SELECT %s(s1) FROM us.d1 OVER(RANGE 60 IN [1000, 1600)));"; + "SELECT `%s(us.d1.s1)` FROM (SELECT %s(s1) FROM us.d1 OVER WINDOW(SIZE 60 IN [1000, 1600)));"; List funcTypeList = Arrays.asList("max", "min", "sum", "avg", "count", "first_value", "last_value"); @@ -3421,7 +3514,7 @@ public void testValueFilterSubQuery() { executor.executeAndCompare(statement, expected); statement = - "SELECT avg_s1 FROM (SELECT AVG(s1) AS avg_s1 FROM us.d1 OVER (RANGE 100 IN [1000, 1600))) WHERE avg_s1 > 1200;"; + "SELECT avg_s1 FROM (SELECT AVG(s1) AS avg_s1 FROM us.d1 OVER WINDOW (size 100 IN [1000, 1600))) WHERE avg_s1 > 1200;"; expected = "ResultSets:\n" + "+----+------+\n" @@ -3436,7 +3529,7 @@ public void testValueFilterSubQuery() { executor.executeAndCompare(statement, expected); statement = - "SELECT avg_s1 FROM (SELECT AVG(s1) AS avg_s1 FROM us.d1 WHERE us.d1.s1 < 1500 OVER (RANGE 100 IN [1000, 1600))) WHERE avg_s1 > 1200;"; + "SELECT avg_s1 FROM (SELECT AVG(s1) AS avg_s1 FROM us.d1 WHERE us.d1.s1 < 1500 OVER WINDOW (size 100 IN [1000, 1600))) WHERE avg_s1 > 1200;"; expected = "ResultSets:\n" + "+----+------+\n" @@ -3453,30 +3546,30 @@ public void testValueFilterSubQuery() { @Test public void testMultiSubQuery() { String statement = - "SELECT AVG(s1) AS avg_s1, SUM(s2) AS sum_s2 FROM us.d1 OVER (RANGE 10 IN [1000, 1100));"; + "SELECT AVG(s1) AS avg_s1, SUM(s2) AS sum_s2 FROM us.d1 OVER WINDOW (size 10 IN [1000, 1100));"; String expected = "ResultSets:\n" - + "+----+------+------+\n" - + "| key|avg_s1|sum_s2|\n" - + "+----+------+------+\n" - + "|1000|1004.5| 10055|\n" - + "|1010|1014.5| 10155|\n" - + "|1020|1024.5| 10255|\n" - + "|1030|1034.5| 10355|\n" - + "|1040|1044.5| 10455|\n" - + "|1050|1054.5| 10555|\n" - + "|1060|1064.5| 10655|\n" - + "|1070|1074.5| 10755|\n" - + "|1080|1084.5| 10855|\n" - + "|1090|1094.5| 10955|\n" - + "+----+------+------+\n" + + "+----+------------+----------+------+------+\n" + + "| key|window_start|window_end|avg_s1|sum_s2|\n" + + "+----+------------+----------+------+------+\n" + + "|1000| 1000| 1009|1004.5| 10055|\n" + + "|1010| 1010| 1019|1014.5| 10155|\n" + + "|1020| 1020| 1029|1024.5| 10255|\n" + + "|1030| 1030| 1039|1034.5| 10355|\n" + + "|1040| 1040| 1049|1044.5| 10455|\n" + + "|1050| 1050| 1059|1054.5| 10555|\n" + + "|1060| 1060| 1069|1064.5| 10655|\n" + + "|1070| 1070| 1079|1074.5| 10755|\n" + + "|1080| 1080| 1089|1084.5| 10855|\n" + + "|1090| 1090| 1099|1094.5| 10955|\n" + + "+----+------------+----------+------+------+\n" + "Total line number = 10\n"; executor.executeAndCompare(statement, expected); statement = "SELECT avg_s1, sum_s2 " + "FROM (SELECT AVG(s1) AS avg_s1, SUM(s2) AS sum_s2 " - + "FROM us.d1 OVER (RANGE 10 IN [1000, 1100))) " + + "FROM us.d1 OVER WINDOW (size 10 IN [1000, 1100))) " + "WHERE avg_s1 > 1020 AND sum_s2 < 10800;"; expected = "ResultSets:\n" @@ -3497,7 +3590,7 @@ public void testMultiSubQuery() { "SELECT MAX(avg_s1), MIN(sum_s2) " + "FROM (SELECT avg_s1, sum_s2 " + "FROM (SELECT AVG(s1) AS avg_s1, SUM(s2) AS sum_s2 " - + "FROM us.d1 OVER (RANGE 10 IN [1000, 1100))) " + + "FROM us.d1 OVER WINDOW (size 10 IN [1000, 1100))) " + "WHERE avg_s1 > 1020 AND sum_s2 < 10800);"; expected = "ResultSets:\n" @@ -5282,7 +5375,9 @@ public void testInsertWithSubQuery() { executor.executeAndCompare(query, expected); insert = - "INSERT INTO us.d4(key, s1, s2) VALUES (SELECT AVG(s1) AS avg_s1, SUM(s2) AS sum_s2 FROM us.d1 OVER (RANGE 10 IN [1000, 1100)));"; + "INSERT INTO us.d4(key, s1, s2) VALUES " + + "(SELECT avg_s1, sum_s2 from " + + "(SELECT AVG(s1) AS avg_s1, SUM(s2) AS sum_s2 FROM us.d1 OVER WINDOW (size 10 IN [1000, 1100))));"; executor.execute(insert); query = "SELECT s1, s2 FROM us.d4;"; @@ -5308,7 +5403,7 @@ public void testInsertWithSubQuery() { insert = "INSERT INTO us.d5(key, s1, s2) VALUES (SELECT avg_s1, sum_s2 " + "FROM (SELECT AVG(s1) AS avg_s1, SUM(s2) AS sum_s2 " - + "FROM us.d1 OVER (RANGE 10 IN [1000, 1100))) " + + "FROM us.d1 OVER WINDOW (size 10 IN [1000, 1100))) " + "WHERE avg_s1 > 1020 AND sum_s2 < 10800);"; executor.execute(insert); @@ -5332,7 +5427,7 @@ public void testInsertWithSubQuery() { "INSERT INTO us.d6(key, s1, s2) VALUES (SELECT MAX(avg_s1), MIN(sum_s2) " + "FROM (SELECT avg_s1, sum_s2 " + "FROM (SELECT AVG(s1) AS avg_s1, SUM(s2) AS sum_s2 " - + "FROM us.d1 OVER (RANGE 10 IN [1000, 1100))) " + + "FROM us.d1 OVER WINDOW (size 10 IN [1000, 1100))) " + "WHERE avg_s1 > 1020 AND sum_s2 < 10800));"; executor.execute(insert); @@ -5672,7 +5767,7 @@ public void testErrorClause() { errClause = "DELETE FROM us.d1.s1 WHERE key != 105;"; executor.executeAndCompareErrMsg(errClause, "Not support [!=] in delete clause."); - errClause = "SELECT s1 FROM us.d1 OVER (RANGE 100 IN (0, 1000));"; + errClause = "SELECT s1 FROM us.d1 OVER WINDOW (size 100 IN (0, 1000));"; executor.executeAndCompareErrMsg( errClause, "Downsample clause cannot be used without aggregate function."); @@ -5680,7 +5775,7 @@ public void testErrorClause() { executor.executeAndCompareErrMsg( errClause, "SetToSet/SetToRow/RowToRow functions can not be mixed in aggregate query."); - errClause = "SELECT s1 FROM us.d1 OVER (RANGE 100 IN (100, 10));"; + errClause = "SELECT s1 FROM us.d1 OVER WINDOW (size 100 IN (100, 10));"; executor.executeAndCompareErrMsg( errClause, "start key should be smaller than end key in key interval."); @@ -6053,19 +6148,19 @@ public void testConcurrentQuery() { + "+---+--------+\n" + "Total line number = 10\n"), new Pair<>( - "SELECT max(s1), max(s4) FROM us.d1 WHERE key > 300 AND s1 <= 600 OVER (RANGE 100 IN (0, 1000) STEP 50);", + "SELECT max(s1), max(s4) FROM us.d1 WHERE key > 300 AND s1 <= 600 OVER WINDOW (size 100 IN (0, 1000) SLIDE 50);", "ResultSets:\n" - + "+---+-------------+-------------+\n" - + "|key|max(us.d1.s1)|max(us.d1.s4)|\n" - + "+---+-------------+-------------+\n" - + "|251| 350| 350.1|\n" - + "|301| 400| 400.1|\n" - + "|351| 450| 450.1|\n" - + "|401| 500| 500.1|\n" - + "|451| 550| 550.1|\n" - + "|501| 600| 600.1|\n" - + "|551| 600| 600.1|\n" - + "+---+-------------+-------------+\n" + + "+---+------------+----------+-------------+-------------+\n" + + "|key|window_start|window_end|max(us.d1.s1)|max(us.d1.s4)|\n" + + "+---+------------+----------+-------------+-------------+\n" + + "|251| 251| 350| 350| 350.1|\n" + + "|301| 301| 400| 400| 400.1|\n" + + "|351| 351| 450| 450| 450.1|\n" + + "|401| 401| 500| 500| 500.1|\n" + + "|451| 451| 550| 550| 550.1|\n" + + "|501| 501| 600| 600| 600.1|\n" + + "|551| 551| 650| 600| 600.1|\n" + + "+---+------------+----------+-------------+-------------+\n" + "Total line number = 7\n"), new Pair<>( "select avg(test1.a), test2.d from test1 join test2 on test1.a = test2.a group by test2.d;", @@ -6785,9 +6880,9 @@ public void testFilterFragmentOptimizer() { "explain SELECT COUNT(*)\n" + "FROM (\n" + " SELECT AVG(s1) AS avg_s1, SUM(s2) AS sum_s2\n" - + " FROM us.d1 OVER (RANGE 10 IN [1000, 1100))\n" + + " FROM us.d1 OVER WINDOW (size 10 IN [1000, 1100))\n" + ")\n" - + "OVER (RANGE 20 IN [1000, 1100));", + + "OVER WINDOW (size 20 IN [1000, 1100));", "ResultSets:\n" + "+------------------------+-------------+----------------------------------------------------------------------------------------------------------------------------------------------+\n" + "| Logical Tree|Operator Type| Operator Info|\n" @@ -6844,9 +6939,9 @@ public void testFilterFragmentOptimizer() { "explain SELECT COUNT(*)\n" + "FROM (\n" + " SELECT AVG(s1) AS avg_s1, SUM(s2) AS sum_s2\n" - + " FROM us.d1 OVER (RANGE 10 IN [1000, 1100))\n" + + " FROM us.d1 OVER WINDOW (size 10 IN [1000, 1100))\n" + ")\n" - + "OVER (RANGE 20 IN [1000, 1100));", + + "OVER WINDOW (size 20 IN [1000, 1100));", "ResultSets:\n" + "+--------------------------+-------------+----------------------------------------------------------------------------------------------------------------------------------------------+\n" + "| Logical Tree|Operator Type| Operator Info|\n" diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/udf/UDFIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/udf/UDFIT.java index 428d1de1a9..5232b01045 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/udf/UDFIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/udf/UDFIT.java @@ -185,7 +185,7 @@ public void dropTasks() { @Test public void baseTests() { String udtfSQLFormat = "SELECT %s(s1) FROM us.d1 WHERE key < 200;"; - String udafSQLFormat = "SELECT %s(s1) FROM us.d1 OVER (RANGE 50 IN [0, 200));"; + String udafSQLFormat = "SELECT %s(s1) FROM us.d1 OVER WINDOW (size 50 IN [0, 200));"; String udsfSQLFormat = "SELECT %s(s1) FROM us.d1 WHERE key < 50;"; SessionExecuteSqlResult ret = tool.execute(SHOW_FUNCTION_SQL); diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/MultiConnection.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/MultiConnection.java index 0c07df7f6f..e0f816e2dd 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/MultiConnection.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/MultiConnection.java @@ -1,6 +1,6 @@ package cn.edu.tsinghua.iginx.integration.tool; -import static cn.edu.tsinghua.iginx.constant.GlobalConstant.CLEAR_DUMMY_DATA_CAUTION; +import static cn.edu.tsinghua.iginx.constant.GlobalConstant.*; import static cn.edu.tsinghua.iginx.integration.controller.Controller.*; import static org.junit.Assert.fail; @@ -162,6 +162,13 @@ public SessionAggregateQueryDataSet aggregateQuery( return null; } + // downsample query with time interval + public SessionQueryDataSet downsampleQuery( + List paths, AggregateType aggregateType, long precision) throws SessionException { + return downsampleQuery(paths, KEY_MIN_VAL, KEY_MAX_VAL, aggregateType, precision); + } + + // downsample query without time interval public SessionQueryDataSet downsampleQuery( List paths, long startKey, long endKey, AggregateType aggregateType, long precision) throws SessionException { diff --git a/test/src/test/resources/pySessionIT/tests.py b/test/src/test/resources/pySessionIT/tests.py index 983faea032..62efdb6bfd 100644 --- a/test/src/test/resources/pySessionIT/tests.py +++ b/test/src/test/resources/pySessionIT/tests.py @@ -265,9 +265,12 @@ def deleteRow(self): return retStr def downsampleQuery(self): + import pandas as pd try: dataset = self.session.downsample_query(["test.*"], start_time=0, end_time=10, type=AggregateType.COUNT, precision=3) + pd.set_option('display.max_columns', None) + pd.set_option('display.max_rows', None) retStr = str(dataset.to_df()) + "\n" except Exception as e: print(e) @@ -276,6 +279,19 @@ def downsampleQuery(self): return retStr + def downsampleQueryNoInterval(self): + import pandas as pd + try: + dataset = self.session.downsample_query_no_interval(["test.*"], type=AggregateType.COUNT, + precision=3) + pd.set_option('display.max_columns', None) + pd.set_option('display.max_rows', None) + retStr = str(dataset.to_df()) + "\n" + except Exception as e: + print(e) + exit(1) + return retStr + def exportToFile(self): try: # 将数据存入csv From 2dc19cbd07466c4545f9605967d96e7f9aa08403 Mon Sep 17 00:00:00 2001 From: An Qi Date: Fri, 7 Jun 2024 21:53:13 +0800 Subject: [PATCH 017/138] feat(parquet): show columns with pattern and tagFilter --- .../iginx/parquet/ParquetStorage.java | 2 +- .../tsinghua/iginx/parquet/exec/Executor.java | 4 ++- .../iginx/parquet/exec/LocalExecutor.java | 12 ++++++--- .../iginx/parquet/exec/RemoteExecutor.java | 25 ++++++------------- .../iginx/parquet/manager/Manager.java | 2 +- .../parquet/manager/data/DataManager.java | 11 ++++++-- .../parquet/manager/dummy/DummyManager.java | 24 ++++++------------ .../parquet/manager/dummy/EmptyManager.java | 2 +- .../parquet/manager/utils/TagKVUtils.java | 20 +++++++++++++++ .../iginx/parquet/server/ParquetWorker.java | 12 ++++----- .../edu/tsinghua/iginx/utils/StringUtils.java | 2 ++ thrift/src/main/proto/parquet.thrift | 2 +- 12 files changed, 67 insertions(+), 51 deletions(-) diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/ParquetStorage.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/ParquetStorage.java index c2bc012f09..6bc2298e71 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/ParquetStorage.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/ParquetStorage.java @@ -178,7 +178,7 @@ public TaskExecuteResult executeInsert(Insert insert, DataArea dataArea) { @Override public List getColumns(Set pattern, TagFilter tagFilter) throws PhysicalException { - return executor.getColumnsOfStorageUnit("*"); + return executor.getColumnsOfStorageUnit("*", pattern, tagFilter); } @Override diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/Executor.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/Executor.java index 16ed980af1..672f75c8b1 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/Executor.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/Executor.java @@ -27,6 +27,7 @@ import cn.edu.tsinghua.iginx.metadata.entity.KeyInterval; import cn.edu.tsinghua.iginx.utils.Pair; import java.util.List; +import java.util.Set; public interface Executor { @@ -42,7 +43,8 @@ TaskExecuteResult executeProjectTask( TaskExecuteResult executeDeleteTask( List paths, List keyRanges, TagFilter tagFilter, String storageUnit); - List getColumnsOfStorageUnit(String storageUnit) throws PhysicalException; + List getColumnsOfStorageUnit(String storageUnit, Set pattern, TagFilter tagFilter) + throws PhysicalException; Pair getBoundaryOfStorage(String dataPrefix) throws PhysicalException; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java index 175811369a..697c2fec91 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java @@ -49,6 +49,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; @@ -285,11 +286,16 @@ public TaskExecuteResult executeDeleteTask( } @Override - public List getColumnsOfStorageUnit(String storageUnit) throws PhysicalException { + public List getColumnsOfStorageUnit( + String storageUnit, Set pattern, TagFilter tagFilter) throws PhysicalException { + List patternList = new ArrayList<>(pattern); + if (patternList.isEmpty()) { + patternList.add("*"); + } if (storageUnit.equals("*")) { List columns = new ArrayList<>(); for (Manager manager : getAllManagers()) { - columns.addAll(manager.getColumns()); + columns.addAll(manager.getColumns(patternList, tagFilter)); } return columns; } else { @@ -303,7 +309,7 @@ public Pair getBoundaryOfStorage(String dataPrefix List paths = new ArrayList<>(); long start = Long.MAX_VALUE, end = Long.MIN_VALUE; for (Manager manager : getAllManagers()) { - for (Column column : manager.getColumns()) { + for (Column column : manager.getColumns(Collections.singletonList("*"), null)) { paths.add(column.getPath()); } KeyInterval interval = manager.getKeyInterval(); diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java index 2bae22e064..81e4b2341f 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java @@ -29,28 +29,17 @@ import cn.edu.tsinghua.iginx.engine.shared.data.write.DataView; import cn.edu.tsinghua.iginx.engine.shared.data.write.RawDataType; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Filter; -import cn.edu.tsinghua.iginx.engine.shared.operator.tag.AndTagFilter; -import cn.edu.tsinghua.iginx.engine.shared.operator.tag.BasePreciseTagFilter; -import cn.edu.tsinghua.iginx.engine.shared.operator.tag.BaseTagFilter; -import cn.edu.tsinghua.iginx.engine.shared.operator.tag.OrTagFilter; -import cn.edu.tsinghua.iginx.engine.shared.operator.tag.PreciseTagFilter; -import cn.edu.tsinghua.iginx.engine.shared.operator.tag.TagFilter; +import cn.edu.tsinghua.iginx.engine.shared.operator.tag.*; import cn.edu.tsinghua.iginx.metadata.entity.ColumnsInterval; import cn.edu.tsinghua.iginx.metadata.entity.KeyInterval; import cn.edu.tsinghua.iginx.parquet.server.FilterTransformer; import cn.edu.tsinghua.iginx.parquet.thrift.*; import cn.edu.tsinghua.iginx.parquet.thrift.ParquetService.Client; +import cn.edu.tsinghua.iginx.parquet.thrift.TagFilterType; import cn.edu.tsinghua.iginx.thrift.DataType; -import cn.edu.tsinghua.iginx.utils.Bitmap; -import cn.edu.tsinghua.iginx.utils.ByteUtils; -import cn.edu.tsinghua.iginx.utils.DataTypeUtils; -import cn.edu.tsinghua.iginx.utils.Pair; -import cn.edu.tsinghua.iginx.utils.ThriftConnPool; +import cn.edu.tsinghua.iginx.utils.*; import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import org.apache.thrift.TException; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.transport.TTransport; @@ -335,11 +324,13 @@ private RawTagFilter constructRawTagFilter(TagFilter tagFilter) { } @Override - public List getColumnsOfStorageUnit(String storageUnit) throws PhysicalException { + public List getColumnsOfStorageUnit( + String storageUnit, Set pattern, TagFilter tagFilter) throws PhysicalException { try { TTransport transport = thriftConnPool.borrowTransport(); Client client = new Client(new TBinaryProtocol(transport)); - GetColumnsOfStorageUnitResp resp = client.getColumnsOfStorageUnit(storageUnit); + GetColumnsOfStorageUnitResp resp = + client.getColumnsOfStorageUnit(storageUnit, pattern, constructRawTagFilter(tagFilter)); thriftConnPool.returnTransport(transport); List columnList = new ArrayList<>(); resp.getTsList() diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/Manager.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/Manager.java index e072f50b2b..3156376ec3 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/Manager.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/Manager.java @@ -36,7 +36,7 @@ RowStream project(List paths, TagFilter tagFilter, Filter filter) void delete(List paths, List keyRanges, TagFilter tagFilter) throws PhysicalException;; - List getColumns() throws PhysicalException; + List getColumns(List paths, TagFilter tagFilter) throws PhysicalException; KeyInterval getKeyInterval() throws PhysicalException; } diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/DataManager.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/DataManager.java index bbe4a16527..38b94363c7 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/DataManager.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/DataManager.java @@ -18,6 +18,7 @@ import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; import cn.edu.tsinghua.iginx.engine.physical.storage.domain.Column; +import cn.edu.tsinghua.iginx.engine.physical.storage.domain.ColumnKey; import cn.edu.tsinghua.iginx.engine.shared.KeyRange; import cn.edu.tsinghua.iginx.engine.shared.data.read.RowStream; import cn.edu.tsinghua.iginx.engine.shared.data.write.DataView; @@ -31,6 +32,7 @@ import cn.edu.tsinghua.iginx.parquet.db.util.iterator.Scanner; import cn.edu.tsinghua.iginx.parquet.manager.Manager; import cn.edu.tsinghua.iginx.parquet.manager.utils.RangeUtils; +import cn.edu.tsinghua.iginx.parquet.manager.utils.TagKVUtils; import cn.edu.tsinghua.iginx.parquet.util.Constants; import cn.edu.tsinghua.iginx.parquet.util.Shared; import cn.edu.tsinghua.iginx.parquet.util.exception.StorageException; @@ -126,12 +128,17 @@ public void delete(List paths, List keyRanges, TagFilter tagFi } @Override - public List getColumns() throws StorageException { + public List getColumns(List paths, TagFilter tagFilter) throws StorageException { List columns = new ArrayList<>(); for (Map.Entry entry : db.schema().entrySet()) { Map.Entry> pathWithTags = DataViewWrapper.parseFieldName(entry.getKey()); - columns.add(new Column(pathWithTags.getKey(), entry.getValue(), pathWithTags.getValue())); + DataType dataType = entry.getValue(); + ColumnKey columnKey = new ColumnKey(pathWithTags.getKey(), pathWithTags.getValue()); + if (!TagKVUtils.match(columnKey, paths, tagFilter)) { + continue; + } + columns.add(new Column(columnKey.getPath(), dataType, columnKey.getTags())); } return columns; } diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/DummyManager.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/DummyManager.java index 24afeaddee..325ad78353 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/DummyManager.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/DummyManager.java @@ -29,7 +29,6 @@ import cn.edu.tsinghua.iginx.metadata.entity.KeyInterval; import cn.edu.tsinghua.iginx.parquet.manager.Manager; import cn.edu.tsinghua.iginx.parquet.manager.utils.TagKVUtils; -import cn.edu.tsinghua.iginx.utils.StringUtils; import java.io.IOException; import java.nio.file.Files; import java.nio.file.NoSuchFileException; @@ -103,21 +102,9 @@ private List determinePathList( Set paths, List patterns, TagFilter tagFilter) { List ret = new ArrayList<>(); for (String path : paths) { - for (String pattern : patterns) { - ColumnKey columnKey = TagKVUtils.splitFullName(path); - if (tagFilter == null) { - if (StringUtils.match(columnKey.getPath(), pattern)) { - ret.add(path); - break; - } - } else { - if (StringUtils.match(columnKey.getPath(), pattern) - && cn.edu.tsinghua.iginx.engine.physical.storage.utils.TagKVUtils.match( - columnKey.getTags(), tagFilter)) { - ret.add(path); - break; - } - } + ColumnKey columnKey = TagKVUtils.splitFullName(path); + if (TagKVUtils.match(columnKey, patterns, tagFilter)) { + ret.add(path); } } return ret; @@ -135,13 +122,16 @@ public void delete(List paths, List keyRanges, TagFilter tagFi } @Override - public List getColumns() throws PhysicalException { + public List getColumns(List paths, TagFilter tagFilter) throws PhysicalException { List columns = new ArrayList<>(); for (Path path : getFilePaths()) { try { List fields = new Loader(path).getHeader(); for (Field field : fields) { ColumnKey columnKey = TagKVUtils.splitFullName(field.getName()); + if (!TagKVUtils.match(columnKey, paths, tagFilter)) { + continue; + } Column column = new Column( prefix + "." + columnKey.getPath(), field.getType(), columnKey.getTags(), true); diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/EmptyManager.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/EmptyManager.java index cbc6daf1b6..fd3507740e 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/EmptyManager.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/EmptyManager.java @@ -71,7 +71,7 @@ public void delete(List paths, List keyRanges, TagFilter tagFi } @Override - public List getColumns() throws PhysicalException { + public List getColumns(List paths, TagFilter tagFilter) throws PhysicalException { return Collections.emptyList(); } diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/utils/TagKVUtils.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/utils/TagKVUtils.java index 36dca6da5d..b4bfc19ef4 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/utils/TagKVUtils.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/utils/TagKVUtils.java @@ -2,10 +2,13 @@ import cn.edu.tsinghua.iginx.engine.physical.storage.domain.ColumnKey; import cn.edu.tsinghua.iginx.engine.physical.storage.utils.ColumnKeyTranslator; +import cn.edu.tsinghua.iginx.engine.shared.operator.tag.TagFilter; import cn.edu.tsinghua.iginx.utils.Escaper; +import cn.edu.tsinghua.iginx.utils.StringUtils; import java.text.ParseException; import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; public class TagKVUtils { @@ -35,4 +38,21 @@ public static ColumnKey splitFullName(String fullName) { throw new IllegalStateException("Failed to parse identifier: " + fullName, e); } } + + public static boolean match(ColumnKey columnKey, List patterns, TagFilter tagFilter) { + for (String pattern : patterns) { + if (tagFilter == null) { + if (StringUtils.match(columnKey.getPath(), pattern)) { + return true; + } + } else { + if (StringUtils.match(columnKey.getPath(), pattern) + && cn.edu.tsinghua.iginx.engine.physical.storage.utils.TagKVUtils.match( + columnKey.getTags(), tagFilter)) { + return true; + } + } + } + return false; + } } diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetWorker.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetWorker.java index 3201bbf694..5f5f829a68 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetWorker.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetWorker.java @@ -44,11 +44,7 @@ import cn.edu.tsinghua.iginx.utils.DataTypeUtils; import cn.edu.tsinghua.iginx.utils.Pair; import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; import org.apache.thrift.TException; import org.slf4j.Logger; @@ -283,10 +279,12 @@ private TagFilter resolveRawTagFilter(RawTagFilter rawTagFilter) { } @Override - public GetColumnsOfStorageUnitResp getColumnsOfStorageUnit(String storageUnit) throws TException { + public GetColumnsOfStorageUnitResp getColumnsOfStorageUnit( + String storageUnit, Set pattern, RawTagFilter tagFilter) throws TException { List ret = new ArrayList<>(); try { - List tsList = executor.getColumnsOfStorageUnit(storageUnit); + List tsList = + executor.getColumnsOfStorageUnit(storageUnit, pattern, resolveRawTagFilter(tagFilter)); tsList.forEach( timeseries -> { TS ts = new TS(timeseries.getPath(), timeseries.getDataType().toString()); diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java index 0453342c2a..8d84724e29 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java @@ -120,6 +120,8 @@ public static boolean match(String string, String iginxPattern) { return toColumnMatcher(iginxPattern).test(string); } + + public static Predicate toColumnMatcher(String iginxPattern) { Objects.requireNonNull(iginxPattern); diff --git a/thrift/src/main/proto/parquet.thrift b/thrift/src/main/proto/parquet.thrift index da88565a8f..f8d1818f43 100644 --- a/thrift/src/main/proto/parquet.thrift +++ b/thrift/src/main/proto/parquet.thrift @@ -155,7 +155,7 @@ service ParquetService { Status executeDelete(1: DeleteReq req); - GetColumnsOfStorageUnitResp getColumnsOfStorageUnit(1: string storageUnit); + GetColumnsOfStorageUnitResp getColumnsOfStorageUnit(1: string storageUnit, 2: set patterns, 3: RawTagFilter tagFilter); GetStorageBoundaryResp getBoundaryOfStorage(1: string dataPrefix); From f0b7fc5e0a809c192aa31dcf9374c3872b09c359 Mon Sep 17 00:00:00 2001 From: shinyano <12236590+shinyano@users.noreply.github.com> Date: Sat, 8 Jun 2024 10:44:55 +0800 Subject: [PATCH 018/138] influxdb get columns by pattern and tag --- .../iginx/influxdb/InfluxDBStorage.java | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java index ca623f630b..fd956889f2 100644 --- a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java +++ b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java @@ -27,6 +27,7 @@ import cn.edu.tsinghua.iginx.engine.physical.storage.IStorage; import cn.edu.tsinghua.iginx.engine.physical.storage.domain.Column; import cn.edu.tsinghua.iginx.engine.physical.storage.domain.DataArea; +import cn.edu.tsinghua.iginx.engine.physical.storage.utils.TagKVUtils; import cn.edu.tsinghua.iginx.engine.physical.task.TaskExecuteResult; import cn.edu.tsinghua.iginx.engine.shared.KeyRange; import cn.edu.tsinghua.iginx.engine.shared.data.write.BitmapView; @@ -263,6 +264,17 @@ public List getColumns(Set pattern, TagFilter tagFilter) { String val = (String) table.getRecords().get(0).getValues().get(key); tag.put(key, val); } + if (isDummy && !isUnit) { + path = bucket.getName() + "." + path; + } + // get columns by pattern + if (!isPathMatchPattern(path, pattern)) { + continue; + } + // get columns by tag filter + if (tagFilter != null && !TagKVUtils.match(tag, tagFilter)) { + continue; + } DataType dataType; switch (column.get(5).getDataType()) { // the index 1 is the type of the data @@ -289,9 +301,6 @@ public List getColumns(Set pattern, TagFilter tagFilter) { LOGGER.warn("DataType don't match and default is String"); break; } - if (isDummy && !isUnit) { - path = bucket.getName() + "." + path; - } timeseries.add(new Column(path, dataType, tag)); } } @@ -299,6 +308,18 @@ public List getColumns(Set pattern, TagFilter tagFilter) { return timeseries; } + boolean isPathMatchPattern(String path, Set pattern) { + if (pattern.isEmpty()) { + return true; + } + for (String pathRegex : pattern) { + if (Pattern.matches(StringUtils.reformatPath(pathRegex), path)) { + return true; + } + } + return false; + } + @Override public void release() throws PhysicalException { client.close(); From 0a0d7b528d5db55a434dea0f73ce2e614900b283 Mon Sep 17 00:00:00 2001 From: shinyano <12236590+shinyano@users.noreply.github.com> Date: Sat, 8 Jun 2024 11:20:06 +0800 Subject: [PATCH 019/138] relational get columns by pattern and tag --- .../iginx/relational/RelationalStorage.java | 38 ++++++++++++++----- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java index 1084b6e69c..8a097c3856 100644 --- a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java +++ b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java @@ -357,18 +357,24 @@ public List getColumns(Set pattern, TagFilter tagFilter) } Pair> nameAndTags = splitFullName(columnName); if (databaseName.startsWith(DATABASE_PREFIX)) { - columns.add( - new Column( - tableName + SEPARATOR + nameAndTags.k, - relationalMeta.getDataTypeTransformer().fromEngineType(typeName), - nameAndTags.v)); + columnName = tableName + SEPARATOR + nameAndTags.k; } else { - columns.add( - new Column( - databaseName + SEPARATOR + tableName + SEPARATOR + nameAndTags.k, - relationalMeta.getDataTypeTransformer().fromEngineType(typeName), - nameAndTags.v)); + columnName = databaseName + SEPARATOR + tableName + SEPARATOR + nameAndTags.k; } + + // get columns by pattern + if (!isPathMatchPattern(columnName, pattern)) { + continue; + } + // get columns by tag filter + if (tagFilter != null && !TagKVUtils.match(nameAndTags.v, tagFilter)) { + continue; + } + columns.add( + new Column( + columnName, + relationalMeta.getDataTypeTransformer().fromEngineType(typeName), + nameAndTags.v)); } } } @@ -378,6 +384,18 @@ public List getColumns(Set pattern, TagFilter tagFilter) return columns; } + boolean isPathMatchPattern(String path, Set pattern) { + if (pattern.isEmpty()) { + return true; + } + for (String pathRegex : pattern) { + if (Pattern.matches(StringUtils.reformatPath(pathRegex), path)) { + return true; + } + } + return false; + } + @Override public TaskExecuteResult executeProject(Project project, DataArea dataArea) { KeyInterval keyInterval = dataArea.getKeyInterval(); From 0e368fb618dfa43c200af1c470275bc99b43e60f Mon Sep 17 00:00:00 2001 From: shinyano <12236590+shinyano@users.noreply.github.com> Date: Sun, 9 Jun 2024 02:53:17 +0800 Subject: [PATCH 020/138] fix influxdb & relational --- .../cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java | 6 +++--- .../cn/edu/tsinghua/iginx/relational/RelationalStorage.java | 6 ++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java index fd956889f2..8d7388b028 100644 --- a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java +++ b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java @@ -243,7 +243,7 @@ public List getColumns(Set pattern, TagFilter tagFilter) { boolean isDummy = meta.isHasData() && (meta.getDataPrefix() == null - || bucket.getName().startsWith(meta.getDataPrefix())); + || bucket.getName().startsWith(meta.getDataPrefix().substring(0, meta.getDataPrefix().indexOf(".")))); if (bucket.getType() == Bucket.TypeEnum.SYSTEM || (!isUnit && !isDummy)) { continue; } @@ -301,7 +301,7 @@ public List getColumns(Set pattern, TagFilter tagFilter) { LOGGER.warn("DataType don't match and default is String"); break; } - timeseries.add(new Column(path, dataType, tag)); + timeseries.add(new Column(path, dataType, tag, isDummy)); } } @@ -309,7 +309,7 @@ public List getColumns(Set pattern, TagFilter tagFilter) { } boolean isPathMatchPattern(String path, Set pattern) { - if (pattern.isEmpty()) { + if (pattern == null || pattern.isEmpty()) { return true; } for (String pathRegex : pattern) { diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java index 8a097c3856..17c4814561 100644 --- a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java +++ b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java @@ -345,6 +345,7 @@ public List getColumns(Set pattern, TagFilter tagFilter) && !databaseName.startsWith(DATABASE_PREFIX)) { continue; } + boolean isDummy = extraParams.get("has_data") != null && extraParams.get("has_data").equalsIgnoreCase("true"); List tables = getTables(databaseName, "%"); for (String tableName : tables) { @@ -374,7 +375,8 @@ public List getColumns(Set pattern, TagFilter tagFilter) new Column( columnName, relationalMeta.getDataTypeTransformer().fromEngineType(typeName), - nameAndTags.v)); + nameAndTags.v, + isDummy)); } } } @@ -385,7 +387,7 @@ public List getColumns(Set pattern, TagFilter tagFilter) } boolean isPathMatchPattern(String path, Set pattern) { - if (pattern.isEmpty()) { + if (pattern == null || pattern.isEmpty()) { return true; } for (String pathRegex : pattern) { From 4836912a4acf3f77d33662046006786f2863410d Mon Sep 17 00:00:00 2001 From: RemHero <1104304963@qq.com> Date: Mon, 10 Jun 2024 23:15:27 +0800 Subject: [PATCH 021/138] add test --- .../execute/StoragePhysicalTaskExecutor.java | 5 +- .../expansion/BaseCapacityExpansionIT.java | 57 +++++++++++-------- .../expansion/constant/Constant.java | 2 + .../FileSystemCapacityExpansionIT.java | 23 ++++++++ .../FileSystemHistoryDataGenerator.java | 23 +++++--- 5 files changed, 77 insertions(+), 33 deletions(-) diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java index 658e615973..b6fbea2da0 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java @@ -331,7 +331,10 @@ public TaskExecuteResult executeShowColumns(ShowColumns showColumns) { // fix the schemaPrefix and dataPrefix String schemaPrefix = storage.getSchemaPrefix(); - String dataPrefixRegex = storage.getDataPrefix() == null ? null : StringUtils.reformatPath(storage.getDataPrefix() + ".*"); + String dataPrefixRegex = + storage.getDataPrefix() == null + ? null + : StringUtils.reformatPath(storage.getDataPrefix() + ".*"); if (tagFilter == null) { for (Column column : columnList) { if (column.isDummy()) { diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java index 9af9fa87f0..c69b6eae2b 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java @@ -87,7 +87,8 @@ protected String addStorageEngine( if (IS_PARQUET_OR_FILE_SYSTEM) { statement.append(String.format(", dummy_dir:%s/", DBCE_PARQUET_FS_TEST_DIR)); statement.append(PORT_TO_ROOT.get(port)); - statement.append(String.format(", dir:%s/iginx_", DBCE_PARQUET_FS_TEST_DIR)); + statement.append( + String.format(", dir:%s/" + IGINX_DATA_PATH_PREFIX_NAME, DBCE_PARQUET_FS_TEST_DIR)); statement.append(PORT_TO_ROOT.get(port)); statement.append(", iginx_port:" + oriPortIginx); } @@ -457,7 +458,34 @@ private void queryAllNewData() { SQLTestTools.executeAndCompare(session, statement, expect); } - private void testShowColumns(List expectColumns) { + protected void testShowAllColumnsInExpansion(boolean before) { + if (before) { + testShowColumns( + Arrays.asList( + new Column("b.b.b", DataType.LONG), + new Column("ln.wf02.status", DataType.BOOLEAN), + new Column("ln.wf02.version", DataType.BINARY), + new Column("nt.wf03.wt01.status2", DataType.LONG), + new Column("nt.wf04.wt01.temperature", DataType.DOUBLE), + new Column( + "zzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzzzz", + DataType.LONG))); + } else { + testShowColumns( + Arrays.asList( + new Column("b.b.b", DataType.LONG), + new Column("ln.wf02.status", DataType.BOOLEAN), + new Column("ln.wf02.version", DataType.BINARY), + new Column("nt.wf03.wt01.status2", DataType.LONG), + new Column("p1.nt.wf03.wt01.status2", DataType.LONG), + new Column("nt.wf04.wt01.temperature", DataType.DOUBLE), + new Column( + "zzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzzzz", + DataType.LONG))); + } + } + + protected void testShowColumns(List expectColumns) { try { List columns = session.showColumns(); LOGGER.info("show columns: {}", columns); @@ -486,31 +514,12 @@ private void testAddAndRemoveStorageEngineWithPrefix() { List> valuesList = EXP_VALUES_LIST1; - testShowColumns( - Arrays.asList( - new Column("b.b.b", DataType.LONG), - new Column("ln.wf02.status", DataType.BOOLEAN), - new Column("ln.wf02.version", DataType.BINARY), - new Column("nt.wf03.wt01.status2", DataType.LONG), - new Column("nt.wf04.wt01.temperature", DataType.DOUBLE), - new Column( - "zzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzzzz", - DataType.LONG))); + testShowAllColumnsInExpansion(true); // 添加不同 schemaPrefix,相同 dataPrefix addStorageEngine(expPort, true, true, dataPrefix1, schemaPrefix1, extraParams); - testShowColumns( - Arrays.asList( - new Column("b.b.b", DataType.LONG), - new Column("ln.wf02.status", DataType.BOOLEAN), - new Column("ln.wf02.version", DataType.BINARY), - new Column("nt.wf03.wt01.status2", DataType.LONG), - new Column("p1.nt.wf03.wt01.status2", DataType.LONG), - new Column("nt.wf04.wt01.temperature", DataType.DOUBLE), - new Column( - "zzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzzzz", - DataType.LONG))); + testShowAllColumnsInExpansion(false); // 添加节点 dataPrefix = dataPrefix1 && schemaPrefix = p1 后查询 String statement = "select status2 from *;"; @@ -790,7 +799,7 @@ protected void startStorageEngineWithIginx(int port, boolean hasData, boolean is hasData ? DBCE_PARQUET_FS_TEST_DIR + "/" + PORT_TO_ROOT.get(port) : DBCE_PARQUET_FS_TEST_DIR + "/" + INIT_PATH_LIST.get(0).replace(".", "/"), - DBCE_PARQUET_FS_TEST_DIR + "/iginx_" + PORT_TO_ROOT.get(port), + DBCE_PARQUET_FS_TEST_DIR + "/" + IGINX_DATA_PATH_PREFIX_NAME + PORT_TO_ROOT.get(port), String.valueOf(hasData), String.valueOf(isReadOnly), "core/target/iginx-core-*/conf/config.properties", diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/constant/Constant.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/constant/Constant.java index 7ef5adbc14..5031b2ef49 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/constant/Constant.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/constant/Constant.java @@ -13,6 +13,8 @@ public class Constant { public static final String EXP_PORT_NAME = "exp_port"; public static final String READ_ONLY_PORT_NAME = "read_only_port"; + public static final String IGINX_DATA_PATH_PREFIX_NAME = "iginx_"; + // port public static int oriPort = 6667; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java index 657bf4de45..32868945f2 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java @@ -4,6 +4,9 @@ import cn.edu.tsinghua.iginx.integration.expansion.BaseCapacityExpansionIT; import cn.edu.tsinghua.iginx.integration.expansion.utils.SQLTestTools; +import cn.edu.tsinghua.iginx.session.Column; +import cn.edu.tsinghua.iginx.thrift.DataType; +import java.util.Arrays; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -22,6 +25,26 @@ protected void testInvalidDummyParams( LOGGER.info("filesystem skips test for wrong dummy engine params."); } + @Override + protected void testShowAllColumnsInExpansion(boolean before) { + if (before) { + testShowColumns( + Arrays.asList( + new Column("ln.wf02.status", DataType.BOOLEAN), + new Column("ln.wf02.version", DataType.BINARY), + new Column("nt.wf03.wt01.status2", DataType.LONG), + new Column("nt.wf04.wt01.temperature", DataType.DOUBLE))); + } else { + testShowColumns( + Arrays.asList( + new Column("ln.wf02.status", DataType.BOOLEAN), + new Column("ln.wf02.version", DataType.BINARY), + new Column("nt.wf03.wt01.status2", DataType.LONG), + new Column("p1.nt.wf03.wt01.status2", DataType.LONG), + new Column("nt.wf04.wt01.temperature", DataType.DOUBLE))); + } + } + @Override public void testShowColumns() { String statement = "SHOW COLUMNS mn.*;"; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemHistoryDataGenerator.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemHistoryDataGenerator.java index 0b3ebfea51..dfe4a78c0b 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemHistoryDataGenerator.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemHistoryDataGenerator.java @@ -43,14 +43,21 @@ public void writeHistoryData( @Override public void clearHistoryDataForGivenPort(int port) { - Path rootPath = Paths.get(PORT_TO_ROOT.get(port)); - if (!Files.exists(rootPath)) { - return; - } - try (Stream walk = Files.walk(rootPath)) { - walk.sorted(Comparator.reverseOrder()).forEach(this::deleteDirectoryStream); - } catch (IOException e) { - LOGGER.error("delete {} failure", rootPath); + Path rootPath; + for (int i = 0; i < 2; i++) { + if (i == 0) { + rootPath = Paths.get(PORT_TO_ROOT.get(port)); + } else { + rootPath = Paths.get(IGINX_DATA_PATH_PREFIX_NAME + PORT_TO_ROOT.get(port)); + } + if (!Files.exists(rootPath)) { + return; + } + try (Stream walk = Files.walk(rootPath)) { + walk.sorted(Comparator.reverseOrder()).forEach(this::deleteDirectoryStream); + } catch (IOException e) { + LOGGER.error("delete {} failure", rootPath); + } } } From 9122833be96523f2b3a6540ad08535d6cf563d02 Mon Sep 17 00:00:00 2001 From: An Qi Date: Sat, 8 Jun 2024 23:13:40 +0800 Subject: [PATCH 022/138] fix mongo --- .../expansion/BaseCapacityExpansionIT.java | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java index c69b6eae2b..29bd00b176 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java @@ -1,14 +1,10 @@ package cn.edu.tsinghua.iginx.integration.expansion; -import static cn.edu.tsinghua.iginx.integration.controller.Controller.SUPPORT_KEY; -import static cn.edu.tsinghua.iginx.integration.expansion.constant.Constant.*; -import static cn.edu.tsinghua.iginx.integration.expansion.utils.SQLTestTools.executeShellScript; -import static org.junit.Assert.*; - import cn.edu.tsinghua.iginx.exception.SessionException; import cn.edu.tsinghua.iginx.integration.controller.Controller; import cn.edu.tsinghua.iginx.integration.expansion.filesystem.FileSystemCapacityExpansionIT; import cn.edu.tsinghua.iginx.integration.expansion.influxdb.InfluxDBCapacityExpansionIT; +import cn.edu.tsinghua.iginx.integration.expansion.mongodb.MongoDBCapacityExpansionIT; import cn.edu.tsinghua.iginx.integration.expansion.parquet.ParquetCapacityExpansionIT; import cn.edu.tsinghua.iginx.integration.expansion.utils.SQLTestTools; import cn.edu.tsinghua.iginx.integration.tool.ConfLoader; @@ -19,16 +15,27 @@ import cn.edu.tsinghua.iginx.thrift.DataType; import cn.edu.tsinghua.iginx.thrift.RemovedStorageEngineInfo; import cn.edu.tsinghua.iginx.thrift.StorageEngineType; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; -import org.junit.*; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -/** 原始节点相关的变量命名统一用 ori 扩容节点相关的变量命名统一用 exp */ +import static cn.edu.tsinghua.iginx.integration.controller.Controller.SUPPORT_KEY; +import static cn.edu.tsinghua.iginx.integration.expansion.constant.Constant.*; +import static cn.edu.tsinghua.iginx.integration.expansion.utils.SQLTestTools.executeShellScript; +import static org.junit.Assert.*; + +/** + * 原始节点相关的变量命名统一用 ori 扩容节点相关的变量命名统一用 exp + */ public abstract class BaseCapacityExpansionIT { private static final Logger LOGGER = LoggerFactory.getLogger(BaseCapacityExpansionIT.class); @@ -343,7 +350,8 @@ protected void queryExtendedColDummy() { SQLTestTools.executeAndCompare(session, statement, new ArrayList<>(), new ArrayList<>()); } - protected void testQuerySpecialHistoryData() {} + protected void testQuerySpecialHistoryData() { + } private void testQueryHistoryDataOriHasData() { String statement = "select wf01.wt01.status, wf01.wt01.temperature from mn;"; @@ -733,8 +741,8 @@ private void testSameKeyWarning() { QueryDataSet res = session.executeQuery(statement); if ((res.getWarningMsg() == null - || res.getWarningMsg().isEmpty() - || !res.getWarningMsg().contains("The query results contain overlapped keys.")) + || res.getWarningMsg().isEmpty() + || !res.getWarningMsg().contains("The query results contain overlapped keys.")) && SUPPORT_KEY.get(testConf.getStorageType())) { LOGGER.error("未抛出重叠key的警告"); fail(); From 4cad9c4a55be1da120163cf6d6204ccfab1a3aa1 Mon Sep 17 00:00:00 2001 From: An Qi Date: Tue, 11 Jun 2024 09:40:23 +0800 Subject: [PATCH 023/138] fix mongodb --- .../mongodb/MongoDBCapacityExpansionIT.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java index 603db64f97..74d184a42a 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java @@ -8,6 +8,10 @@ import cn.edu.tsinghua.iginx.integration.expansion.utils.SQLTestTools; import cn.edu.tsinghua.iginx.integration.tool.ConfLoader; import cn.edu.tsinghua.iginx.integration.tool.DBConf; +import cn.edu.tsinghua.iginx.session.Column; +import cn.edu.tsinghua.iginx.thrift.DataType; +import java.util.ArrayList; +import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -23,6 +27,33 @@ public MongoDBCapacityExpansionIT() { Constant.readOnlyPort = dbConf.getDBCEPortMap().get(Constant.READ_ONLY_PORT_NAME); } + @Override + protected void testShowAllColumnsInExpansion(boolean before) { + List columns = new ArrayList<>(); + columns.add(new Column("b.b._id", DataType.BINARY)); + columns.add(new Column("nt.wf03._id", DataType.BINARY)); + columns.add(new Column("nt.wf04._id", DataType.BINARY)); + columns.add( + new Column( + "zzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzz._id", DataType.BINARY)); + columns.add(new Column("b.b.b", DataType.LONG)); + columns.add(new Column("ln.wf02.status", DataType.BOOLEAN)); + columns.add(new Column("ln.wf02.version", DataType.BINARY)); + columns.add(new Column("nt.wf03.wt01.status2", DataType.LONG)); + columns.add(new Column("nt.wf04.wt01.temperature", DataType.DOUBLE)); + columns.add( + new Column( + "zzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzzzz", + DataType.LONG)); + + if (!before) { + columns.add(new Column("p1.nt.wf03._id", DataType.BINARY)); + columns.add(new Column("p1.nt.wf03.wt01.status2", DataType.LONG)); + } + + testShowColumns(columns); + } + @Override protected void testQuerySpecialHistoryData() { testProject(); From cae24f7d4d323606546d3b1e1c75a593b6d3efa0 Mon Sep 17 00:00:00 2001 From: An Qi Date: Sat, 8 Jun 2024 22:51:05 +0800 Subject: [PATCH 024/138] fix --- .../cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java index 81e4b2341f..6fdccafcc9 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java @@ -266,6 +266,9 @@ public TaskExecuteResult executeDeleteTask( } private RawTagFilter constructRawTagFilter(TagFilter tagFilter) { + if(tagFilter == null) { + return null; + } switch (tagFilter.getType()) { case Base: { From 48ca3fd20a2b2c0ebdd24096f8bd72a7140425f5 Mon Sep 17 00:00:00 2001 From: An Qi Date: Tue, 11 Jun 2024 09:52:43 +0800 Subject: [PATCH 025/138] test parquet --- .github/workflows/DB-CE.yml | 96 +++++++++---------- .github/workflows/standard-test-suite.yml | 40 ++++---- conf/config.properties | 4 +- .../iginx/parquet/exec/RemoteExecutor.java | 2 +- .../edu/tsinghua/iginx/utils/StringUtils.java | 2 - 5 files changed, 71 insertions(+), 73 deletions(-) diff --git a/.github/workflows/DB-CE.yml b/.github/workflows/DB-CE.yml index a6a941df54..5c4f347fc3 100644 --- a/.github/workflows/DB-CE.yml +++ b/.github/workflows/DB-CE.yml @@ -27,7 +27,7 @@ on: description: "The database to run the test on" type: string required: false - default: '["FileSystem", "IoTDB12", "InfluxDB", "PostgreSQL", "Redis", "MongoDB", "Parquet", "MySQL"]' + default: '["Parquet"]' env: VERSION: 0.6.0-SNAPSHOT @@ -70,53 +70,53 @@ jobs: run: | mvn clean package -DskipTests -P-format -q - # 第 1 阶段测试开始========================================== - - name: Prepare CapExp environment oriHasDataExpHasData - uses: ./.github/actions/capacityExpansionUnionTest - with: - version: ${VERSION} - DB-name: ${{ matrix.DB-name }} - Test-Way: oriHasDataExpHasData - - - name: oriHasDataExpHasData IT - shell: bash - run: | - mvn test -q -Dtest=${{ matrix.DB-name }}CapacityExpansionIT#oriHasDataExpHasData -DfailIfNoTests=false -P-format - - - name: Clear history data - uses: ./.github/actions/dbWriter - with: - DB-name: ${{ matrix.DB-name }} - Test-Way: clearHistoryData - - - name: oriHasDataExpHasData Normal IT - shell: bash - run: | - mvn test -q -Dtest=${FUNCTEST} -DfailIfNoTests=false -P-format - - # 第 2 阶段测试开始========================================== - - name: Prepare CapExp environment oriNoDataExpNoData - uses: ./.github/actions/capacityExpansionUnionTest - with: - version: ${VERSION} - DB-name: ${{ matrix.DB-name }} - Test-Way: oriNoDataExpNoData - - - name: oriNoDataExpNoData IT - shell: bash - run: | - mvn test -q -Dtest=${{ matrix.DB-name }}CapacityExpansionIT#oriNoDataExpNoData -DfailIfNoTests=false -P-format - - - name: Clear history data - uses: ./.github/actions/dbWriter - with: - DB-name: ${{ matrix.DB-name }} - Test-Way: clearHistoryData - - - name: oriNoDataExpNoData Normal IT - shell: bash - run: | - mvn test -q -Dtest=${FUNCTEST} -DfailIfNoTests=false -P-format +# # 第 1 阶段测试开始========================================== +# - name: Prepare CapExp environment oriHasDataExpHasData +# uses: ./.github/actions/capacityExpansionUnionTest +# with: +# version: ${VERSION} +# DB-name: ${{ matrix.DB-name }} +# Test-Way: oriHasDataExpHasData +# +# - name: oriHasDataExpHasData IT +# shell: bash +# run: | +# mvn test -q -Dtest=${{ matrix.DB-name }}CapacityExpansionIT#oriHasDataExpHasData -DfailIfNoTests=false -P-format +# +# - name: Clear history data +# uses: ./.github/actions/dbWriter +# with: +# DB-name: ${{ matrix.DB-name }} +# Test-Way: clearHistoryData +# +# - name: oriHasDataExpHasData Normal IT +# shell: bash +# run: | +# mvn test -q -Dtest=${FUNCTEST} -DfailIfNoTests=false -P-format + +# # 第 2 阶段测试开始========================================== +# - name: Prepare CapExp environment oriNoDataExpNoData +# uses: ./.github/actions/capacityExpansionUnionTest +# with: +# version: ${VERSION} +# DB-name: ${{ matrix.DB-name }} +# Test-Way: oriNoDataExpNoData +# +# - name: oriNoDataExpNoData IT +# shell: bash +# run: | +# mvn test -q -Dtest=${{ matrix.DB-name }}CapacityExpansionIT#oriNoDataExpNoData -DfailIfNoTests=false -P-format +# +# - name: Clear history data +# uses: ./.github/actions/dbWriter +# with: +# DB-name: ${{ matrix.DB-name }} +# Test-Way: clearHistoryData +# +# - name: oriNoDataExpNoData Normal IT +# shell: bash +# run: | +# mvn test -q -Dtest=${FUNCTEST} -DfailIfNoTests=false -P-format # 第 3 阶段测试开始========================================== - name: Prepare CapExp environment oriHasDataExpNoData diff --git a/.github/workflows/standard-test-suite.yml b/.github/workflows/standard-test-suite.yml index a4f8234894..f5b7a22f3b 100644 --- a/.github/workflows/standard-test-suite.yml +++ b/.github/workflows/standard-test-suite.yml @@ -11,27 +11,27 @@ concurrency: cancel-in-progress: true jobs: - unit-test: - uses: ./.github/workflows/unit-test.yml - unit-mds: - uses: ./.github/workflows/unit-mds.yml - case-regression: - uses: ./.github/workflows/case-regression.yml - with: - metadata-matrix: '["zookeeper"]' - standalone-test: - uses: ./.github/workflows/standalone-test.yml - with: - metadata-matrix: '["zookeeper"]' - standalone-test-pushdown: - uses: ./.github/workflows/standalone-test-pushdown.yml - with: - metadata-matrix: '["zookeeper"]' +# unit-test: +# uses: ./.github/workflows/unit-test.yml +# unit-mds: +# uses: ./.github/workflows/unit-mds.yml +# case-regression: +# uses: ./.github/workflows/case-regression.yml +# with: +# metadata-matrix: '["zookeeper"]' +# standalone-test: +# uses: ./.github/workflows/standalone-test.yml +# with: +# metadata-matrix: '["zookeeper"]' +# standalone-test-pushdown: +# uses: ./.github/workflows/standalone-test-pushdown.yml +# with: +# metadata-matrix: '["zookeeper"]' db-ce: uses: ./.github/workflows/DB-CE.yml with: metadata-matrix: '["zookeeper"]' - remote-test: - uses: ./.github/workflows/remote-test.yml - with: - metadata-matrix: '["zookeeper"]' +# remote-test: +# uses: ./.github/workflows/remote-test.yml +# with: +# metadata-matrix: '["zookeeper"]' diff --git a/conf/config.properties b/conf/config.properties index a347c1095a..2aa296164e 100644 --- a/conf/config.properties +++ b/conf/config.properties @@ -14,13 +14,13 @@ username=root password=root # 数据库列表,使用','分隔不同实例 -storageEngineList=127.0.0.1#6667#iotdb12#username=root#password=root#sessionPoolSize=20#has_data=false#is_read_only=false +#storageEngineList=127.0.0.1#6667#iotdb12#username=root#password=root#sessionPoolSize=20#has_data=false#is_read_only=false #storageEngineList=127.0.0.1#8086#influxdb#url=http://localhost:8086/#token=your-token#organization=your-organization#has_data=false #storageEngineList=127.0.0.1#4242#opentsdb#url=http://127.0.0.1 #storageEngineList=127.0.0.1#5432#timescaledb#username=postgres#password=postgres #storageEngineList=127.0.0.1#5432#relational#engine=postgresql#username=postgres#password=postgres#has_data=false #storageEngineList=127.0.0.1#3306#relational#engine=mysql#username=root#password=mysql#has_data=false#meta_properties_path=your-meta-properties-path -#storageEngineList=127.0.0.1#6667#parquet#dir=/path/to/your/parquet#dummy_dir=/path/to/your/data#iginx_port=6888#has_data=false#is_read_only=false#thrift_timeout=30000#thrift_pool_max_size=100#thrift_pool_min_evictable_idle_time_millis=600000#write.buffer.size=104857600#write.batch.size=1048576#compact.permits=16#cache.capacity=1073741824#parquet.block.size=134217728#parquet.page.size=8192#parquet.compression=SNAPPY +storageEngineList=127.0.0.1#6667#parquet#dir=data#dummy_dir=/path/to/your/data#iginx_port=6888#has_data=false#is_read_only=false#thrift_timeout=30000#thrift_pool_max_size=100#thrift_pool_min_evictable_idle_time_millis=600000#write.buffer.size=104857600#write.batch.size=1048576#compact.permits=16#cache.capacity=1073741824#parquet.block.size=134217728#parquet.page.size=8192#parquet.compression=SNAPPY #storageEngineList=127.0.0.1#27017#mongodb#has_data=false#schema.sample.size=1000#dummy.sample.size=0 #storageEngineList=127.0.0.1#6667#filesystem#dir=/path/to/your/filesystem#dummy_dir=/path/to/your/data#iginx_port=6888#chunk_size_in_bytes=1048576#memory_pool_size=100#has_data=false#is_read_only=false#thrift_timeout=5000#thrift_pool_max_size=100#thrift_pool_min_evictable_idle_time_millis=600000 #storageEngineList=127.0.0.1#6379#redis#has_data=false#is_read_only=false#timeout=5000#data_db=1#dummy_db=0 diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java index 6fdccafcc9..96d0605f9a 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java @@ -266,7 +266,7 @@ public TaskExecuteResult executeDeleteTask( } private RawTagFilter constructRawTagFilter(TagFilter tagFilter) { - if(tagFilter == null) { + if (tagFilter == null) { return null; } switch (tagFilter.getType()) { diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java index 8d84724e29..0453342c2a 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java @@ -120,8 +120,6 @@ public static boolean match(String string, String iginxPattern) { return toColumnMatcher(iginxPattern).test(string); } - - public static Predicate toColumnMatcher(String iginxPattern) { Objects.requireNonNull(iginxPattern); From 366cd86a0c2e9315e323c3ec64ce7ced8529fef9 Mon Sep 17 00:00:00 2001 From: An Qi Date: Tue, 11 Jun 2024 09:57:53 +0800 Subject: [PATCH 026/138] fix parquet --- .../parquet/ParquetCapacityExpansionIT.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetCapacityExpansionIT.java index 178847bcd6..f8b739a08f 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetCapacityExpansionIT.java @@ -3,6 +3,9 @@ import static cn.edu.tsinghua.iginx.thrift.StorageEngineType.parquet; import cn.edu.tsinghua.iginx.integration.expansion.BaseCapacityExpansionIT; +import cn.edu.tsinghua.iginx.session.Column; +import cn.edu.tsinghua.iginx.thrift.DataType; +import java.util.Arrays; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -20,4 +23,24 @@ protected void testInvalidDummyParams( int port, boolean hasData, boolean isReadOnly, String dataPrefix, String schemaPrefix) { LOGGER.info("parquet skips test for wrong dummy engine params."); } + + @Override + protected void testShowAllColumnsInExpansion(boolean before) { + if (before) { + testShowColumns( + Arrays.asList( + new Column("ln.wf02.status", DataType.BOOLEAN), + new Column("ln.wf02.version", DataType.BINARY), + new Column("nt.wf03.wt01.status2", DataType.LONG), + new Column("nt.wf04.wt01.temperature", DataType.DOUBLE))); + } else { + testShowColumns( + Arrays.asList( + new Column("ln.wf02.status", DataType.BOOLEAN), + new Column("ln.wf02.version", DataType.BINARY), + new Column("nt.wf03.wt01.status2", DataType.LONG), + new Column("p1.nt.wf03.wt01.status2", DataType.LONG), + new Column("nt.wf04.wt01.temperature", DataType.DOUBLE))); + } + } } From 54562b3910c917ce60d49702a7466fcee7a5fc1d Mon Sep 17 00:00:00 2001 From: An Qi Date: Tue, 11 Jun 2024 09:58:01 +0800 Subject: [PATCH 027/138] Revert "test parquet" This reverts commit 48ca3fd20a2b2c0ebdd24096f8bd72a7140425f5. --- .github/workflows/DB-CE.yml | 96 +++++++++---------- .github/workflows/standard-test-suite.yml | 40 ++++---- conf/config.properties | 4 +- .../iginx/parquet/exec/RemoteExecutor.java | 2 +- .../edu/tsinghua/iginx/utils/StringUtils.java | 2 + 5 files changed, 73 insertions(+), 71 deletions(-) diff --git a/.github/workflows/DB-CE.yml b/.github/workflows/DB-CE.yml index 5c4f347fc3..a6a941df54 100644 --- a/.github/workflows/DB-CE.yml +++ b/.github/workflows/DB-CE.yml @@ -27,7 +27,7 @@ on: description: "The database to run the test on" type: string required: false - default: '["Parquet"]' + default: '["FileSystem", "IoTDB12", "InfluxDB", "PostgreSQL", "Redis", "MongoDB", "Parquet", "MySQL"]' env: VERSION: 0.6.0-SNAPSHOT @@ -70,53 +70,53 @@ jobs: run: | mvn clean package -DskipTests -P-format -q -# # 第 1 阶段测试开始========================================== -# - name: Prepare CapExp environment oriHasDataExpHasData -# uses: ./.github/actions/capacityExpansionUnionTest -# with: -# version: ${VERSION} -# DB-name: ${{ matrix.DB-name }} -# Test-Way: oriHasDataExpHasData -# -# - name: oriHasDataExpHasData IT -# shell: bash -# run: | -# mvn test -q -Dtest=${{ matrix.DB-name }}CapacityExpansionIT#oriHasDataExpHasData -DfailIfNoTests=false -P-format -# -# - name: Clear history data -# uses: ./.github/actions/dbWriter -# with: -# DB-name: ${{ matrix.DB-name }} -# Test-Way: clearHistoryData -# -# - name: oriHasDataExpHasData Normal IT -# shell: bash -# run: | -# mvn test -q -Dtest=${FUNCTEST} -DfailIfNoTests=false -P-format - -# # 第 2 阶段测试开始========================================== -# - name: Prepare CapExp environment oriNoDataExpNoData -# uses: ./.github/actions/capacityExpansionUnionTest -# with: -# version: ${VERSION} -# DB-name: ${{ matrix.DB-name }} -# Test-Way: oriNoDataExpNoData -# -# - name: oriNoDataExpNoData IT -# shell: bash -# run: | -# mvn test -q -Dtest=${{ matrix.DB-name }}CapacityExpansionIT#oriNoDataExpNoData -DfailIfNoTests=false -P-format -# -# - name: Clear history data -# uses: ./.github/actions/dbWriter -# with: -# DB-name: ${{ matrix.DB-name }} -# Test-Way: clearHistoryData -# -# - name: oriNoDataExpNoData Normal IT -# shell: bash -# run: | -# mvn test -q -Dtest=${FUNCTEST} -DfailIfNoTests=false -P-format + # 第 1 阶段测试开始========================================== + - name: Prepare CapExp environment oriHasDataExpHasData + uses: ./.github/actions/capacityExpansionUnionTest + with: + version: ${VERSION} + DB-name: ${{ matrix.DB-name }} + Test-Way: oriHasDataExpHasData + + - name: oriHasDataExpHasData IT + shell: bash + run: | + mvn test -q -Dtest=${{ matrix.DB-name }}CapacityExpansionIT#oriHasDataExpHasData -DfailIfNoTests=false -P-format + + - name: Clear history data + uses: ./.github/actions/dbWriter + with: + DB-name: ${{ matrix.DB-name }} + Test-Way: clearHistoryData + + - name: oriHasDataExpHasData Normal IT + shell: bash + run: | + mvn test -q -Dtest=${FUNCTEST} -DfailIfNoTests=false -P-format + + # 第 2 阶段测试开始========================================== + - name: Prepare CapExp environment oriNoDataExpNoData + uses: ./.github/actions/capacityExpansionUnionTest + with: + version: ${VERSION} + DB-name: ${{ matrix.DB-name }} + Test-Way: oriNoDataExpNoData + + - name: oriNoDataExpNoData IT + shell: bash + run: | + mvn test -q -Dtest=${{ matrix.DB-name }}CapacityExpansionIT#oriNoDataExpNoData -DfailIfNoTests=false -P-format + + - name: Clear history data + uses: ./.github/actions/dbWriter + with: + DB-name: ${{ matrix.DB-name }} + Test-Way: clearHistoryData + + - name: oriNoDataExpNoData Normal IT + shell: bash + run: | + mvn test -q -Dtest=${FUNCTEST} -DfailIfNoTests=false -P-format # 第 3 阶段测试开始========================================== - name: Prepare CapExp environment oriHasDataExpNoData diff --git a/.github/workflows/standard-test-suite.yml b/.github/workflows/standard-test-suite.yml index f5b7a22f3b..a4f8234894 100644 --- a/.github/workflows/standard-test-suite.yml +++ b/.github/workflows/standard-test-suite.yml @@ -11,27 +11,27 @@ concurrency: cancel-in-progress: true jobs: -# unit-test: -# uses: ./.github/workflows/unit-test.yml -# unit-mds: -# uses: ./.github/workflows/unit-mds.yml -# case-regression: -# uses: ./.github/workflows/case-regression.yml -# with: -# metadata-matrix: '["zookeeper"]' -# standalone-test: -# uses: ./.github/workflows/standalone-test.yml -# with: -# metadata-matrix: '["zookeeper"]' -# standalone-test-pushdown: -# uses: ./.github/workflows/standalone-test-pushdown.yml -# with: -# metadata-matrix: '["zookeeper"]' + unit-test: + uses: ./.github/workflows/unit-test.yml + unit-mds: + uses: ./.github/workflows/unit-mds.yml + case-regression: + uses: ./.github/workflows/case-regression.yml + with: + metadata-matrix: '["zookeeper"]' + standalone-test: + uses: ./.github/workflows/standalone-test.yml + with: + metadata-matrix: '["zookeeper"]' + standalone-test-pushdown: + uses: ./.github/workflows/standalone-test-pushdown.yml + with: + metadata-matrix: '["zookeeper"]' db-ce: uses: ./.github/workflows/DB-CE.yml with: metadata-matrix: '["zookeeper"]' -# remote-test: -# uses: ./.github/workflows/remote-test.yml -# with: -# metadata-matrix: '["zookeeper"]' + remote-test: + uses: ./.github/workflows/remote-test.yml + with: + metadata-matrix: '["zookeeper"]' diff --git a/conf/config.properties b/conf/config.properties index 2aa296164e..a347c1095a 100644 --- a/conf/config.properties +++ b/conf/config.properties @@ -14,13 +14,13 @@ username=root password=root # 数据库列表,使用','分隔不同实例 -#storageEngineList=127.0.0.1#6667#iotdb12#username=root#password=root#sessionPoolSize=20#has_data=false#is_read_only=false +storageEngineList=127.0.0.1#6667#iotdb12#username=root#password=root#sessionPoolSize=20#has_data=false#is_read_only=false #storageEngineList=127.0.0.1#8086#influxdb#url=http://localhost:8086/#token=your-token#organization=your-organization#has_data=false #storageEngineList=127.0.0.1#4242#opentsdb#url=http://127.0.0.1 #storageEngineList=127.0.0.1#5432#timescaledb#username=postgres#password=postgres #storageEngineList=127.0.0.1#5432#relational#engine=postgresql#username=postgres#password=postgres#has_data=false #storageEngineList=127.0.0.1#3306#relational#engine=mysql#username=root#password=mysql#has_data=false#meta_properties_path=your-meta-properties-path -storageEngineList=127.0.0.1#6667#parquet#dir=data#dummy_dir=/path/to/your/data#iginx_port=6888#has_data=false#is_read_only=false#thrift_timeout=30000#thrift_pool_max_size=100#thrift_pool_min_evictable_idle_time_millis=600000#write.buffer.size=104857600#write.batch.size=1048576#compact.permits=16#cache.capacity=1073741824#parquet.block.size=134217728#parquet.page.size=8192#parquet.compression=SNAPPY +#storageEngineList=127.0.0.1#6667#parquet#dir=/path/to/your/parquet#dummy_dir=/path/to/your/data#iginx_port=6888#has_data=false#is_read_only=false#thrift_timeout=30000#thrift_pool_max_size=100#thrift_pool_min_evictable_idle_time_millis=600000#write.buffer.size=104857600#write.batch.size=1048576#compact.permits=16#cache.capacity=1073741824#parquet.block.size=134217728#parquet.page.size=8192#parquet.compression=SNAPPY #storageEngineList=127.0.0.1#27017#mongodb#has_data=false#schema.sample.size=1000#dummy.sample.size=0 #storageEngineList=127.0.0.1#6667#filesystem#dir=/path/to/your/filesystem#dummy_dir=/path/to/your/data#iginx_port=6888#chunk_size_in_bytes=1048576#memory_pool_size=100#has_data=false#is_read_only=false#thrift_timeout=5000#thrift_pool_max_size=100#thrift_pool_min_evictable_idle_time_millis=600000 #storageEngineList=127.0.0.1#6379#redis#has_data=false#is_read_only=false#timeout=5000#data_db=1#dummy_db=0 diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java index 96d0605f9a..6fdccafcc9 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java @@ -266,7 +266,7 @@ public TaskExecuteResult executeDeleteTask( } private RawTagFilter constructRawTagFilter(TagFilter tagFilter) { - if (tagFilter == null) { + if(tagFilter == null) { return null; } switch (tagFilter.getType()) { diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java index 0453342c2a..8d84724e29 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java @@ -120,6 +120,8 @@ public static boolean match(String string, String iginxPattern) { return toColumnMatcher(iginxPattern).test(string); } + + public static Predicate toColumnMatcher(String iginxPattern) { Objects.requireNonNull(iginxPattern); From 55d84e27b6759ef34114ae50088741f3a231d574 Mon Sep 17 00:00:00 2001 From: RemHero <1104304963@qq.com> Date: Tue, 11 Jun 2024 17:03:07 +0800 Subject: [PATCH 028/138] format --- .../java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java | 5 ++++- .../cn/edu/tsinghua/iginx/relational/RelationalStorage.java | 4 +++- .../main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java | 2 -- .../expansion/filesystem/FileSystemHistoryDataGenerator.java | 4 +++- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java index 8d7388b028..0f91947422 100644 --- a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java +++ b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java @@ -243,7 +243,10 @@ public List getColumns(Set pattern, TagFilter tagFilter) { boolean isDummy = meta.isHasData() && (meta.getDataPrefix() == null - || bucket.getName().startsWith(meta.getDataPrefix().substring(0, meta.getDataPrefix().indexOf(".")))); + || bucket + .getName() + .startsWith( + meta.getDataPrefix().substring(0, meta.getDataPrefix().indexOf(".")))); if (bucket.getType() == Bucket.TypeEnum.SYSTEM || (!isUnit && !isDummy)) { continue; } diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java index 17c4814561..f730b3733b 100644 --- a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java +++ b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java @@ -345,7 +345,9 @@ public List getColumns(Set pattern, TagFilter tagFilter) && !databaseName.startsWith(DATABASE_PREFIX)) { continue; } - boolean isDummy = extraParams.get("has_data") != null && extraParams.get("has_data").equalsIgnoreCase("true"); + boolean isDummy = + extraParams.get("has_data") != null + && extraParams.get("has_data").equalsIgnoreCase("true"); List tables = getTables(databaseName, "%"); for (String tableName : tables) { diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java index 8d84724e29..0453342c2a 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java @@ -120,8 +120,6 @@ public static boolean match(String string, String iginxPattern) { return toColumnMatcher(iginxPattern).test(string); } - - public static Predicate toColumnMatcher(String iginxPattern) { Objects.requireNonNull(iginxPattern); diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemHistoryDataGenerator.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemHistoryDataGenerator.java index dfe4a78c0b..64a04d429e 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemHistoryDataGenerator.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemHistoryDataGenerator.java @@ -50,8 +50,10 @@ public void clearHistoryDataForGivenPort(int port) { } else { rootPath = Paths.get(IGINX_DATA_PATH_PREFIX_NAME + PORT_TO_ROOT.get(port)); } + LOGGER.info("clear path {}", rootPath.toFile().getAbsolutePath()); if (!Files.exists(rootPath)) { - return; + LOGGER.info("path {} does not exist", rootPath.toFile().getAbsolutePath()); + continue; } try (Stream walk = Files.walk(rootPath)) { walk.sorted(Comparator.reverseOrder()).forEach(this::deleteDirectoryStream); From f23bd5d7824081a54012b44390ff03d52a9071c2 Mon Sep 17 00:00:00 2001 From: RemHero <1104304963@qq.com> Date: Tue, 11 Jun 2024 21:44:42 +0800 Subject: [PATCH 029/138] fix parquet --- .../parquet/ParquetHistoryDataGenerator.java | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetHistoryDataGenerator.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetHistoryDataGenerator.java index fb8edc8443..0fe4ce18e7 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetHistoryDataGenerator.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetHistoryDataGenerator.java @@ -11,10 +11,7 @@ import java.io.IOException; import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; -import java.util.ArrayList; -import java.util.List; -import java.util.SortedMap; -import java.util.TreeMap; +import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; import javax.annotation.Nonnull; @@ -148,17 +145,24 @@ public void clearHistoryDataForGivenPort(int port) { "delete {}/{} error: does not exist or is not a file.", dir, file.getAbsoluteFile()); } + List pathList = Arrays.asList( + IT_DATA_DIR, + PARQUET_PARAMS.get(port).get(0)); // delete the normal IT data - dir = DBCE_PARQUET_FS_TEST_DIR + System.getProperty("file.separator") + IT_DATA_DIR; - parquetPath = Paths.get("../" + dir); - - try { - Files.walkFileTree(parquetPath, new DeleteFileVisitor()); - } catch (NoSuchFileException e) { - LOGGER.warn( - "no such file or directory: {}", new File(parquetPath.toString()).getAbsoluteFile()); - } catch (IOException e) { - LOGGER.warn("delete {} error: ", new File(parquetPath.toString()).getAbsoluteFile(), e); + for(String path : pathList) { + Path dataPath = Paths.get(path); + if (Files.exists(dataPath)) { + try { + Files.walkFileTree(dataPath, new DeleteFileVisitor()); + } catch (NoSuchFileException e) { + LOGGER.warn( + "no such file or directory: {}", new File(dataPath.toString()).getAbsoluteFile()); + } catch (IOException e) { + LOGGER.warn("delete {} error: ", new File(dataPath.toString()).getAbsoluteFile(), e); + } + } else { + LOGGER.warn("delete {} error: does not exist.", new File(dataPath.toString()).getAbsoluteFile()); + } } } From e258635aad24b58403fb70c536e90641a9d44e41 Mon Sep 17 00:00:00 2001 From: RemHero <1104304963@qq.com> Date: Tue, 11 Jun 2024 21:45:43 +0800 Subject: [PATCH 030/138] fix parquet --- .github/workflows/DB-CE.yml | 2 +- .github/workflows/standard-test-suite.yml | 40 +++++++++++------------ 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/.github/workflows/DB-CE.yml b/.github/workflows/DB-CE.yml index a6a941df54..7a90a73f08 100644 --- a/.github/workflows/DB-CE.yml +++ b/.github/workflows/DB-CE.yml @@ -27,7 +27,7 @@ on: description: "The database to run the test on" type: string required: false - default: '["FileSystem", "IoTDB12", "InfluxDB", "PostgreSQL", "Redis", "MongoDB", "Parquet", "MySQL"]' + default: '["Parquet"]' env: VERSION: 0.6.0-SNAPSHOT diff --git a/.github/workflows/standard-test-suite.yml b/.github/workflows/standard-test-suite.yml index a4f8234894..f5b7a22f3b 100644 --- a/.github/workflows/standard-test-suite.yml +++ b/.github/workflows/standard-test-suite.yml @@ -11,27 +11,27 @@ concurrency: cancel-in-progress: true jobs: - unit-test: - uses: ./.github/workflows/unit-test.yml - unit-mds: - uses: ./.github/workflows/unit-mds.yml - case-regression: - uses: ./.github/workflows/case-regression.yml - with: - metadata-matrix: '["zookeeper"]' - standalone-test: - uses: ./.github/workflows/standalone-test.yml - with: - metadata-matrix: '["zookeeper"]' - standalone-test-pushdown: - uses: ./.github/workflows/standalone-test-pushdown.yml - with: - metadata-matrix: '["zookeeper"]' +# unit-test: +# uses: ./.github/workflows/unit-test.yml +# unit-mds: +# uses: ./.github/workflows/unit-mds.yml +# case-regression: +# uses: ./.github/workflows/case-regression.yml +# with: +# metadata-matrix: '["zookeeper"]' +# standalone-test: +# uses: ./.github/workflows/standalone-test.yml +# with: +# metadata-matrix: '["zookeeper"]' +# standalone-test-pushdown: +# uses: ./.github/workflows/standalone-test-pushdown.yml +# with: +# metadata-matrix: '["zookeeper"]' db-ce: uses: ./.github/workflows/DB-CE.yml with: metadata-matrix: '["zookeeper"]' - remote-test: - uses: ./.github/workflows/remote-test.yml - with: - metadata-matrix: '["zookeeper"]' +# remote-test: +# uses: ./.github/workflows/remote-test.yml +# with: +# metadata-matrix: '["zookeeper"]' From 39e11a7f645f0030e5d32d92732a6270bc856115 Mon Sep 17 00:00:00 2001 From: RemHero <1104304963@qq.com> Date: Tue, 11 Jun 2024 21:46:29 +0800 Subject: [PATCH 031/138] add test --- .github/workflows/DB-CE.yml | 2 +- .github/workflows/standard-test-suite.yml | 40 +++++++++++------------ 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/.github/workflows/DB-CE.yml b/.github/workflows/DB-CE.yml index 7a90a73f08..a6a941df54 100644 --- a/.github/workflows/DB-CE.yml +++ b/.github/workflows/DB-CE.yml @@ -27,7 +27,7 @@ on: description: "The database to run the test on" type: string required: false - default: '["Parquet"]' + default: '["FileSystem", "IoTDB12", "InfluxDB", "PostgreSQL", "Redis", "MongoDB", "Parquet", "MySQL"]' env: VERSION: 0.6.0-SNAPSHOT diff --git a/.github/workflows/standard-test-suite.yml b/.github/workflows/standard-test-suite.yml index f5b7a22f3b..a4f8234894 100644 --- a/.github/workflows/standard-test-suite.yml +++ b/.github/workflows/standard-test-suite.yml @@ -11,27 +11,27 @@ concurrency: cancel-in-progress: true jobs: -# unit-test: -# uses: ./.github/workflows/unit-test.yml -# unit-mds: -# uses: ./.github/workflows/unit-mds.yml -# case-regression: -# uses: ./.github/workflows/case-regression.yml -# with: -# metadata-matrix: '["zookeeper"]' -# standalone-test: -# uses: ./.github/workflows/standalone-test.yml -# with: -# metadata-matrix: '["zookeeper"]' -# standalone-test-pushdown: -# uses: ./.github/workflows/standalone-test-pushdown.yml -# with: -# metadata-matrix: '["zookeeper"]' + unit-test: + uses: ./.github/workflows/unit-test.yml + unit-mds: + uses: ./.github/workflows/unit-mds.yml + case-regression: + uses: ./.github/workflows/case-regression.yml + with: + metadata-matrix: '["zookeeper"]' + standalone-test: + uses: ./.github/workflows/standalone-test.yml + with: + metadata-matrix: '["zookeeper"]' + standalone-test-pushdown: + uses: ./.github/workflows/standalone-test-pushdown.yml + with: + metadata-matrix: '["zookeeper"]' db-ce: uses: ./.github/workflows/DB-CE.yml with: metadata-matrix: '["zookeeper"]' -# remote-test: -# uses: ./.github/workflows/remote-test.yml -# with: -# metadata-matrix: '["zookeeper"]' + remote-test: + uses: ./.github/workflows/remote-test.yml + with: + metadata-matrix: '["zookeeper"]' From 155f95b7805b7bb651d0439846f411ad8b382ecf Mon Sep 17 00:00:00 2001 From: RemHero <1104304963@qq.com> Date: Tue, 11 Jun 2024 21:47:08 +0800 Subject: [PATCH 032/138] test --- .github/workflows/DB-CE.yml | 2 +- .github/workflows/standard-test-suite.yml | 40 +++++++++++------------ 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/.github/workflows/DB-CE.yml b/.github/workflows/DB-CE.yml index a6a941df54..f1a26934dc 100644 --- a/.github/workflows/DB-CE.yml +++ b/.github/workflows/DB-CE.yml @@ -27,7 +27,7 @@ on: description: "The database to run the test on" type: string required: false - default: '["FileSystem", "IoTDB12", "InfluxDB", "PostgreSQL", "Redis", "MongoDB", "Parquet", "MySQL"]' + default: '[ "Parquet"]' env: VERSION: 0.6.0-SNAPSHOT diff --git a/.github/workflows/standard-test-suite.yml b/.github/workflows/standard-test-suite.yml index a4f8234894..f5b7a22f3b 100644 --- a/.github/workflows/standard-test-suite.yml +++ b/.github/workflows/standard-test-suite.yml @@ -11,27 +11,27 @@ concurrency: cancel-in-progress: true jobs: - unit-test: - uses: ./.github/workflows/unit-test.yml - unit-mds: - uses: ./.github/workflows/unit-mds.yml - case-regression: - uses: ./.github/workflows/case-regression.yml - with: - metadata-matrix: '["zookeeper"]' - standalone-test: - uses: ./.github/workflows/standalone-test.yml - with: - metadata-matrix: '["zookeeper"]' - standalone-test-pushdown: - uses: ./.github/workflows/standalone-test-pushdown.yml - with: - metadata-matrix: '["zookeeper"]' +# unit-test: +# uses: ./.github/workflows/unit-test.yml +# unit-mds: +# uses: ./.github/workflows/unit-mds.yml +# case-regression: +# uses: ./.github/workflows/case-regression.yml +# with: +# metadata-matrix: '["zookeeper"]' +# standalone-test: +# uses: ./.github/workflows/standalone-test.yml +# with: +# metadata-matrix: '["zookeeper"]' +# standalone-test-pushdown: +# uses: ./.github/workflows/standalone-test-pushdown.yml +# with: +# metadata-matrix: '["zookeeper"]' db-ce: uses: ./.github/workflows/DB-CE.yml with: metadata-matrix: '["zookeeper"]' - remote-test: - uses: ./.github/workflows/remote-test.yml - with: - metadata-matrix: '["zookeeper"]' +# remote-test: +# uses: ./.github/workflows/remote-test.yml +# with: +# metadata-matrix: '["zookeeper"]' From 039a7b41d0fc37af7ac80f71e5756a39ff0d3f8a Mon Sep 17 00:00:00 2001 From: RemHero <1104304963@qq.com> Date: Tue, 11 Jun 2024 22:05:44 +0800 Subject: [PATCH 033/138] test --- .../expansion/parquet/ParquetHistoryDataGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetHistoryDataGenerator.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetHistoryDataGenerator.java index 0fe4ce18e7..64990f94f4 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetHistoryDataGenerator.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetHistoryDataGenerator.java @@ -147,7 +147,7 @@ public void clearHistoryDataForGivenPort(int port) { List pathList = Arrays.asList( IT_DATA_DIR, - PARQUET_PARAMS.get(port).get(0)); + IGINX_DATA_PATH_PREFIX_NAME + PARQUET_PARAMS.get(port).get(0)); // delete the normal IT data for(String path : pathList) { Path dataPath = Paths.get(path); From f8e06e18060067a89e43c3429f13467591e4c2b1 Mon Sep 17 00:00:00 2001 From: An Qi Date: Wed, 12 Jun 2024 12:14:00 +0800 Subject: [PATCH 034/138] ci: manually run full test suite (#355) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 合并后,可以在 https://github.com/IGinX-THU/IGinX/actions/workflows/full-test-suite.yml 页面手动触发完整测试套件 --- .github/workflows/full-test-suite.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/full-test-suite.yml b/.github/workflows/full-test-suite.yml index 31266b2a0f..a7e34ee6f8 100644 --- a/.github/workflows/full-test-suite.yml +++ b/.github/workflows/full-test-suite.yml @@ -3,6 +3,7 @@ name: Full Test Suite on: schedule: - cron: "0 0 * * 0" # every Sunday + workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.ref }} From c3928c329c970a6f5b4dad60c98e9f213489387a Mon Sep 17 00:00:00 2001 From: An Qi Date: Wed, 12 Jun 2024 15:54:09 +0800 Subject: [PATCH 035/138] fix parquet --- .../cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java | 2 +- .../tsinghua/iginx/parquet/manager/dummy/DummyManager.java | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java index 6fdccafcc9..96d0605f9a 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java @@ -266,7 +266,7 @@ public TaskExecuteResult executeDeleteTask( } private RawTagFilter constructRawTagFilter(TagFilter tagFilter) { - if(tagFilter == null) { + if (tagFilter == null) { return null; } switch (tagFilter.getType()) { diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/DummyManager.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/DummyManager.java index 325ad78353..464529b61a 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/DummyManager.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/DummyManager.java @@ -128,13 +128,12 @@ public List getColumns(List paths, TagFilter tagFilter) throws P try { List fields = new Loader(path).getHeader(); for (Field field : fields) { - ColumnKey columnKey = TagKVUtils.splitFullName(field.getName()); + ColumnKey columnKey = TagKVUtils.splitFullName(prefix + "." + field.getName()); if (!TagKVUtils.match(columnKey, paths, tagFilter)) { continue; } Column column = - new Column( - prefix + "." + columnKey.getPath(), field.getType(), columnKey.getTags(), true); + new Column(columnKey.getPath(), field.getType(), columnKey.getTags(), true); columns.add(column); } } catch (IOException e) { From 4d311808e4979dfebed71a03c51deb3ad940658b Mon Sep 17 00:00:00 2001 From: RemHero <1104304963@qq.com> Date: Thu, 13 Jun 2024 17:59:13 +0800 Subject: [PATCH 036/138] format --- .github/workflows/DB-CE.yml | 2 +- .github/workflows/standard-test-suite.yml | 40 +++++++++---------- .../expansion/BaseCapacityExpansionIT.java | 33 +++++++-------- .../parquet/ParquetHistoryDataGenerator.java | 10 ++--- 4 files changed, 40 insertions(+), 45 deletions(-) diff --git a/.github/workflows/DB-CE.yml b/.github/workflows/DB-CE.yml index f1a26934dc..a6a941df54 100644 --- a/.github/workflows/DB-CE.yml +++ b/.github/workflows/DB-CE.yml @@ -27,7 +27,7 @@ on: description: "The database to run the test on" type: string required: false - default: '[ "Parquet"]' + default: '["FileSystem", "IoTDB12", "InfluxDB", "PostgreSQL", "Redis", "MongoDB", "Parquet", "MySQL"]' env: VERSION: 0.6.0-SNAPSHOT diff --git a/.github/workflows/standard-test-suite.yml b/.github/workflows/standard-test-suite.yml index f5b7a22f3b..a4f8234894 100644 --- a/.github/workflows/standard-test-suite.yml +++ b/.github/workflows/standard-test-suite.yml @@ -11,27 +11,27 @@ concurrency: cancel-in-progress: true jobs: -# unit-test: -# uses: ./.github/workflows/unit-test.yml -# unit-mds: -# uses: ./.github/workflows/unit-mds.yml -# case-regression: -# uses: ./.github/workflows/case-regression.yml -# with: -# metadata-matrix: '["zookeeper"]' -# standalone-test: -# uses: ./.github/workflows/standalone-test.yml -# with: -# metadata-matrix: '["zookeeper"]' -# standalone-test-pushdown: -# uses: ./.github/workflows/standalone-test-pushdown.yml -# with: -# metadata-matrix: '["zookeeper"]' + unit-test: + uses: ./.github/workflows/unit-test.yml + unit-mds: + uses: ./.github/workflows/unit-mds.yml + case-regression: + uses: ./.github/workflows/case-regression.yml + with: + metadata-matrix: '["zookeeper"]' + standalone-test: + uses: ./.github/workflows/standalone-test.yml + with: + metadata-matrix: '["zookeeper"]' + standalone-test-pushdown: + uses: ./.github/workflows/standalone-test-pushdown.yml + with: + metadata-matrix: '["zookeeper"]' db-ce: uses: ./.github/workflows/DB-CE.yml with: metadata-matrix: '["zookeeper"]' -# remote-test: -# uses: ./.github/workflows/remote-test.yml -# with: -# metadata-matrix: '["zookeeper"]' + remote-test: + uses: ./.github/workflows/remote-test.yml + with: + metadata-matrix: '["zookeeper"]' diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java index 29bd00b176..d30e3d6f82 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java @@ -1,10 +1,14 @@ package cn.edu.tsinghua.iginx.integration.expansion; +import static cn.edu.tsinghua.iginx.integration.controller.Controller.SUPPORT_KEY; +import static cn.edu.tsinghua.iginx.integration.expansion.constant.Constant.*; +import static cn.edu.tsinghua.iginx.integration.expansion.utils.SQLTestTools.executeShellScript; +import static org.junit.Assert.*; + import cn.edu.tsinghua.iginx.exception.SessionException; import cn.edu.tsinghua.iginx.integration.controller.Controller; import cn.edu.tsinghua.iginx.integration.expansion.filesystem.FileSystemCapacityExpansionIT; import cn.edu.tsinghua.iginx.integration.expansion.influxdb.InfluxDBCapacityExpansionIT; -import cn.edu.tsinghua.iginx.integration.expansion.mongodb.MongoDBCapacityExpansionIT; import cn.edu.tsinghua.iginx.integration.expansion.parquet.ParquetCapacityExpansionIT; import cn.edu.tsinghua.iginx.integration.expansion.utils.SQLTestTools; import cn.edu.tsinghua.iginx.integration.tool.ConfLoader; @@ -15,6 +19,11 @@ import cn.edu.tsinghua.iginx.thrift.DataType; import cn.edu.tsinghua.iginx.thrift.RemovedStorageEngineInfo; import cn.edu.tsinghua.iginx.thrift.StorageEngineType; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; import org.junit.After; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -22,20 +31,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; - -import static cn.edu.tsinghua.iginx.integration.controller.Controller.SUPPORT_KEY; -import static cn.edu.tsinghua.iginx.integration.expansion.constant.Constant.*; -import static cn.edu.tsinghua.iginx.integration.expansion.utils.SQLTestTools.executeShellScript; -import static org.junit.Assert.*; - -/** - * 原始节点相关的变量命名统一用 ori 扩容节点相关的变量命名统一用 exp - */ +/** 原始节点相关的变量命名统一用 ori 扩容节点相关的变量命名统一用 exp */ public abstract class BaseCapacityExpansionIT { private static final Logger LOGGER = LoggerFactory.getLogger(BaseCapacityExpansionIT.class); @@ -350,8 +346,7 @@ protected void queryExtendedColDummy() { SQLTestTools.executeAndCompare(session, statement, new ArrayList<>(), new ArrayList<>()); } - protected void testQuerySpecialHistoryData() { - } + protected void testQuerySpecialHistoryData() {} private void testQueryHistoryDataOriHasData() { String statement = "select wf01.wt01.status, wf01.wt01.temperature from mn;"; @@ -741,8 +736,8 @@ private void testSameKeyWarning() { QueryDataSet res = session.executeQuery(statement); if ((res.getWarningMsg() == null - || res.getWarningMsg().isEmpty() - || !res.getWarningMsg().contains("The query results contain overlapped keys.")) + || res.getWarningMsg().isEmpty() + || !res.getWarningMsg().contains("The query results contain overlapped keys.")) && SUPPORT_KEY.get(testConf.getStorageType())) { LOGGER.error("未抛出重叠key的警告"); fail(); diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetHistoryDataGenerator.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetHistoryDataGenerator.java index 64990f94f4..e5f872a12a 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetHistoryDataGenerator.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetHistoryDataGenerator.java @@ -145,11 +145,10 @@ public void clearHistoryDataForGivenPort(int port) { "delete {}/{} error: does not exist or is not a file.", dir, file.getAbsoluteFile()); } - List pathList = Arrays.asList( - IT_DATA_DIR, - IGINX_DATA_PATH_PREFIX_NAME + PARQUET_PARAMS.get(port).get(0)); + List pathList = + Arrays.asList(IT_DATA_DIR, IGINX_DATA_PATH_PREFIX_NAME + PARQUET_PARAMS.get(port).get(0)); // delete the normal IT data - for(String path : pathList) { + for (String path : pathList) { Path dataPath = Paths.get(path); if (Files.exists(dataPath)) { try { @@ -161,7 +160,8 @@ public void clearHistoryDataForGivenPort(int port) { LOGGER.warn("delete {} error: ", new File(dataPath.toString()).getAbsoluteFile(), e); } } else { - LOGGER.warn("delete {} error: does not exist.", new File(dataPath.toString()).getAbsoluteFile()); + LOGGER.warn( + "delete {} error: does not exist.", new File(dataPath.toString()).getAbsoluteFile()); } } } From 73260217823159946d5d1db307b7aef32bb7a09d Mon Sep 17 00:00:00 2001 From: Xu Yihao <48053143+Yihao-Xu@users.noreply.github.com> Date: Fri, 14 Jun 2024 09:04:54 +0800 Subject: [PATCH 037/138] feat(optimizer): Join Factorization Rule, Optimizer Independent and Confuse (#352) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 实现了Join Factorization规则: 如果UNION ALL两端的算子树具有相同的分支(即扫描的path和谓词都一致),可以将其提取出来到UNION ALL之后处理,将2次数据扫描和处理减少为1次。但一些情况下数据顺序可能会发生变化。 实现了Optimizer模块的独立和混淆功能: 为了单独将Optimizer打成Jar包,将Optimizer独立出来成为子模块,并通过调整,使得Optimizer单向依赖core模块而core模块不依赖Optimizer模块,core模块依赖Optimizer模块的地方,将interface留在core模块,再通过ClassLoader来调用。 实现了Optimizer的jar包代码混淆,使用了proguard插件,执行mvn clean install时就能自动生成jar包并混淆,并复制一份到core/target内。IGinX的构建流程和以往一样。 修改了CI流程,可以用上传的optimizer jar包来进行测试。optimizer jar包放置在optimizer resource文件夹中,本PR更改CI流程,将上传jar包替换构建出的jar包,因此可以使用jar包中的规则来测试。 --- .github/actions/confWriter/action.yml | 5 + conf/config.properties | 3 +- .../cn/edu/tsinghua/iginx/IginxWorker.java | 31 ++- .../logical/optimizer/IRuleCollection.java | 9 + .../optimizer/LogicalOptimizerManager.java | 36 ++- .../logical/optimizer/rbo/RBORuleCall.java | 16 -- .../engine/logical/utils/OperatorUtils.java | 2 +- .../physical/optimizer/PhysicalOptimizer.java | 4 - .../optimizer/PhysicalOptimizerManager.java | 45 ++-- .../shared/operator/AddSchemaPrefix.java | 12 + .../shared/operator/CombineNonQuery.java | 8 + .../engine/shared/operator/CrossJoin.java | 14 ++ .../iginx/engine/shared/operator/Delete.java | 17 ++ .../engine/shared/operator/Distinct.java | 12 + .../engine/shared/operator/Downsample.java | 15 ++ .../iginx/engine/shared/operator/Except.java | 14 ++ .../shared/operator/FoldedOperator.java | 8 + .../iginx/engine/shared/operator/GroupBy.java | 12 + .../engine/shared/operator/InnerJoin.java | 16 ++ .../iginx/engine/shared/operator/Insert.java | 13 + .../engine/shared/operator/Intersect.java | 14 ++ .../iginx/engine/shared/operator/Join.java | 12 + .../iginx/engine/shared/operator/Limit.java | 12 + .../shared/operator/MappingTransform.java | 12 + .../engine/shared/operator/MarkJoin.java | 15 ++ .../engine/shared/operator/Migration.java | 17 ++ .../engine/shared/operator/OuterJoin.java | 16 ++ .../engine/shared/operator/PathUnion.java | 8 + .../iginx/engine/shared/operator/Project.java | 16 ++ .../operator/ProjectWaitingForPath.java | 13 + .../iginx/engine/shared/operator/Rename.java | 12 + .../iginx/engine/shared/operator/Reorder.java | 14 ++ .../engine/shared/operator/RowTransform.java | 12 + .../iginx/engine/shared/operator/Select.java | 15 ++ .../engine/shared/operator/SetTransform.java | 12 + .../engine/shared/operator/ShowColumns.java | 15 ++ .../engine/shared/operator/SingleJoin.java | 15 ++ .../iginx/engine/shared/operator/Sort.java | 12 + .../iginx/engine/shared/operator/Union.java | 17 ++ .../shared/operator/ValueToSelectedPath.java | 15 ++ optimizer/.gitignore | 38 +++ optimizer/pom.xml | 113 +++++++++ optimizer/proguard.cfg | 16 ++ .../optimizer/FilterFragmentOptimizer.java | 8 +- .../optimizer/FilterPushDownOptimizer.java | 3 +- .../logical/optimizer/RemoveNotOptimizer.java | 3 +- .../logical/optimizer/core/Operand.java | 2 +- .../logical/optimizer/core/Planner.java | 6 +- .../logical/optimizer/core/RuleCall.java | 14 +- .../core/iterator/DeepFirstIterator.java | 2 +- .../core/iterator/LeveledIterator.java | 2 +- .../optimizer/core/iterator/MatchOrder.java | 2 +- .../iterator/ReverseDeepFirstIterator.java | 2 +- .../core/iterator/ReverseLeveledIterator.java | 2 +- .../optimizer/core/iterator/TreeIterator.java | 2 +- .../logical/optimizer/rbo/RBORuleCall.java | 17 ++ .../optimizer/rbo/RuleBasedOptimizer.java | 4 +- .../optimizer/rbo/RuleBasedPlanner.java | 32 +-- .../optimizer/rules/ColumnPruningRule.java | 36 +-- .../rules/ConstantPropagationRule.java | 4 +- .../rules/FilterConstantFoldingRule.java | 4 +- .../rules/FilterJoinTransposeRule.java | 4 +- .../FilterPushDownAddSchemaPrefixRule.java | 4 +- .../rules/FilterPushDownGroupByRule.java | 4 +- .../FilterPushDownPathUnionJoinRule.java | 4 +- .../FilterPushDownProjectReorderSortRule.java | 4 +- .../rules/FilterPushDownRenameRule.java | 4 +- .../rules/FilterPushDownSelectRule.java | 4 +- .../rules/FilterPushDownSetOpRule.java | 4 +- .../rules/FilterPushDownTransformRule.java | 4 +- .../FilterPushIntoJoinConditionRule.java | 4 +- .../rules/FilterPushOutJoinConditionRule.java | 4 +- .../rules/FragmentPruningByFilterRule.java | 9 +- .../rules/FragmentPruningByPatternRule.java | 4 +- .../rules/FunctionDistinctEliminateRule.java | 4 +- .../rules/InExistsDistinctEliminateRule.java | 4 +- .../optimizer/rules/NotFilterRemoveRule.java | 9 +- .../RowTransformConstantFoldingRule.java | 4 +- .../iginx}/logical/optimizer/rules/Rule.java | 6 +- .../optimizer/rules/RuleCollection.java | 14 +- .../logical/optimizer/rules/RuleStrategy.java | 2 +- .../naive/NaiveConstraintManager.java | 2 +- .../naive/NaivePhysicalOptimizer.java | 5 +- .../naive/NaiveReplicaDispatcher.java | 2 +- .../iginx}/physical/optimizer/rule/Rule.java | 2 +- .../iginx-optimizer-0.7.0-SNAPSHOT.jar | Bin 0 -> 212055 bytes .../iginx/optimizer/IteratorTest.java | 6 +- .../tsinghua/iginx/optimizer/OperandTest.java | 6 +- .../edu/tsinghua/iginx/optimizer/RBOTest.java | 6 +- .../iginx/optimizer/RBOTestUtils.java | 4 +- .../tsinghua/iginx/optimizer/TreeBuilder.java | 0 .../tsinghua/iginx/optimizer/TreePrinter.java | 0 pom.xml | 6 + .../integration/func/sql/SQLSessionIT.java | 226 +++++++++++++++++- .../iginx/integration/tool/TestUtils.java | 66 +++++ 95 files changed, 1106 insertions(+), 203 deletions(-) create mode 100644 core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/IRuleCollection.java delete mode 100644 core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rbo/RBORuleCall.java create mode 100644 optimizer/.gitignore create mode 100644 optimizer/pom.xml create mode 100644 optimizer/proguard.cfg rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/FilterFragmentOptimizer.java (96%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/FilterPushDownOptimizer.java (99%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/RemoveNotOptimizer.java (93%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/core/Operand.java (91%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/core/Planner.java (77%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/core/RuleCall.java (89%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/core/iterator/DeepFirstIterator.java (89%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/core/iterator/LeveledIterator.java (96%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/core/iterator/MatchOrder.java (56%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/core/iterator/ReverseDeepFirstIterator.java (91%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/core/iterator/ReverseLeveledIterator.java (88%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/core/iterator/TreeIterator.java (73%) create mode 100644 optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rbo/RBORuleCall.java rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/rbo/RuleBasedOptimizer.java (81%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/rbo/RuleBasedPlanner.java (78%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/rules/ColumnPruningRule.java (93%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/rules/ConstantPropagationRule.java (98%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/rules/FilterConstantFoldingRule.java (95%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/rules/FilterJoinTransposeRule.java (93%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/rules/FilterPushDownAddSchemaPrefixRule.java (96%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/rules/FilterPushDownGroupByRule.java (96%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/rules/FilterPushDownPathUnionJoinRule.java (98%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/rules/FilterPushDownProjectReorderSortRule.java (93%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/rules/FilterPushDownRenameRule.java (96%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/rules/FilterPushDownSelectRule.java (89%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/rules/FilterPushDownSetOpRule.java (97%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/rules/FilterPushDownTransformRule.java (98%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/rules/FilterPushIntoJoinConditionRule.java (94%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/rules/FilterPushOutJoinConditionRule.java (98%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/rules/FragmentPruningByFilterRule.java (96%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/rules/FragmentPruningByPatternRule.java (96%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/rules/FunctionDistinctEliminateRule.java (96%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/rules/InExistsDistinctEliminateRule.java (94%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/rules/NotFilterRemoveRule.java (85%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/rules/RowTransformConstantFoldingRule.java (95%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/rules/Rule.java (88%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/rules/RuleCollection.java (95%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/logical/optimizer/rules/RuleStrategy.java (63%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/physical/optimizer/naive/NaiveConstraintManager.java (98%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/physical/optimizer/naive/NaivePhysicalOptimizer.java (97%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/physical/optimizer/naive/NaiveReplicaDispatcher.java (95%) rename {core/src/main/java/cn/edu/tsinghua/iginx/engine => optimizer/src/main/java/cn/edu/tsinghua/iginx}/physical/optimizer/rule/Rule.java (93%) create mode 100644 optimizer/src/main/resources/iginx-optimizer-0.7.0-SNAPSHOT.jar rename {core => optimizer}/src/test/java/cn/edu/tsinghua/iginx/optimizer/IteratorTest.java (91%) rename {core => optimizer}/src/test/java/cn/edu/tsinghua/iginx/optimizer/OperandTest.java (89%) rename {core => optimizer}/src/test/java/cn/edu/tsinghua/iginx/optimizer/RBOTest.java (94%) rename {core => optimizer}/src/test/java/cn/edu/tsinghua/iginx/optimizer/RBOTestUtils.java (92%) rename {core => optimizer}/src/test/java/cn/edu/tsinghua/iginx/optimizer/TreeBuilder.java (100%) rename {core => optimizer}/src/test/java/cn/edu/tsinghua/iginx/optimizer/TreePrinter.java (100%) create mode 100644 test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/TestUtils.java diff --git a/.github/actions/confWriter/action.yml b/.github/actions/confWriter/action.yml index 117ddbaa2e..ea38d91995 100644 --- a/.github/actions/confWriter/action.yml +++ b/.github/actions/confWriter/action.yml @@ -200,3 +200,8 @@ runs: echo "$RUNNER_OS is not supported" exit 1 fi + + - name: Copy Optimizer Jar + shell: bash + run: | + cp -f "${GITHUB_WORKSPACE}/optimizer/src/main/resources/iginx-optimizer-${VERSION}.jar" "${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/lib/" diff --git a/conf/config.properties b/conf/config.properties index a347c1095a..892b496f93 100644 --- a/conf/config.properties +++ b/conf/config.properties @@ -55,7 +55,8 @@ queryOptimizer=rbo ruleBasedOptimizer=NotFilterRemoveRule=on,FragmentPruningByFilterRule=on,ColumnPruningRule=on,FragmentPruningByPatternRule=on,ConstantPropagationRule=on,FunctionDistinctEliminateRule=on,InExistsDistinctEliminateRule=on,\ FilterConstantFoldingRule=on,RowTransformConstantFoldingRule=on,FilterPushDownAddSchemaPrefixRule=off,FilterPushDownAddSchemaPrefixRule=off,\ FilterPushDownPathUnionJoinRule=off,FilterPushDownProjectReorderSortRule=off,FilterPushDownRenameRule=off,FilterPushDownSelectRule=off,\ - FilterPushDownSetOpRule=off,FilterPushDownTransformRule=off,FilterPushIntoJoinConditionRule=off,FilterPushOutJoinConditionRule=off,FilterPushDownGroupByRule=off + FilterPushDownSetOpRule=off,FilterPushDownTransformRule=off,FilterPushIntoJoinConditionRule=off,FilterPushOutJoinConditionRule=off,FilterPushDownGroupByRule=off,\ + JoinFactorizationRule=on # ParallelFilter触发行数 parallelFilterThreshold=10000 diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/IginxWorker.java b/core/src/main/java/cn/edu/tsinghua/iginx/IginxWorker.java index 16d95a0167..a71ddbdee9 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/IginxWorker.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/IginxWorker.java @@ -35,7 +35,7 @@ import cn.edu.tsinghua.iginx.conf.Constants; import cn.edu.tsinghua.iginx.engine.ContextBuilder; import cn.edu.tsinghua.iginx.engine.StatementExecutor; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.rules.RuleCollection; +import cn.edu.tsinghua.iginx.engine.logical.optimizer.IRuleCollection; import cn.edu.tsinghua.iginx.engine.physical.PhysicalEngineImpl; import cn.edu.tsinghua.iginx.engine.physical.storage.IStorage; import cn.edu.tsinghua.iginx.engine.physical.storage.StorageManager; @@ -1215,12 +1215,37 @@ public ShowSessionIDResp showSessionID(ShowSessionIDReq req) { @Override public ShowRulesResp showRules(ShowRulesReq req) { - return new ShowRulesResp(RpcUtils.SUCCESS, RuleCollection.getInstance().getRulesInfo()); + try { + IRuleCollection ruleCollection = getRuleCollection(); + return new ShowRulesResp(RpcUtils.SUCCESS, ruleCollection.getRulesInfo()); + } catch (ClassNotFoundException e) { + LOGGER.error("show rules failed: ", e); + return new ShowRulesResp(RpcUtils.FAILURE, null); + } } @Override public Status setRules(SetRulesReq req) { Map rulesChange = req.getRulesChange(); - return RuleCollection.getInstance().setRules(rulesChange) ? RpcUtils.SUCCESS : RpcUtils.FAILURE; + try { + getRuleCollection().setRules(rulesChange); + return RpcUtils.SUCCESS; + } catch (ClassNotFoundException e) { + LOGGER.error("set rules failed: ", e); + return RpcUtils.FAILURE; + } + } + + private IRuleCollection getRuleCollection() throws ClassNotFoundException { + // 获取接口的类加载器 + ClassLoader classLoader = IRuleCollection.class.getClassLoader(); + // 加载枚举类 + Class enumClass = + classLoader.loadClass("cn.edu.tsinghua.iginx.logical.optimizer.rules.RuleCollection"); + // 获取枚举实例 + Object enumInstance = enumClass.getEnumConstants()[0]; + + // 强制转换为接口类型 + return (IRuleCollection) enumInstance; } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/IRuleCollection.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/IRuleCollection.java new file mode 100644 index 0000000000..806e364b05 --- /dev/null +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/IRuleCollection.java @@ -0,0 +1,9 @@ +package cn.edu.tsinghua.iginx.engine.logical.optimizer; + +import java.util.Map; + +public interface IRuleCollection { + Map getRulesInfo(); + + boolean setRules(Map rulesChange); +} diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/LogicalOptimizerManager.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/LogicalOptimizerManager.java index d14b7508f6..08b11e4a5b 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/LogicalOptimizerManager.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/LogicalOptimizerManager.java @@ -1,6 +1,5 @@ package cn.edu.tsinghua.iginx.engine.logical.optimizer; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.rbo.RuleBasedOptimizer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -10,14 +9,11 @@ public class LogicalOptimizerManager { private static final LogicalOptimizerManager instance = new LogicalOptimizerManager(); - private static final String REMOVE_NOT = "remove_not"; - - private static final String FILTER_PUSH_DOWN = "filter_push_down"; - - private static final String FILTER_FRAGMENT = "filter_fragment"; - private static final String RULE_BASE = "rbo"; + private static final String RULE_BASE_class = + "cn.edu.tsinghua.iginx.logical.optimizer.rbo.RuleBasedOptimizer"; + private LogicalOptimizerManager() {} public static LogicalOptimizerManager getInstance() { @@ -29,18 +25,20 @@ public Optimizer getOptimizer(String name) { return null; } LOGGER.info("use {} as logical optimizer.", name); - - switch (name) { - case REMOVE_NOT: - return RemoveNotOptimizer.getInstance(); - case FILTER_PUSH_DOWN: - return FilterPushDownOptimizer.getInstance(); - case FILTER_FRAGMENT: - return FilterFragmentOptimizer.getInstance(); - case RULE_BASE: - return RuleBasedOptimizer.getInstance(); - default: - throw new IllegalArgumentException(String.format("unknown logical optimizer: %s", name)); + try { + switch (name) { + case RULE_BASE: + return Optimizer.class + .getClassLoader() + .loadClass(RULE_BASE_class) + .asSubclass(Optimizer.class) + .newInstance(); + default: + throw new IllegalArgumentException(String.format("unknown logical optimizer: %s", name)); + } + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { + LOGGER.error("Cannot load class: {}", name, e); } + return null; } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rbo/RBORuleCall.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rbo/RBORuleCall.java deleted file mode 100644 index 444d7b74be..0000000000 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rbo/RBORuleCall.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer.rbo; - -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.RuleCall; -import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; -import java.util.List; -import java.util.Map; - -public class RBORuleCall extends RuleCall { - - public RBORuleCall( - Operator subRoot, - Map parentIndexMap, - Map> childrenIndex) { - super(subRoot, parentIndexMap, childrenIndex); - } -} diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/utils/OperatorUtils.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/utils/OperatorUtils.java index a8b963337b..cd412cb750 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/utils/OperatorUtils.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/utils/OperatorUtils.java @@ -92,7 +92,7 @@ public static List findPathList(Operator operator) { } } - return pathList.stream().distinct().collect(Collectors.toList()); + return pathList.stream().distinct().sorted().collect(Collectors.toList()); } public static void findProjectOperators(List projectOperatorList, Operator operator) { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/optimizer/PhysicalOptimizer.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/optimizer/PhysicalOptimizer.java index 7d7cdeb0bf..d9b8f77e40 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/optimizer/PhysicalOptimizer.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/optimizer/PhysicalOptimizer.java @@ -18,12 +18,10 @@ */ package cn.edu.tsinghua.iginx.engine.physical.optimizer; -import cn.edu.tsinghua.iginx.engine.physical.optimizer.rule.Rule; import cn.edu.tsinghua.iginx.engine.physical.task.PhysicalTask; import cn.edu.tsinghua.iginx.engine.shared.RequestContext; import cn.edu.tsinghua.iginx.engine.shared.constraint.ConstraintManager; import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; -import java.util.Collection; public interface PhysicalOptimizer { @@ -32,6 +30,4 @@ public interface PhysicalOptimizer { ConstraintManager getConstraintManager(); ReplicaDispatcher getReplicaDispatcher(); - - void setRules(Collection rules); } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/optimizer/PhysicalOptimizerManager.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/optimizer/PhysicalOptimizerManager.java index 4e14ba2c04..8e75984242 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/optimizer/PhysicalOptimizerManager.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/optimizer/PhysicalOptimizerManager.java @@ -18,10 +18,7 @@ */ package cn.edu.tsinghua.iginx.engine.physical.optimizer; -import cn.edu.tsinghua.iginx.engine.physical.optimizer.naive.NaivePhysicalOptimizer; -import cn.edu.tsinghua.iginx.engine.physical.optimizer.rule.Rule; -import java.util.Collection; -import java.util.Collections; +import cn.edu.tsinghua.iginx.engine.logical.optimizer.Optimizer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -31,6 +28,9 @@ public class PhysicalOptimizerManager { private static final String NAIVE = "naive"; + private static final String NAIVE_CLASS = + "cn.edu.tsinghua.iginx.physical.optimizer.naive.NaivePhysicalOptimizer"; + private static final PhysicalOptimizerManager INSTANCE = new PhysicalOptimizerManager(); private PhysicalOptimizerManager() {} @@ -44,21 +44,30 @@ public PhysicalOptimizer getOptimizer(String name) { return null; } PhysicalOptimizer optimizer = null; - switch (name) { - case NAIVE: - LOGGER.info("use {} as physical optimizer.", name); - optimizer = NaivePhysicalOptimizer.getInstance(); - break; - default: - LOGGER.error("unknown physical optimizer {}, use {} as default.", name, NAIVE); - optimizer = NaivePhysicalOptimizer.getInstance(); + try { + switch (name) { + case NAIVE: + LOGGER.info("use {} as physical optimizer.", name); + optimizer = + Optimizer.class + .getClassLoader() + .loadClass(NAIVE_CLASS) + .asSubclass(PhysicalOptimizer.class) + .newInstance(); + break; + default: + LOGGER.error("unknown physical optimizer {}, use {} as default.", name, NAIVE); + optimizer = + Optimizer.class + .getClassLoader() + .loadClass(NAIVE_CLASS) + .asSubclass(PhysicalOptimizer.class) + .newInstance(); + } + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { + LOGGER.error("Cannot load class: {}", name, e); } - optimizer.setRules(getRules()); - return optimizer; - } - private Collection getRules() { - // TODO: get rule from conf - return Collections.emptyList(); + return optimizer; } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/AddSchemaPrefix.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/AddSchemaPrefix.java index 04ccd02bf3..461a3e7a9c 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/AddSchemaPrefix.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/AddSchemaPrefix.java @@ -30,4 +30,16 @@ public String getInfo() { public String getSchemaPrefix() { return schemaPrefix; } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + AddSchemaPrefix that = (AddSchemaPrefix) object; + return schemaPrefix.equals(that.schemaPrefix); + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/CombineNonQuery.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/CombineNonQuery.java index 6334e28223..2b7f163fe9 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/CombineNonQuery.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/CombineNonQuery.java @@ -24,4 +24,12 @@ public MultipleOperator copyWithSource(List sources) { public String getInfo() { return ""; } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + return object != null && getClass() == object.getClass(); + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/CrossJoin.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/CrossJoin.java index f6aa73092b..962796b97f 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/CrossJoin.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/CrossJoin.java @@ -48,4 +48,18 @@ public BinaryOperator copyWithSource(Source sourceA, Source sourceB) { public String getInfo() { return "PrefixA: " + getPrefixA() + ", PrefixB: " + getPrefixB(); } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + CrossJoin that = (CrossJoin) object; + return getPrefixA().equals(that.getPrefixA()) + && getPrefixB().equals(that.getPrefixB()) + && getExtraJoinPrefix().equals(that.getExtraJoinPrefix()); + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Delete.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Delete.java index 72ec71ecc6..96c2e692f8 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Delete.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Delete.java @@ -66,4 +66,21 @@ public String getInfo() { } return builder.toString(); } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + if (!super.equals(object)) { + return false; + } + Delete that = (Delete) object; + return keyRanges.equals(that.keyRanges) + && patterns.equals(that.patterns) + && tagFilter.equals(that.tagFilter); + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Distinct.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Distinct.java index 3a4faf76ba..5fe46ebc85 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Distinct.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Distinct.java @@ -32,4 +32,16 @@ public UnaryOperator copyWithSource(Source source) { public String getInfo() { return "Patterns: " + String.join(",", patterns); } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + Distinct that = (Distinct) object; + return patterns.equals(that.patterns); + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Downsample.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Downsample.java index b64040507e..24ca783c72 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Downsample.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Downsample.java @@ -129,6 +129,21 @@ public String getInfo() { return sb.toString(); } + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + Downsample that = (Downsample) object; + return precision == that.precision + && slideDistance == that.slideDistance + && functionCallList.equals(that.functionCallList) + && keyRange.equals(that.keyRange); + } + public boolean notSetInterval() { return getKeyRange().getBeginKey() == KEY_MIN_VAL && getKeyRange().getEndKey() == KEY_MAX_VAL; } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Except.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Except.java index ee841d088a..e11032f886 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Except.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Except.java @@ -77,4 +77,18 @@ public String getInfo() { builder.append(" isDistinct: ").append(isDistinct); return builder.toString(); } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + Except that = (Except) object; + return leftOrder.equals(that.leftOrder) + && rightOrder.equals(that.rightOrder) + && isDistinct == that.isDistinct; + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/FoldedOperator.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/FoldedOperator.java index 47d345c9a3..2b1a60e298 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/FoldedOperator.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/FoldedOperator.java @@ -32,4 +32,12 @@ public MultipleOperator copyWithSource(List sources) { public String getInfo() { return ""; } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + return object != null && getClass() == object.getClass(); + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/GroupBy.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/GroupBy.java index c0f2317114..766b24c3bf 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/GroupBy.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/GroupBy.java @@ -67,4 +67,16 @@ public String getInfo() { } return builder.toString(); } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + GroupBy that = (GroupBy) object; + return groupByCols.equals(that.groupByCols) && functionCallList.equals(that.functionCallList); + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/InnerJoin.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/InnerJoin.java index 5cac1359a1..f5ec0f683e 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/InnerJoin.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/InnerJoin.java @@ -222,4 +222,20 @@ public String getInfo() { } return builder.toString(); } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + InnerJoin that = (InnerJoin) object; + return isNaturalJoin == that.isNaturalJoin + && joinColumns.equals(that.joinColumns) + && filter.equals(that.filter) + && tagFilter.equals(that.tagFilter) + && getExtraJoinPrefix().equals(that.getExtraJoinPrefix()); + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Insert.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Insert.java index 44bc02bd22..18545b76dc 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Insert.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Insert.java @@ -36,4 +36,17 @@ public UnaryOperator copyWithSource(Source source) { public String getInfo() { return ""; } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + + Insert that = (Insert) object; + return data.equals(that.data); + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Intersect.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Intersect.java index 5eaac74c00..1471701daf 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Intersect.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Intersect.java @@ -77,4 +77,18 @@ public String getInfo() { builder.append(" isDistinct: ").append(isDistinct); return builder.toString(); } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + Intersect that = (Intersect) object; + return leftOrder.equals(that.leftOrder) + && rightOrder.equals(that.rightOrder) + && isDistinct == that.isDistinct; + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Join.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Join.java index 4eb706d0d2..c4b1e307d9 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Join.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Join.java @@ -56,4 +56,16 @@ public BinaryOperator copyWithSource(Source sourceA, Source sourceB) { public String getInfo() { return "JoinBy: " + joinBy; } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + Join join = (Join) object; + return joinBy.equals(join.joinBy); + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Limit.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Limit.java index a3ed3180bc..9c17a51757 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Limit.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Limit.java @@ -58,4 +58,16 @@ public UnaryOperator copyWithSource(Source source) { public String getInfo() { return "Limit: " + limit + ", Offset: " + offset; } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + Limit limit1 = (Limit) object; + return limit == limit1.limit && offset == limit1.offset; + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/MappingTransform.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/MappingTransform.java index 171bbd3d6b..e00feb5321 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/MappingTransform.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/MappingTransform.java @@ -72,4 +72,16 @@ public String getInfo() { return sb.toString(); } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + MappingTransform that = (MappingTransform) object; + return functionCallList.equals(that.functionCallList); + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/MarkJoin.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/MarkJoin.java index e11769ac0d..e111d5d807 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/MarkJoin.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/MarkJoin.java @@ -126,4 +126,19 @@ public String getInfo() { } return builder.toString(); } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + MarkJoin that = (MarkJoin) object; + return filter.equals(that.filter) + && markColumn.equals(that.markColumn) + && isAntiJoin == that.isAntiJoin + && getExtraJoinPrefix().equals(that.getExtraJoinPrefix()); + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Migration.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Migration.java index b558ec4776..95dfb6a898 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Migration.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Migration.java @@ -51,4 +51,21 @@ public UnaryOperator copyWithSource(Source source) { public String getInfo() { return ""; } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + if (!super.equals(object)) { + return false; + } + Migration that = (Migration) object; + return fragmentMeta.equals(that.fragmentMeta) + && paths.equals(that.paths) + && targetStorageUnitMeta.equals(that.targetStorageUnitMeta); + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/OuterJoin.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/OuterJoin.java index 32c6fe9a61..62e752f94d 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/OuterJoin.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/OuterJoin.java @@ -169,4 +169,20 @@ public String getInfo() { } return builder.toString(); } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + OuterJoin that = (OuterJoin) object; + return outerJoinType == that.outerJoinType + && filter.equals(that.filter) + && joinColumns.equals(that.joinColumns) + && isNaturalJoin == that.isNaturalJoin + && getExtraJoinPrefix().equals(that.getExtraJoinPrefix()); + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/PathUnion.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/PathUnion.java index 357fe177d3..7fd7345477 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/PathUnion.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/PathUnion.java @@ -41,4 +41,12 @@ public BinaryOperator copyWithSource(Source sourceA, Source sourceB) { public String getInfo() { return ""; } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + return object != null && getClass() == object.getClass(); + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Project.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Project.java index e58b6d6090..7e13d257d8 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Project.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Project.java @@ -8,6 +8,7 @@ import cn.edu.tsinghua.iginx.metadata.entity.FragmentMeta; import java.util.ArrayList; import java.util.List; +import java.util.Objects; public class Project extends AbstractUnaryOperator { @@ -108,4 +109,19 @@ public String getInfo() { } return builder.toString(); } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + Project that = (Project) object; + return patterns.equals(that.patterns) + && (Objects.equals(tagFilter, that.tagFilter)) + && remainKey == that.remainKey + && needSelectedPath == that.needSelectedPath; + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/ProjectWaitingForPath.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/ProjectWaitingForPath.java index 0bc20fd39f..cffe981363 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/ProjectWaitingForPath.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/ProjectWaitingForPath.java @@ -37,4 +37,17 @@ public UnaryOperator copyWithSource(Source source) { public String getInfo() { return ""; } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + + ProjectWaitingForPath that = (ProjectWaitingForPath) object; + return incompleteStatement.equals(that.incompleteStatement); + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Rename.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Rename.java index 45346f456d..9d88bc56ce 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Rename.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Rename.java @@ -57,4 +57,16 @@ public String getInfo() { } return builder.toString(); } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + Rename rename = (Rename) object; + return aliasMap.equals(rename.aliasMap) && ignorePatterns.equals(rename.ignorePatterns); + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Reorder.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Reorder.java index 0f609f87ab..e594b87c63 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Reorder.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Reorder.java @@ -97,4 +97,18 @@ private static boolean isUdfPath(String path) { } return false; } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + Reorder reorder = (Reorder) object; + return patterns.equals(reorder.patterns) + && isPyUDF.equals(reorder.isPyUDF) + && needSelectedPath == reorder.needSelectedPath; + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/RowTransform.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/RowTransform.java index f7e4739a28..f0acc74d43 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/RowTransform.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/RowTransform.java @@ -70,4 +70,16 @@ public String getInfo() { return sb.toString(); } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + RowTransform that = (RowTransform) object; + return functionCallList.equals(that.functionCallList); + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Select.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Select.java index 2c2f371f5f..13354a378b 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Select.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Select.java @@ -56,4 +56,19 @@ public String getInfo() { } return builder.toString(); } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + if (!super.equals(object)) { + return false; + } + Select select = (Select) object; + return filter.equals(select.filter) && tagFilter.equals(select.tagFilter); + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/SetTransform.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/SetTransform.java index 689f491e9e..9aa2ddcb77 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/SetTransform.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/SetTransform.java @@ -102,4 +102,16 @@ public String getInfo() { return sb.toString(); } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + SetTransform that = (SetTransform) object; + return functionCallList.equals(that.functionCallList); + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/ShowColumns.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/ShowColumns.java index e01a7b6c75..9b0daf1f1d 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/ShowColumns.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/ShowColumns.java @@ -83,4 +83,19 @@ public String getInfo() { } return builder.toString(); } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + ShowColumns that = (ShowColumns) object; + return limit == that.limit + && offset == that.offset + && pathRegexSet.equals(that.pathRegexSet) + && tagFilter.equals(that.tagFilter); + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/SingleJoin.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/SingleJoin.java index bc16a4ec41..7636a82d1b 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/SingleJoin.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/SingleJoin.java @@ -90,4 +90,19 @@ public String getInfo() { } return builder.toString(); } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + if (!super.equals(object)) { + return false; + } + SingleJoin that = (SingleJoin) object; + return filter.equals(that.filter) && tagFilter.equals(that.tagFilter); + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Sort.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Sort.java index efaa4f86e7..6d2f512309 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Sort.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Sort.java @@ -68,4 +68,16 @@ public enum SortType { public String getInfo() { return "SortBy: " + String.join(",", sortByCols) + ", SortType: " + sortType; } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + Sort sort = (Sort) object; + return sortByCols.equals(sort.sortByCols) && sortType == sort.sortType; + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Union.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Union.java index ea2ae11b7c..bf69c88f4f 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Union.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Union.java @@ -77,4 +77,21 @@ public String getInfo() { builder.append(" isDistinct: ").append(isDistinct); return builder.toString(); } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + if (!super.equals(object)) { + return false; + } + Union union = (Union) object; + return leftOrder.equals(union.leftOrder) + && rightOrder.equals(union.rightOrder) + && isDistinct == union.isDistinct; + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/ValueToSelectedPath.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/ValueToSelectedPath.java index a7bd115753..10943627fe 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/ValueToSelectedPath.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/ValueToSelectedPath.java @@ -35,4 +35,19 @@ public String getInfo() { } return builder.toString(); } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + if (!super.equals(object)) { + return false; + } + ValueToSelectedPath that = (ValueToSelectedPath) object; + return prefix.equals(that.prefix); + } } diff --git a/optimizer/.gitignore b/optimizer/.gitignore new file mode 100644 index 0000000000..5ff6309b71 --- /dev/null +++ b/optimizer/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/optimizer/pom.xml b/optimizer/pom.xml new file mode 100644 index 0000000000..75bf60216a --- /dev/null +++ b/optimizer/pom.xml @@ -0,0 +1,113 @@ + + + 4.0.0 + + cn.edu.tsinghua + iginx + ${revision} + ../pom.xml + + iginx-optimizer + IGinX Optimizer + + + 8 + 8 + UTF-8 + + + + + cn.edu.tsinghua + iginx-core + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + org.apache.maven.plugins + maven-dependency-plugin + 2.10 + + + copy-dependencies + + copy-dependencies + + package + + ../core/target/iginx-core-${project.version}/lib/ + provided + + + + + + + org.apache.maven.plugins + maven-antrun-plugin + 1.7 + + + copy-native-libraries + + run + + package + + + + + + + + + + + + + + + + + + java8 + + [1.8,1.8.999] + + + + + com.github.wvengen + proguard-maven-plugin + 2.6.0 + + ${project.basedir}/proguard.cfg + + + + + false + + ${java.home}/lib/rt.jar + + + + + + proguard + + + + + + + + + diff --git a/optimizer/proguard.cfg b/optimizer/proguard.cfg new file mode 100644 index 0000000000..b19333e1aa --- /dev/null +++ b/optimizer/proguard.cfg @@ -0,0 +1,16 @@ +# 保留指定类及其所有成员 +-keep class cn.edu.tsinghua.iginx.logical.optimizer.rbo.RuleBasedOptimizer { + *; +} + +-keep class cn.edu.tsinghua.iginx.physical.optimizer.naive.NaivePhysicalOptimizer { + *; +} + +-keep enum cn.edu.tsinghua.iginx.logical.optimizer.rules.RuleCollection { + *; +} + +-keep class cn.edu.tsinghua.iginx.logical.optimizer.rules.Rule { + *; +} diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/FilterFragmentOptimizer.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/FilterFragmentOptimizer.java similarity index 96% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/FilterFragmentOptimizer.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/FilterFragmentOptimizer.java index cdc222c317..099ebd3d08 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/FilterFragmentOptimizer.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/FilterFragmentOptimizer.java @@ -1,7 +1,6 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer; - -import static cn.edu.tsinghua.iginx.metadata.utils.FragmentUtils.keyFromColumnsIntervalToKeyInterval; +package cn.edu.tsinghua.iginx.logical.optimizer; +import cn.edu.tsinghua.iginx.engine.logical.optimizer.Optimizer; import cn.edu.tsinghua.iginx.engine.logical.utils.LogicalFilterUtils; import cn.edu.tsinghua.iginx.engine.logical.utils.OperatorUtils; import cn.edu.tsinghua.iginx.engine.shared.Constants; @@ -18,6 +17,7 @@ import cn.edu.tsinghua.iginx.metadata.entity.ColumnsInterval; import cn.edu.tsinghua.iginx.metadata.entity.FragmentMeta; import cn.edu.tsinghua.iginx.metadata.entity.KeyInterval; +import cn.edu.tsinghua.iginx.metadata.utils.FragmentUtils; import cn.edu.tsinghua.iginx.utils.Pair; import java.util.ArrayList; import java.util.List; @@ -92,7 +92,7 @@ private void filterFragmentByTimeRange(Select selectOperator) { Map> fragmentsByColumnsInterval = metaManager.getFragmentMapByColumnsInterval(columnsInterval, true); Pair>, List> pair = - keyFromColumnsIntervalToKeyInterval(fragmentsByColumnsInterval); + FragmentUtils.keyFromColumnsIntervalToKeyInterval(fragmentsByColumnsInterval); Map> fragments = pair.k; List dummyFragments = pair.v; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/FilterPushDownOptimizer.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/FilterPushDownOptimizer.java similarity index 99% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/FilterPushDownOptimizer.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/FilterPushDownOptimizer.java index de2680ebc9..924dd3316c 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/FilterPushDownOptimizer.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/FilterPushDownOptimizer.java @@ -1,5 +1,6 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer; +package cn.edu.tsinghua.iginx.logical.optimizer; +import cn.edu.tsinghua.iginx.engine.logical.optimizer.Optimizer; import cn.edu.tsinghua.iginx.engine.logical.utils.LogicalFilterUtils; import cn.edu.tsinghua.iginx.engine.logical.utils.OperatorUtils; import cn.edu.tsinghua.iginx.engine.shared.operator.*; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/RemoveNotOptimizer.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/RemoveNotOptimizer.java similarity index 93% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/RemoveNotOptimizer.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/RemoveNotOptimizer.java index 0456e3f239..a0d3bf9002 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/RemoveNotOptimizer.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/RemoveNotOptimizer.java @@ -1,5 +1,6 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer; +package cn.edu.tsinghua.iginx.logical.optimizer; +import cn.edu.tsinghua.iginx.engine.logical.optimizer.Optimizer; import cn.edu.tsinghua.iginx.engine.logical.utils.LogicalFilterUtils; import cn.edu.tsinghua.iginx.engine.logical.utils.OperatorUtils; import cn.edu.tsinghua.iginx.engine.shared.operator.*; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/core/Operand.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/Operand.java similarity index 91% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/core/Operand.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/Operand.java index f07e42d6e5..b2966c78bf 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/core/Operand.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/Operand.java @@ -1,4 +1,4 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer.core; +package cn.edu.tsinghua.iginx.logical.optimizer.core; import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; import java.util.List; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/core/Planner.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/Planner.java similarity index 77% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/core/Planner.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/Planner.java index a7badfa467..9b9380980e 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/core/Planner.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/Planner.java @@ -1,8 +1,8 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer.core; +package cn.edu.tsinghua.iginx.logical.optimizer.core; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.iterator.MatchOrder; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.rules.Rule; import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; +import cn.edu.tsinghua.iginx.logical.optimizer.core.iterator.MatchOrder; +import cn.edu.tsinghua.iginx.logical.optimizer.rules.Rule; import java.util.List; public interface Planner { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/core/RuleCall.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/RuleCall.java similarity index 89% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/core/RuleCall.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/RuleCall.java index 5d6f300b20..efefd6f160 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/core/RuleCall.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/RuleCall.java @@ -1,4 +1,4 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer.core; +package cn.edu.tsinghua.iginx.logical.optimizer.core; import cn.edu.tsinghua.iginx.engine.shared.operator.BinaryOperator; import cn.edu.tsinghua.iginx.engine.shared.operator.MultipleOperator; @@ -7,6 +7,7 @@ import cn.edu.tsinghua.iginx.engine.shared.operator.type.OperatorType; import cn.edu.tsinghua.iginx.engine.shared.source.OperatorSource; import cn.edu.tsinghua.iginx.engine.shared.source.Source; +import cn.edu.tsinghua.iginx.logical.optimizer.rbo.RuleBasedPlanner; import java.util.List; import java.util.Map; import org.slf4j.Logger; @@ -24,13 +25,17 @@ public abstract class RuleCall { private Object context; + private final RuleBasedPlanner planner; + public RuleCall( Operator matchedRoot, Map parentIndexMap, - Map> childrenIndex) { + Map> childrenIndex, + RuleBasedPlanner planner) { this.matchedRoot = matchedRoot; this.parentIndexMap = parentIndexMap; this.childrenIndex = childrenIndex; + this.planner = planner; } public Operator getMatchedRoot() { @@ -47,7 +52,10 @@ public Map getParentIndexMap() { public void transformTo(Operator newRoot) { Operator parent = parentIndexMap.get(matchedRoot); - assert parent != null; + if (parent == null) { + planner.setRoot(newRoot); + return; + } // replace topology OperatorType parentType = parent.getType(); diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/core/iterator/DeepFirstIterator.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/DeepFirstIterator.java similarity index 89% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/core/iterator/DeepFirstIterator.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/DeepFirstIterator.java index 72b9648e3d..25e0091ba0 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/core/iterator/DeepFirstIterator.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/DeepFirstIterator.java @@ -1,4 +1,4 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer.core.iterator; +package cn.edu.tsinghua.iginx.logical.optimizer.core.iterator; import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; import cn.edu.tsinghua.iginx.engine.shared.operator.visitor.DeepFirstQueueVisitor; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/core/iterator/LeveledIterator.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/LeveledIterator.java similarity index 96% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/core/iterator/LeveledIterator.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/LeveledIterator.java index 493cefe0c6..d76fe1905b 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/core/iterator/LeveledIterator.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/LeveledIterator.java @@ -1,4 +1,4 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer.core.iterator; +package cn.edu.tsinghua.iginx.logical.optimizer.core.iterator; import cn.edu.tsinghua.iginx.engine.shared.operator.BinaryOperator; import cn.edu.tsinghua.iginx.engine.shared.operator.MultipleOperator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/core/iterator/MatchOrder.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/MatchOrder.java similarity index 56% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/core/iterator/MatchOrder.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/MatchOrder.java index d9803ad785..96f0ec8922 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/core/iterator/MatchOrder.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/MatchOrder.java @@ -1,4 +1,4 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer.core.iterator; +package cn.edu.tsinghua.iginx.logical.optimizer.core.iterator; public enum MatchOrder { Leveled, diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/core/iterator/ReverseDeepFirstIterator.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/ReverseDeepFirstIterator.java similarity index 91% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/core/iterator/ReverseDeepFirstIterator.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/ReverseDeepFirstIterator.java index 8e7ed32a6a..8e6d323e0d 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/core/iterator/ReverseDeepFirstIterator.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/ReverseDeepFirstIterator.java @@ -1,4 +1,4 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer.core.iterator; +package cn.edu.tsinghua.iginx.logical.optimizer.core.iterator; import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; import cn.edu.tsinghua.iginx.engine.shared.operator.visitor.DeepFirstQueueVisitor; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/core/iterator/ReverseLeveledIterator.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/ReverseLeveledIterator.java similarity index 88% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/core/iterator/ReverseLeveledIterator.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/ReverseLeveledIterator.java index 43c01a3bd2..c42f720463 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/core/iterator/ReverseLeveledIterator.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/ReverseLeveledIterator.java @@ -1,4 +1,4 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer.core.iterator; +package cn.edu.tsinghua.iginx.logical.optimizer.core.iterator; import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; import java.util.Deque; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/core/iterator/TreeIterator.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/TreeIterator.java similarity index 73% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/core/iterator/TreeIterator.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/TreeIterator.java index 885e0c88a8..c226fc2c03 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/core/iterator/TreeIterator.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/TreeIterator.java @@ -1,4 +1,4 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer.core.iterator; +package cn.edu.tsinghua.iginx.logical.optimizer.core.iterator; import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; import java.util.Iterator; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rbo/RBORuleCall.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rbo/RBORuleCall.java new file mode 100644 index 0000000000..1298ad240f --- /dev/null +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rbo/RBORuleCall.java @@ -0,0 +1,17 @@ +package cn.edu.tsinghua.iginx.logical.optimizer.rbo; + +import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; +import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; +import java.util.List; +import java.util.Map; + +public class RBORuleCall extends RuleCall { + + public RBORuleCall( + Operator subRoot, + Map parentIndexMap, + Map> childrenIndex, + RuleBasedPlanner planner) { + super(subRoot, parentIndexMap, childrenIndex, planner); + } +} diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rbo/RuleBasedOptimizer.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rbo/RuleBasedOptimizer.java similarity index 81% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rbo/RuleBasedOptimizer.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rbo/RuleBasedOptimizer.java index b122626f82..aae3b09b6e 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rbo/RuleBasedOptimizer.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rbo/RuleBasedOptimizer.java @@ -1,8 +1,8 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer.rbo; +package cn.edu.tsinghua.iginx.logical.optimizer.rbo; import cn.edu.tsinghua.iginx.engine.logical.optimizer.Optimizer; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.Planner; import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; +import cn.edu.tsinghua.iginx.logical.optimizer.core.Planner; public class RuleBasedOptimizer implements Optimizer { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rbo/RuleBasedPlanner.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rbo/RuleBasedPlanner.java similarity index 78% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rbo/RuleBasedPlanner.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rbo/RuleBasedPlanner.java index 5f90c53d6d..5aa212dec5 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rbo/RuleBasedPlanner.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rbo/RuleBasedPlanner.java @@ -1,26 +1,26 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer.rbo; - -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.Operand; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.Planner; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.RuleCall; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.iterator.DeepFirstIterator; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.iterator.LeveledIterator; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.iterator.MatchOrder; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.iterator.ReverseDeepFirstIterator; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.iterator.ReverseLeveledIterator; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.iterator.TreeIterator; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.rules.Rule; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.rules.RuleCollection; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.rules.RuleStrategy; +package cn.edu.tsinghua.iginx.logical.optimizer.rbo; + import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; import cn.edu.tsinghua.iginx.engine.shared.operator.visitor.IndexVisitor; +import cn.edu.tsinghua.iginx.logical.optimizer.core.Operand; +import cn.edu.tsinghua.iginx.logical.optimizer.core.Planner; +import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; +import cn.edu.tsinghua.iginx.logical.optimizer.core.iterator.DeepFirstIterator; +import cn.edu.tsinghua.iginx.logical.optimizer.core.iterator.LeveledIterator; +import cn.edu.tsinghua.iginx.logical.optimizer.core.iterator.MatchOrder; +import cn.edu.tsinghua.iginx.logical.optimizer.core.iterator.ReverseDeepFirstIterator; +import cn.edu.tsinghua.iginx.logical.optimizer.core.iterator.ReverseLeveledIterator; +import cn.edu.tsinghua.iginx.logical.optimizer.core.iterator.TreeIterator; +import cn.edu.tsinghua.iginx.logical.optimizer.rules.Rule; +import cn.edu.tsinghua.iginx.logical.optimizer.rules.RuleCollection; +import cn.edu.tsinghua.iginx.logical.optimizer.rules.RuleStrategy; import java.util.*; public class RuleBasedPlanner implements Planner { private Operator root; - private final RuleCollection ruleCollection = RuleCollection.getInstance(); + private final RuleCollection ruleCollection = RuleCollection.INSTANCE; private Map parentIndex; private Map> childrenIndex; @@ -91,7 +91,7 @@ public Operator findBest() { continue; } - RuleCall ruleCall = new RBORuleCall(op, parentIndex, childrenIndex); + RuleCall ruleCall = new RBORuleCall(op, parentIndex, childrenIndex, this); if (!rule.matches(ruleCall)) { continue; } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/ColumnPruningRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/ColumnPruningRule.java similarity index 93% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/ColumnPruningRule.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/ColumnPruningRule.java index fab9fa0b41..573815ffbf 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/ColumnPruningRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/ColumnPruningRule.java @@ -1,10 +1,9 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer.rules; +package cn.edu.tsinghua.iginx.logical.optimizer.rules; -import static cn.edu.tsinghua.iginx.engine.logical.utils.OperatorUtils.covers; import static cn.edu.tsinghua.iginx.engine.logical.utils.PathUtils.*; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.RuleCall; import cn.edu.tsinghua.iginx.engine.logical.utils.OperatorUtils; +import cn.edu.tsinghua.iginx.engine.logical.utils.PathUtils; import cn.edu.tsinghua.iginx.engine.physical.memory.execute.utils.ExprUtils; import cn.edu.tsinghua.iginx.engine.physical.memory.execute.utils.FilterUtils; import cn.edu.tsinghua.iginx.engine.shared.Constants; @@ -20,6 +19,7 @@ import cn.edu.tsinghua.iginx.engine.shared.operator.type.OperatorType; import cn.edu.tsinghua.iginx.engine.shared.source.FragmentSource; import cn.edu.tsinghua.iginx.engine.shared.source.OperatorSource; +import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; import cn.edu.tsinghua.iginx.utils.Pair; import cn.edu.tsinghua.iginx.utils.StringUtils; import java.util.*; @@ -78,7 +78,7 @@ private void collectColumns( } else if (operator.getType() == OperatorType.Reorder) { Reorder reorder = (Reorder) operator; if (columns.isEmpty() - || (hasWildCard(columns) && checkCoverage(columns, reorder.getPatterns()))) { + || (hasWildCard(columns) && PathUtils.checkCoverage(columns, reorder.getPatterns()))) { columns.clear(); columns.addAll(reorder.getPatterns()); } else { @@ -89,7 +89,7 @@ private void collectColumns( } else if (operator.getType() == OperatorType.Project) { Project project = (Project) operator; if (columns.isEmpty() - || hasWildCard(columns) && checkCoverage(columns, project.getPatterns())) { + || hasWildCard(columns) && PathUtils.checkCoverage(columns, project.getPatterns())) { columns.clear(); columns.addAll(project.getPatterns()); tagFilter = project.getTagFilter(); @@ -106,7 +106,8 @@ private void collectColumns( } else if (operator.getType() == OperatorType.Rename) { Rename rename = (Rename) operator; Map aliasMap = rename.getAliasMap(); - columns = new HashSet<>(recoverRenamedPatterns(aliasMap, new ArrayList<>(columns))); + columns = + new HashSet<>(PathUtils.recoverRenamedPatterns(aliasMap, new ArrayList<>(columns))); } else if (operator.getType() == OperatorType.GroupBy) { GroupBy groupBy = (GroupBy) operator; @@ -250,8 +251,10 @@ private void collectColumns( if (PrefixA != null && PrefixB != null) { for (String column : columns) { if (column.contains("*") - && (!covers(PrefixA + ".*", column) && covers(column, PrefixA + ".*")) - && (!covers(PrefixB + ".*", column) && covers(column, PrefixB + ".*"))) { + && (!OperatorUtils.covers(PrefixA + ".*", column) + && OperatorUtils.covers(column, PrefixA + ".*")) + && (!OperatorUtils.covers(PrefixB + ".*", column) + && OperatorUtils.covers(column, PrefixB + ".*"))) { /* 如果现有的列中包含通配符*,这个通配符会受到当前Join算子的限制,不再能下推,再推下去会导致取的列过多 例如最顶上Project的test.*,但是JOIN算子左右两侧是test.a.*和test.b.*,这是的test.*实际上取的列是test.a.*和test.b.*的并集 @@ -270,9 +273,11 @@ private void collectColumns( break; } - if (covers(PrefixA + ".*", column) || covers(column, PrefixA + ".*")) { + if (OperatorUtils.covers(PrefixA + ".*", column) + || OperatorUtils.covers(column, PrefixA + ".*")) { leftColumns.add(column); - } else if (covers(PrefixB + ".*", column) || covers(column, PrefixB + ".*")) { + } else if (OperatorUtils.covers(PrefixB + ".*", column) + || OperatorUtils.covers(column, PrefixB + ".*")) { rightColumns.add(column); } else { // 如果没有匹配的话,可能是连续JOIN的情况,即SELECT t1.*, t2.*, t3.* FROM t1 JOIN t2 JOIN t3;(这里省略了ON条件) @@ -290,13 +295,10 @@ private void collectColumns( } else if (OperatorType.isSetOperator(operator.getType())) { Pair, List> orderPair = getSetOperatorOrder(operator); List leftOrder = orderPair.getK(), rightOrder = orderPair.getV(); - if (hasPatternOperator(visitedOperators)) { + // 如果左侧将要替换的columns和右侧order有*的话,我们无法确定具体*对应的列数,因此不裁剪,继续往下递归 + if (hasPatternOperator(visitedOperators) + && !(columns.isEmpty() || hasWildCard(columns) || hasWildCard(rightOrder))) { // SetOperator要求左右两侧的列数相同,我们只对左侧进行列裁剪,然后右侧相应减少对应的列(有顺序要求) - // 如果左侧将要替换的columns和右侧order有*的话,我们无法确定具体*对应的列数,不能进行列裁剪,直接return - if (hasWildCard(columns) || hasWildCard(rightOrder)) { - return; - } - List newLeftOrder = getOrderListFromColumns(columns, leftOrder); List newRightOrder = new ArrayList<>(); // 去除右侧,索引超出左侧的列 @@ -499,7 +501,7 @@ private static Set getNewColumns( for (String newColumn : newColumnList) { boolean covered = false; for (String c : columns) { - if (covers(c, newColumn)) { + if (OperatorUtils.covers(c, newColumn)) { covered = true; break; } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/ConstantPropagationRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/ConstantPropagationRule.java similarity index 98% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/ConstantPropagationRule.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/ConstantPropagationRule.java index b2c42866df..b578662561 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/ConstantPropagationRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/ConstantPropagationRule.java @@ -1,6 +1,5 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer.rules; +package cn.edu.tsinghua.iginx.logical.optimizer.rules; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.RuleCall; import cn.edu.tsinghua.iginx.engine.logical.utils.LogicalFilterUtils; import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; import cn.edu.tsinghua.iginx.engine.physical.memory.execute.utils.ExprUtils; @@ -10,6 +9,7 @@ import cn.edu.tsinghua.iginx.engine.shared.expr.*; import cn.edu.tsinghua.iginx.engine.shared.operator.Select; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.*; +import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; import cn.edu.tsinghua.iginx.utils.Pair; import java.util.ArrayList; import java.util.HashMap; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterConstantFoldingRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterConstantFoldingRule.java similarity index 95% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterConstantFoldingRule.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterConstantFoldingRule.java index fd625e7415..70a2c15fd9 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterConstantFoldingRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterConstantFoldingRule.java @@ -1,12 +1,12 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer.rules; +package cn.edu.tsinghua.iginx.logical.optimizer.rules; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.RuleCall; import cn.edu.tsinghua.iginx.engine.logical.utils.LogicalFilterUtils; import cn.edu.tsinghua.iginx.engine.physical.memory.execute.utils.ExprUtils; import cn.edu.tsinghua.iginx.engine.shared.expr.*; import cn.edu.tsinghua.iginx.engine.shared.operator.Select; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.ExprFilter; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Filter; +import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; import java.util.List; import java.util.logging.Logger; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterJoinTransposeRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterJoinTransposeRule.java similarity index 93% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterJoinTransposeRule.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterJoinTransposeRule.java index 79c815cb03..bd26369a56 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterJoinTransposeRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterJoinTransposeRule.java @@ -1,12 +1,12 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer.rules; +package cn.edu.tsinghua.iginx.logical.optimizer.rules; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.RuleCall; import cn.edu.tsinghua.iginx.engine.shared.operator.AbstractJoin; import cn.edu.tsinghua.iginx.engine.shared.operator.MarkJoin; import cn.edu.tsinghua.iginx.engine.shared.operator.Select; import cn.edu.tsinghua.iginx.engine.shared.operator.SingleJoin; import cn.edu.tsinghua.iginx.engine.shared.source.OperatorSource; import cn.edu.tsinghua.iginx.engine.shared.source.Source; +import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; public class FilterJoinTransposeRule extends Rule { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterPushDownAddSchemaPrefixRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownAddSchemaPrefixRule.java similarity index 96% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterPushDownAddSchemaPrefixRule.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownAddSchemaPrefixRule.java index b8f96b5d58..0ebf6eeb8e 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterPushDownAddSchemaPrefixRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownAddSchemaPrefixRule.java @@ -1,11 +1,11 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer.rules; +package cn.edu.tsinghua.iginx.logical.optimizer.rules; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.RuleCall; import cn.edu.tsinghua.iginx.engine.shared.expr.*; import cn.edu.tsinghua.iginx.engine.shared.operator.AddSchemaPrefix; import cn.edu.tsinghua.iginx.engine.shared.operator.Select; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.*; import cn.edu.tsinghua.iginx.engine.shared.source.OperatorSource; +import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; public class FilterPushDownAddSchemaPrefixRule extends Rule { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterPushDownGroupByRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownGroupByRule.java similarity index 96% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterPushDownGroupByRule.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownGroupByRule.java index 727ecb29f0..1c5e13f439 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterPushDownGroupByRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownGroupByRule.java @@ -1,12 +1,12 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer.rules; +package cn.edu.tsinghua.iginx.logical.optimizer.rules; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.RuleCall; import cn.edu.tsinghua.iginx.engine.logical.utils.LogicalFilterUtils; import cn.edu.tsinghua.iginx.engine.shared.operator.*; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.AndFilter; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Filter; import cn.edu.tsinghua.iginx.engine.shared.operator.type.OperatorType; import cn.edu.tsinghua.iginx.engine.shared.source.OperatorSource; +import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterPushDownPathUnionJoinRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownPathUnionJoinRule.java similarity index 98% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterPushDownPathUnionJoinRule.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownPathUnionJoinRule.java index b8a4732330..cc045cc3ad 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterPushDownPathUnionJoinRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownPathUnionJoinRule.java @@ -1,6 +1,5 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer.rules; +package cn.edu.tsinghua.iginx.logical.optimizer.rules; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.RuleCall; import cn.edu.tsinghua.iginx.engine.logical.utils.LogicalFilterUtils; import cn.edu.tsinghua.iginx.engine.logical.utils.OperatorUtils; import cn.edu.tsinghua.iginx.engine.physical.memory.execute.utils.ExprUtils; @@ -10,6 +9,7 @@ import cn.edu.tsinghua.iginx.engine.shared.operator.type.OuterJoinType; import cn.edu.tsinghua.iginx.engine.shared.source.FragmentSource; import cn.edu.tsinghua.iginx.engine.shared.source.OperatorSource; +import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; import cn.edu.tsinghua.iginx.metadata.entity.ColumnsInterval; import java.util.*; import java.util.stream.Collectors; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterPushDownProjectReorderSortRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownProjectReorderSortRule.java similarity index 93% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterPushDownProjectReorderSortRule.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownProjectReorderSortRule.java index 4ff8029199..9d44733996 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterPushDownProjectReorderSortRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownProjectReorderSortRule.java @@ -1,9 +1,9 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer.rules; +package cn.edu.tsinghua.iginx.logical.optimizer.rules; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.RuleCall; import cn.edu.tsinghua.iginx.engine.shared.operator.*; import cn.edu.tsinghua.iginx.engine.shared.source.OperatorSource; import cn.edu.tsinghua.iginx.engine.shared.source.SourceType; +import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; import java.util.Arrays; import java.util.HashSet; import java.util.Set; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterPushDownRenameRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownRenameRule.java similarity index 96% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterPushDownRenameRule.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownRenameRule.java index 979923feb7..01c248c08a 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterPushDownRenameRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownRenameRule.java @@ -1,12 +1,12 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer.rules; +package cn.edu.tsinghua.iginx.logical.optimizer.rules; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.RuleCall; import cn.edu.tsinghua.iginx.engine.logical.utils.PathUtils; import cn.edu.tsinghua.iginx.engine.shared.expr.*; import cn.edu.tsinghua.iginx.engine.shared.operator.Rename; import cn.edu.tsinghua.iginx.engine.shared.operator.Select; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.*; import cn.edu.tsinghua.iginx.engine.shared.source.OperatorSource; +import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; import java.util.Map; public class FilterPushDownRenameRule extends Rule { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterPushDownSelectRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownSelectRule.java similarity index 89% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterPushDownSelectRule.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownSelectRule.java index ed3eb9558c..27663a0e8f 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterPushDownSelectRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownSelectRule.java @@ -1,8 +1,8 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer.rules; +package cn.edu.tsinghua.iginx.logical.optimizer.rules; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.RuleCall; import cn.edu.tsinghua.iginx.engine.logical.utils.LogicalFilterUtils; import cn.edu.tsinghua.iginx.engine.shared.operator.Select; +import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; public class FilterPushDownSelectRule extends Rule { private static final class InstanceHolder { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterPushDownSetOpRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownSetOpRule.java similarity index 97% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterPushDownSetOpRule.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownSetOpRule.java index 396860f51d..935707782d 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterPushDownSetOpRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownSetOpRule.java @@ -1,10 +1,10 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer.rules; +package cn.edu.tsinghua.iginx.logical.optimizer.rules; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.RuleCall; import cn.edu.tsinghua.iginx.engine.shared.Constants; import cn.edu.tsinghua.iginx.engine.shared.operator.*; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.*; import cn.edu.tsinghua.iginx.engine.shared.source.OperatorSource; +import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; import cn.edu.tsinghua.iginx.utils.Pair; import java.util.*; import java.util.stream.IntStream; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterPushDownTransformRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownTransformRule.java similarity index 98% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterPushDownTransformRule.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownTransformRule.java index 4b7d6bf362..c69e11bd29 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterPushDownTransformRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownTransformRule.java @@ -1,12 +1,12 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer.rules; +package cn.edu.tsinghua.iginx.logical.optimizer.rules; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.RuleCall; import cn.edu.tsinghua.iginx.engine.logical.utils.LogicalFilterUtils; import cn.edu.tsinghua.iginx.engine.shared.expr.*; import cn.edu.tsinghua.iginx.engine.shared.function.FunctionCall; import cn.edu.tsinghua.iginx.engine.shared.operator.*; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.*; import cn.edu.tsinghua.iginx.engine.shared.source.OperatorSource; +import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; import cn.edu.tsinghua.iginx.utils.StringUtils; import java.util.*; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterPushIntoJoinConditionRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushIntoJoinConditionRule.java similarity index 94% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterPushIntoJoinConditionRule.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushIntoJoinConditionRule.java index 916116b379..99124f28a9 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterPushIntoJoinConditionRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushIntoJoinConditionRule.java @@ -1,9 +1,9 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer.rules; +package cn.edu.tsinghua.iginx.logical.optimizer.rules; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.RuleCall; import cn.edu.tsinghua.iginx.engine.physical.memory.execute.utils.FilterUtils; import cn.edu.tsinghua.iginx.engine.shared.operator.*; import cn.edu.tsinghua.iginx.engine.shared.operator.type.OperatorType; +import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; import java.util.*; public class FilterPushIntoJoinConditionRule extends Rule { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterPushOutJoinConditionRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushOutJoinConditionRule.java similarity index 98% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterPushOutJoinConditionRule.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushOutJoinConditionRule.java index 1dc1905636..2480e36edf 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FilterPushOutJoinConditionRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushOutJoinConditionRule.java @@ -1,6 +1,5 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer.rules; +package cn.edu.tsinghua.iginx.logical.optimizer.rules; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.RuleCall; import cn.edu.tsinghua.iginx.engine.logical.utils.LogicalFilterUtils; import cn.edu.tsinghua.iginx.engine.logical.utils.OperatorUtils; import cn.edu.tsinghua.iginx.engine.shared.operator.*; @@ -12,6 +11,7 @@ import cn.edu.tsinghua.iginx.engine.shared.operator.type.OperatorType; import cn.edu.tsinghua.iginx.engine.shared.operator.type.OuterJoinType; import cn.edu.tsinghua.iginx.engine.shared.source.OperatorSource; +import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; import java.util.*; public class FilterPushOutJoinConditionRule extends Rule { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FragmentPruningByFilterRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FragmentPruningByFilterRule.java similarity index 96% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FragmentPruningByFilterRule.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FragmentPruningByFilterRule.java index 63634c6612..9dad7ff188 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FragmentPruningByFilterRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FragmentPruningByFilterRule.java @@ -1,8 +1,5 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer.rules; +package cn.edu.tsinghua.iginx.logical.optimizer.rules; -import static cn.edu.tsinghua.iginx.metadata.utils.FragmentUtils.keyFromColumnsIntervalToKeyInterval; - -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.RuleCall; import cn.edu.tsinghua.iginx.engine.logical.utils.LogicalFilterUtils; import cn.edu.tsinghua.iginx.engine.logical.utils.OperatorUtils; import cn.edu.tsinghua.iginx.engine.shared.Constants; @@ -13,11 +10,13 @@ import cn.edu.tsinghua.iginx.engine.shared.operator.visitor.OperatorVisitor; import cn.edu.tsinghua.iginx.engine.shared.source.FragmentSource; import cn.edu.tsinghua.iginx.engine.shared.source.OperatorSource; +import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; import cn.edu.tsinghua.iginx.metadata.IMetaManager; import cn.edu.tsinghua.iginx.metadata.MetaManagerWrapper; import cn.edu.tsinghua.iginx.metadata.entity.ColumnsInterval; import cn.edu.tsinghua.iginx.metadata.entity.FragmentMeta; import cn.edu.tsinghua.iginx.metadata.entity.KeyInterval; +import cn.edu.tsinghua.iginx.metadata.utils.FragmentUtils; import cn.edu.tsinghua.iginx.utils.Pair; import java.util.ArrayList; import java.util.List; @@ -153,7 +152,7 @@ public void onMatch(RuleCall call) { Map> fragmentsByColumnsInterval = metaManager.getFragmentMapByColumnsInterval(columnsInterval, true); Pair>, List> pair = - keyFromColumnsIntervalToKeyInterval(fragmentsByColumnsInterval); + FragmentUtils.keyFromColumnsIntervalToKeyInterval(fragmentsByColumnsInterval); Map> fragments = pair.k; List dummyFragments = pair.v; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FragmentPruningByPatternRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FragmentPruningByPatternRule.java similarity index 96% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FragmentPruningByPatternRule.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FragmentPruningByPatternRule.java index cb8040d8aa..23a08832cf 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FragmentPruningByPatternRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FragmentPruningByPatternRule.java @@ -1,11 +1,11 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer.rules; +package cn.edu.tsinghua.iginx.logical.optimizer.rules; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.RuleCall; import cn.edu.tsinghua.iginx.engine.shared.operator.*; import cn.edu.tsinghua.iginx.engine.shared.operator.type.OperatorType; import cn.edu.tsinghua.iginx.engine.shared.source.FragmentSource; import cn.edu.tsinghua.iginx.engine.shared.source.OperatorSource; import cn.edu.tsinghua.iginx.engine.shared.source.Source; +import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; import cn.edu.tsinghua.iginx.metadata.entity.ColumnsInterval; import java.util.ArrayList; import java.util.List; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FunctionDistinctEliminateRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FunctionDistinctEliminateRule.java similarity index 96% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FunctionDistinctEliminateRule.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FunctionDistinctEliminateRule.java index fffe718ce9..ab6518e5b7 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/FunctionDistinctEliminateRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FunctionDistinctEliminateRule.java @@ -1,12 +1,12 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer.rules; +package cn.edu.tsinghua.iginx.logical.optimizer.rules; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.RuleCall; import cn.edu.tsinghua.iginx.engine.shared.function.FunctionCall; import cn.edu.tsinghua.iginx.engine.shared.function.system.Max; import cn.edu.tsinghua.iginx.engine.shared.function.system.Min; import cn.edu.tsinghua.iginx.engine.shared.operator.*; import cn.edu.tsinghua.iginx.engine.shared.operator.type.OperatorType; import cn.edu.tsinghua.iginx.engine.shared.source.OperatorSource; +import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; import java.util.*; /** 该类实现了GroupBy节点中函数中的Distinct的消除。该规则用于消除函数中的Distinct,比如在min(distinct a)中的distinct是不必要的。 */ diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/InExistsDistinctEliminateRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/InExistsDistinctEliminateRule.java similarity index 94% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/InExistsDistinctEliminateRule.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/InExistsDistinctEliminateRule.java index 4d616d58a3..9408ae86fc 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/InExistsDistinctEliminateRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/InExistsDistinctEliminateRule.java @@ -1,10 +1,10 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer.rules; +package cn.edu.tsinghua.iginx.logical.optimizer.rules; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.RuleCall; import cn.edu.tsinghua.iginx.engine.shared.operator.AbstractJoin; import cn.edu.tsinghua.iginx.engine.shared.operator.Distinct; import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; import cn.edu.tsinghua.iginx.engine.shared.operator.type.OperatorType; +import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; /** * 该类实现了Distinct节点的消除。该规则用于消除IN/EXISTS子查询中的DISTINCT节点, 例如SELECT * FROM t1 WHERE EXISTS (SELECT diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/NotFilterRemoveRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/NotFilterRemoveRule.java similarity index 85% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/NotFilterRemoveRule.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/NotFilterRemoveRule.java index 207ce87ff8..6c4b00d962 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/NotFilterRemoveRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/NotFilterRemoveRule.java @@ -1,10 +1,9 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer.rules; +package cn.edu.tsinghua.iginx.logical.optimizer.rules; -import static cn.edu.tsinghua.iginx.engine.logical.utils.LogicalFilterUtils.removeNot; - -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.RuleCall; +import cn.edu.tsinghua.iginx.engine.logical.utils.LogicalFilterUtils; import cn.edu.tsinghua.iginx.engine.shared.operator.*; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.*; +import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; public class NotFilterRemoveRule extends Rule { @@ -66,6 +65,6 @@ public void visit(ExprFilter filter) {} @Override public void onMatch(RuleCall call) { Select select = (Select) call.getMatchedRoot(); - select.setFilter(removeNot(select.getFilter())); + select.setFilter(LogicalFilterUtils.removeNot(select.getFilter())); } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/RowTransformConstantFoldingRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/RowTransformConstantFoldingRule.java similarity index 95% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/RowTransformConstantFoldingRule.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/RowTransformConstantFoldingRule.java index 4a5ce5dda5..499154b87b 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/RowTransformConstantFoldingRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/RowTransformConstantFoldingRule.java @@ -1,12 +1,12 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer.rules; +package cn.edu.tsinghua.iginx.logical.optimizer.rules; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.RuleCall; import cn.edu.tsinghua.iginx.engine.physical.memory.execute.utils.ExprUtils; import cn.edu.tsinghua.iginx.engine.shared.expr.Expression; import cn.edu.tsinghua.iginx.engine.shared.function.FunctionCall; import cn.edu.tsinghua.iginx.engine.shared.operator.Rename; import cn.edu.tsinghua.iginx.engine.shared.operator.RowTransform; import cn.edu.tsinghua.iginx.engine.shared.source.OperatorSource; +import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; import java.util.HashMap; import java.util.List; import java.util.Map; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/Rule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/Rule.java similarity index 88% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/Rule.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/Rule.java index cac1297220..ccea39df2e 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/Rule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/Rule.java @@ -1,8 +1,8 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer.rules; +package cn.edu.tsinghua.iginx.logical.optimizer.rules; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.Operand; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.RuleCall; import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; +import cn.edu.tsinghua.iginx.logical.optimizer.core.Operand; +import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; import java.util.Arrays; public abstract class Rule { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/RuleCollection.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/RuleCollection.java similarity index 95% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/RuleCollection.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/RuleCollection.java index 13aa0f4e20..517e14a6c7 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/RuleCollection.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/RuleCollection.java @@ -1,12 +1,14 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer.rules; +package cn.edu.tsinghua.iginx.logical.optimizer.rules; import cn.edu.tsinghua.iginx.conf.Config; import cn.edu.tsinghua.iginx.conf.ConfigDescriptor; +import cn.edu.tsinghua.iginx.engine.logical.optimizer.IRuleCollection; import java.util.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class RuleCollection { +public enum RuleCollection implements IRuleCollection { + INSTANCE; private static final Logger LOGGER = LoggerFactory.getLogger(RuleCollection.class); @@ -16,14 +18,6 @@ public class RuleCollection { private ConfigDescriptor configDescriptor = ConfigDescriptor.getInstance(); - private static final class InstanceHolder { - static final RuleCollection INSTANCE = new RuleCollection(); - } - - public static RuleCollection getInstance() { - return InstanceHolder.INSTANCE; - } - private RuleCollection() { // add rules here // 在这里添加规则 diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/RuleStrategy.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/RuleStrategy.java similarity index 63% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/RuleStrategy.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/RuleStrategy.java index 4fa03e64f2..761e34e82b 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/rules/RuleStrategy.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/RuleStrategy.java @@ -1,4 +1,4 @@ -package cn.edu.tsinghua.iginx.engine.logical.optimizer.rules; +package cn.edu.tsinghua.iginx.logical.optimizer.rules; public enum RuleStrategy { FIXED_POINT, // 一直执行直到不再有匹配 diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/optimizer/naive/NaiveConstraintManager.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/physical/optimizer/naive/NaiveConstraintManager.java similarity index 98% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/optimizer/naive/NaiveConstraintManager.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/physical/optimizer/naive/NaiveConstraintManager.java index 31b9a08741..5887797ba4 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/optimizer/naive/NaiveConstraintManager.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/physical/optimizer/naive/NaiveConstraintManager.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package cn.edu.tsinghua.iginx.engine.physical.optimizer.naive; +package cn.edu.tsinghua.iginx.physical.optimizer.naive; import cn.edu.tsinghua.iginx.engine.shared.constraint.ConstraintManager; import cn.edu.tsinghua.iginx.engine.shared.operator.*; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/optimizer/naive/NaivePhysicalOptimizer.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/physical/optimizer/naive/NaivePhysicalOptimizer.java similarity index 97% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/optimizer/naive/NaivePhysicalOptimizer.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/physical/optimizer/naive/NaivePhysicalOptimizer.java index 3a65425d29..2450a17cfb 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/optimizer/naive/NaivePhysicalOptimizer.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/physical/optimizer/naive/NaivePhysicalOptimizer.java @@ -16,12 +16,11 @@ * specific language governing permissions and limitations * under the License. */ -package cn.edu.tsinghua.iginx.engine.physical.optimizer.naive; +package cn.edu.tsinghua.iginx.physical.optimizer.naive; import cn.edu.tsinghua.iginx.conf.ConfigDescriptor; import cn.edu.tsinghua.iginx.engine.physical.optimizer.PhysicalOptimizer; import cn.edu.tsinghua.iginx.engine.physical.optimizer.ReplicaDispatcher; -import cn.edu.tsinghua.iginx.engine.physical.optimizer.rule.Rule; import cn.edu.tsinghua.iginx.engine.physical.task.*; import cn.edu.tsinghua.iginx.engine.shared.RequestContext; import cn.edu.tsinghua.iginx.engine.shared.constraint.ConstraintManager; @@ -30,6 +29,7 @@ import cn.edu.tsinghua.iginx.engine.shared.source.OperatorSource; import cn.edu.tsinghua.iginx.engine.shared.source.Source; import cn.edu.tsinghua.iginx.engine.shared.source.SourceType; +import cn.edu.tsinghua.iginx.physical.optimizer.rule.Rule; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -58,7 +58,6 @@ public ReplicaDispatcher getReplicaDispatcher() { return NaiveReplicaDispatcher.getInstance(); } - @Override public void setRules(Collection rules) {} private PhysicalTask constructTask(Operator operator, RequestContext context) { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/optimizer/naive/NaiveReplicaDispatcher.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/physical/optimizer/naive/NaiveReplicaDispatcher.java similarity index 95% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/optimizer/naive/NaiveReplicaDispatcher.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/physical/optimizer/naive/NaiveReplicaDispatcher.java index b8b7a2f301..0537878559 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/optimizer/naive/NaiveReplicaDispatcher.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/physical/optimizer/naive/NaiveReplicaDispatcher.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package cn.edu.tsinghua.iginx.engine.physical.optimizer.naive; +package cn.edu.tsinghua.iginx.physical.optimizer.naive; import cn.edu.tsinghua.iginx.engine.physical.optimizer.ReplicaDispatcher; import cn.edu.tsinghua.iginx.engine.physical.task.StoragePhysicalTask; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/optimizer/rule/Rule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/physical/optimizer/rule/Rule.java similarity index 93% rename from core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/optimizer/rule/Rule.java rename to optimizer/src/main/java/cn/edu/tsinghua/iginx/physical/optimizer/rule/Rule.java index 12b3ae64ef..37e9e2b4d8 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/optimizer/rule/Rule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/physical/optimizer/rule/Rule.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package cn.edu.tsinghua.iginx.engine.physical.optimizer.rule; +package cn.edu.tsinghua.iginx.physical.optimizer.rule; public interface Rule { diff --git a/optimizer/src/main/resources/iginx-optimizer-0.7.0-SNAPSHOT.jar b/optimizer/src/main/resources/iginx-optimizer-0.7.0-SNAPSHOT.jar new file mode 100644 index 0000000000000000000000000000000000000000..668020ee9dd019223a25d41e8f03869bbbf04227 GIT binary patch literal 212055 zcmc$kLyRyC(4@z}3QH?40|u#i@5q5(LY7)wdd{h$N%>BeT5?M1&H+XV za-3Xhc1nqHg&D;B=m-cP|9=rA1erjy{Qv^oPyzuE{YPM7W?}12V`uMdVPoNG;z&bJ z%Sua6qa-UJuOu#~OlxW22tdHU*Y|&pxJUl~w(-9R($0$%9{>OWzWxFJKibIdQc=#< zTB3>W`rpM&D-g&su(Ol1e;d=q1>$CrNB|k|?J?KZ=QO(ex6(Csepa}u@>X4`;k4SM zDTIjy1_=ZN1SrVsJPiPp%OrgySNw7|@bOeWc`4pVRXNd6C0R*1IbnHKUoq*Ul#`>N zU}~ZzsA6i8nWtmEa;Sd7%l=}VnWdubshp`PW}+k?BE$^j1$C%4Z<4B}3vq$P&^vFU zn$7SDJ;*SaU97g5$AF}bEPC(#5*$4LzQy(q6Z`iGiUwo|2MZMVHCNGs-Bl9<-_@2@ zl+_ayN7_}?QoHs!EQT3q{~4&6(y1@rHKN6gp%73U3@*H)uWsvn zdd$ynxKIcEvo{`x&vPAaWFSJOj+*yv+o_Bg!<-fa+8FYP^ED#ueWo*+@L zXB?Rl6$9THTA3e-5VQ`U2tICbU2iEa(7gXj=u0s~KTbbU&rV@c{tqL+LMoblqxkQi zb2<)Z4k*(&y1IYiEF~kjC}0O5BoSPgiFU7s{)5jx0m?0~x`LFLBySllCSb_AOl6+v zDRU^?KbFkWT{WAJ3l$*{ zs08hb^dvHNuI$)vSv0I+u&)mG!+4hq6OI`g~?y3ua=^$fjn+l14KNw|IL zvoIGl^737fNO<9FnNUIfkvMaMrc^5U_-W_8ICx2@vlrW;Bw&nz(J#t+L*th8XJUgiYTr&3-U2W@689gSY$dr$AeI`O%kz%VA8V?dNMnddviVGa;;N$V>9 zur$i4dyRBA!$e1vUbIJ=(8f~cz2-EpW~X9!yQkGFWp>LTC}jys>v{!4thx4{U`ohL zj&M%y#y5ZFo_0u2{e85{>OJM0c5K#`w}6^(J?1Dr+$ily1L>jN9EayR}z_O|9{c>DD$PL!GRfDH?O&rm9(}r|Xxs?jJ zj*@@iIC+oqWykdPQg)Mq@zrKH<^)CvjD9gbygrT%9#y~4@S7UOOKH%NvBY8VF{FlF zkbh8p2J9khx(R{dw$jCaMyo}gb@QZawspGF$-6^|<;lDCUc#R4((sf5zQVhp$;C>3 zOo)$O)%>;~r7jxDZrCt=f22NX;nLy%=5^J>UQwKgiD%SaeA@W^l-9Hl0EqM|4$@NP)xJ_RGg{saA2QSs+s%kR z$2v>VmFc^CkS$}uc}8_H8@kQlXL-f^EVajelK2OqWWaRM07;7COfXH5r~*GPBtL(C zFg6=jomqGP!*@s)r35+42k-}is(Num8VNiyeDI7zCQq*j=eFBZ6% zR&?0~#Ul&r^Q=?HfXG9TBtZ~~i?Z7q3YPN0#?~+sR5!qp|FCQHzEwnEBX%+StBeLg zf5UQsQ`5t;78f=Y(J;%k1bZd6Df*{r(r&75iJ=clhn7q_^{M>i;fcm+lc^+%1%4Q4 zF13Y2;khDWLTspqA0~-3Zxg78+cn87aCm&++%FHEkw&6vF&+WoD*o@M zyZ$53BcXty2!tj=p>8~lDeVe@ne&sVC;_X0QCLt)MN^xGq6u4}1vC%c>Bh8Q4iyQ_ zlLR9?f|55m_(g!EE5%D>O<6g`Z|-}_2XXlIG+-cOpkSZ@@M|p5Qi@ofdmcHFKIg>B z#JZ&iIs;>yrtM zL<8#Q#eP<<`Z%cgjjdYP?WsL?}7RDcj|{#1>TpiR-!O-8t>w zdL;PeP*hIcPCuHL=75tT8XpMvP|AR!Q%%dIupALp1%tNbD+=mAH=MbDkgBfLC$AJM z8BowH9O6(Sn4-OhR-n{Hc?j@|$!>TR+9*#E=M`uLSmAITQlByKJNqELGBEj}`^@K* zpP*@X*lZOHG&7! zSUvo@2%;op6J9eRK2=@m#}@=B0$hSNnjfax|m2yCIntEWc^yxPJ+J!vIVPg}Ua+m+3Ji7e32N(Oo23-3K0!niDm@`5@2;&BJLo&)j1pV(4Ee+8H)&KNp_{D?CA z0Ao-7{E5HMdkMk7!NXw3PNBn2q02_W$ic(Jz{bGK$ibgQXgCo)v}D#irFb%LzVQ0~ zJ+XfIw8CH5s00%gt#b2?5b(4$k8^KO>=3MUf8*_}?yrQhCcRQoFP&Z=rohbs%}Zxz zsVb)@<-yJ@i4V=}O)l5ckN2C?_L>ai<{`0)jm_+GM!F6-{Zi|Q!OgBv2^gsC%$g>+ zS_^~8V#Uq|9ukAFjN->s&I94b0_gc?Tx4Nv1VGar@?ukoQEPMf-7u6mmmqW%qRSAvWu|cR_wUbgQ61 z$XqJ8AD)xCE#OOld>2C z3m^fqz=4*ICi$xeuAdS_3iF0$icOCK+Y{a25lhB==ObJU#t+#4w*u-iu)it79k?cE z8)Fh;k?ngHc-Xp*9UaA{mX;;5_qRIq2r7^Lz%pZJzkn}?tb<)t8a+IccwJJwA85B` zlEIlK;6NsL0nAeW1g6TBL3j$FKTb2MhAs~?>E!ZR?vY>%$bn1Ro9s{=_ngk z{7R2n2a-`;h)k;EK@|*~41M{c(r&VmU86ONE4*hany{Ez7M#(opQOe_)lTlQrWxJ* z<}~80iEYi^NtrcgSnS3d%BE`ll2MS^<8@@tU6{-EJq`c&q_{H`mq9*q1pitLmF*J; z7?ot_oN_$n;%wz)_V7@>@J`CwbyM3AOPO=Pd@R@D4IhvG99NG58O;_As+RKcjDCN4 ztK6Bh)~0c?lENVe-hf&iCsQ;@0%;7SdGHb;n~ZD%%OnSmaptb+zwHDL+VTZevvcv} z-zD=ZHzkGwH{fA4MFzUdL*_k90#x0X>CNMKfU;`Mf@AZo>e&_wUUg?)*w8z9i``*NvVMOX-aY z=!Ob93lfx_sTZo~*)!j+=rvV3f$Vvf_A}5;IhjwrSx&{18Tl1q%JhQl+i{KY`Ns5O zrnu66x4&((zhqOhq=GWjFW6lPENwE$+4IO~q3h&d8iv}b{l{>!%WN$Sb=~091Yac1 zBi;bzwvw%ppZtcpFmfXhq~0+3w*3AuC4`=)HhLHaR&iZbhbB;es96BaK*~~_XG_>`Q<%FEOb~yxW(ZWY5~;kdiv!#&h<;*00x=Xx zF_F3WggYOS;DhKza-xs@?A(*TL$JlDCv)Orh}D#)^_iSxC6}n=!W`qi1zCYxt^}U1 z3NF0)fg-|!KN_i@kquDI(p&XJ z_QH2}_p3&6JM~PL>dI6W4sNOUSb;Q)@RW1m^*Zl=!yCOl7`<>EcO!;zq_D~i&UXj} zoMXi(M@RxI7EOVF8hGv-J3VjRy+-g1UDxkjxMHOBNM`l=GDx3X^4m_%1tnPSnmC~& zAN%>MZXaW%qZ?m)>H=GbXPEPc%Pn~lX*^}0$*>_8ZjuKGW@NJY^i zHnqGnKUj(~Di5GmA1yB8=Y_bQ#$?UV7r+-6(vMj|ax_}*>W#~4S|r9CASdj7ANwOF z4*;)fj#{SJgUX0T3Hu3Gdja=~cE*t&rJHkV+k7B!2UAAE~U^`>~7)Y02Nm)O*Lagy^Nw%T&NvGk=`)jQ6{nbd61Z z=OLtQYt&vLBks6gHXjQ?C5ksvUJwyIifIJgePL}m2eCDe9Y3A z$#tTSdFNnTza!>6s>$|J`!+}qF zqjCwQd{vGTh!#ZnJ70E38r0%r|CaNppo`+gER_xcrk?CvPmBsY@ zjD*&b*PLmde>~3c0&mQLh>r82p8>cML=0~cncw_57e3711t)-~$neFB&foxbNSY&h zNc6rV3u5*iq!Z=D4K6s!ODhYIj^aySnJg?xMk9w-J}==W8C%( zi5CPC>9W}w5i}4XlB1QZP?YIV^6mi}E3zYxI-9`xGf~OdsCycou8px<7!cb!Cy1@J zD=fNEYLc0;UeoKXN~P@~VLf65ObK=vlkj4C43EZ0c0P-?)pb*_f*^JG3;xiv9!xS~ zA8&=Hmg<^Iw{!bnHHX>Tkp}#ExQD=Cvtzlq(bsYvum&G;8t}|EN@SvhJ6kJ6q~bxNFCKqXY-1Yot@29>V<1y4yS^zD(W1zyV)R4nvX1HeSI3hrlbNQVp z%Tx|ZSEOwc)|WtMu`lWBm3i<^;MI#2CwrXGx{r{HJ7YDjSv~yB&wo=F8r(BHB}l4f zo(Omfgk`z+V=_f9&(MZ8i%V_5!Igc)FM~!c zLwn&Fcr2J)98D?odSK~A57HgY29*rLkMqfUA`k~T8no0jldiab$`P0 zNNf5qPF3?}^vk)oCLSMv;6AKE&w7pzOT3M94_`wjOm4O`_QMOBuF+tG`@&@1zxk^M zKhn7wf!9bP_@2_%xi^-39rE^b&Yd5Ur}yTAX(8ky-_uZ4r9&W6$H(pU*8I?pMmK`U zMMC?-xlO(+6;80*^G0gEBoI_UJ#z&)O#0H{iz&2;w0$bu7gva3x+t^(>tgb3j8xf_ z^Hq8!yTp5&O0X<$U{y?UVY~ytL8NE_n0S8Gt)}or{^eMG`syFs{buB(%>VJMecwGV zv#RK&^ds7kigi5fSW<{W#If{E;6z0rdJQoDmGlFTM1-J9ZyVjLEtgVBdlmfl!_&ql zXyW*EDEx6=+wDn!gTy&YyEwV=ogD$9TA;UJ}Eph}Sf60bC8qyB7Zw`%suPk3styQhypmM|&C)cLj079lY*Cshn9? zrkaY3N|wr(utRiUVJWXQbH+1yta5P#wXYkC9p>l8%PEWb(@w^A9Ylq{YtBG=wcb+rINsk_m!!i%uCJ$X28ZOfa-|iM4X#ofj4XAQYN%<_h&!qA zD`wiZ8U_yzsIYC5vuz&*x@Ew-!~7f()vM*sLtI9f$tA3x2^$eGw6=O`e`#)bP-Uu< zCrq#>@W4G?TiUmfMeckY6_6Fl%$pXUqD_>gh_s+M95M_|%W$xEZP3nvaS6CzDL0%i z_)G7Ql}d=s_5(=;n)cJ9VEwC;uV-Np=F)Hz(w0Qd6TFpqn&b8kb1x zG}~!?W9zWqHbIMui@+x+I%7;OLqh3U=p6zx%I>I(cp4n%jFk{B`AID1b8< z>&W*|g-r)d$8nzV6xJ})Yzko@Su~Q&JSmwMmMPY)mY<9o0BXSO)4Do#=&V#Rv{p}4 zA5sAtC8e+0bbMzPog{3il9v%B8p?)z2P{4VF&j5(DchjA@*cPhjB^~_Xo>l#-V`K1 zN$X~uylP6B9wolTZ7S2}&opsOYD#&{++ELdWEA*qeK9`nB=f@+ zLI6hd8y~fO;V#_(3y2hGw>EFcupd5bk2>J zE?ww4mgon+F_IWDNsb*YQ(g3a+7t^jHd;|wH(_RFIjx*uJlhliXjJU52XAETKadk zh_yn_kI2@KKa;qS5(b3|VWW3yMT~>z6#odKW1%bDmsxAQT0h#g6P*&mkbg7Bj@BA9jfFKM6U5kb?xT}S%1Qis`BUmYwO zQgg(M7v=fQ%Ol8@M1N?Ni=ZJ;C`pdFmUs?q)9MUNtCT(k(`CO0Y5i+VBIMq!S2nn! zM_+3xnQSY~w&EPZzytv<_)V;h4;>;AM@ZbF1zi>VIKV6pWm`6|WV3EQ&&Bg>joG2)aDZ`rcS`2geJ^o!Kpek{iYsDcOok-t$!_f5IT=Lf3W* z9T;-W#PK=4?q7c%{;GsuM|Q{cK;B0H2U`9LB0uhdMQ2gY20R^4WK3@ephqNnXVv>- z&z=>s=vSQB4zEf#7CV(?F$UtnMs(AYNyeo#9{n_Kt88io`P<$wv^64h%FWf3jK6(1 zmUI>|bLlsmX(jph9dSFyD(g>Nw}W#8H4M7l8At&H3KdL%_yMJ((J?nK5tvw~kC zAWB{WnuzE4=bgLlzE z&)8gBZ2!;5~>bxC=I%{r3>Tzs7@s(2(n3dSmo`Akz9%4-H3tM z-2I)MdSZwlu2YYgW%C|CqFTQ6r(d=&Q+#wSy4U_bT^rJhLIKG`VcoxR?ACI0|H`Dc zL^p?mmyyf^EkYC*6x;~D`KH3+XaDd~MV5s88TFrd1C-`^2WX3j2F5~iAP61|xx~0& z{;1e3ky8-S_kz-?n-9V?F{ zJ!IGWcpnJ-j|WcSZ#QObuq#I3UvU_pcfTOfe!W?>HT5s}kv_9pAT9za!#I1BF_J-9 z>H^sd3d0s|TUvSF))o%rrIf1T)xf7f=J5oON&cF{C3sqk2q05e#cc~+OF1Ur-aXs4 z$GZ{mz#!hHrWV2E?REnWX42#ribcxu5bM9m(5}P}SCNb>-HQM(q-VrB_Arsn7t$xL! z1PvQFhKYj6Xe0l{Hn0}}oqwJ?Z=sefWbIwjp-=eh;yg-x>v*zCKD`R_egiX~I5Zg+ z6Qj@B`d^*ilh?#???kaZ83~n917(=k-Ayt%o(Qt`(GvTusS>Xts&Ty?M$7K)w*9YK zzow99+cM|Ng*L?W87%ly-&3|!)(eG4ZR4Alk9MxxG%FN0DcaoK_}#%F)yJ&pCA-m6 z&C~3lvza0>T7|PVGbb67RW@wbd$1OQ*pH*J8*_n8n%7fUhYp5lFi3Lf>|#tA#${*{ z6Fu^p(m#rDz}y&XFk05-Y2$N5%}M6?=4uT7!cMw%~gy*-R%iuG`?42Z1qqg_`D2 z&2Fh0W&6y0&=8_3)a<%P^sIIi!&bTmUdl{UGa3d9h}$%lLx1lc270t$-T?tgk7VVD zo9MEwPR2fiHljA{!r=EIzQ#`-WxiDzeJg||JQdXv=5n%vZ61&8Nxvj;A-@1u$DpH*Dq<>3r;KKsUwgDMG6)U0Xnod80Y5%f{(Pd?{HU&1xj+k##iH9s}>V7W!Wa2 ze#C5Op22XeXl4i{c3zsG8-KD4=o@>52TO=CxzyG#U0ZV;dGNFp2!4MaSKtkS_cx?F zoCoPPg3JyA{MX%B^IogdntYt^>aQ*c%Yba<0q{D*hErh448NW8SJF#b@4<ea zo^Xd6`o?@UXFXKP&0_D&c++U42q}F9O^44ps+Hm+P!uawe-!+g{11&;vQrWtlL_7C zECxTt`$2Wa-@^xBbLJEQ*Ly^s{}md$XLa~22Pn@`OLqv(9G*=Pl!D*t8bh%yZM5nZ zCiBO)GjYYDH6BU$6!ftW=RY*6b^h*Lw>&g~`c01#8UHr;QQR_}y@kAHV^ad_BvW}S zIP~;GO|!V|qr00D;*s*~Tyl~gBntmz3WCa8m~v6yQb?*2Y}H{ks{fT@8hQwR2?vY@CDJV~0JQiTIPgOY{qajZON8Dm8-@BDCUdG8Tvh zzRuJSGA_YoWw~sJGEI?T`ym(zvoE2w&dt!zZrQEnipP4xIm{8u-9^?y3@j5+I$7ju zf9|$d%ZtI=UDv({Dt!DCzMZE|L(#6I`64UbXFxs6f1eG61RV2O=oLG&UvxOv0l%uA z+Fni!s{>oVWn2D?{>BqH_F=%Dql|u2O>nj>9O?<~BdQSt?;Bi4e)rs7&uh-_OI*0{ zDIKsvJxk7o%e|Ra7oT7tDMZhmy_|R#R24ob%FMfoGZuXZJ+9s)Cs`Y`vvxamkcpM+ zQ)jLqBiri!#wI-+ZWQ-|s#A$k{R{o|@Pl@yl-sBH=>L2BHO1p_`-`gv`K_9u`BC#D zhp&n;*B{@NQm$t;zcK0SXGJ94o}W*_Hu_quN6k?U_kKCk8OB?!(8p%jiCW1QjSgOHz8u~3e5M0(>nEm}{P^39yP@gs|NCVk zjNQq@!Fzn$D zDZ1im!9EOEPS@>4Wl``*tw$gu%7rS|twD=H+esD6g=8X;5;Dxntj2SE0()XoG*!LzaIhTC zTGVj>1Spy)Iy7;xx9|Swkrb9Wcr=vfa0H2t4>e@|>VbaLoUk5FOJogCaf%-%W?(QC z2+C_{h^{dcSD9%}`oxF8YU(z^u>@=GPd&&7{3^-@@s5v_k7Rbvh@XiV@uITCQC$L8 z+>p`K0auesT$H4&+xWpOz)kSS4|WEh0n`027|3*I3Or-8*Qa~(mm6YwWgibrs0yq{ zmMvNi#h>8qeyDCz+pc3pHw_z>4~62^S^Cy6E`^!vhTnh!47wYf&xU+s#d5_kw%%@`|8x<kuzgg+=a=?8tp(U?FHXW3YyVGnx zXlI}b+UCBok)Pp{CWDHmZ^n7>3IzO_x1`?ujd~@pzhu(z8`Dx! z`MxtPwMq<#?^_-U|4&eG@oD9s!_dvZD(heoxbNC}@6{Q^@=0kd+2G}n=Fd&6Rfx)3 zm$JAJv<8W`&Be;7XpG>pE~AQ+3Jo1Pn?erOqc~_Lh^5bNimsj5A_6#Mi%-)o9MsFu zW2GiBt(zGW;il&64cJhdxeszHl)V@MjyXnKYYcNM=>`T;2k;r1>rmQp+V#;gUf%mt^+2~AwZOc`iDx^B-Zi)310Jx7CbcohkS<=hL z4@3W(e@u26mYkSRdiDvg|NU-LnIdRRZMg;vls4U`KeO53!<#T@1>3*O9tDg*wA?GI znYLD=NMfkI0#e6ubVm2ElHhP}Y0QuD>i(wFANoosFXR!Zh!U zFeA0-7EcD-D$BeD>#@R*>UH))#5uY^uh<<(pkc^CL8uuG-Pw@@A?_M{s`b3BG1sR9YrGlXXs3c%avFcYu8RBdxBRf{*XEuoKX?39un(q>g-`{`3StQ6&F$JaNokfj=^MI`Jh%KX z1nmcf2bBlx_;>&pl#2n*FuqEGXP}?E3h+vK*oUPQT+qH^?)yR|j>m(5)(zbZ>Gj&& zzX#qV!3e+Zx#6nGn@S>`-v|ZLDRvmN>8`b|U{#xzvIi-hQkk$LVRWmtM=~V0YgO6LS0kme zmcgYsKTHAe3Vqe)doX@m6>TpnLwL-!7kWeBPxN1kQ2y%+x3auD6FmtJunIxaJ6}-z zZzD5enBCNV{~&+yv3EB8_8)i**iXLch7$+hCQ4H_Ohds0j!vpJt^u}7>zq_bNF>)uu#aIRfyzw%L+5Y_n|GC!5yoEKlEm!3Rfupv-Bbe?l>TDtxn z+rAvGXSI9awXx{54)z~jzYE}1dS?uVZ1j+zTEgLa5_N`Y^c>*ZdeC*iX!IK3)B3sk zr*Se2x=`?Ug9juLq#z-rV1cY98CZ&T2ql2aghR~w5OxZnkYuR}4P5r;(Umj(77pOh z_|*jB>-1%HV+vve5sy>Lqs<(1MZ7mx2^Z;hk&Y9?M{z;Kxt5g%+9>kv;^xw$qga^P z*hsQ{!ZvED`eN`7z#_;AJPN)@B2qld!IKnWd`_SnNGO}1nNYKDm9Q)M?Kr~Xp|G28 zC3qkGJ9rF(yST)myn%y*IVn`|VY2~;GxiTgm4i(gkPs|=Me1Tej~WB#fKT8L$(Ex- z`&+qbpz+0_OQ>id#Lii(yp1G zlqs%~qRWI9#>D_~DrC@c%{=tlEi^jq0vUcPJv}T}bz9}rm?b*cCy{Q~H+cBJ(?3Ed zuD4I+5|%jxaE1gEhb5b+gq4fjIvuee`me7dGmnlxFVVw@ZQC*N$bf;50qVZSN>TC! zZA0HTP^P&!ypP#;EcL=36r}7b`z%rD6U)5g8euLEO*Fo}YKg5wYWn2_z?4G_5!$#b z9PlG|dTVGiNr#^T>1$HBQX7(g-e9hPoZv~kGmt;*o7#m94XexF5K$h5L~|`SarYqG ziXVVF|5@kG`<9#a^!Tb|3eUgUq0zDlhcEA$5Y%-D*DH4Jpt6W)&g!Y!Zhi8c0(y8* z$!M>>%4amJX~j{Y+JurZu7c!8t@Lyc<>H<;Hbbn-1J_d0Ke_L)T$#Mh-t?`SA&vd| zr}yYFKz*XP=@6^1S++U5oK|^SZzH?@H9z_%IIg|ffR4mdnDPCRVyLN^!%L5Pl>I8H zW+b{T$K7Nu`m}bgjHDHTudo<+A+t)?WTu(YUaJ>E#wCFoM)+^6Z=~`Iwk=s&v<4Iw z^CTTHZrAxKG>+n@L~V^to~9U4#N@{FAQK63#SO^R3N7-6AUg$6-WWTL4>cSgJ$7!f z@nzURG4!js>vP1^6O%ms?B6YhN;vUI+&Y~=!!#vs{ELSF_mWlZHJ!xhBH~KK9*qsL zC+Rn?x38$EirZKY+oC4v_%SIm^?;M3l~05&v=-ck3@&Z@{4hvA^#Gk^@S7T-U(x#* zns-1im!l<}a&7EQU?*^NVjyuxRZrw;o1TgoMrpvz1(h_GHF!I#dJ~9aJD2Q6A6)4I zX?iXFIa3jnqa`Zskw1iWj;msgK0S>DaIgA%1 z0ft9c6R*Ex-A~NZ5Q3?mTiG{0(k8eTMEYQs(PcA(ls3e?UWezc5a_RVT__X!(%<+Z z|0Io75Jq|9b#vqU=l!;=O%6mmci-23XP*3iu*K|-(Z;?}vqna#`9pYd}@CKIHj zj8pE7xNBanQ#FrAk)@t85DXenKnM$sI*z3YsGQz~`oefgLV7cW%DKMp!Hs%9i_As6 z1K5v~23w=Q>!TpIx6U5Q`N~Gfd3953HvZwm+h#6F8l`Vs9_at797&ERQ?69qq8-Js;9A`x^bxJ^wY^bqleyYW-nRj{IFY=lsSk zx!4aV?pP4xnd)giB|$(?{9{r5`_Kw*?uv@4X=y9^(xWOJL|DN00(#ToRe84Bug6gq z#(>3{G&cQ4fGhzCW`PQbVFf2IHKN^Gv+0&F^>}9(LB0L;GF_cQ;aoFnWL1fj0U|01 zVHH)oIniC2+XH``MoEbUt|4~uS)lOmmh z3NNZ+$+As}XewpNvPcO(QVGbf7iI_@!KfWcG)M_b${$HIK@AzwHsI%KEmg_0Scwzj z_94jf90v>pfJDBY3;27U=t%`b$WZ{s0TMQwzYm8tyI#ayy;w>Jc3D~tpD>&TGi3;Z zUoY&$3CPj*fedS-I8LQwCXiWA0Vh$ntw*Y^^%HfE_48^k@RM#|vMmD5)5rkL)W`wN z(pUjh%-gUJ^%Hi-RfkJmTf}~W+=h5_Alx(2EVPwc`Lx@=5+jhR)}7{dlkx; zpXpRX&)0y(6~K6hEPiw$V%t%ZV$BgTu={ifowB&GZ1zGTo69xxE&u*aawJ`A*| zKFDr{>*aZw0j@wg1m#HYsJ$8w3fK5hKW@(wXS(kw!mu(~3*6D>a-ZGHVzq0M)onkH zgJG<7jp2O4YIQCR3nvu|!(x@%eDy93tA9)ragy~fx~VXxsWQAta3o!!Hf*=lm{dK2 zuK8Y3;Wb#p!UoxwOs}|>@FBr0(OC(>gjT7F>cp7HoNPRSZ}zUd#!g#~PP>}?(6EMD zsYh4+v7=q1x4P@}fg(}-%Nsnn@^bP>pSBh{HO6kT*;HKR`Q340OHIa3jqp0NW|^Jo zM2C6L#*x8@eX)qJF}Q|tw@5A!fEx+5W;=`ZVuxqu4$C0rO5!mN`f|3Y+iy-*!~9be zwVc_D^zrF?u_9^bo2W`_{x-P%X3oO8JZv5N622)}GhrGG@eXjZ?is#|k!b}Fh7ju< zH;v`%7u(wjy@XFSKnxx+?e0c{1jj+=b>#FqhB_B8*0$94w#MComvK|D^<+yU$W=0aS@&GF;_z@6N)$BT1o2PvGDwcj&_;h}6L zWjf}0_Tjh1S(Z^X&Dx6_Y*TlwmfYm#XZ3OuzdPQKVEgv9dCOH&JnRFO*R+T1GPfAK z3LfJkHs&-HovP#*F{0GFuue_6L)l(B0%M1!OJ54^FFENy>x-rOPCMKd}q1X;8}D->>Q3uepeY>mnqc-~52KLm}3n`(g|_9J3&Pb&x}b^qJb63xVOyp@_;MRxOC`$Rg}3Asmuk z43T$J{vI68w>95@tETx)X(hFH*$3wX(MocuJ8-WNlL>Kal2+~!jp$~%OQ18ThUFwN zPQ@o6Uv6|rZ0tGAJVhWu!Tr8FtISJ`%3;-hJMQon${mB%CJ%JT-Xgj%%SaSBMMqO?Az3HW z_|d#gBkQd`SOY&l*-le*C%FfBA?06eQprVcn z#7tm70tx-#RP0cZIjW zbgV7W6NONc6ePJmOhe8&zG}15R&uB=KWb?Yu~dQ)>)fyFWaf=uStM&AvPRT>ezd!L zGp3~0|E7_Cz6zWe=^A&9>EnzH8L>z{vf=3MW``zj6uKUUvxTp>^0f3SJeSV5-om*# z)AJmaE0N|^`W&!*r^+BKYM=oG!S}uRI#`(ks!BNOD{Xfj^X+oo@nZkNIu6r*QXc(Rl1Qm`(EGUS&a`XOWjdCz^85K z53Oz~!Vv>>SVZO!RRicsJS)I5K$T=!=Y%|0p5pVOi5bJFyBQm^i&NV}2qQ*% zhf)Z~8fIq$KOnZ)K?imp`ki)CMeU=0}?I$ke{Z zbr0s|pd#TgtUdVRP*;2^PDRk%qX%l!S65%6l9E+Y``#zg1loa>FplnkbKAE(W-j=TQ6-<;O7PUEG^ z8S~K=HH~9p@Wc;ll^d8tL-C+3boC`4?Pm(Z-)DZU0yIbkzTHgu2G++L9RW9r$|NAYF~2S5#$W zHor(J3VvD2k9B@-zVX(l)(m=iG*H4`}#J4v`R4jh(F66ySSyYVFn(5b2= zykPjj0^v%#8z+h|m^`wWqacP-e;bK|?y!(H=Vf~f2vIn*(w!k^Z$g3zZfI-=UXGY5 zxJnFejs$$TeTwl#eCIsXtr3;;sBHr|n(+#-CK|m5m~A2l;%rQ*v0QyxP=;Eb3jmCG-i#tv0?2 zcRC6!&j?zX{C}LiV{|6GyY}67>Rz=ywQbwBZCg|8s%_g-PHo$^&8wQWQ_Oqs{XF|w zYv1p;|CeN~79@cft{rB9=o%-FcaAy0IWYK%bz%fdyciyNHw23% zJx2sYi?CjoK%S|Icg`_EekNZde;V{!zA26>z1*`VAIZ_>7yl&kK1UE8ptynB!7l!U zEieWLN1DBOCYxP{!?Ug+hn^GvglZX&Mr}?btz4wtJk)W%|Lb({FGzweI&Nw+0vOl~ z*?$r#3jZfkdUWBu@mEm4q|&=vyJav=z$nOF97mE#MbW-1!WyH8qHnP@9u3zDn&LFKUOWTQUD5 zd{*O}KYUipI#e_b-a*|uMHHL5S*HjAvs1b#2D4hVQnyGBqf?Vap{NHw9Me{Vx>z|! z^akF88bga(CECV2qrVGkmkhM4+V0ZTUjcc`I6|0Z|V~NHf zQss~_ON=A5-d0dcT0L*?<(uvP)g~@H0%R*J~ z3R$A;3e}E&)8I0Qse7|vE699IZ$;zC;Bq*5>`bNx=`zgMu6_gvrt0S8Yg(Usgfz`0 zy)t-O%?T=9Kho2ZU+NE2B?Va3%@VpC5E;?y7NwQyF@2TIY5EXs8k<0&8ubX`D)j`T zs^#ysH?L8$ao#dzQ}@lXd?3BFY>-`A_B~gcCtB4qDdY9voJOZ8x#(+^Y}Y+o+V6cO zS_2shS_6vO8mPK~JM~2w4I5$xWg1yFb=FGxGMs>tMGteeiD5NbihGzer2Q9&Kns+d z`iu$WXnQUO=K~#VLr+wF^<&bm7y?FD^yuyyTZV1f^?d^kY|fCRRr7iIb4gz*RfNl% zP8VhzmRBq|O5SGgQVyJ}=wS{vEM!L|E>1MgGrFyEsTpa0ZL=MC6=U0*0n1u}nnGG9 zs2zi(p9nJ_{j#eC#mVCIxX4l=3afD^AxD!EW;Z{yV;-8zcdPdL8SO;kC{|BNP?aRf zqKrSoetSsD*J`k}7z=P+a){X_410~V)G@~7BBo490Mxj;LRT8Co0g=P@un}q8GhKh zm0Pq)bVf|fSa$etf-~T(#Qxs@-SbXr!dB5W5&KK_Hb3V=G5ZI*ww)zgjo)xgYbh${ zb0(_&F*CD5d4o{kaAFv4f^}YTmJ@#Mv16k%mq~n^r+kTR50vE>DC+7d?0nOM*FEmS z%3>f}ubgzc+d!ofG|U)v34NyyKZf&hhClV~hbXb5o809F>5ZTh_=z#?mwXv?^gtVi zIfxpm!ghFLmp|I1{X42+Zs=||!a2=qV|M%M?t}wP8PD`MK4xPN!6ll4mjo!Y@s1AB#39Y(ybGUYXQ{10j zCqcPe1;iQ*CEF9!xJ$8Pz=Y+vZ;hX*JUO1jx=c&4nuerPm!^%M6LoRuv;-v9go_A2 zva(%GH#9n&YFezDW!h#9TXwfi_0Go@1$MQ}xwsYN?vd{3n!aJ^cCY@B(ipryB>jdq zAgPdnLVvH=q!E4TdKcD}4A8mG`v}u(q9Is8+}W0=-c5CEuQp{#=~Hj6Q-`L6rK{#B z*^bOQap+vo-7U)^jB?$fR?>b-wK~^TXwVwdCHq)ODJo{kXD?-SuZTD1^Zt7vqG#4A z(r$gZH*5$0s)#6$HM40_P{qG1uqu^B_hNrXWQR=cU|#2mC(kcp6FVlJ%UnCLJowH- zlHJlH8c8NF*cu@wiZ>>T5J6_Z-z074fXUv;qZ#|0jeDE;@^Nnu!rz?I%5)wGQ@1>q zF4Hl%q`^$eTa@4yLVlA6EEa#MMUgTc6Uu*o@1(3RtYEe97g>pIU}WmB_g=+PCWFnX zNS_Hq^zkFKSk=0uqY>Je{)ww&M1=2PSi-{;>Qgt@O@a52zMkJEPIi#{L9XgCn;}(% z>t!Mj8vEsfJxWgX3VBK6u4+ekZjxh~7N@sT>DK;z}eqFW2TsJJ3CNNQsR zyUJ55iTwke?cM-hw7Cq<{} z0r-;GZlhE6p!U0-;QAN8E~doAJQ`wB==F=fz<|{^wWT-%-n$E#-ApovKO#iMRITow zSv#6F5;2$Z_ECu);iT( zT+hDz({%7V#vXck4%sER?TQ~2Mi;k*x}#AEG65}7)wh;CDPv0kiYcFi=c)>U9VNrU z(b&?XMxIIu2%6#>5MW+^a9|C^b$~@PD+M?nuJXU3PISK8kn9;ymz}&)M9wzk!#)&z zQqT4Ztt9UaEjncgH}1~WI&W=Pf0DF|O88egTn_yCJo8%u=o@@p=9yk zpu;kP7D6zg1Up0T*IUdgk*JRFyor#$`}%_!oEeY3SUc_r{5E_#t#gBvA{3D^>{oN2 z!K>D!QD;~W!$I%a(iiY@BStyY;tz?uP;^kvAJn#kacL&kY3v*x$Ql7pUm;Qn(x!Cbl! z8`8A`0{gQ8B8q)tVO8iW{`Gs}D)AV9_PsSGAp~FqiwxKw+ zo{ZNxjfA{gR_<#RU~BiG&%WSNmmjZo?8n~PcB8VkkzC%p^_(({cLkn?8@y*l7f_U} z)tHSA+<||g*7Z5x6gUMAG^ZH9pSwKmM~i8nxH!|U5{PyLqF7wNx=-CBd?V^Q@wA98 zO3BX%0XFDK?DH(pKs`;F%m3yQi(XM?wA ztQdCv*7L>Wjs^11ygQ&~i3gPzxDSQ|KZ3SU@~|v$cmYIJ;x z)bQT6{RFEYdilBfa{q%r$+3rI=LZ_sLBz%Cj7=2P{igjD$Hr>S{p;U%=Q6_U(X{tv6GrQB@ie2ygZC-6PO9g>_AK&^p*3sK7 zj7RznzSTgl0=C(l_xjU=9ljwW`q}Mwi7`8mibK0mN;-?g#88eZ&lg*p68NO(E84lt z4nrztafdxp%6Df-VBJ}n99*+2c-!CsGRj9?Qa4#_owT(FBd~hKbz+$4=}SzDs*Tnf zjZMC3(euxnq7!Ss%Er{Uyh0P}yb{G=1@v|~(96i|3?YBvfGrRlM4?CwOCJg8A*MTnm44}d&pQ{2_l3ewB@qJoJ z1A8UO;~7%PGdBDgi{MMGZ6Pkld6Sv!S+{4AF*LK=FT?H>)2lRUpYE1-X z^lYkHsV^R=LzC$|`FnX|_4Hy)1tI9B-yF!?{-KpnC5koYzzI-V4YMuPc0?L&qS=-% zx3+w&O07e&G!Tp`wVF~ji8;{T?CgA$-mKOl#tvEio3_fgoBvn)0kaA(;3ghqTL+la z@c-+wO#3|e4$ig7z?0d?cQUXpTHivd@3nK0dUNqH5MGIlU90r*Om`S>SM=N`V8hV{`BlAydmJlwcGCEC`6E|OweZP^O zP&78F&?P!Y9r|!yk%SY36~XSl2t%TQ0g%c#0mDhya)SSIg!+(@Rt4ekoO1-P^;2Co- zrNn70Y*)cek~Y%W>pJ8VZ~Psw;$AqjH5unz>c3~!OrWiDG4uU1?3{Ib0@vv+HQ^qzBS zwj}eXalSn3us)N($J^r;*Rp(rE%()i%;k&Tvlor8Kq)t2cs9zi6Xwh1FSB5j!W7G+ z=pfrOA5vd`4uFXTp}SuXx3pq{;KK!hnU_!(F7i5Vef+(V`vH z(;#(sAg!+Vrpy`|6}fye>!j0zh(EPAVZol{hm<( z7`1T=^0xS{_`vWtbT>+(Y;SYZ-QkcZQ)nzkZRvw*sBal7&NHG+vwF-dmPN=J%g!UB z&}V;=MkVlhS%<$G$ocBfnx9gcBi1;x$ZH*x`_z5mkqv+d~nO>A~j{O!bvnlHc zwp|_rJ=xgZC#>Jee7fmKbxsa?W5v-VKXkTeSn01!jeG-0$$EF$#ryxt>_>3SVG4?% zJI(QtC+>%!_#ld_zgSGS!CG*q=m8=WxhifRG_*S96vvG2fF@Hh0xRqi>^IgJJ2$XR zGt6h!T((wvC-Aw8_%7eunL_Z49wi8{y_(gFYpPcI(9=^Qg(Z5z+%I<}m_W%Ez$abp zGyognxcjk9X7gqX&CB4o4jDdxJW7|dK}SJivIHpJGRP*?1%qiNpnk=T3W4YoR|D-I?UgAOJ7coYJiwf8aieH{W@-?e7#(BySQF z5PzAFeG&>_9^r_cm;s1QKxS+KuyW3u_fSvs9+2D{(6e7*Dl{C-%CdoST7aWB$=`IW zX;s^(l7eRJ;kikHdzRXxJDfw@2KF>fB^7{U0Kt&szC0cA*S~g|yqm!UOjt0m56u5$ zYKr_1R~ya`V+Hr`oFP+Io^X?}OB9SqKLtrVJSnuS0%_{tai4T zVIo_m8~=5L=2{1b3lWWeM>JLIYZEQ2%)?d^(R0E(1Xx} z`(Qsb_FaPe;64og&-F+~e;-sninr>%P+FxZai~EQUN`W-f%U_iVyFgZw;v>l3%)(+ z+!g!%C1e}nUmgGAd!3r-kF_n60=|I0Xm?-9LE$##Tnwx(i?dQ90-H+04M<%se>&1!VW4!q+G-Yw4CJ!v|JKG z>JOIS64!X_9WE zB*qhSG`p80WORlcHK&v&pT7M+%-n zi*L)%eAQZTff^o7%^P}mPU&^^I{Snqm#3edBMzs<{R@kiNDKmX`;))ajrBV0Rke;B z#au6AU2*9g$Xfte?y&(!SPzQznKreD5o z`R32y*>?}w_#4`KTkM^i@>co=YWDFi1D37Bvn0%&fGuiTUF@8px2FA1H&p%%Yrza* z%Lt~JG}NRCo~ZeOw$aJ>!(`@*d1(Ei9IM4a{nkzeHfx0?2{tHg8{v9>1OdnH)lu1{ z$lt7Wd#Otbf_BB(jWjZ?H9wyi+i-ryDkwDC{Bm4yk3GKsV{8Jq7hZ-}4Hw967Ovxp#HouS;wlEorFv_VeN+&Ew5*hnA2h~v=DhnVA7q)AsM zr+uB)=fKnTqI+e@R>zn3ZL8{X9+Ai3c&?z?1l>wH+p_vFKK+{P5~(%^QwGncm?Gs* zkQi5Kx@=N{`z2v^%Jm7HTjB*LQ*dTim2kSoXik@piA==^bIY~yJ$z|fcvG|e?$ujc z9X$=Nynx-(YN{P$ot1tS-DGm-K?& z@-D?xxAIiFHH}`e$LLU=%%EIX*{`(klli3xJvkKWs%_rY@XuS%L=|i~hbG)J5`~$P8tj{nrM@xhSoB0y{JTz! zgw5Wxa)*{*rC#5vrBh<2!f5W&lN;ew*cZcC+Yx0zLDPs+SDcJhz)fn;)hJvbfi3ufzu=(?lYx|ZzWtUi= zMOiS?d3KM`nX5Gaz_^-oONX*Mbr^J>cuu6l*hf?F`gIwz?Vme}?1WCKgxmg6ei1pX zx4xYCNRxM<_`C?s>D?2ODzUYF!^Rl}!t@XYwqjS>p?Y34{)uElgC`Kxe! zIgA23Vy-*2g2hMfz_SHmAYrj@OaA#-zO@}cie?EzyYcx+6q-ABVg~Xe7?r4zn!g9G(H8b`#ECMnbUk3_ z_=9Ry4q?-sAs-_#H#Hc?WKUsJogp9i&ssCu3BYLm(p^z9s$(C#wiLkCzZ!K|8+fCNWsPj($%xy5i z2#Xu}UTS^)WKvOK&JVjr<_@nw5TpSiOMA+<&Zi&9~RGyIG zc&048TSs$m|7PQj%=)otV9VTT-y$l1Gv=9H4aqz*hJ%9=%99)!S z|6W;J^Afw(`FpgXVfWWv+++JFW?AYF?{0Jb@I=0~{we}qAgl&JB%Bm2mMSC(3^O{N z#9lB20l~xt65B^ZY|sks%4Ub@`<0Va2+?iNx4AJsgdTi^o~{N2ug`xyYOQR362JU& z1m^jVvRV88D^k#K_~!_W5};~GO0pgj#Pk{ho7rkDtdi1gu(8rqcBDBP7xNb_EA6QU zzeeMH7_>f81|uSTUASBukXL_2IUxp*hSA1ayaF0?Eyo3kYZDeE+l^Z5g6Tp?cD}@d z#HJ4%vXCExg!Yg(RUboty38D6Ae;jUkGb(L-$T5hlVQ4wJ&q1>A&m2u1GhL-Q zDSXmnaNc_aE!H>1uhTz1Iov2GB1`K(U|3h!5wuiV(%JI zWLDimn6Y0iXGv?(ASew&itGC=$za^1$Z?`{h}wRO(Z-Ns1w!j`q54eyz=`PPNbwV@ zlESlL-0`ME+k6$|4ZJCpp5f=WBlK9~m=oKXqq-4SztLjQOn}cYur`q$un2M}^&t?W zM@4|46HXqbMKq4fN8P5lG28S=QXri0rtLvs;An^`U#21#{Ql8G8uOKG!iD&ZGx6K~ zlC1fOC|icpfAme@TxzvVZk6FFY;`heva(ioRkO^tX0ea0hR&ijB7IqJ(v}!Ih{-zU zVEjiR=X_pu^|wQyT(x2}>SAg52y$uF^$X0cd+0)Siaph*f_vc^)&Gv9V4_#-|J+3G z{Xf$Bng248htCO@390|Im-d6`#EZPOUT^1cu{wOvb-bil)B9FSBA9kQ2#H42AHk|9 zV+3Z!wwF7>6Z81k#Rt|tFh3TaFg#`viSz**W*93ti1RHMy>9Hn;8vT-wr+J4bFRfy z4X4dS4~tSOeQIs8JJYM@P{ZLl`wF*+Pmvf_Bwg=Fo+D%WC)8c5zV+Y}aZxF(U-6Ck z7%-83CC9Wzf8a$)E>9~{n!}(f#(AZgbXf+XNH|ryPTZ4im#RB~3@Q?(buXzs=i*Kz zVUPPgq)h<+^a?`dJQNzw*X1!CrafVc4fwooC!J($b zRBCIFad z7>AI+I5hcwS2)T;cR0!edLSzt<&iuz_7E*x`91+~i99nphJqU^26r2PK#>{$iy||) z3=o5Zhs!C)oC0Hcs1FyNRe~dj^G`SKs;u&$J;k)Km)LXMj!eD z=iCc9rINU>{+c3wJ8jaytc`0AAPvnM7+{VsG7QlG!9e7WHHe0+Xj2X7zLr2%9Au%X zo1hM10IL8kfGeC<7W<4syj`+>Kj_2CfoHU3S0jcGoe&T0?*l)!X$PQhxBC5al#>eK z@;a2m*j!EU7|klpx$}y6uuu1^IvT(-SnVgmd4EoX|9E1y9}kbCW;=%1>yk}0Eiv)k-MT`{A7F3FH3)iSa+jDfYd`H04-Mi8E1x}X8_lf zH})>m(Hicp#VhoXKcEM|0*tr^$L$-cmHHss-$sdP|Q|f#7iq%sYqL)kZ5ow77vmM#=ZMADly>tb#FI6W(F9 zA6$l`!UTT@uFOAz^oaM*%s-gy_<#ni0g>RiLW42p{P6*}LZgr7{J~uou}4TcVEjf{ ziH1<%WKD@f3<#d%A!&M?A3y0M%|ndG5X=XHO>`2yzhieS#xwO%AfMYG}t7WQ42fq{1*|gmb(~=xEEGB2*kWG$~75(W$d7GcO+s>S&KCk2U0% z+3yGc&}>F!N)1<7r}<~>-zmF0!Ro2|?NH{U5|46?5*oI7`ieNtf46vam7oST^pxm% zyl;ID^f($N5(#>hiXpylZuj;Wn7r^p7?B?$Lurxzd`->e>k6$^F?CtPMLaa%)7)jS z)xL=}FA`WjL8w_!UhmnkM!Czj_woAkO~q*4ph94j^m}z{S6lTB9QcY3!ur~YTxLU> zq4ao@5)C=pB~sg;ZHCRz*KM)~DAAiQO%7q(k}t)-Bj!z)no(vlSOf>RK}^Li3gmSL zmqaUs%Aq&6Gkl(Jx+O!Mdc`Ja(mN^Bx3`r-`*jJFnl;Q0g#*MUBu7iU_$!Q;bc$DU zVY65d;4>_f=UPyXA{?70N^UOk|&!Rzb5ZkL(WD%-Pj=aa&(FdtCDFE zTTJdEFD2H)0=v~DQe}}$%PZscZzw$v?gTUc99UBm$@&_4bCl?n!_kuZ=&o4@-5uW?+$$bg?QyHXpVJB(lhoj(XOs8 z&3IboIF+qaGrVPu_*uTdSL--D*yh(3H6@qw>)+YR-}l+#Q*KIPlkhbYm^mTF5}Rkj zB{e@vT|(H@250BxntuVGk+Q&kF}fnrpbL(4q>Yvk3KvYP9TN0B?ZeG^{r4?kS4{E1SXa%<9AZysPJ`p z_qRGa)zs6;LRIKQI@{ly?-6>Re|~Ba_WYjrZ4-L<8ra(HdY>&>+qu8(SCG2v?$c01 zA%TZ<@#kLN(dbEVUxo?oZKw;~OpPWxhMe4{GD2j+6ASO;eis*gwk~%g3)BW-Tk>+c z;@4zz<@J^M7#MtJH49=S8VvVw{Ddas6FX4UU6u?*N-HXu{Cf3ESw3+QM(vqU7VE;ROFtq^n_;g-^hSr{;H%O8;r9CyED!d#GbOFJ@ zP{f>c+#t{}?-3DdzMuVbJUA)rDnJlS|2@A4wChqg}cneuBs0V&7#48#t z@BI+W80N<~$Rs%>B+rCs@$gcxM%G!H4bl51m=>u>$bmHNVZtSa2Hp_2hmvkN&?yn; ziDTbV(&XWB9b@g6*E_51O|0?KtLfTB0-W*_li!hvT$rL3n@?uZXFccTFGqm7GYd#Ay!?NtPrA%|*U zk-j6=%uK@5-o{Ga6P*LO6jR5wEZ=bBrfRvwQN=TNv*Uas+Dh-ou68cPuk?KZv%ls^ zH@$~b{u&JoE`4*FKAU6UVH{LioBopx%)O4wDm)7p2$IkB1RM9+x(d4w^mU~=DsAyN z-^eiYe}v!8Ht9-eXFB-jw4fbQ&rX|Y>IOsyFD^(wk#1JPUe^{Gt3Sh3+1Q;tB;xlX zbZHRL&*MMe3@EQ_l}NTbZ(kt0sbnqPl1)?mgnwOu%|nEh*whP(>5(?zUbc}mCwjiZ zE~M;HFMsjSjnl1csT|*5Hr9kgx@6bU3Dy~!A7MY4=|)$%$XTqR!;umgZIu1-h9^mw zQwdQa73yT={wv=_Cn-Q<92?5X|Oa zZz1E__wTMzd+cmAsz%iw#2oKieA69`t51hfG~D>voIK55{#Vjbo*I{OEsn0TuEuLu zUAYFL*q)7IaqMrulkpKgl8P`hjuV#gw9Ja1q*gsVC90Hh&(`2;$PMy^7E2|&hHU%W ziQdTcemm6EE=evjs=R%TCtlmXNX?vv9ZM)Nl{HHgq&+aOpnzIxf~%c=vhPv5NS%U5J zU*pRP$44oj_{-8#2zNgR5BhRQ#wr54q>q+oC~bUfxXg6V4K}lnuYV`Or3X#=wSrk3 zTf;buxE#DNeOkzg%Z2lI^HWX@POknpsmTl_-!L2 z$&|L4j6Z}`9Fp6fZsL7+HD?{HJOVr%rnitD!BG zR!5W~vwHQhjhE&!@@nR86!*WT@MSlbjQ2>uJGY#TS$0N|HHONC2ZNA5*=tdgJ2a|X zQiFzhZvJ+-c3umH@>*~LcI_wbbWeRV*W1DUp)3+~-+0oLmV=Jz@O zUO5^fN?~Z*5K9IfjHyS&KB~D-F}hCBU}L5>Ir+Zd8`?0ig*9th1zi_&w0S+ZX$4DOp?}qz+(Bj(du?%ImBWe!+bh(E$rDV-dr0}msO?NI(Dp>Svk>p zs_lVYUq+C{vGC88?rkE#FU&2U3mr8!ZBOyH;?%LyWcwB+QkUCd`1({16R7$YWdmuO zi}FRhP=p54NRluw?y;UE7P8w-syj?L z8hBACgX!4v^U-eP8r^qyLp!@FPq+KMEmAI8#^YWm$Zmw+nHN!>C1&*`Du_6<2&{Wt z$GAfEUMkau+20~kX#@;1@rdTDij!&n!Hn@j36RihbwDx19FOP0fU&gRf$^d~o#J^J zc!n{_fB8=TnEo=vHEr?pJR)a;`EWuv^Tp{L(I1^By{+8GC*#hwoWX+-k=tI(7L`y=Gf_#dcH5PDdJu??~| z5rdrjdA2@gboh&pk16M>qnm%N<&b6k?o!H;L_#DH-wy(wwB#ge{*LmYw&y|BMdj<~ zaers1w@e}})%}GdS62i9K`k1Zj_ud$@7;rRh%edGhW??`E16F7Sx(DY^=ny9)v2Z^ zoEJ)W;XdMl(UN^q6@8KC9QQlruXrgR(}tNc$G-%cu3Wrfj8Ou{6v;N{dL#4(a7uy?7_N`c~Zpv2fVg zDB{6mZuKC8Fig^E)S}?Y`Z&!R*hjEKW)2JCu#t(PWaI&gcDeEZKn04J{{;(5822=c z3{?cVOByVGB*Z@V&x$r~trD@w%EsUpxbH|yk|PJpRW6zQ_R@b%TCWspqgdvl@tYa5 z?N3;!KTxj6gtJ9Q4Iv(wRoI6RHES>>DxsX2s4c>?s@Ox%t%?-!VXml9Lqxb;)J5kf zDEShGyj`^jcBPZo5~ROS?Je3SY>-wi+Uq#k5fZsBF={fE^-4}2T(h*!(IIC!w9H^d z$|=~#;)hr-Dd*Cg3c0x@i^<38qL zlA#D14B#Vowbauq<5=g1qM;x%TD+epe)4wBl7GRjIekJTR*BBpk?P?EyOf2x(4Gm6 zPR_j@tC{1iyd)mH%ae8JHXaQobh>X3U4?~wjcC{4LtV)TM-_)7Y-yVx8d=6`3Dg<| zrx1J#+0%4!f_V?XW~Pl0*hfCXMjFw%2!mEdCl{R5g8dF3q%KS-Q54S$DaO?-*~d<69#?#`VOCUZ0qc4>UIo7jvAC zkZLm^j~+Um@mmuyvWF7oH}g8)O5m&Omk~Qg^bPaxo81Hcry?~s^wZU zn(@#_mUaqohMRT?&&rL~2SF?0-J|!&{0!TmXa2TyXO}fo z6NeU`?W@iftsb{ay2X;o7wQ-G*>dh#uM@D@?`Ab^7%DdUxGkRM%Et6o()`9iZi%>5 zh$ve``=&?#Wtn6lblemg%jXtN(zHFmbhQbfNG=X85v(d~t_No`pVuMG&FJojT z|AQ0}q($kw0lqH(ZuHmLe5{_bSIhw-XSJ=>c?9eO#A0pn2yY)@9K{t;H_2c)1-`y{ z*g_O^id7$Xd&gjyRCmc>$hR~3oIoZ;6v}yIhq+tp4=u(ms|TX@#-9877e&Muob~uW zXVWe}4X7*Dgxbm48*=%=Lq2;V{A+~>9CZBZuGR!P{Tc$Hi)2!#o zLAeY)pd-noT;*2dmpy#~?5YW_g)LzI*R^objps zG+P7jyedJIgO6=gx3;>z^Vcw3d!W|;ADd=bE&lF5XVa+vo5I@2pkC`J{R*KSC+UU4 zWv`$wEUzs%CFgT|FIz|ftVh#NG#-R`RT-r@fHCHDJ5{_j*xu{=1n+0N_22#z>AxLb z*#VF(y|u2oBF5WL!n${ zE8ksMVTSgR{1<6f54!iK{ZF_A?671~P*&?NLNQT(4Z0D{j?_KDa^8vi?T?w?lw|>HkOG zVvGN$T>GytT)q_bepq)Y3lAeu?=moWK#3%UXv0&xvJDtN-OShB40z~ywLyNueT9BO zpzp~;j=+4Yr~D!|i{#Z4(JPFy=i+g*JbTF7$m3x%3JmyyFb4ZY(8dGgK_eg|C?W9T z9_6OwDd)a**+vdJDiu?N8gS-?CFTva?$7%EfwUHhP69c9l6Z>}!i_Hqdxr6J)D)tJ zqs|-#4&~({BZ78@8G95Rg7E`We!n=xMqe2O<_{Q3%HL=%vdt>C)mt1tjTTMQvH4k* zEs|5N%VT1T%V9JxZ*r#aoVDyQqmB&^2lR9`M6D5B2~X0%PS){OTAnPca*FyLp67# z>;^tjeAppBZKqyt;uJQi3HMmh;`o|* z1pB;kC6d{ahTgjTv$5dT6)a+G48k=9^f-dx*#ysI(NZ_~Hf_YU@y{B)f-uCE( zhWr8VS9*Tuf>b5@c^8?V&!~f6rJLCZTXYIkgW%e5a zF${SDa!s-ZjHy{*fp|kN0LIX@hycIJL(JTCQ~hW*)m$yqkulmI&Wh1W>ch^mP(xC* zKUk_oM=~*NFkMR3t>?=!)mehf2~cz6jx^+@lcJ7L7>8LRWAIMzvoLsQ9#p4oUg5P$ z$7Nj9#83-twFhE>O&FLo^7=~+(QnDcm(n`u!$?q#9Zt@59AQ9 zUiAmwj;&`KJXGM__tAf!T(Er^wu`+}x|UPLi6@uD6m{43 z%X)eMc8GSxGj6fEA{HsxCK%`R{^Z#rU-Jap!TJl@Q|bl$$X^rXt4JY489Rp;)oV#% z_!!sSex%IcCAF`3%9kcOz7UxaN`A9__@2QRllG-@U2K!{MFF+&QwN^koug=AqAd_ZhHzQ-HDTJET?hEWd^NQ5T}+dl0)<* zI}SU#*w;tJ@XRorHI}G0R0%h{`!8-u;)_9}dGDlu2`P19CE*W~_`D3-jTFBIxzt}R z!n598T|?ZMk}l&+(Sp@3b)o|haY!oowt<85DWm)=QgIvT>h=?FNorz~C^26ly{6{q zchgRXuh8)Vh-=7$WA&sg5Pe&OI~wmub`M2b?|5q# zqp>TGZk6f2e$YB4l9OqB=HBqQ*poQ1(B>P%LuM>ZJ7#CpwQ=S(8|_))Uy&Y>ZLy+* zH!oTg->T1|i!6C!8hf+C_F(iZYhFN6qGMP?>MjDw(o!S|x^FOD)H>E~nN=!wV5jtW)biF_SPFmivjB#*camCmuGjk`6t4Q&CjTSvO=%KQCd zms8ahUy4Q>IxTp?5=W!v72V6zT1tUKlmhfGjC`)nVR;-17}!4Rf3gy({Xc`avHHr2 zpcN~dS2_$XB_(edg*~e|WqhPE4rCZCMRFKL5R#+6Ipsv+f4^&MJFMv1VcY5H0Ou#XuM&(5?h(u3$@0P#We(Sdv+`j|j4nwju(EPinZ zK0s`oUdM1+cUEtEV`20mKm61IT>Q*^TnKhHSbSLTbTF&Ueh4E{<4JfUa$)nz)?mUZ z9D0Bnt|jwyQ!u1aLf z3FnkGagzX&Z`vZR14IfQGcA!pcU2T zdILP>g0+vs!S;EC1Q*2)L^@JQKn7>!gwP;_rVT*%IWJ}#okPN5^P0d9sRLb4d2z~J zmZA`*6i`Yl^73b0+3bs~=mfUTZHlb;1hf|1I0V3d)D@lS{-`TC`|-oE@QmR}dlrDuUh4XgZMau04~<+ z6p)j5cv#?A7vcJTKLb)KVf$8aEfRp||KskRqCEMwF40Qcwr$(CZQJ^#D{b4h?X0wI z+h(P+y1Kvf-5%%MF>a6hf9x?L_Cv%|%)KJ^+-t3vvwk|@8h-1rPaa|fX<{o18&SO- zgRNEEx4@5Jvkp_bSwkW^xNChVhAFQ0aJA->#e7_DwvGBZ?zZEr#yam~LOE9r@>GlV>XIk3M z#%?;oA~5e=sE-vg{La$|r=}r}J>C6e2M%Ld4eka)hfJ-rz6J$!DuXJsZGjb$ixmCN z@8pZa*c6mHmrII=hVHM%qI5KL>DSh={R64|*Dyr%>?l3$m2#d#$?~|dh@lA^Y3iRc zbZHE(ry8MPQNt6$fjm)9i<0Q*XAHLc$Q}VE^@;$q5%rR;yLGL4e~evY=Chr?lN=%g70Pua82jWRp~%R$mfKWE!*v9~QR zE@Uexnx<=Ki|R0UsC^q~1!<)n`eQ6C3&-t*>d|dP3_ngB}E0AJqWxyp+BhFMvSJD zTI*1vBZM9t^=Q+Q$XZEF)a1xHzqosH@B}b39j~k?axhIE8OCSz?`=p1j|fs#O3Amn zGg5Ts@f3cvz$a~O;}y_v$tlnbR5Fbw%D-Djvsco&h28AYM^+#|Ehgnx)Y4jEuZ9#k z`}l8w>J7;(%xLbHph$Z`rll5_)tOmYzYj2E^rb-e8zip8USahVi<)g99u6xc;QnIA zRt+jwjcb~L3|>y!3{S3;eiahbR{09}fj3UJBt<6GhOQTB+|rzx=0m3ME4{L&-#7x# zoi@VrT>cYRMwIWMIhja%*;Ik5h7DbAVxQ7&W3f2#GoG1f!8TolpDJhYziZuv3Maz0(}p*h~4<~#Z9w{i|Zk0#jraH z&Ot+Mb72h6VZmPx)shk8mON3>K)1D%z&;|&R=#4+E~%_20;f7pM3E`-F~%jqnUDo- zw?A}NK{gQathX&CeSf?!Is@MpoMg3-;QhnQts*Iwk)!U@F1gDc!i-z!nElwa_*OL< zf86HK$@3R?&nX(UKT>IoyF)Sx9v$!Q%;zq)={ZMeQBFa=wY#-DlW0@MvkWNqv!%C< zLODe;S%FV&Cjd%lpSkBX?h|Q-LAh6P%uV^pwE?7*{<#=!f@cV5BZW(Eq`Wb9#gZ0# z0p1KL>H?KPJ=u6|4e!vAU8yR^CV9wGR{Ag7lcn63pxuE}L0+F9jyz8`lQ9+7CMH>k zhT3Rp)-Kfqvft*FV%50o~&*Isc&U z84+6BE>r%@GKjeZFSxT<;-0tS-~)>lTqnG;gu=vv5W@c{M}b;n^@`H1z09oo6RP?L zAg+vHB@fg)zk)y=4_sy4Ng zK_ER$KVtW`psq(v*vG&Y2L8{|LB(U{7(ul@Gj}a;!&$^F>z`F#Dhf}fH+0;ABL^gw zPg$4mM#F@!V`NR@TDqk~0E%t>kV$4(0wBylZ#YKC2%^_`<35LncG<5x^VBYoeaQ6a z(aG3FW}@CWM)=<>jB-D}%ru?Q6$L})GHsNbcgTB01mV6A;sc!-EuLnSF_(YT^}_4TtE02PO4`dV>?B5c=G*SwZ>v2#1(je&YSKSMFMJzy*>4+WA5Ih!Zu6IxKjfkBp12O$!y%*hy=x znh~~N1ZF&O(0K6~hqkA~b!XL%`aA6CT(sub&ntvjm#$rI1eER;M<=awW=A&g+i9me}usuR(io5A&(PSCgdB(j-)2q#$TWrpQ*`fRi#V5aO0*oXX=mNZ^^69HS!1o?4J zywXxbwD7AX8Lm~a)7z?gCbRZjd9@I>D1CJK>b6ChYbDYSAqJK{`2p1Gx%KM&2j;bB z!^wpeumxkP_QXb4B%~rmxiy0{)kys?fZB}9J9%cta@D_+A_O(}qq2|aV zBjeQhk5FysemN4xEcquu{x}QhZJ|r5`&!pqyN<+=H^6f$K-`Rq0AiM@9v~msQn!*6 zyD4}`RsKY25q>XJ?;X*t!&NO&uOL8!5tN`ui^3STl`(xYt)e|and~kH{$lnpJK}F& z`sS_r__D$DrI&PD_kl^Uak_W4hy~#dWMMPn_8aj=IcK=bQpi$j?qWV$^A(czrTAq4 z$?=X*HLg5=pm*Nf9NqFtj;{!=S&F73vxf`BkJY~qCa&Mrp>!DQ9I1B?Yr9^LbbfE1 zB@&6s4M&2G)&yiL;V?;J+)_nvBuQ}nAyL2H<_KB3k3^C*-(j24Cp)gk8#W$Gl3WKGy?)o4UwSn__=P>|P%*n#-la27*Sw5G-_8nM z$-Njw!I4)H`|2jFq=%7Xx<;)dRp}ges1i^=j*c{!h9 zC?m|x2+XLgV!Wu-!Vz`Dm%ssy+xPmqF)8%-dASGBJP+2{Cl_1iQNZG6=h?3`t6P2a zbf)_FW(5du&!C1SOL$*O2He%$0aTfIGNC!qo~NYjQb<*&2Ji#?2aA1F}|hk74;)k$skYKG9o|{=)!B z%BjvY1*F|z(q@x$mT5PuwkvR&gfWSEF~-lN#%rI&X}?7GHP=j-&G4WYNdHtqKQ^}0X^*X zyPTA6_bf~ttU2H=hVe)ZMiL$2xzzqrj?UvgAKsFk4?BZT#-`6X_0}HMgXR2)4`8i$0Kf4t~@&r#v+!xyomtmp2%qfHXg>=Pg$%5_gRqZ4lV32mzBK|U!zxSbd zW7DXUF>(tfj`>R``3h9NxY-I-M7Y_?RR-Ii{-cz|FmBO>3-seh^xu>H|9{*5f4e*> z&PxLeq4FJ8-*nomXR6OZr1Qy&JrxEUf(KgGBR!)Q(Ql4%k96Y98<-&oD-p~|h)JQP&3aquNNqG8gz4sqQo+&=bqR+orKY{&|e3JOTGTW+~_KSjue3#8m zD7cbD$9`4;frrhuNRpDp$uiQpz`Q>^Ej`z{t6Za+Vz1oP00(LDkc9ZJKlq^=;8TdV zG>!WgbdNH)czAfY1^oOz;P>cPY}?r{*m-f_aA?@=Qy8PHD^FD18es!f%utotf>6v* zowoXk(Q#=Hr7LTB+5>Fh?GGx0)RrKv?R%O=e`CR=UoEClBRB4nQno+S_jhjIlO6X2 zS8D#*mBU2yB|@M~+i=9bZ47^*6u=aJf{J=mxxV8>FR(2=#vwlzZamWi-z$I;9Qth2 zHABS5B5W4Mq9JcWjDsWGP~tpmBpjC?Fpa+!egESWWg(S6#5m@D*Z1S#Il0X8bQ!|P z;FUIiUoj#8FiV0>1{8O0?&5v{4%WqA*E^K}@Cvi0Y3LP||zNH`>6yutql1c)s=$Vn_Kf8n$e4SZaX z-vWg1^Wtb+|LV%g0BP!`Ort-OJh$)!4<@8Cg&8)#hCHKTnYXB;s@M!E&2432t%;Qf zh^>xEcw7go|F^nC`eSeY1JXGMLgZrDx(xR2f_wi5XxH6|{2|N4M$QNH>0p)A`}*Kh zWGZWptgyv{NZNzQ>EGi~1mmHLpS|QVYBAvs=HJ6f3w)vVpL?`v{ zn&_cHiNxFm)fyFhYoOkovs`L>qrE5!k^>ofU?9Yu;sLdOUqFDTL;8VtuRX#K5LUb; z+$B6#-lM%_A<8$(!Dpoqg)xs#pnkj%ZLE}7JD&HD0n!N40s%OSaGX#a zQQZCy-|}QDwgV>Y!pLz%75qhf7W_CS3}Y-4B6Y@@xnI2v9)l#IInObNgKN+!N5q%b zo7ShwXQ{2XA&scguA2)LqQ!W}rm5TszGsw3Uk%{nT_$TX*f z766FkYCBUXTw$us4%on^^5|yT`|^|2Xai?Ed>i z>#(D%0RB$0{6A_daR1ke^S>p_OD=_l`f-R4z+_*ElADu}JO1|gvg+`o2~e}&5K4iaYdvPIId>;JSQwfD z%Brj8EC(?d9*bE^gS9XpU_{1|5>4GvQ-s2iytObNLc`tZwB84Mg9QkNkUoK(GFjMQ*WIk+;cq4GFx_i!D0yvi0`IE9696TtTls;idT}q%!E{ zHbvRAD5(pj770DXnzSe=S=bed^3LJhxA=~Ek2(Y%6$-6v|Gqs6I#0`@q?xD0DOE#~ zOYc#~oTM5Lv_k4j<9Wad=|qzObSK6nH$L0eye=HvPHivV?k6kc6-SrI^9TRwjpFqJsV`rfL_%wDEZ1-v`!cEd{kW(AR+^Vl z%mSjg6v2j5l8aKwlePF=P)6}PLGsVgo=3TXfW8r}<5dBA(TK20X$#f%2J6lSD^_~w z^2o9_`4>pU6c9cB!2l4wU1%*zz@_OP_lDzjO~-FL_LK3A?q5_-ewT2?z$)bVv52A+ z;RS|an2@D>{muB{|DnE5-p3iT`1hOj4Ej$(S^mF5xkW|J;V*geH3_4a(vvIzgCyNlA8E7bw494GB9MM{!8~IC}z&?|{foCLR5OH6DJ}D>G=pY1Dnbqi~XJXlI zd*=D4UkD6-0kwy<3W^vi?M3#f1=s+ug4si|R;Blif0mz)y21fdkUQa)@lNeGhsjt1 zH2b>4CfoN4LR>)G*0srat>_^VmV#tAmP7|*WTjYG=Xokf=Dv&YC# zDvrJ;{MN^*Ql*t$o8~f=%Kb?^brX-44NRWChY?3aP|D*QR=U{;T#1utmnyE@S5{Lw zmQxcm*b01d!~)oyNDb-{L8|F3Ewa4%3L-=Y+BVIk>jV2tw{t=ECTYOJfy2o zupuT6rM%UomR9mP$lw62wmZg@b~u%d`Pzb_)kL4N(Z#bT0eZk{OZ&| zG3~JMmoNWwPGR&-NU&yHrE}i*KaZ-zB=z-zGZq57rLF(Jre`_WJFObKRil{I1Y4U2NB8^tMpV7nllsD-kt; zl9M-As$;{Pv%4p1-~PB|+n(zq4cZcmgan^A>(VRKzefpwg6Eaw-;Z4e=0AxN(SJpW zCKLc?80~vCk?q0SgvJ?}Q3{0uv2ctXCRotrkdsNO0guC3HswiM#zrTi+ori{s1ze) z2ZGP)QqimJ$o>t zF~}6!g~ea72h<(94+l#ED}iNi0^s-WDW60mHSVF9r-vIiLb<2I;&i+BYRG_hQE-SW>31vwY5kJt{Hy#J%ZAjtE$5y zM+IzKqj0_O?hL##tMb#VG*L+p&I0>DWp*Ns@#8>=PKf&YRqzwMQC)@YKvM%$f;nZ5 z&JDt88F^Lcy1ta0wMfBE$}&}KNsOi3+YA0e$s3-_mO=_HAx$>`hud9Vf%;xk!+d8%2Pt*i9B=})`Tv5E$9vd0bef3u8&*^{)`F!1MkmN z+k3_Nc#MHAu{9uKcyggLO?oSZM^v;Z%9de(*yT36)mo*zB!DM@$B zA;GASPhpRz!!d&=M0$3s*M2OmGAzc;z8EbTCk0D;rA-l8lWT0e1|`^ED3Wg_gPL-cJ+#=nf=Bn#aklv{D2wQLn@k}Q+m*Dm#QELXwZ`_ z6&+})JNsDj1M#gL>i#CK&3gw9xvZ$U{6jsNz^>uw^W^l{h8(IY|1i&?GimG4WgBvc z-^$!F<>M+yD_Vnr^)+G$EjB@V+6c4ptja}VMeq4?9DH=>Caj_3umkSXvA-YNhkr}0 zImovG^zkC%DGzBwM_?q*&)<}3N78l2@>uQ!FnJ3v_J+f$r$ z{KWmE|0s!n+gS)0$;dW@{0eA(IgnL2_#= zUsv)1p?$!l%QUf=$E^`_(Iwe`IN;2tZY*U?N;;hZN|JMQSYoxMvsYXd!2pf13LLO5 z8*v-jEZfZ33<##akiYh%dwFbJsbE|7R9ztImk2)3HU(0_sZ$j2I42AF%3Ll$NPu$VF63I5P}{EefOq1WTEhQxRmm50RP7sDe#Nv}3imX`O1+}Z zu#CbY1=ix;iONBdv{BzA`-heqtJN{HS*Gcois$^;_lAbA!}8=!XxLZ0CCzb1OaFRY z0z`MiZQ%rGjAOyh6qiDlMCU_{Tm_CBJ+sWYb?1UZB|_6TPG6vFg>B_jqs}Xnr>T`v zDu*X?yJDTRdm=Ly_(s95d=^`F$b|%-#-@35g$^gphzK1dp72qF<>F0o*kCo>IWhNh z>0y>HmToi~-@kk^R$sWu(?^X`5h;F~LJ7qQEO;^2LnD;~F9LQa49|kv=19rd3ljbq6dPzenf$vNa1Kjf( z=}a7`u1Wj*cQy*BF57aMQVjGrer5`OaY|Q(-bwE&o>NCBH#Rv^cyQ)esT>MG94u4! zQk;eTeurSzxkM8DcCI!Q>MCJQe7Xf$t2=<(u6lY9Ul&ih$P6^)MoIhT;%D;6Z=|Kr zS0mibg|!5%uEVLI+VdQ3=ohTUX5l^H0JOeCO`<)nn3A}Hf!WaABsL=+EJdkn=Lerb z%v$XJz!B~j&O z)MY;gCSOL3IN`bZGc@5d3geNQDfrp)BJT|S9ZI%YB zlFT5v} z^xYDsQXR$siELfGAUtRaCl3`%3XEVQZ+~F!v4RN0TG+`H{{tn%VXtXvOk`PDtNWUy z8-BVHnr5GVOD@Qu`%bC4+p3NDQ^a?C|HXxa%+gUjA9(gd9=HY@!|)W&J* z5LkpYje#Zl_#uVuUYoNQ@?s`wneDt%`S$b?zt?c=Wa7{C_{n$7_p|_NU1cf8l1%5O zs=$tV?yYKfDmC6imGW~U_-Rj{3JmPXVLdq(rd4)TdjN@zokUByMiCuu-3=JtD8gkf zjSt0^;!fv_ID3xyW*Xfo716m2L753A|HxQ;CG~!Y6DgH#dEd8=@wBm0erI z*`ym*`EV?alsM+xtHe%_KHr&=ytPy6s)JnuY86$;W;~k=TQM0(qE)jc?9`k-wjn0r z)Y*2?^32&Y3C=vuT2r&XX;Csq%w({}SXL<@`KrAqh=^xHY{6X5v1?9ji{3rq74j?Q zEaf__yCe`&%g7)2PXLff6ulJpyy-+rrS=n0IdkS2@=2yYBS3ncAvQNBblq@p%?^%~Thl6J(;U?wYfxHQ(ue(RC({+d>FL|nXZ=!6TgE$jOkq>0ZZ_03(ahy5${Pz9&(JrzpF)ML( zNG%HDhZC$G3_k#=r;BVaap-xWStmmeKVp`p+%O*PZJuR8u9o^ZI&d`=we#59{NC5( zE$qUoj~qzaGLm6ToH35nZPmLHoW&w6h4d=AIUdVJv{OkjtlklgQB@-kqbtKER}sZn zt&L+V?~O2+D345sJy!@lEU=Bn0b2ujoWk!}3@V`nPM z^U?fd+8c-OJ@116*s*l&x?h0rwGCnxFvLzZQS2zWpFBVoq61A8A`$6Kg-X?}T&_Ho za6n3RBCSLuR)We;bt0uiHta)HS)xfeEKK#Oyd7}y0iAbU&7s^m&%+*^EiS`;n4g4BNtZ6Bdu@?nvpfpTvUt_+J0c*jOJzXD4Hq(EKg|9Z;QB4*( z%j^>y&}nl|r&evE88@mnA4pJ6JQB_RsfxyPhohz&K3i@~;a48%{;7tBx3v+H2gM0Y z)0WvTXQ*aqCPR!j&+|bnPM>jeakEG~UTgYpD5|h16L-|vQoVz9z649xs3Y@yZUe?X zt0*b3mK9@5Jm=D3O5WpIxIVu-8M%^N8csS(E#6q8F>5VOF5`SU^LMq6l1<%KtiI|s zotSG%m_CU@Wu2A|xNfqHklyf;;&j&CS1qN7STH|0 zJozfO3b?6)vWZqAEhm25Q{#k~r>1%_N$M@*|vzqmjps2-@J@i)o zBr#+m0WMh^%-rd&dCGXfBpZ_hRNj&-OI0GWmd6!12cPmFUM^jTNESja|Iz+i34 zWMRAyZ8V=iM?}Q1lZ0ZGt1+DRGO~GYbL-_Xj!ZDJ7Cspu`HjF1HoMFE_!ftPqTJ}% zm>7Fwdm?S;FtH%O;P|v0S26Q5!!_3}LX|m(l^wEubserDcWpXDUe8d-g*=C)xw(NP z>wLMBHE3otC)o#;k|ygiv7^&jeUe*6r#jbcpPn3wwYS{I!NY$>HJ{+< zd>keLkKIZoK$v23%Ju1tFT+-#VgbcB)P9q7I6d@WA-wmGxsQYOg7f>(c0})?Iemt# z&HDFv<9x=XIaPKilNR7QIs}G`Q_IT@3PWtey6Mka>1_cP&AMCjpgM+{`o=RVT34F% z^&x7}h-+Dj@>7Riq>l=DQf3OUzK4)d^V4DD&^kr$lg!gDK!`@Em(2wAXqNt(5lK@c z(a>EzcC!F$8w?CbMv1ZF6(%^6b2Jh=2T@aPtHBsgCxLjju#k*9DwT4l(pOBz6>6zx zNrPMu966)8fNaqf*z>75;o4!f; zjW)vcWg)r)LET$x=>2p2pN~X=_)uKl(4!@%E49w;x205l> z3MQJ^UiJk&hlA49^l9rapKX#=IYov!=WW-TLNNJ1{=(2>OHsrjjuQ|gs9#G4oe@c< z6O=3_==itj@))fkxH9WSSP}L)-HJO!7F|!Vv|V!)Dvrn~!DNGTA={HB} ztw}dTRL=JH#5gWVO%1#p38HEmmKCIW$*wHY(;2z?m0Ft7Vw`B7W!c}oKkJ0{43?_$ zIsQ1|_g?^24GUzfZIQ*3|KdKQc~s*h7#epPMMS<9nS;2G^q#&KwjE`-x{sR!NZnov zd+KsWMgnB;PuoC6g3hAbU=LG(!}gqU;o%Oc1B|*ed#@{e!IEAS52XW?Scgmo0cdTN z+Jl4bnK~&AhQ6E^wlT{HLX#w1k%CLdK7CjooZN->zg$4w?j3t}k3A5K4e+zR>_@FL z$30(T8+7o()+Ko@=tsH4^(m7yNtF`{NozsdY59?PWDL3`GYr*Xk$Lc z1abk6sLP&Lm_zG9XZVEf*F>)wa?u;S`u08aMkkP|qrS01#rXIhIXGrfxx?d>hXk!x z9jOT}xKHGC{jY@daUtUMoHIA)*r7_H^(l&GpE4O_2b#bL6ycaKVfJA(yoiN>5uNLB z?#stD0ceFwq->$wE0nRKmVNrxeW*pm^l`M}vb5ZfbI<58oinDh4zj5T=D-wF83!BA zIJ&|77!0@f9Cx3KcDE8VbPZp|BM&9kP^WrW)Wos@)-SMqpoN1tZaX%mwB3wRdX;%V z`sKi(_Ld(;g_DBvWApC0$8p2vt*IQ$L4#qqY)8EKQN!YrK1y8YBS0%Ej}hOboALts zo;O1TGUR#$`IikO9)E(wJK_@3>%okWE#6*e5Dpm7E~NFL5&o8ZhugiNkRSb`RS5a~ z?McL`)3<$`5_6lV9?241=yY&*G-U(fHGUIIxE*hMD#Y!6e_Fg-G6Blt+f)yGaFZ+# zz>y8XKFTRGq#D;`^evW#NpXxuDZ=xCt2x>TNY^}3LrPV;x>?1SD}_W8^``SWM=+?e z{Wh#?4q=}07oRN_9BWdEAfSNyMPzW+xUmz25vN`u4 zX|$4dQ@=_}aM?NB0%wG_eWcY?_;__|I((AVZ5qWj-EZ7^0G$UxKQ(nc*ADV&h7NH1 z{0_CmCJinRH z+Dv#$5N8_1Y>6^k+TaE*sU@@y*TNVrLqoR{xkLT23e+s6wIjN4Bz0)B`7D@RiugdC(u=f2Z3I1mjC+AU}Rc z{3FR{)Bi5=YN?Wb+dlH{(b+k>G9*G0kKa83JQt@IagXz z8Z(8F+(>tzI+zRUQ3!O7d`OLGBcvTY5TQ+^yw8ouK3FkCN7yxlaNitKs5ul-*n+Kc zo=7FVKAIDM0&|1}OM#Kp1o*{N)>v^Qc`mm=XT*g_e=j!Libz>_ig17tGq!jkbby6x zxPgtND^&%Jt_q6>n#1xSvZqv=x9Bd1P9}q}-%f`mhEs&av$krpvam{AUCWX7q4YS? z(KNz{S{HelS%K^N9K*Aj1+c;ltxsP>xgtvbY`hOzt~mX zPvwKq(l`6Jc&$aMpQJKDQ(DKrl028SX!4`e#I=;4aT)r$8A9i$t5en8fH^lxf5+<9 zWY5@<;W1FvVm#Qs)zL<=Y7c;=b}YN)x*sH%g;p9(&t-!K`AsjZ{aBcMrx9WV= zg^a{g-u_nXPyOyqWz{JX3#BmA>qX{BVDJb{V5Z3t>R9Wrzy!8hbX1+r7cqR&9Ns-q zbs}!jx;YZ~HNFT_1dB`;eigBAHQp`#n_D5Lc}i}7Owqsdw*u`K9XGV=gNTB!Nzg5` zs(qA;FhR=z;aOpy!7a)cTz-ajHjhf0i^YZ0l2wp>8(zM@0AWqmy9L>_-TWHSMIm2U zd{IwWc|_|wf)dVGw9E(MFYs>RrN@eb{i6N{@{;y*dnc7T3+%!bI$6AiGoYim~$pi+x}k)2rX#eV*4X^>85Nx0`s3ROZy=7WxI#4UfJ?#j}bm55|&7e!oGrMuocj~ zgax{ic@R>7c=`vs2cMTYL51nlc;Gv{qObJuKs1`(Q~cTFLPj)J1jKfuP*Ic0QrGs*w9aJke#(Lnq|C#9*Wt}m=( zyS$>Vr>}?D46O=hMWw0FCW&)q)1;L+TrcCnA$>L2OYr+mV~ycU@tO;0q9Sbe3*mis zX~vc~7#ctADEn)h$K`e^C*$upz5D0e6G2eGuR=(Bs4*Ntl#^H&DK|Vj+=jR|N)sso z+ytmJ8de0oj-|Vwak8G$1Zt6)meg!5e6l^D&D1CS#ndO52KIL174wjpzuydt z1B-t+IeHe8e>6CnfsyJEqMPJULjRMZo9fVl6f|39W7JKCO_^)iMUEzC+^RBzy#{T$ zzMM&wqlimfx+M)x;?Y(jhuRGsEE|Ek%g~%}P)Xv`TmYJvu4cyaoDOU-0PQF(h7Q9# zoRF-HKqbQF6n9(k&`-qqBG*}q$L>NqHT8Ll>=C@9x&mA32`t{xS!+;DLaH*P7`??N zGjqAR8T$n{k<@(=#C?XP=_0sQwmW`-pC(@oizY2ynjX7Tq6lPyzb!LGUy*vRn)hpV?M`7~y!FK3kgIh-ZI9ZuQakQVCc!pqC+m3n*3jM2fbm z<7Uq%{{lw4iXu5o#&WgNdfV;*H%~4O?}LxFRI-K2j3{n>oz{xOZjykfcIwvZ;5Rx{ zIo3i`shQU)m?}aF_kMZ~Gw9L??xq{VdMVkSrBhs)i@o{OgRS|9EsfcOSK2va;krqx z8Rzgi291CR&V+0Xj_r9sd)c|hIc3&-Vt0Q2d_t*~C$p~0I*u_JSTwKm`LXQIb5VyW z?Yg`^n>sAtDb_c)Jyk-TV;=o4L4MJs+EdF;4cNX6!A7%$OBhm24#4DjWi{;@^cxU zNxyDHD$1Z(Az(~=5(+yZVvYM6EL`>-NuWJvM`?8aVHni@lOXNNa>G2v+MawyefgHw zq%sE2;|qQR12K(NVHUGkzPSeK#wAXrPg<#lOPtnZv$mfLbGmfg&STSVoz4ZQ=P9$M z=%w|i$me^pelX_~FExlbMAIBD)E_V=Bx`uFPj|S{ z!wAMhZ27x3=;PSB0;sk-cd0=wufnkM>kHbwHF9EQD8B2fh;-?VE&YBx?sgZ5iW4)h)3{yC+-1>@)g3s`rgE@4#M)E@*%|h_f-; zbrpb{sUyM>D9m5Xp^d@)j$Pgzg@Fmtz9_%~@Q$qw!#QxY-^$38OS5N5A?N=cOR!iK zJgVqM(1gm4#70a^+~rNMEe7tBsO?Kriud#q;xECjn3u1pP9faP9+C)K#^_#M_=wPq zN)qv(PKcrpQV#z-$Eo~(66}Gc{l7@C$IpE{tn(jNbFBWmnllX#B!n1T^>uChl>-2k zmpc&G)g`k>9&I46GMj?#BHoe4B_+l06Nw7YoVj;9Pi$>CwhM!_mmSGKyEyT%&$z_SLX>m1={iah&aeq_7$1 z4tZlj(#}0So7Zd=Pyp)x>b*r2_N{@BjA=wtz_7t1KjR*&2BB!?_t`xvI+LaBsycs< zoA8+XjQj-aczg-?521v7t=&VazwA>M`=5Xz{lB|zP*#z?^XSf{s-EGATZi7+L>5`XBEQ%#e)QgUmAoJ& z#<#O{CDIvKk+ywT`&*p!WN7oFe~LH3V-EgBMw5Rm%Rid3e;Rpu;llp-o| zl-W-ZP8hfpB75g85A2_tb;J=_2(li+LdIV@XorAt6b=BXGv+Mmi@>0A{BN7HYuGwd z0Nvmw=8YoZd{JLa8e@0nJ{+ur+MZEHm>Iq~nmJl`bbuxUJe8tW=>uwtnHgtcJ}y&8 zwog5ASAtLGV`}0xo@ z#{3JwCEv%_z?WZ>JOko{*iv9q#r986rOiKgif~4Om4fi+1sgSFL`ebw{;UNV_o9Xt zscVFeA_bjcPw7~4pc~Z?Se6+{0eqt$MZ*9iYrX(JZH0UN^yWJNZliuPx&^5iy=~m3 z_{ziug(Vr50@=X4VB0fcPhYiH10W86#kje);^mxz5}++e5|aXENvhmn$y}e)e3GzY zbX|@fZY8c@c-lWWU(Y4CWk)_n7-8dbkX$hee0>5qP*uP_n@h3{esIbQ`2dUkfPpc8 z>@Uuk8z2vJ9>iTN*fuZ~nyN1|oNuK>)%)&HU4`AT&CL>WKL5?7m3}dg+ck>qkJK{I z#i5?7Hk@J`}vEDSIkTsX_kDPNA%&A+aG9~LN^(j4Qw#)RL(|LhMWVJviuTl zgCy&7F>Cutd^K^w1c`>|be7eBm-gXH>H%Xp66FqJ4dKVXF(PRWIMY#l!Oc~evyO?FEW~@aoJt1YGWEb_sw*T z6G>qcPS?3K(p@u7sPCTyh3gR|x>AV?codz{Hk0~TS~pv}O_F-En>r|+6TeZ8KM3}( zk==ss5;dIe))6G`u)K#&VA)-p4qM_n8l6@(noH=ZZdux|l4UEuBzVSvXt@OI9N8eu zJCj1h(<;y-7_mpsqnp3K%aM$T$0;c5&z(GyCTV}OVx84<@f3P%k=ED#_|he9s=SQq z-LAOCDBjErr$`#6JSjQ32t=ibZK?-*obfXgiriMJwF_tou{thUE;X*KS`S}47p&VG zK69xW!-7ON*b%GcpT~h_W2|ABi(1D07(k&7zcS0w+3alw!-j6hhR(z*Wk3h>lc3Zz zk?6<91EzsqtY^US;IvQAv{(Fa3O@W=LI(2~JhP*U(Mj}@1ZCbUDUFK7Axn#2D z@e%Jro)>v%x|k)MGRsLj+meD*W#)L3L_=PWoPLvynqCWA&7PebLz^mw->_*WJMcY1 zRJv-C7CCeX0Z!Di!CS8)>na=_v#6kG`~95N+{DbcUXoD}jNSyZRg=Y~P?y_IvvFRM zFA>E?;ic@W6x50n`}^@&b~D4P0FpNSxF_r;F9N5AD`75n6R0|yxP(qsF1*!hT)*?1 za%S-tA#}2W-+KO+Y$vN#nQtc6P0WK5_V1NLaf+z)1CjkG`4JSP?YT4Gp`>h14zdh_ zPgDK7p7HN=e*Rgzk!#-rucZM9K|`WHBO=K#_}^gRqntn*ofJoJ(0iii-YOq4Rfn6z~ zlO8v8!KMj+Fs)~T6Hu}Sud$-V>K~YcL=UNy0dJUP_jLhRz!}Q@2%B4C3mh&G3J#3L z-Je3DceWd*v}Ru854H(PTuVWz?y|y!IKQOj%O!GzphtG9>Z7C<7Mf+umA|cYhKvy! zPCMS3^7QNi0Zdq3*^<_Y2st}X{`f3Y;tG6-H$mh8PhoX`vweH;>EMWQLrHoVma(gv zyb;cj({sT#Ls9XaV6;cV>`Sr?obA72k#TIA&0=t8wu#{5k388?(G*NxEu8S7-vNs& z9j)|NExvU5X~7n*!rXVZV}Rxtkx8h1oU2J1lAr5 z7FW2E8eIT>acC7FV7R*U$9OAKQ^y-BYE)6!#ftrwj0a^%EyCG{RtFTnQF0TNq8zeQ zTuED+tF@VBk~95$f?3`?FxIvKG$%&AS)u>72)Cx7_;;v}{KPy`atJoW{D}*^(J7%e z_V}dv2Ez>`5E7Jb| z{tGMzv5QUXV4@RAPP98k6B7D=GSMmk5Cr&1k5T09TPNQS*g0247e$Y`yZ9g#@PeZv z*i{KMexlv;8K@h|rHOJ^+s%0fRB|a&s4pu^O>wL;Z?gk6a?Rlh-2c(qTL8tiY;nH? zcXtgM+}#pvaCdiicL)Rt?oMzgxC9UG?k>SyLVy5)$N9cd0~W61f4Tq7qANxO#a|oYOz5qv*V1lGN-6`Vl&w zW`|6r)+VazY(#Rz$1kXG0v%v(l=c`5(SHZUwVuj?2-WgV^Re=>4)u4GzL$fQ^CQX% zdLMmyg$eG9Z($t&slnwQDbTznF`$E%m3EG5NjSwU4pt?G`OU0-o?tfDs%D*{sr$N6 ziE-z^$9MkiIHoCBiQ~(mxlgsx{e4Cy2-6!X#dSSkH0dHmhjald;%E98-=wbqc zuN;af4Z9)wS-&*Z+j){@)0bvP(HqY?0iL?LlXU0h)MV7O=0EKAxt6@mtQ8UZJ!86GQYm{1vA?y zjtoK+6;*_qt1^F|ZI$(YXi_P^(ID%iNZfl#3Rc?WWPu(*grUjhT011y{9?_@Dua!x z<@!pK4VVM?WgDwzlxuG93<`lQqDu&*``5SqT^U3TBwMYytb34|Ey-~7i|}-T;SEF{ zFj#l-D*3fS=K^PP!u-B*z3~!X!(2A$x(do(cUtR`ZSx7O@aO8$po>ouKI|0=^ndw4 zHjL1Tp#LZ z4&C7KLfJf=Vlqml4ml}`4uzehQiVxom{>7tqtV&OD+UyrO9o9Dy%|>cE(}ndv3JZ! zQ(T1S@J{vwNq%@WiMn6B0(`B8azp9+#;HHvOyZ2h+jt;Sv87QCxX*W!(vfg5DFb{L z$rVr%7Kwz{P~N)l=aojffZSkPF4(V;XjTqoh}CtF(dQa@B{6yn(&Py02(pQ{^=9*Q z>zszm*O|n}5MMgN-_re(#2w(%`!jNK4qvBl5?zg`1If-A)+&5GxFMzsZtLl1F-eM? zkEPrctK}_!b~*~OoBslFmnn5$8NPNwsaViYUA@!v9i-t*0~_ohpn#^+bSWMvFc6Tu z7scke{zvE3{jX&8k94A>#1gO0`Ogos%b_wv(5c-poP}?E&6BEQDN>9+d@G#9Ilt{f zTE9ubUlYW!$TF*C@ig*1{k2-f;Qs63`ymGiX>vWI$wqmgCuT35lv;8vqw$6SQj>kV zRIn8ze$9j*sR_4!E?lrR=+#ocUM2#ZsAm;iAJoS)JzYp|)>{ItJ{&0W@Z|ma5As^h zc2HmN^27M*U6gL-cLwb=}DmAzTAhcUicVbXvO^EA8SUn_s zK2Y#Eloza2FIiGK9e43J+7~@+yh!{-K2Vsib7_ebs7eYYtLo)Tg(#spvqaUV1+(?l z?~uZEcEna>sMFarJ`sIqMvFO(ZVXO|DV5&h*S8D^X7oiQ@k0%TLxwmHifdDsxUJ!$ zi+DoAewmxLNGD4FA0J7A%Bywb;FA=S5QKC)Eg>nen?#TsXlgS}u@|ZmIT{cIx-;Qg zIW1k_IUdd}d+qKj*f{ETl=3JQ&4(WzPFT*I20Taf=JM(9Y?jX`S9LrXH{N0(G=*AS z@EKySDmY?HBv-&RiB!EV+2SMj8arL_Gs7!8lcOwssD{@SiyEHp&qyTxX%ozBC!!qL zOkXTqmf^&ZHocC@)&kGgDdS|sBP9xEmhS_Q9xJdXz=CNNZ|<5V<1s&`L08qs8m-7F zJcC)dX8h`-WLHn+)*U^ON{7jxRd|CkYI^C@eIh;JC_S*k8cwzp;BcJnPP7=QshO{ z?;nZvR#mqTiYR0IV&lfY785Np$Osll@n1(7%tzo4*2blzPlWq6H?^*vtQ?m+Kel*& z$82}!{B<)RJkxEB<|?(!W55|SEnM?sjZ#&|y7oePhOt&eTYnJIv3iUYtIWg1t* zU1RzPe`}xGF}e;S!xU~DEfAy6`+>G?tlfa~Ba8Z_K4%y@EIc_J$2nM+bC5dRTSI^S zP(S!Db|D+pfm~X(a(#J$eUzGRor{VY_wZP>ynSqN4EA0A-L-+bc0KL!e7w6if^_vF z=uJL`#dLv7cE8xNy-+0rB&+i=MaGrra3JXH3rm&Yr4Ai@om<7~x{o4XL!sR{AwwP~ z<_cSjBFi2PeD@DJ6pIoBoK)ZOK*R~6Zl*)#&Ri)`E_UOR&DuJMgt}~b)Ht=MMd((9}|vglim|TjS-r>?dj^fORn`4BSsUoj=<;U zlPAPetEv0GDrrLVSd6A~EQOT)c-r%2Q$Y3>foXGq@iXrPwaUcD_0-;^`O7Q5`TE3o8zHPks3LT*)`aBm%#={UTl0>|l>UzJ5 zn=g^~x;)DQ4|}eSTusWCF;ZBehd1A%%6~zWyBt^SWf;VI$setMwqg-CqCJ!9mULoC>6ByD23Yi!o4Z7q^qh=4C+7D3qwuSC5-XA&qum5+{fl?Gg z+dui41uqKFRsDO^#c4}|{uOJk&h~b4x>~l>vPKU!2ai;)G>xPg8mtv}MO?IATV1v4 zK{*;+`x5L{enK7XGN;u}o0F%Dcb9hYdM&5vBc)Q74Olxmp%!c%Ba%1tx*b` zNMcE4VTjPLQ&PkxvzxB*$X95#?I*0jJYf4`x385l*r*4cNT$CXtFt5ZT6cOjf%hkFlbh@fTa0J_^aB<)I9Nxp zd2guec?pMvXKn+B#C;U7q=+jl6E^>o7mN$_k~S3lj|*%qiza~VQ%{F)T~SZj_Khdh zdkRBDB&-MXEX<6JV*C39{c-H~@(ptFTh{7wvj=n+eFosY?*HX5l^P{AvN|w=s-;Eu& z6X*~j5Lq5SN7m}YC){%jO^-C~KU8aXCK$tLk&^=m^u_wCQZh;zJ6dY?)^|vES)4~@ zkd~>05T}mJ;FK)X1@(wb?Pf^cS+A{Ela~?D(`tabE(MXME}ua6ommCjN=%_4R;Z24 z-D!x&&?1Q{)LA<^CC+?`L^Hs-cxT(aJ0ZThpz|@08DD$^r=Hub)2V!4OsKpIg0GsiP{$dn4L6q-kM&xm)?PE!*jhbZ_S*159%l5tWvCh5hvCw{=_Im|- zP{?K+7_!QF30;rzIKLi_Tog z|L4rbkSCfl`r``OcH+QzB6>*zHO8x{0(&=0m>g@2Vlwk=UfT6dcAQB+Ck0cA`J5Y{ zuWK4AKJmL1^7&CYV0xn+>DOPh{r#p^qu6|EVTYJ3QR|VlY z^X3C^^>Ru@g7$Ith2dick8IeXbB#K*bTf4@4cJF+8b=~=@qfEX-b9O(#Rxbn0{0}} zQ>_H`M&&JjPnw-Y=!qUsCFC!PUNleM;R8`xsVD$ePh-}N2Af)`DFD9I3BAq)LzuMw z9(;h&e-9=XQ8suYTn8ot))0X(Q7;p`m~l2ovxf>^GFsUl7Yr3Yc0C}J1zSF*kA+&t zPtKlDh+3ydAEQFNan4?<2amJpn>5U7?7B64i5pa(a!Xho^{Nn{=MMD_L{!-;l9alw z8;-iozxxFH3ssx8^Jo3nf-8;%&qI!d*?R;(;ldb>Ym1E9w>L~Vx5KYEJsjxXn>UzCJuYgR_;DVO|A*Yg$fzm}< z?r1SP+2-&G%Ms{)Z`dkO)bD<{<~;p;g3$ybHmEuM<%B|!YL?Ll~@808II zJWj1{S5RsBmW5Z)E=}y4eJY%+Iv(~2&s}6(8JW%UwRVOqdN(fi4?k+=1%I(bU}F7z z6``CiESU5mNj#;)ZUj>D@&JAujRXAtgNq0MIvlU+RdhM$PTiUBni&fNFwpiar%&DSmXGzEq0JmzfLN;H#X z9wr2QdLs?X5c?^2H#B`2y~B zL6h46L8Y zm_AxcXsaFsAqJ&MtW2Wx5#*m7h^^O0zRF9$oyy)Q@dKrRM~_jau9yz@D_n;(Iqz_OpMp)nZOOVygq_wEjq2G~{TH|6y9O!y6Ph{24- zMQR&}Dektpn>h^C9^QXCRp1EROtA{oXZx*H6}v! z0jJ6%dfgnNL^nb!X5TNNRZbtMJbZ-e<11eZTj{S80_stK;$#&?C%wpKecD3$(gG0> zU7y&@;u&j=&dtMoG18^f*#ZW-HgdkN@hkfCN8ZOPpB!H=b}Q}NXKv&`Kw;(6{W1>f zPE|yM@5z`m75fCi((Mv5A{EOQOWoz*%OY!t2{CR_E+(tM_)RoGsJC)**Nf?lFzU;0 zBtlS3(^(f6O(w!;W;1lTI|FRk7Kc3revHx4tJSumTX?YG19T>#iuZtPU-)w+sg(l| z^`?1Qx|QS0L^5&Me)$4rF;GlL0zA zr*lt=i%*J!R}@oTvx$!-NJMP6=~F)Fvp*6f4M;z9?~S=`^f zRIz@g9=#0K{~E5pXDJIbXL+axJDcqlaVS6h@i_hG=8+T3S8LLjE5dKz%M*2oePr?i zc^iM8UZO7T##o%TvgZ5fX+p6(eDw3`*AU@*La9`2b|wRZ>F(qZDNsII&JoTo&ZKt)qbwS6tho{P#NvMJ08iMYiMURTWw8xvA?EV)FNfhe0HRHb zO-xbS?@O;C6|fD$b4deXoS5igr=49^${cjoWlZP3IjzPt$;J5Da`h;Ph?kmi9V+mU zY21=;@B2?58q3O{)}CsXPhqx=TF3u*-+uG8d@Hf85OgkXD3QQSRz`Vyj{3Z##hOcn zQ3@uK3*r@Nt`{BhkXqygJNR&T;YBHTR)2$L*2j*N@jcJf9JI&6#EC_?;-RK^Lo(4~ zoNHw{RI_9R%I`SJ8H$qZX5H931N)ihhAVNTS76E$Sf#jS{b8;d2#(RU1b%_1}v zR;jpZvSre#Tgq0)L&mrJs?({l^$wxThodSN`Baiif#PG1=A@JQj9+SVzSjyA9AfMl zS#xi&twO$Ck&ZylzY5LMyupGL3sx(p`_>R3Gik#dWrnZY+-$admwF%2wdB?3V%Oc@ z8eAn;N3mdLhGt}#9TCS?>VhR&8iv2P!_)YoU@a_~?;ShtB4l;dI3by3P<@6KZ>@Rt z{#!udd|G2!Al)>nAAq&%9h}C5%%T9@isWK2lZ7&vI&Zh(6or-q0J}rcyUes}w z|K4;_(Eh9A@=aA(4}n@|4+e*pVbp65+~^5PA@oMy2zP?X=bRfa5-gf0(k;lq+?FzC z6H9ddCA@aRswt;IxJThRw#?;t(l`9;`}H-(dk#C=mddlq&ZfW!cx;o16b=egDgH3* zBie73rqS)`5g6#!pEpt>cGaroJJIlrH&xE!H_8-OtRb~LyvseQ&Hm348CIqd9-8d5 zPK1(gl`k=Sd?or+B#gU@#GL1wu$?YAU0a3F86nEnR) zLNFuxnlvD&@lmqf5_bg~!3`9GrL>khS)9Ot>%v?IhK{?@-?+MTYsPFGEx_^wg4xFU zecqkL`*_cgnf6MvFajO@FfY-ju5{_r_sgSZRIZi6f8JnG=JVK4IOdRq%NqB*nWMyhi}K>l`vonsrI+USXOvJgQD08}LR<=KF7Z(O;vI%Flph!k`mH~Pp zj){_4e=)WpCx}pwfR^4(fWC|fEKU#$JeDX^cwDa7dVJ8*P51^}5JnIK+j0+i5Dh%p z4Xz}-D%*0GF~V9_o<7=lTznnXz8pv_INY|bLR>GcDdcYjK@^E>yzO)dNau|~bhNPW zhl-M*SeM1dQ*56lrl7%=%4Sn1D@*H}jn(Mc5>ck}Y?a|F^nWs6dTn}Cu#hrhB{bXc zWN+hzeF{QPUn%r&x4bPdj^{==4^O(ludqm)B#z70{_^#W;be3-CxPDv2LTNu`$y+w zHM|QyR{VXH2!%Z~$AZm9Wj}lG;)=_hwhGtkdfYbqz;;;BB}dicc9V+g9e;j3vE-Jb z$KYh%uVIe2AXWO`VE6>>hW#jA!F|R_p`4-{hVOa0D=sf+K3^*vJraf97M-{csZ* zlPXU3r{sq5Z4^+C?<1Vbens zC09W3P|z5e4Oy7GLWYar!j;PG7~bVhuQ|4~3*i3xK76*=`aVx*n9eVkVL+by01<-g zGYq9OPVC@&j||N%{_AA4t?@}MM$`sHur&Pi}szvR|j8{vAh)|)2Fy)2}K z@}t2Vej@6~xZ1kqhoUTD)_mMrZm4Yb6`(#aM7w*a2ea2TyY}ps-e8Wo5fgD&lT%3y z{afI?uoskuI|+M?+2%@NGOl1`z&>W=mTOkLqcy(uMjh=)>%@WtwK#)&u4#!F`8s1A zfc=XX+a1m2FrvaXJOAq`q5=p3IHJ0<)hN#B?Bap>Uzn@D>H5CV%f!>KAKnoPX5Utq z-g?OXAZvvv<&PcM3C;6@GTeqg-kDe26Wa5D@C6Fn@+O;c@`DEf$tQowv|#u5p;-+W zH^n}bhrYziqe4?!t8%CS7GhAT?i6r)a6CqAD?vt4@J7PwN(`fcm<*V$w$r;HtyWNT z$*FF0V;&iW$z~Y7$;-A=_SVxNc9>7@va!ZPE~F{9Q+KW|t|l%nt}ZSaTdHf`8^$1T z`va({x#P@%vy`J{QAHNvD^gLz4Ng{M8OfEdDTO!+%&R;*4;6BZv5MmAlgXIl>IVG?6O4HMKEMq zDD0Hh4?*8z-h{wnohZwPl7d!1djZyKKr^v!a@v!?bz zx!n?(~A7L`76;Wc= z1}L21jqnouBm>9FEmUF(ON)6X*@v2)xOolws29zY7$>P0{+`}0ww)wmG>17tWn3+y zr?C!ra ziw9g!aYhinR?dYo4*(#^Hv*90cu6WVC0My%$N9u(O&GeV=JwfZ<-V~S7NSR@BE&t; zt|FX-32S9J{2;GeRJ>wJ(K)e`=+cE{gD84^D=1Gd*d`o?g2eXIz&g7@zxP{Pjbb-y z=Y^NCYapo!qa^bE;v1Unjo48sz-#yf zAzHQG(@WTe#gsGBR^zIJ51Yz05@C|=?C?F=$*~zH^5$STyifIVzX<7#@IXI*1VWIM zgF|M$_VGj(PNax;9hE;<0sL@P%$J~~(RhNC>0omGULim!twcb?m*EsfWT9MTJKHMP z9Tm7QXaLVcNUitWwtj`a@14)EK8KBjZ&S4}5!MvQH89Z8I|=KIBCKwJx4oJz-w2?x zf)8n{2`Y@@*oxFQ@8?tQYN58_d9`y%f5RA2Oc2SW*%e~9c&O?gOmHSLvcC#S(gw}1 z_;J0G-2j_|4Nr>Y(H8O=ZQy+Em4-}~kPVRuWbEd8OQU0}`|@swzc42{pjDlwhS`7& zRnlcEL3At4dH8Hc#|UiIIv2`dnOlr!Y-{+{A{-7i!CAee#!beGNpz3CXOsyIjOcZ@ zOR!h^Y;AYyEbat_OsPzHRFBJ-F9^rA-rzM}6k{@;{n^H*J6GkbBr&~}2{U`Ew5HO= zEU~BqN`>x@q|T$->iY!!OLN<`h@^O2Q#?jj>`JqB^E^%(9PvlfkL1lO+&My90bm}5 zUCr7Q&Y`Y-StseOZ8E2bVPB2R8BrsHMz+D{Ceb&FLV8HRk+3L`Y-$&lGS)K^stS;? z>NF1yxgP5_mwT^-hf3!2CnACts>uiAVv_4ZbRm-E#pn-I=WHlGV?TJVhi-g*ublaQ zt|HV=hjP$S2YJv@f!$T;N5Ky)o8{W3`V%dkdq~o@C7qnfVPq*&mDp=@#g){$78eUr zBvhCMc;koyl;sgaD|VMbX4Mnye$xJRJ~sajxwHXWXnV zEpo(sj2pNp0*J^}JhuzwXf&4_ZR=!#;L~(o)a6SoQkR^xOsmC{+M^?0g_M>CuEF84 z(=_rsh4by7&PuDONn3O%L{8K~-o_$w{#W^0LxK+ziVAl;m9~~*IrB1 z1)aG53tZP6I@Hl3d9(r)4z#6Cil|+Qyd$S%Vs*$QoSM1Z?(l`BAb0FACXi4j9iI{d zim51tSu|x|Bt#BLlx2-kQMV-fPFu9;T7&3** zE*)m@oZ!vlWU_BYeMcu5V^4AI7ZnO3~Wc1*l4K-kS6OaN3;rZ zayaQdq?0AOZXS>v1%Cm9OWB9bezQ(#!4k?T1x{RNLxA-c>(bALsia$;VH0#hZJG8B`|C`vp@C0$IL;p41&Kcv@8HE&SEKH6(QMsuA9%(b)??ccCTD53b zQ-l;($eMhex`|AtsXDU=S1Kzrfh@mBC)q?Swu8^wL4w%wQ{1jhFGJ%c%Cv|k0!3CD zg3dr~z?JOwAO>MEKq1C z9OR447bKZ-H0M)~5U53O&(byr<;3v@xx314~YwbOkX~yhS`)SHI^twBWe8JQZy`k&!?0sL^K77tB&q z{fWGH()(U<4mWQ8gmW0`y&2W!VG(Cg@21y#d^tu9Kh2G<_nQqL#`FpVI-DLj8`Haq z*0HIhHuJO)A<)XA#&e7)2CWj!!K&vEXd`S5i~Ug&PSqfMBlT~2lJ%wxd+~)vc*c(w zHH)|-Ni>-heAPn%-v`=~sE^{bopAdg19xv(GfTclW)->d6O{xh^$;f@6o)EO`-oD5 z-jo>@@i-d1U(4t5%z|*bBGwsnEcx8S|31xQ9dVDIUwl%t=Tj3)NW`c4@vLSKIVx$* zI8I5mBd{uU*YierRx<+ddX+1~g?uYd7TK&8ZU_tVj~ZxaM#5)ztP! zB_{}Xp(v46k%#QCu30E3c;za1k#}ChQX`tO?&Cz}po>Dah#&E%PcV@|N$gDz)8PaR zSuD+dDE5m@T8BY*)x+!yL>%5|Z?_r8wzCJZfv3dx`dJe0l5^}njOAkb_R8r^^8k9= zD}yn^Z0};!5rg!esx6teW#1uzEmx|8dU$6ZA47TDZz}h6w6tl%CzDhUaW}1Jfk<_uANRt$-h7(S-S{fkhdZ`nBn0Lh^e)!@#BsE7 zH{ElLZ=w0?ue;4Lkf5s11}Z)2p`O$yr8jClZ>V>adF9TFL&ub`sWFvlMaKQUkdu*J ziXwOLpa{o=$8yr@3wMgZB<0A(gvS0z5AdTj;KULFIh7bUgf?J=gxEENCZ_XK!xmyP zYk0lk055u$5tNoZ%@`3L6cs&VCs~aH<7%fZDAOerZgGRZiQ5)^mJc3jiF<(^XD1@` zN)Z?H%ny=yg9b(fhFoh#@0)kfP{@N+$7D}u=m~d_GHsdN3MKBWp|%<;^a_=|ChgvK zXl0{j{f`t#9K&R*xjF5!k0$TAP$~QS`9E-OV>G|MRJX-mdhFD^$K?usocp4n;T#Ui zVLnn`W#vU@weqc(G~3bPkob$p!^cC4FQKHTLIP~(TN-F-lbog! zNv%j!k$f+b5WReapt$&c)N3cc>9sSO-44vBtr$LU5x+A`Csv{i=|nxYd}~P^PuEx1 zsNZ<26lc=d6V_>hZCT137u0jC{FN16b@5`fJh@z+sVDNW-;X=gql)gUXIWSVrxwfj z*Tx8yGrmK*4!gEv_C?c#t6IV?z2=BMWExo4LIsrAdlBKZ`^B)%tuTL~2uVS{W{qz$ zGQ0(tC+z7f5ke(tCR}491j@^HSL|X*8%Nx&l^g6Ij(pnWqg%(=gGOg}arsziHLxIw zZFzURWd|)oZ5EMNyqrG8>ibVON&oqVq5{TCdmRsS4gDsu{R;#I_$Zv0=z25g z8rn@;I}*4L5KJRMkk$Xv`F{{b{H!P!6H+ZXs>qIwM0clf9NLZgg>wGrR z?yHm_Ri?9yhd-36*V9BY;eiQPXbw2CSajZ($u@}BZWhFZQmq}QyWLy3=ub98XJxTW z(l(rSQ>!q#`%x`kLf=JYX`?S}no*wg%^px2sy}1sgBHei0!X27E|)HzWyvRsnGQ;D&e8e zZ!68T=SxD{=Voc64|aBy_5V=rUbA zoY*R8eh#}e)u>8yl_124&J>W4l2H_8o`Ua{0?OUSnw1pNXbSUvT&`6sgfGar;f}1E z`#48t+h&ROKm=ysBvb`=hEBEf!Sd~)%bd4CNG?X2DoG%FR$4|hE_Rjd6!+&yjmUt4 zSE@AWyg3O_b^380ugz<_EJY4F>yuj6#rlOCz{NR{e}L9*E$6jTcj6v0(v~s12ou%O z7{bk^1)M!E}ZhyqFEo<5zW&GBLbO~mS5#f z?Cwp0fa=m?0apMs9LHxZvQopaKG(H6>$XdskCi`y5+5*WH?I1ZuBZ!*22{R&!;QRQ zjIq<478Q4j+t{Ok;4Z#@V_mm?8^$JZD95r7ZArUtyZ@l<5oB>ToQy0TAQ+Ijg+R6aq-2;>l_FJOuS!2#aFKMEDyb#xfoq%Ii`RSpKGhAg z*dAZikZ=>-CbhlQs!<=;RjY%Kw%!e8BzP(jX0go%v<&@wulce&1f7KepADvj4u*w)X9Hc55}JhrqiszwT#6kd=M}5+~erUiN?8-3gb2Sb2W=$clUuM%uPo+Rzx$>qhGPZqjoGO1}4Q4YUW0ZD?9Z4 zF?S+plh%mM$r`J79oso*>dv?*jO1ZuNH#|Dhwz5?)Rh?tpqgr~kpb_zj*VvP^hdmS z?y*j0u_ma;Y3;z6M)cpH+|}j54_r@uJHuslrxC6E&b5e$`vH5$S+lbNyvCz9Ek<}e zFGftwnRLK!u=EZni(LHJ0AlJ+E0rdYh3$ zl1tJ?DOd~*AtWgc$FIZDW#UxRd=#1UP*RkYwQiaHR>HGcI}Iyvk(u#&wDCHf$93nS z;cFvUWvDt_1zk(k*=#2d91Ho@`utwk`v@N;EB-|5EqNElP+}-FY*)s>)DPzHu%Bmk zU6$XK%*L>WAhukgh#&8-3%kT;W8%b8GcKkN9w)aT-XZkPL8xSs1CFPJo41A-nVWLQ zlxV>w`y`sA@bnj75yV|moo$teqzu~mdY`1dt9b~|gPkwRsLtMs9w62g_a1GhFg%nE z#p2M?g<7;sqJHXa-q}*)ZA}JxVk@M-qwR#;F~E7-x(tKS)2y* z9}`i|>7|&mBE^&s=z*aJ0AWQOq{tzd+D-DtUO~R-||COs^r9VJJw;C!^T>Ns=V$UL|`J{+VtK<42oQu-VIUy`gA4y4*(wA^8osP2FU)9)K&!t0oi`~ z6Vv|yXyE_91N8r`&DE?PICGvp`vNF%@e|0;DgIwReJ-erT=dh`5eRVcov6<#{$FaJ zba9X!@2PUKV1R2s8|_)2{@(yCKatbt{|a;h0|p>qKM(LP6=X3HV9xYZ_hR6{0CwEx z0sdvo&9z#hZ$I5Z@IUUL0snab<39tK%9Z8j|LTta7y&1Q&jXnJ84%|;+e-TC{|X!Y zF97TH^8o)c2GYt&5&v69;@?3=bpApFNcbXAT zjXVPbj4&pDF2eE82%64a+xh>JnD}iXRL?~S{TYGlV_5dr0XijEV1ym@a}j2LMkr3R z6aKlmgXy1(_?Ky8NK2Wm>5qs6hUX$o|BT={TYQK7^jMBZ21evCJ{Mv0X9O(^?BU!W zn;U}Txrl#xKC`tK8!!A3!NB=kg!rEkMwFID>rZ1M|7p4t{2zoS*GsfNglw&>j18U4 zZU3d#wu@k}{))H|hX%f-G@S^0JQpGRXM_eCPJHc?2Qxwn zjIb1cE<*ax2#1g#mTpf&ed-?*mV@$h5%zyZgtCbQiak{n)jukVPyM+Fl|Lgs9d|}y zJT>(_1~6h?^SKCtKO<%qe-T|j-38Y_D(aola}id5M)(olVEuV!4>f%*!tKw9H5niM zl&6&sJqIwN&g|JK;r@*9e8s%==Lsv@`?(0~KO?3UBTxT4VGa2_7oqfL1kp`cL&H;Z zYyD#ax%Pc7;$M6=1T?8-jwg>(6%H5y`r)|<^*oDSYmJt%XI0Ibv-aAKPtJasAAMAZJ#gE<3V%A*pNEae2BG)R z3k9xyc~Zdihv58r$M)W`Ux9072>@L{qQ4~#R?7P7xUs;hXayGyro3{yrn~w%y$2c( zJga*5r{QEQ?qSX2kXMMP@6FGN%7?Jin;tlm@Aq5U^AF-P9wtzA-cNx~WN)m=93SDR z5JfXjYw0w`Wy|ozB-_XT*V^ujoAxtUr-$ z@4{SJ|NQ8WkS(jG2k{$76DUB{vvY`$zv=$7h_<Jv^>iv;T@u})!-9E9oug5wci1%MztOz5a1&5gBetTJ8W`7sp ze3;zGG=A@Phwi~J^dK2MaD^a6B*J`@%u~oS*lz17g~)~XX90+BBL=ZTD>{%B1A}ry~iPgq)};17(t%EY$O$S!HH`mkP{FuWT#is;m!nu z$BzwPpc7z5DG@66kT|0cQ1Y3=u%=yBM znq~TkQp?p^!T7}M>CuP6gWz8dyW84kIr^@t`=Obku<64Y0F!eb~ zoNQMMWfV_Ye#~rG5x_UE5+M(YSmg~4*ZtaO&u-Q~V_}$XCDS1g`OBjQt8t%``GKFUOK%2iP&t>3pUOZWbn*zJo} z0Zx=v^3)hu(FyX2L6J9D-aC#dpYk{7Df}XwrZX^-v4&ViBa75pnq(!Nxy$XEZIatF zjw57s`D>u$bVX_cjIyIoFP@Z`$t@@cnkYPD^*U~qcn&Ce4hne=JTh-5S{iI=^@Yc| zGH=l{ZFX&i1j@gV<*#O8EoyOIV7$IWDWSMX(wO`rE0k`;6t9NYM6v0 zZG?*O7W5TMBQs@nv3W7nFiJ<0w~J9KlM|_G(HgbP6&BOumVJ{(rQCPC zI4NDScT$~>-(rtDOX4BC(MF7PYw z?;NLgUv4jaDz}t=AHT~zGPp1vyE3T}qM(>*)sdoFurnWzn^{e>TCy{GqgOVj6ElgE zMR5@1W(;HrUt4oLxv@DHhgJ!c-NQ)eB`20s^IHCn8J3;1u?lih^{HOqNM^-4WHz6d|cA15&^6ra7pr|>&<@zc^cX&*nl5ubE_h&w1D1eeVbEG4Dp zt3BMAPgzKLIF+H4sd=#<*w~BO7X%G)@CP&!k34~gOex{ro>(ws)=I42uW-X5y6Y(& zf=I>eJ<_FfoFO#TWmw=|qDUrEI+y)$%^b_Jm!ln@#Llt98EQ{PxK%EKJ7`N2txi56 zsP}b*l6%+Yi{{w?-Ll<@N#uI`h{3_bMQ^y7aOhqkGe3g&R7R0&uXg-}r{*f)>~c}> z_ue%CBVGB|V256ygL7nLGD8pvFubl;EI)M~2)t(N5(9}y@cC`S8=Q0eXwnt#C785y ztvB?=K$IA`MXS)2sc{dJ!Ivo(zym<9C&SnSDI4aKUbHTWV+xU=NmNic$q^ON=<-P~ zz9T0d5fG{K$pn^}IMz+hI2IrB_Me;b+14M`gNpYL^^KG=K? zB)_Qe{4!@bnMf!^oU9wyA0wZp1CR>2os{DND-&W+&3b>BV(p)VN&4OXqA1w#(eL`f z=QM07oQwJh`}ck!*$_7_0S*SX2>##q3yc5l7b&V^@{nR^RdPJvCo*jO`}-dyRTD!L zdx)qh3i8T6Nv?;KuE1tSoH^<8QhW&t-2LQ>jxN#@hv6rf-pDzpWhA7;yJ5U_l?%4I zysdkvyQ90O%lb9H%v2u~4Ri&^PiDF;i7Yc!mXMNY{ziSVz+F|)7w^bbix(|@_Z-^0 z?k0g<-XxI#TE4@_lTzr?Z09|4^`_5`H^a{!rTQ*$$Z_75aNU(4d!>o>OGdp+R0@?M z8uDONwI8IpQ6VFOo_HB}i%E+^a!*!?y5EJB9}VGx{vhr2q5G8Yl}zO#ey1$lG1=oa z=Ng4$GF_wlqhx52L~-0a)jMb&vtjyZ8##4Cq)G?t^RGS6$zx$qU0{msksD@8Ys{;-#seVIiH!eU(n^R8o4ox-{_>`OmV)O>~bz^C#?5x#}5q<@deMZ}b$_Mdn} zLV|%w{+BUP_i(TjH+8eLQ2EdHUrk*@L8VU=?L8HuSQXp&@yj;6WFszWw>VOcA{P~j zBA?TmlAd~N5%b_<R3Uj5Q z_E=6gE~QB=oAZJ~%a`eo7K%>vUVd!d=qxOD@Dl>B8LlE}gnF5@ zIEdSOcgxHx+E=l?$*H-G7~KMhg_U2PTLV+3Ev`}4{i83qeFCMR ze1j#LwtuL{N`$EN?u{zmANaof0N27UGJIK9Jd@1aNwIKDG1pe{D_+5*Hk_$fM@Sg_ z?{Nz^j~y8Qvr_&SwPf~JnEuofNEIu~ywJyPF6B$GQSx42HaS)YGn64#d#4=B4e%^x zpM2LiA}TnTbXz8(RZK*bpN-8L24>Pf;AbF2+u-=X_o(uy13XRm7CP+22s z*@3m`0NoH~EzR_x{vDk7qX?~^e^!$J0vyx-1xMiCc}W-s1_l#`#S;d_6GoW@Mj8f( z1cnDjTN>zzoVzdhHlM8imbg3K`73%>@@@RrcqhW!ydYUhg>hDbZgNIJu5rA6vTmYr z(G{wt?u!L=D)nhvs>R{)3k{A5pq?-zDL3bPRyrhC4HYMEBSW+7Pda*IkrjQ;=!BpN z8cx>6ew1Ubqt|3jX&6Vd7}h|!DUn-cz$aZ-?jE;L3 z${xHsfFR!wnjSyDI{#!n^>+T{>0u=|5E5?yRoK7xhB|ySVSk!Worr&kK_;WHr@r@w zdx$tzNyHxygN?~VvPTa*@+&XowV8O21sG8X#2~~qC5|ZA4A?3gK`7!L#3Xz=4uBnw zcN1Q`?}<#X4NVfw89p83+6j$g6J-}_Grm5W5u#@Fu@i#VV!b~y+CX-A7>@0_Jeu2| zVvnb0jE$Xkn-c#_H#uP-I+|!RDFOEyn`NwyjS(bm2&CL*5l+5A#RXmvBOBvCm5XjxDf`IF8I#V-_mjzilt(|D>Q-wW-K4-eh;? zaCk2SJJuhcR8PrY?*^?fmr~3@-oesfpuwv-pxJ0^$^N6n9wkD8+ohLX(Q>mctnThB zTg@Tu*g-8@XrY_ZMpncmF%EBlD~0d)d&IQ}=~7#MmUPPx4bC(kt_3Qu*m|e+1?Bv@BKsM6G>z*4M^aBS*&8aF^(qs0#1$5A zf=}>#G`3nv1+=|R2JA;JS9^;}bDdXCI#&8}mY5h{CfVHQt5vZHHe?k9B=?kOq|^l4 zEhE%d7y`~`+dB{}u@eC#Q=0!SS$sH?~w`6I+J9plrU z*K3LjekRQ$B`)>&?SxWkS~0KA>Uy3(m^xA^itU$h&6cn!R_3Y7b0_b?-W0A2WQbbb zaWQC}zR%_xlziv#h$w6wpX*hahn1GO7u@0Ag^|4?U&ZuOT$)DVHv{|2DHAw`54bpl8?Kq}jE{T~o2NJ7$H=(X*2LJd*Z0cAz5)Vorh zit3 z7uSMmN}F!xjf<V&d==SW8&LRJ*tHA( z0r_{9(sg*}EBM3MD-i!JOZ~;!+3H5l7-CpLxHveAQV4GtYL(1NrsdzcW^ir&Pmn$ri@ck?cOL$H!>}{bk7=3E zOJIr=61g0q?`r%+epsHMn`Mql{sqgR99p+?W88N~2Zq4&;R7tzec!~-TOze{q$ z5c?_;q5zDOfX`g|KyUwEBn>Nc(;&DHoXHVr>H* zA}O?YU)B>#&*9Hd(b9Xn)Ot9>c*xQXP>^kdk~osG6gT|mJROjrbAC=j@Hfh9$Z-Xd z#IpDlHzenrJ?HCzp9zI#_nSe2b)iC)<&_7i4~u0OzfTNJ%SJI$1`!*DFtV9S zRW3S^7p&Y_xm~p1mni8X42Qazw6Bi#xsx;$6(sh^jwK0}76M03Ke9kZ@ksU!7a*0$ zE;pz(z73?BV{kIl9ym&mw@@AsbgCTQ#l#jL#Ys?4NTOnm2s&d(z0Rj1E!R!;rI}^W zrm~i+`5LEHwVM&ityr!*#0}i>-m(~+m24^c5o>yIOKrsI3T&=`kAlhnnY!XY;G%}6O>w-WnK-si18ZX$s_X6O~GzvAEy*kY(H~8e} zYbs}9i19E#K)uA)eCD*5Hxq!E1f*>4y6HB+_6^^0eN7ijHc;%(<&B&TyL{ZCBu<=a z=g}+EMUJ*m1aYjZ0Wm4L2YJAOm%LLLtyck%8iWq{`aENTrMA8s zxZ(wW+Tq#T5Nmu^ONJ3yU|xyi|)!0VM8FesZ4k5y9OitB?#qLI`T^NXT(&>Xs4^VGi+?y5=VAvL^44*kc9V*g z?2@{J-u^{AZQaZS*B_BpE4w@VK4{3>1yT;eyU2+ZG%t!@%UM+X+obY0=QhSsN*gcU z=rQHB3H}it&$NP~AwQuk>EOlN!bcu@nCbPf2p?!?t&le%oP-VQtB_eI5rPt5m;E(X z;m7P=7-ds{`Xw-pYEw)q%tpxCDcfYbndxQod*{jX?&hK5D_8# zh;IBU%LT!Xfe}F1Zthjrq$EInta8J9ofjcK-T!#5a@*@|-AV(z?rRzO!P)wdCE(@y zd^Xie3g)y&Go%%3Pqg&O3E)jMhDisi&JQgKD<^O?;MSa}3fWO4HcxK>EcQZJ5i{*( zg(;xam~8f9ObQ&EO!gvJ;a#=}u)fNceP&TCDa^}N$cH4pfX7x-r8pbYyqC->)6C$* zJ{#B-264Hx9@PBLIHkV3x!Paiq&)Cs{aCegT&sr8z{!gT_7S-A*{?rGdv}F?q=SF% zBgz5g0kXOtmVfq;T;f1&T?6S79@e>&V>YmrAqn{hwmNcBe^PfX1_)qX^a(E~j;qhS zII)y}Vtm_SfDDO|HY&^|F91I=dPd+mL_VzPivDbiBO2CjIU(r5vZds=jcZLKtw4m& z)HMGkIPkFEz6dcErb-?ooZKnFveIHPlDq1jMsK4A7Z7w!ak098&N1L~g?4{M*CpKl zcu zLCg+GE(uAbS6J^PHHyV5lB1Qb(igT2Sr{_#A3fJ@Ce)VwkHC_J`tK9P;{PQIrW%@1 zEA#pnhkRyDXe=qo=dd%_va%W2X-N$#X^8^ow2S7hI)|mp)I5;^k!?iO47#F3yxceH zcjy4LBPSiHUtv~_oL*K(Su1XwcLzg5DqvRZQ)-80fN_A~cH6j1n0cx>OAuWwExOp} z%mk{ip~T}kav5Q0ASV4UbInY4N97Wu&AL3+a?Pk_p&dufC8ikd8D4gUS26K+X`#qknGgFfe$@q=qXl4*LKy_v?J zJUl(TJ+|yYxodtWr&J`NKH8t=!_?YgUgQ2lSMN%Y|SMHi?6hdyB6#8VU&-rYb(KwL^QS(d+{RG;FqB8SUGrOIl;2q-t}G@7O!%3&9^Fj!(oKydVW zItMOn-nN%JyP>c6^s&13G%ZAI>y}IYLFPmcbM-BifH*SzRI1__t(coK(;&{$%ZNvO zmu&=arYU2p`}~t7daa#aLLING+PE?&{uh_>unz6Mi1jw{cR@7)Ab+;t>Scxw(!n0@ z0Na;y?c?yb?0Ju-VttQnGCIq9m*h8Bq5qG#HMMu$8Rkdw|(mD z99rTRlU5i>>kM6DBT8B~T2*Y<;QpFnYaHYbdP5Cyq(^=)Pte;aXgX8wcfkvtjs`g>qr1!At8Wo4o96R)H0xG`K!vS&@Etn5b(t>J}&(J$<&-5qQJ zoM^JcUU`rxTEH633fG{1v$R1ai4sb~w@ob8T`@FQ%-~W-g56Yi%8bZIExVqOZ{EKP z`&U!}X+F+}6G-DPPj8P9fM}uEujZNNtsyvqkP0yVkVcSgXEEaPu0yBJwdwt0YFYxb}@BhNC>iDzb_=7q3e=~3P zaIkb^)%okzR-6z*pD0%7(Nmh_o^i3v^eO!^Jx@!pQNOEFYFmSoBqq8uHBN9a?6vAH z!{?r$ARp)SUB7N8R4_;`;(4NZVlKh`?PM{!Cpyr*TA0ePS37twahN`SO01*6b66i$ z1XaEWGV&PRo_nog=O|RA?sv*FD((E~EC-EdHQFD0MkNP1A>=_&K_6LfUFnzv_AY2u zVG%wphGT3}Q{soreEDxXFEqG0-1%m;sTU#@>ta!ik+@isTdpc;@hhY=!!wx3$g4$z8z0F_a8NsZ-|tQuO_& zmM*|ezLtcvhX5geMiXTrz)_=Ow~^Rg!#yc`DFbAJw55y9*J8iqv&o6e9jicsIL7%l z=rOA~dKuIYd-x+X$+&1UHLDlooP08Ef9&nWiw5@uPQHK6g8RbsJGhw*eJZscN&Od- z#bz+(DrvW~t6B?<=EXw8o6LfMjf>PxaNpBQ58>a@aQIo7>hni%>A?OQG<^P=185m& z{Aqaasq?@V@chVKY^ed!po0>K0~)eOb(iyFr01q4dqSEb#l(v1On+5U1inI0qsZuu zLsBf?XDe~eBsb;XV_u$j7b{s;BHjLwY(ccuZIzUj=F&q|v7dBmCs zn&@Y_GfGi=F01p1omLwzmTJnv@DOA9GJC-2Ap`#?g1MZMsD;L(7GS@&N}0GFjJJo5 z=d_SYvPG>;Ti?=e&|BGUd6%`E&pvS;I5KTn1B_?R!Z6-iPlV2$w!I6jC@Z?N;%q2G zYA)g6;`VbB;5Uv)4 zX${z?=VR+4Vc;VajJP{qIsc|Wyp=8UZ|r*H>K#-7PvBP;k1NWz^2rNLV(R^p@|foM zI8=+@E{77|L?BRapzWO47qB?FvxI|FDYrg(f4gJm6Bifg|AcKrr~+$mLs;+vCXIZ7 zk021da*g@-TvpCUs;&J~)mISzCYLq;%H_mA_CX8_xE0j0Rvo1YU4CzXwOYvz(=~&J zHH{a>;CK$L1G-#BQMTr3>>zt5ubJt`GkXMor`y9fQ&;RXZ}i#pY4{{yE&Sz8SQxx6 z)br~T*aM^>Tpe1l>F8d;P?OBYp87XzcxZs^hR|3 zbn|qFX5-vjNRVA+*BcLyAr15trzH$X9Kfx5$e9KdzjdI?QfyNy#{A(SC?ZRJ_1a7_ zq5(W@)MYHZwFJ&qC{al`PF!XxMyo4fbh@_48WXWqWd+te17$TBEU-DhsQHM|p>kAE)VuJ(pY(YzROA7&ldtUJ`Xoq6WDgp#cTke5YQ%)L%G^5FL z>4Csq)N2C~Iw9Jo-}4~rj|5}E%@ryhO`-6KoJOz9&F@E(0omCi@6Q)rU~_PHkICjS zdn`jju~U4)M`eKZBi*CN;5~)dTE6bXN8p}8EP+fmXm6P*?`tD8QST3k&wZg`NF~TW zEXb|fvUd13IroFZz@zawoO-24DAL(12K&$^4e$nw!YHI+o7I`oBNZ7p;sM&>=$r~@9(F~CjyGM$5s4m>Ts73$9;@b%Tn zmfpyZfoIbRw_=sl!Ohf%!dYXhfmf(lZbnX&tk(tKH7%Sj@=>&6IW@U3I{>fK41 zMlQI2m@1klM(V=|>}N(tgRmYon}vR&59qhwY>1v_E9Y}6ma5O980zZ^OwaF@o5bEG zO_a>$(`CE67t0#c5>#`Mxc-DJFQsfLbv4CPn4vG%?m#-4!#1mgl^i`)ipksG-(dSz zjElx+tl{G7%Z`Nh(#eMSYXP2xwi~;q7k5$+n2#F=jHR*9{twwNO%lLpTjc)15OYpNQ)GbYNyUts1hbZY znRXHup$+mQ_l9B;bLK{R_G8oLGvhTX02Jnp9x_#k>LncaPQlWYv*Pd!KRjsI>2`SD zX+4?cc4+bbdbG3!ZrI-{x9`q$On2N?yw?&dMXbOtyreeoA|s}gPJJ2~-EMpEX{g&Zm~&^x?W z$qW11Y0kZT>;k8wbe8@^=h!8u8%xU&mv-271M9ZuK8TZLO*Odrn}w>2HOFGJws-L_ z)eR(}Fck%-OH1XlVH@!j4W$*_9GnD|%7}f%D5A(!nWx$vEpa_;M3mO`+G|LZH?#A~ zHQ1c3_4p_Y=@(0Mci}pQEXCI?zA&I(?20Dh$cA_WaKsj@3+N?J#^aw=X;|5h3_k*F z@!S*dI_1L!^>)N+cH~PnwtBO0C+%yNyMHL3-I~Q`i1Z9DnaGPHqkW ze)%kY|6T5Cs{{3Ywi6(*@!%?7Or<6CIRXi$1GQU%J!bD$tgQGO2GvGC6kY?@S*hAv zQ?AQ#X^W(DBx*q|?J;{nH)@t#eR9bg@NFOmXOph!`jFN8O|30whs3JzUS!%$rqIQ< zEy7$S54%yRQ-8c=+IU=e5MH0_74M2|eFzVJ2tS8RZJe8Zx^D+Z{YeqCws~NE1t<0u zj#2^?K-CnE%JY8ggXhGn;*GQl17pjZy(#V;S^x6{azsULKy@Hym|X4-DhBc6WO~>s zoPV>Z#s=T@Foh=83Z_{V&%f?wsZh!Ix!yUPbr0)Ug-3!94SHGjp65mz(V4Xw1pMcK zU1Oey{Be`l>VLRj=4zQknf~g2aq(R+6zYt&uksA#4-CzZIkjt$J#db= z$hb5rB3l+L&@$aEl>yVy^?%&& zFn{bH_dE2Wcrh%{7a;xsdQc)^ zSPaeR;&1sV^MtLgp)*ny3?%jb$C-{XLoM$1e~pIq|9=+nXy5{+9oHYbyexlCm0Ing zuW*KLCAluoL`8+Nty&O)SXPwiTdN**_0%o|_G<=C6-5keNNgPyn(eRvT?T5EUvZhm>;(xf znnStukO?z3=$2oa9s+Ey6#UAt9U*14R!LtJKGNRLOMi6{NuoL6W}x~XO=S8wTWvOT z2EGQ|aC}X9oQTrt^p@CW4nlW(=x@on>J$du9TIJ0E|4xb7+m6zL^3Qj%?qRPm&wg(csN4?(!;{> zxJa!EV@zp5PQY+{k{j}`LI|-tYA~7k;XAfKYrGsw@6Wws-b%fdNX~m;62ZMz-ibRN z&{x~^&{wSpDNWDlJrr8LM?)Aym3K5Pe+#A=Lhx<> zl|Xr3fI_c#Pnx1T;?7V}x#J+=dK&5)VKM&A4qktehd-v!-9l+W)+`J%LX$t=ph8Z4 zfyzTwpsE~xBD#ES4fRwlbD0zIyvdPj9>=er`CSdN8aU9%D8nwHk9%X-E9KYFrqUN} zGS*hf1x1TbQq|7Pm-2{rgq8oHWU6Z&Kv+@|7u&|q7qM*G+n9u&HR@EFXxq6{ECxG6 zlAR1UkdNOpT7j37 zBlA{b;-$re*I$s$;3X+k(t;kM!B!YYz0944TPn%*GU75#2L`l;&U*OtZDgHK+uC3% zv5%K2ogD>R$*e{?%agFTmL#6kl;mVBZ zXezm+&Goh52uX$k(iSHLDpy5v=BQ&3iWX;jZDwl}xTACmf;{2RoV|mC@4Wp|S2NBI z6dN=3u;62vrk9;o=$Y-Vc$zg;cG7>{yA~CBzo*3RORu-|CFtrNZNKm;D5Ux~Gnp=R>(OdGb$JH3Y3)uoUdAj{x#oM59L z41jK6Pspp|-*HmE$_IdVubsK6GzJe^U0<=(0P{oci05~Ug5MI?;wYge(5QDWbz05rDD=g}Rbt>U zuY^d6G+VJ%EN;p%lq$mm6)S1u=&f-vk{pJ-)c$NtfR@JPs8BAvv}^iMo`@avm_6Zf zgO$%9w_+b4w@$Pit13|X&aymY?Li&=3YR*wX3a0OOEvs@OExN@LhGA|c0_%ur8*|! zC6byuruN!D633G7MG!Y-be{J5`GHz7s_iw$a4oKQ=L^%`hj3Y!-io|ozxgLUdTB=Z z-8Zew-d%EUiTTAPWD^N^At|d4n7UYal{KI7@~J#4Fna|61j*9Lvn=8L)ZSrIy0!>Z zLT{%=TbJ-y2mKJ^gvlknB4Mb=F6#*>k};tLyebWlb#TU!z7=O65mFZW%hWQYL)6>G z<2f{}>_^m54YgT}WM({}JS;n>`d0Wt(CnA>#NO;7HFN;1JnXb;a91ht1IarwdkgY% z*RDB7p)9fu;u6qLd>zVJ=9W9T`l8fFHwvszR%B3R*~YfO7{`;wUb9Po-5y01#Yhjp z7Va~hpC02K%aJk)vU`TCF$?=DsK~l`PNs@?oiGzPFw+T|oCeT04-GFX0JmM4X$`_} ziFv(NZ!c{CjUta!=0vmG_@TTQ*A{>^vQY|;063U+e5PX%aXwfK{kVQIdE9;s+0yO) z>gLzXqa^eYe5NYP@2i{W3YroGz!c;NSBt3w>Ka_u*#1>P4$Kd$1hD{g+^1Y7d6H5v z0}pUFS8(7zAIW6mL^xae*Z$4*KmLu~sZSJ5>fA~27ECzUJ4B1a$;gKBDhF~S%c>{k1-oypI7=x+UJb7QEzj!05g=~TC@Q7oY zhWf3e12;CgT&j+!aS8WkrOKC!1_SCQ)RXAOR@&JZ@5{{>_=Lr?K$oQ5Yvki@0_e*d3}l@owf;I-op&qPRI* z%HQx{V3fpQVB-HZR{!&ukc6{?gQdB-Lt+6b3?U9uA6z z6B9;U6dFogmW)sCs|lIznlKIPNYB1fRv1QgbJWJe1Wt$UMIy^8gN=Bedi$#W+Uly^ z!=jVtmiIgamQ*+KqWftLaguMbQQ-F{bsB;LRGZNXy9(g*|H_HvzGhhk{g z`Oa_*sB%)$;|mlKq#|AEHR-M7*bO2P=oyOBDZ^wCYO&mk(`ltru3`^5ow^zLLb1$@aNU)T5 zVKCwi4K(h~1Om&T0oMF>H3CcT8Wz)_AO59wU8oUDuMtA(t^|UeOY%-5LaM1`uPc$7 zYB&htbzMIqE*TUamqPh9j>Er!NX$Qv=-yid1dA^`c})*g;Ur=lLa?gpu^vV5VurlRzXV{ajeRaLpFHo#$k5zZX+2LwkuJ7Z1Rg=2wlF&+?Qis6U*LSt?ELm z-V|#QN^RkbFSr&#fkdB>Oah>^bYU0a;WG=kKgu z?E6NfcenVSxe_X2KbYd)q1#t4#&Dl~SYmyiU@nBib9Rk$R02J^b&43`ED2GwoxiNgl=6=v7}Wb+7f9+dv&UzKne`xJ*doTxch9$B@LQ=}fizX><$_X(2lvvJsPHO(`)@7}uGaWCz)_1Ma|iS( zVkd`_;Febvh4tFQ{#s>4x^B|E2ED6BAuYyDXi9%oO)}0W$#J38AiNaQIUiE^%}(d4 z=`wkJsshyFV~(2p-yCu4q|-=Fj`)|;FefXHB6FSNlU$qu2SseZK6e-hnJ9U;;wWfX z%TeL*%6`7>yvK#ZVw2&LdaCva3C$^Ga$LdAPtn?T4i3gQK(umTO|LIBk@oA2HiAG7 zV-*fUK58^WjBThik@o714uIx7zSq|~zKZIjPYB*)$YNJz+cW8n?z0XkGm&mEk#08` zWXrZm$Re)H()^>7scPp}M1S&B4VoAQh!Lkp0GgG3F$G zN5QB%sO0yPsnjzwLD5!PvemcBEzHSvo~PBBprw@)Gi$)4tJ$UUw?@Onaa7V0IP*$A zscE3v3og=|?#QQ+6R6>CehmgrXIDLjv#NZ1`AH%ADrA!5h2#FE=O(xxg%#eVu@fbd z;)I81NN*HlUMizd))lSxBjEhZZtg~gA}W{8jfyx)UNro74a(|VH!995P1LUz+pByfzY z70Fs#T+WpahgyHdLe?GfyMr}~oh5?_f#oUr94qSG_l*^q%L#4QI|lE1sANKUUY$E! zB{0ONLK->Lz#~q}a(d#|AoMcB;atfRAC%F4<=3yvA0?#>iLWZ3fLeuZzmWEg4&A;V z_p{PC5|yOv-aM_`M#E_E^z|WHlvy~CZx@3J8`Ffy6YTl%dO-1W^$saKh2tRje0mn|bUQjZ(@NfZn%Bb*efTKi!X3{4|qmh1(WnLdlCg@nM;Nx~V;_wEzcQmda;yo|;3Lwmhv-1;BrAv^~mh}$Q56JlHV>8_WhOliSPPb zHi%-hSF9ni5IMSlo-H;+`MkLy8?+VRIEFYJ%gi|3kib0TGR$td9J{p!Txi*;`uafy z^lo_}8cz4vMr~O!TXWO;3VV(}u;8b%tG~AH5$;GjXwDhV{bn#pJ7MTO&tu;lZj>Tt zL-dBS4#B##WJ_PxHz~kjy9}Qxp|{{JK0lpK?Y&NN2WNQbdqHNv?*^jsg^o4D4!2@cETOo>@q`pFRN2x=k*l+_Iez!8gBrDe}804U?+r4*!( zGL7k&_$qro6xE)O__*~Lmha_-J-MgZPP8Y@M&}608Dp!8w@c zk80K|f*)^A>p}2eQavt!#y$96~ELI3aP#aHz{-`R6ASJhf)v*xIIjWMqATW|m7nmVpR zz}0|)fRKa#PZYSr|CGbh9sb)*U>D+a2?YZp+(jGN^$-H6NA6GnowR96v=J_379dT@Dy#@YDnk$t8 zKgoV^f=y?+h0+B7iHD$$x~lq6XaX`-uCA%BTzN+g4sILHi=o{LAye2?cPmO~lP$)! z6JA1|ZP__O zByOGlZ=ZCXBz0cdh4vW`-9;U7S`wTeoiGZDuaiG6s~ufIh^jplcPT7EC%f05BH zr|RPZ7N;0t0%8Milg(NPv+y~+@K<5qI;!%(5XvbGi|LktuIQpH{8hL*3)tP$zUTb= z0<${i-l77e?}RY`0{rDJJoC>QG{%WSK>yLRvxcUSyxSI?bJ9V(2JmHt$s%MkO&Xa# zRF=Ku4?vWojo`w?jUcvDWf!hBr#Opt<}mw;>>zua%sksA>krhEVo{tx&>n3(JTguv zd!NzyZiA+a&aC&0`io}6x#J1L!3G7TT|(g4ZwkdL=zTqrfDKfYLg3}~U30$1mhBez zZb;T`Uv^J_?9xXSVGf1t0ro@}Q^a)s9d+XU=O0S^f6u6^aDC|VU?Ctf(f^ZEs`0;= zqu>6^l6XN&J6@ZPN$q(snxdfAa%e2n?x@93^&K2br0(D`4<4s4Jrg;W#aj3Mw+0{s zHLO~kWhVugdu_o_n7_!R-LLu4}inpwRsKRM*~L!NZE+2U$e}D&63Qb_VK{1 zU>(31zA|gT%s-Mn7jatDAI93;0mhn)z7%T<<_gO-HjdpD5(oeqSfyD+#vwws1f!9& zW2xm*?-6;xpQW%7uT51AQ9~M7YL;qML~tW@iVbo@=ChxCC9_~|NL35VwVcLm`)!Lv z7L_ZZ8@vU5MwS=b8EizB7kPs=E5jHb(b=5CZTIrXZYb?i8d~XA8SD?eO|yp%nMmh@ z-+{DFv*!%?0`Fryhy-P8=A zI_*>d;X?Hf_aU~d*Y5cX*6hhxV!g+~VZTFZfanD4_H+b`_jtC8_q-pq%}uCCQqWW# z3@Gcg9Vpy1mN4;WJOMvy1;AXTQ>^}+J7wZ)dCtz42=yEmqefu%Hiw7wrtsPd`kw49 z!Q=3`08fVct?f2PCyjpb7NsDoo!wUBtfG7Z&S9i%m{4&pDFo*-mM72R9^soy0dZHX^o( zA-DX9nO((6Oj4aHzVF*;V{M)V7*lHK&w^&Tky})CT9wv|)&+{d5$G+=@7j86Vje!* zJNE899j3c-%Z{3rXY}G-)=!RsQfKY^)7EZval~tFRXX9ZoOZ`{i8F{RkxL_$l;Vy` zZQ~s|soQQt0s(wIKj*W`l^@;2j$-8g(BSjw1#?zo9)b%|TD=FbRm`*e>vp=u}W~I86CW-i3=?2m*D-F*~$~UsQ#L?dmZSYo2Y@2P6*n@%X8{2)#s=zi!aEZ z{%VA<%Bb!z1DVyl^H$+U+;sY>3pf?QMhwM{O8x2^mU<0QTOJ8*5N5R8VpN)gP2 zsXtT6AZn8Jy57jAx9Rlx6va=U zCT7IA2&5D@DLuqse#Win+FK16ZFhx#1bPSXu!@gMDX`U}oTgHIQRlqvM zdRn9todELdV|1SrocvIgz7o#bK2Vr}H^%duxu%f4IXM~r z`ftkW3XZ2Z)X-7-c?wVYY8sNQFgE#F#n9_o;SK5 z3{X3PU&Deq@n1+e8m?#9PdP=hTDjr6*$%t%Oyb3MlDW|l7whHHZSez^ZM2|tX@N?XNU~WJ_DJrh-CyUjRL7dh~i$h}) zD~hS|Pdi0`(Z>F>_cSk5*f8xoDpZ!#G&5VOYbdjoH!^t~S-o>GgMC6?h{&*E zd!fZak41`fO_zM$P=#XGZ(?D!E>xHOZoxfyuLB7Y6)x!9Yh@Id$tQl z3Dn+PUASU+sN_|m-=KN!cthp4*N)_%(K)5ihrzTZK9-_;T_HiO4vRLX5JIrVC0m0I z9{6};9A7YPxmcqsVJpx$SmSYFcfXF#<2vLjZ44=%Mx4?M{3ys2w@T|{Qq0Yw+x9%q zvfDp-P@cq!g~_nQ>&3|A63Wgfp!`zs;595cJ89$OJ^HL@qo5ytJ;3d?nViiy@vT*P z(6r8}OH>DM)O_thpu>)Taf;8}aAR>Jn?)&gbG}mr^PBIKMs9}h?0A(51u1h^b6`3Q zL#7&?9r~(<-qVCfcxs2D&NS5&U;hSj7nRhmMn;xaL*{bi>&D+k9UW!@`X4ABXA;fs zpre41rj~S`A+((FawQ=1&t_IYn$d6@ZemEW{X%MW;y3qiat(S%s;23^mMNnI@mLa# zjq-Y~?u6Epr5f}DgLu?|AsuP8oFXGExThXJ139CYS{S&IVD~v#`q6(ak4;WeNOb(o zmF!aFShi8TO=+WLDyU)CT)cV&bh=lz$Baj zoGQeT8IGg!p9e+-Ba#+x20QlR$&^X&{`<=(~i9r0sjpBRH`T9^!KxPF)os%M-s!8LXtZ{Mg6=hy_EbTK08 z77ULgJ4XVry#zAlL_yZC8KIg+a{DEUF+bA}`iqPm9J z!7cfKFEoXOM43H*qL^JrAh4~Zgq@T8fN2|#L2pebuUe$vJkWE!|Ld~R$X`t%We2v^WQWioo(d*!f>A*d+boJUf~#WB7r!<%A;VQ#TC9~Ol> zP)t2jKTOKjqDj~x_1(sj?4KFgDij?J(#$`WFqPxBwmvfVsT9%7hYI}QH#ZO_=Zgq< zyWQ$=IhlFqaM?A8l`$dl!5if7ZVo@mn9rta9SC<;wapfXjL>Gl(mZpFSf%wy5O=`V zublUbnAJKHjF{E24HHjCbkej<700D*)hkBA?v^c%#ja7W(l1uP>eePxD(*v!z_!<- zEm6%Czee<=#nPcwi?Q>`9PEMFrMTNw?{w=Ktc1Q{9wFM+j)8fN8T8Jll`h0YL_rGB z+Y?Yu+Y1UQRZc4zi)QZ~LBMvw;iYD!y-UJey7!{7-cy45qC7qP2JP(mAbE@X8axOG zBTVTkyH^TTi1u1GXarS=^BOm}mY)^T!N*4E;%UyjyFZ-mGl+n?OXoTi?aNC(&u}M2 za}t~U>%IunW*?mf=irAj;}9W?F!P-g&E&ln4UR$~?uV7@0ZK^Zlq+mPrWt}T%Uv5g zMz!7;^21} zW9uSy$Vz#VoJ#esLGzGusHuC45F6+MY#(LQsE`T-McgcwCfRcA*PefLFH22p$`!ru zJyN=MvOzf_z4io+egOGN=?~3^snSB6npP?Oe^UOKb*r)}&Depe)^tNC4y{d~NUdfh zX|-meN%ivA`s>$d`FJ0>@~Qh)d4W5F^qf0~^qhO1bT5qRWpd`Lp*gK?aZ2&mYWbdf zj`Zg}6?!8%DtaTT`dXL<(5>d8oR%FalPaA&hbDWKVmV$=>7u8l#>B7&J=Hy2I?CP) z)ORbi+{Vla)EGw|Cf9vETw^bEL(L=do>(Ggcg&dHT6?B#`Sm>`EnM!<uxtzJhoRH1Zw_PpE54I%a~y<4jfcx6&`L3?o)=X3Yi&ML0yX-L^V_UYmjxl zP;C*t3(SsDavjpl`=I=4VM&T4BR;B3sM2cuap>Wsl*P55ZtO#A#cuV_L1qWBc&gPC zGISMbifGf1@MlkH#d0w+gEcsqV;$8SAdVO-LrZmAL1<=e{>`GmgrhiMSu~HwC%p$~k_Vx(?PHwE@Gi z?PciPPg&@WN35($6-^@Fhm*qb6K(TLvRw%4kDQxbdCU?zycA3A`(Ug;@1ids!_PK7 z`90##ZLB~!1{LJfy+&$Pcf-ul7qGXQh+}x~r-V~q{KQF}zbRa7kY5YCKpvaYe=3&4 z#(+AoEbnMhD(#0ib_HY1I=`YT=Y{R|BAwB#Hs^G%?oK$-mGd2qFZaPH3gsNqx$R;_ z%kNJ%JJlU)m+OqhNwzF)!jrs;=mzl%;x9dzdHqZq*zxx&EU`*;3P~xP(a8H=cd*7T zR-ZFnu>(e^UF*&&`PCay)}iZG{o=tCN8kb}6G0^9xafY{=n;L`ChG)~+>)0nE;f7;HsyZtK+PtaO~qs2Y$vzZIJx9hZIyHs6EJ+WQCVGiFR zV2byn=QucTtB_QSsdRgS7Jn&j44Aka|E2i@oiEpGSf6DnPTQD#>cYJFW1=A*lb(po zmUt1#FFVKGd_$|trMAtsRjy;!xNUda+~90%QD|4kl80AG;U49dq2&vfe($QEjMmWo z0r?jUkhD@J8soiki&o5q`)znn3PA5F|2^EGg^p+id1qUZb~nwrv&Nh)bwIPVK@*l5 zo}q@TbUP~h*r|I#f44lFINE)ORz>$Q&E`yBsYz!{pW=NbwYY?>fU}IQ4m-l57Fw_R2(YZC21<{a_%#!n`2nGG7Sp$ z218^vX3@>(Z3TR5>U3uTr#Z8EQ2an1BY7whuO8}DggB|2|sHvM|YMdcN_ zA#yt#_=WD8?r)S*zV*qhToM`SI0G|0v^d z_@?T$JOE#kI_>nTA2gmDiLQPK>SIft&to7bhh4oG3W03CXe`AW@!y`y?PgIp{ShN6 zp=tN<%HGkgm5RMkbc}YkruK{%hQOS~J6)fH%gmFo&tL88&`N!@TN`Aej(hZ~*R?Wvc33;(fHL6guBEP}0Z~PK6HIR3 zbe0Z}z~IP;9(gPyB5Fx!LV|nsyy%iC+Pphg@4B^J^Fh`rE)`hibOC-gzT!2Hr@0s&SUM~`xgQA_ z__-EVgQ(v#g(gLHLO zt(;;W6=l+CofTe%R&_ZskUMX1NQ@Ej>7YimigZZ9p<)0|r{@|V)LDT$laAtWP;vsB zSh~2s-(?+14<(#fikoTh<9F;TiMXEVyqSoh$NGZ>f(4(WL?`|T;x=Liy=#+JOQsNKA0aak7kY1~{s=vpB!e-Uyi z)1W_1k@vi-d4uft`@FM!A?4{_BHyrT7_D>YW8s>!Hs(i5yQsBvgB(qUx}hg6sG26~4MkBK(f)R4tc!8UDDxVK*AZrr{C%aVM?< zoNh)&Ni<0(9<&kO6m;uEtyY1qEI&$2sYMVi5N)WIbf*8Z=PTBDq#MNXACE11z($yz zZo_cvJesa?n~3o_->vE&saQaUA>Iu^XMejpFv!Yv7V;x-0ZJ+~hMW zzJR7;tHElr?*aS^vu?=!TZvm}UwexA>zUi*UW|n9v70OXDv@~CcQmW3SC6TCq%R~r z$6i)3#i<3Ep};2n_ohc>!U`SqKKxDMf&;|DpNH^(J<$x$3O>yjc+JEeo?>H@)!oDM zw9E1J>gatY&uqJx4;-7PPfnYuce_~}ZF=Fv#jyNH-bJF%Eb&%gOjaA0VQ z^)~qX#!BGVZ@ga2ZrPy!%zFT8m-x{6fqM`rh$9#ar4P$O2j@U^6&~vXc90k0#>W{&x(->D!hhTF|Vo8a+dN?jsER{L89W(b}RoWG3{OlYZ1vnG(TQ zIu_jD=C$cmI{a4l!uMgXLx9#+(pN~pK(yH$PP+Obz{26=S-Iy;u*18fcB%0D!26d$ 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 z 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 OLGX%l-ZFS!CH)Jdm^aV> literal 0 HcmV?d00001 diff --git a/core/src/test/java/cn/edu/tsinghua/iginx/optimizer/IteratorTest.java b/optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/IteratorTest.java similarity index 91% rename from core/src/test/java/cn/edu/tsinghua/iginx/optimizer/IteratorTest.java rename to optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/IteratorTest.java index 50ee56edee..dfcf058cea 100644 --- a/core/src/test/java/cn/edu/tsinghua/iginx/optimizer/IteratorTest.java +++ b/optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/IteratorTest.java @@ -1,16 +1,12 @@ package cn.edu.tsinghua.iginx.optimizer; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.iterator.DeepFirstIterator; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.iterator.LeveledIterator; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.iterator.ReverseDeepFirstIterator; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.iterator.ReverseLeveledIterator; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.iterator.TreeIterator; import cn.edu.tsinghua.iginx.engine.shared.operator.InnerJoin; import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; import cn.edu.tsinghua.iginx.engine.shared.operator.OuterJoin; import cn.edu.tsinghua.iginx.engine.shared.operator.Project; import cn.edu.tsinghua.iginx.engine.shared.operator.Reorder; import cn.edu.tsinghua.iginx.engine.shared.operator.Select; +import cn.edu.tsinghua.iginx.logical.optimizer.core.iterator.*; import java.util.Arrays; import java.util.List; import org.junit.Assert; diff --git a/core/src/test/java/cn/edu/tsinghua/iginx/optimizer/OperandTest.java b/optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/OperandTest.java similarity index 89% rename from core/src/test/java/cn/edu/tsinghua/iginx/optimizer/OperandTest.java rename to optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/OperandTest.java index 91c606176d..aeebada545 100644 --- a/core/src/test/java/cn/edu/tsinghua/iginx/optimizer/OperandTest.java +++ b/optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/OperandTest.java @@ -1,15 +1,15 @@ package cn.edu.tsinghua.iginx.optimizer; -import static cn.edu.tsinghua.iginx.engine.logical.optimizer.rules.Rule.any; -import static cn.edu.tsinghua.iginx.engine.logical.optimizer.rules.Rule.operand; +import static cn.edu.tsinghua.iginx.logical.optimizer.rules.Rule.any; +import static cn.edu.tsinghua.iginx.logical.optimizer.rules.Rule.operand; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.core.Operand; import cn.edu.tsinghua.iginx.engine.shared.operator.AbstractJoin; import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; import cn.edu.tsinghua.iginx.engine.shared.operator.Project; import cn.edu.tsinghua.iginx.engine.shared.operator.Reorder; import cn.edu.tsinghua.iginx.engine.shared.operator.Select; import cn.edu.tsinghua.iginx.engine.shared.source.EmptySource; +import cn.edu.tsinghua.iginx.logical.optimizer.core.Operand; import java.util.Collections; import org.junit.Assert; import org.junit.Test; diff --git a/core/src/test/java/cn/edu/tsinghua/iginx/optimizer/RBOTest.java b/optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/RBOTest.java similarity index 94% rename from core/src/test/java/cn/edu/tsinghua/iginx/optimizer/RBOTest.java rename to optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/RBOTest.java index 68eafbbaf4..a9df7870a6 100644 --- a/core/src/test/java/cn/edu/tsinghua/iginx/optimizer/RBOTest.java +++ b/optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/RBOTest.java @@ -1,8 +1,8 @@ package cn.edu.tsinghua.iginx.optimizer; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.rbo.RuleBasedOptimizer; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.rules.RuleCollection; import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; +import cn.edu.tsinghua.iginx.logical.optimizer.rbo.RuleBasedOptimizer; +import cn.edu.tsinghua.iginx.logical.optimizer.rules.RuleCollection; import java.util.List; import org.junit.Assert; import org.junit.Test; @@ -10,7 +10,7 @@ public class RBOTest { private final RuleBasedOptimizer rbo = new RuleBasedOptimizer(); - private final RuleCollection ruleCollection = RuleCollection.getInstance(); + private final RuleCollection ruleCollection = RuleCollection.INSTANCE; @Test public void testNotFilterRemoveRule() { diff --git a/core/src/test/java/cn/edu/tsinghua/iginx/optimizer/RBOTestUtils.java b/optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/RBOTestUtils.java similarity index 92% rename from core/src/test/java/cn/edu/tsinghua/iginx/optimizer/RBOTestUtils.java rename to optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/RBOTestUtils.java index 04801f7384..a4e3c01e26 100644 --- a/core/src/test/java/cn/edu/tsinghua/iginx/optimizer/RBOTestUtils.java +++ b/optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/RBOTestUtils.java @@ -1,13 +1,13 @@ package cn.edu.tsinghua.iginx.optimizer; -import cn.edu.tsinghua.iginx.engine.logical.optimizer.rules.RuleCollection; +import cn.edu.tsinghua.iginx.logical.optimizer.rules.RuleCollection; import java.util.ArrayList; import java.util.List; import java.util.Map; public class RBOTestUtils { - private static final RuleCollection ruleCollection = RuleCollection.getInstance(); + private static final RuleCollection ruleCollection = RuleCollection.INSTANCE; /** * 禁止给定规则之外的规则 diff --git a/core/src/test/java/cn/edu/tsinghua/iginx/optimizer/TreeBuilder.java b/optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/TreeBuilder.java similarity index 100% rename from core/src/test/java/cn/edu/tsinghua/iginx/optimizer/TreeBuilder.java rename to optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/TreeBuilder.java diff --git a/core/src/test/java/cn/edu/tsinghua/iginx/optimizer/TreePrinter.java b/optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/TreePrinter.java similarity index 100% rename from core/src/test/java/cn/edu/tsinghua/iginx/optimizer/TreePrinter.java rename to optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/TreePrinter.java diff --git a/pom.xml b/pom.xml index 85ca2f59f4..47e906a459 100644 --- a/pom.xml +++ b/pom.xml @@ -21,6 +21,7 @@ example test assembly + optimizer @@ -71,6 +72,11 @@ iginx-shared ${project.version} + + cn.edu.tsinghua + iginx-optimizer + ${project.version} + cn.edu.tsinghua iotdb12 diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/sql/SQLSessionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/sql/SQLSessionIT.java index 27a94c7edf..dd68971772 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/sql/SQLSessionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/sql/SQLSessionIT.java @@ -7,22 +7,14 @@ import cn.edu.tsinghua.iginx.exception.SessionException; import cn.edu.tsinghua.iginx.integration.controller.Controller; import cn.edu.tsinghua.iginx.integration.func.session.InsertAPIType; -import cn.edu.tsinghua.iginx.integration.tool.ConfLoader; -import cn.edu.tsinghua.iginx.integration.tool.DBConf; +import cn.edu.tsinghua.iginx.integration.tool.*; import cn.edu.tsinghua.iginx.integration.tool.DBConf.DBConfType; -import cn.edu.tsinghua.iginx.integration.tool.MultiConnection; -import cn.edu.tsinghua.iginx.integration.tool.SQLExecutor; import cn.edu.tsinghua.iginx.pool.IginxInfo; import cn.edu.tsinghua.iginx.pool.SessionPool; import cn.edu.tsinghua.iginx.session.Session; import cn.edu.tsinghua.iginx.thrift.DataType; import cn.edu.tsinghua.iginx.utils.Pair; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; import org.apache.commons.lang3.RandomStringUtils; import org.junit.*; @@ -7720,4 +7712,218 @@ public void testDistinctEliminate() { assertTrue(executor.execute("EXPLAIN " + statement).contains("isDistinct: true")); assertEquals(closeResult, executor.execute(statement)); } + + @Test + public void testJoinFactorizationRule() { + if (isFilterPushDown || isScaling) { + LOGGER.info( + "Skip SQLSessionIT.testJoinFactorizationRule because filter push down test or scaling test"); + return; + } + String openRule = "SET RULES JoinFactorizationRule=on;"; + String closeRule = "SET RULES JoinFactorizationRule=off;"; + + StringBuilder insert = new StringBuilder(); + insert.append("INSERT INTO t1 (key, c1, c2) VALUES "); + int rows = 50; + for (int i = 0; i < rows; i++) { + insert.append(String.format("(%d, %d, %d)", i, i % 10, i % 10)); + if (i != rows - 1) { + insert.append(","); + } + } + insert.append(";"); + executor.execute(insert.toString()); + + insert = new StringBuilder(); + insert.append("INSERT INTO t2 (key, c1, c2) VALUES "); + for (int i = 0; i < rows; i++) { + insert.append(String.format("(%d, %d, %d)", i, i % 20, i % 20)); + if (i != rows - 1) { + insert.append(","); + } + } + insert.append(";"); + executor.execute(insert.toString()); + + insert = new StringBuilder(); + insert.append("INSERT INTO t3 (key, c1, c2) VALUES "); + for (int i = 0; i < rows; i++) { + insert.append(String.format("(%d, %d, %d)", i, i % 30, i % 30)); + if (i != rows - 1) { + insert.append(","); + } + } + insert.append(";"); + executor.execute(insert.toString()); + + insert = new StringBuilder(); + insert.append("INSERT INTO t4 (key, c1, c2) VALUES "); + for (int i = 0; i < rows; i++) { + insert.append(String.format("(%d, %d, %d)", i, i % 40, i % 40)); + if (i != rows - 1) { + insert.append(","); + } + } + insert.append(";"); + executor.execute(insert.toString()); + + // 待优化的语句 + String statement = + "SELECT t1.c1, t2.c2\n" + + " FROM t1, t2, t3\n" + + " WHERE t1.c1 = t2.c1\n" + + " AND t1.c1 > 1\n" + + " AND t2.c2 = 2\n" + + " AND t2.c2 = t3.c2\n" + + " UNION ALL\n" + + " SELECT t1.c1, t2.c2\n" + + " FROM t1, t2, t4\n" + + " WHERE t1.c1 = t2.c1\n" + + " AND t1.c1 > 1\n" + + " AND t2.c1 = t4.c1;"; + // 优化后的查询计划与下面这个语句的基本相同,会有些order、filter顺序的不同,不影响结果 + // 例如project t1.c1 t2.c2和project t2.c2 t1.c1的区别 + String optimizing = + " SELECT t1.c1, t2.c2\n" + + " FROM t1, (SELECT t2.c1, t2.c2\n" + + " FROM t2, t3\n" + + " WHERE t2.c2 = t3.c2\n" + + " AND t2.c2 = 2\n" + + " UNION ALL\n" + + " SELECT t2.c1, t2.c2\n" + + " FROM t2, t4\n" + + " WHERE t2.c1 = t4.c1)\n" + + " WHERE t1.c1 = t2.c1\n" + + " AND t1.c1 > 1;"; + + executor.execute(openRule); + String result = executor.execute(statement); + executor.executeAndCompare(optimizing, result); + String expect = + "ResultSets:\n" + + "+----------------------------+-------------+------------------------------------------------------------------+\n" + + "| Logical Tree|Operator Type| Operator Info|\n" + + "+----------------------------+-------------+------------------------------------------------------------------+\n" + + "|Reorder | Reorder| Order: t1.c1,t2.c2|\n" + + "| +--Project | Project| Patterns: t1.c1,t2.c2|\n" + + "| +--Select | Select| Filter: (t1.c1 == t2.c1 && t1.c1 > 1)|\n" + + "| +--CrossJoin | CrossJoin| PrefixA: t1, PrefixB: null|\n" + + "| +--Project | Project| Patterns: t1.*, Target DU: unit0000000002|\n" + + "| +--Union | Union|LeftOrder: t2.c2,t2.c1, RightOrder: t2.c2,t2.c1, isDistinct: false|\n" + + "| +--Reorder | Reorder| Order: t2.c1,t2.c2|\n" + + "| +--Project | Project| Patterns: t2.c1,t2.c2|\n" + + "| +--Select | Select| Filter: (t2.c2 == 2 && t3.c2 == 2)|\n" + + "| +--CrossJoin| CrossJoin| PrefixA: t2, PrefixB: t3|\n" + + "| +--Project| Project| Patterns: t2.c1,t2.c2, Target DU: unit0000000002|\n" + + "| +--Project| Project| Patterns: t3.c2, Target DU: unit0000000002|\n" + + "| +--Reorder | Reorder| Order: t2.c1,t2.c2|\n" + + "| +--Project | Project| Patterns: t2.c1,t2.c2|\n" + + "| +--Select | Select| Filter: (t2.c1 == t4.c1)|\n" + + "| +--CrossJoin| CrossJoin| PrefixA: t2, PrefixB: t4|\n" + + "| +--Project| Project| Patterns: t2.c1,t2.c2, Target DU: unit0000000002|\n" + + "| +--Project| Project| Patterns: t4.c1, Target DU: unit0000000002|\n" + + "+----------------------------+-------------+------------------------------------------------------------------+\n" + + "Total line number = 18\n"; + assertEquals(expect, executor.execute("EXPLAIN " + statement)); + + executor.execute(closeRule); + assertTrue(TestUtils.compareTables(executor.execute(optimizing), result)); + expect = + "ResultSets:\n" + + "+----------------------+-------------+------------------------------------------------------------------+\n" + + "| Logical Tree|Operator Type| Operator Info|\n" + + "+----------------------+-------------+------------------------------------------------------------------+\n" + + "|Union | Union|LeftOrder: t1.c1,t2.c2, RightOrder: t1.c1,t2.c2, isDistinct: false|\n" + + "| +--Reorder | Reorder| Order: t1.c1,t2.c2|\n" + + "| +--Project | Project| Patterns: t2.c2,t1.c1|\n" + + "| +--Select | Select| Filter: (t1.c1 == t2.c1 && t1.c1 > 1 && t2.c2 == 2 && t3.c2 == 2)|\n" + + "| +--CrossJoin | CrossJoin| PrefixA: t2, PrefixB: t3|\n" + + "| +--CrossJoin| CrossJoin| PrefixA: t1, PrefixB: t2|\n" + + "| +--Project| Project| Patterns: t1.*, Target DU: unit0000000002|\n" + + "| +--Project| Project| Patterns: t2.*, Target DU: unit0000000002|\n" + + "| +--Project | Project| Patterns: t3.*, Target DU: unit0000000002|\n" + + "| +--Reorder | Reorder| Order: t1.c1,t2.c2|\n" + + "| +--Project | Project| Patterns: t2.c2,t1.c1|\n" + + "| +--Select | Select| Filter: (t1.c1 == t2.c1 && t1.c1 > 1 && t2.c1 == t4.c1)|\n" + + "| +--CrossJoin | CrossJoin| PrefixA: t2, PrefixB: t4|\n" + + "| +--CrossJoin| CrossJoin| PrefixA: t1, PrefixB: t2|\n" + + "| +--Project| Project| Patterns: t1.*, Target DU: unit0000000002|\n" + + "| +--Project| Project| Patterns: t2.*, Target DU: unit0000000002|\n" + + "| +--Project | Project| Patterns: t4.*, Target DU: unit0000000002|\n" + + "+----------------------+-------------+------------------------------------------------------------------+\n" + + "Total line number = 17\n"; + assertEquals(expect, executor.execute("EXPLAIN " + statement)); + + statement = + "SELECT t1.c2, t2.c2\n" + + "FROM t1, t2\n" + + "WHERE t1.c1 = t2.c1 \n" + + "AND t1.c1 = 1\n" + + "UNION ALL\n" + + "SELECT t1.c2, t2.c2\n" + + "FROM t1, t2\n" + + "WHERE t1.c1 = t2.c1 \n" + + "AND t1.c1 = 2;"; + optimizing = + "SELECT t1.c2, t2.c2\n" + + "FROM t2, (SELECT c1, c2\n" + + " FROM t1\n" + + " WHERE t1.c1 = 1\n" + + " UNION ALL\n" + + " SELECT c1, c2\n" + + " FROM t1\n" + + " WHERE t1.c1 = 2)\n" + + "WHERE t1.c1 = t2.c1;"; + + executor.execute(openRule); + result = executor.execute(statement); + executor.executeAndCompare(optimizing, result); + expect = + "ResultSets:\n" + + "+--------------------------+-------------+------------------------------------------------------------------+\n" + + "| Logical Tree|Operator Type| Operator Info|\n" + + "+--------------------------+-------------+------------------------------------------------------------------+\n" + + "|Reorder | Reorder| Order: t1.c2,t2.c2|\n" + + "| +--Project | Project| Patterns: t1.c2,t2.c2|\n" + + "| +--Select | Select| Filter: (t1.c1 == t2.c1)|\n" + + "| +--CrossJoin | CrossJoin| PrefixA: t2, PrefixB: null|\n" + + "| +--Project | Project| Patterns: t2.*, Target DU: unit0000000002|\n" + + "| +--Union | Union|LeftOrder: t1.c2,t1.c1, RightOrder: t1.c2,t1.c1, isDistinct: false|\n" + + "| +--Reorder | Reorder| Order: t1.c1,t1.c2|\n" + + "| +--Project | Project| Patterns: t1.c1,t1.c2|\n" + + "| +--Select | Select| Filter: (t1.c1 == 1)|\n" + + "| +--Project| Project| Patterns: t1.c1,t1.c2, Target DU: unit0000000002|\n" + + "| +--Reorder | Reorder| Order: t1.c1,t1.c2|\n" + + "| +--Project | Project| Patterns: t1.c1,t1.c2|\n" + + "| +--Select | Select| Filter: (t1.c1 == 2)|\n" + + "| +--Project| Project| Patterns: t1.c1,t1.c2, Target DU: unit0000000002|\n" + + "+--------------------------+-------------+------------------------------------------------------------------+\n" + + "Total line number = 14\n"; + assertEquals(expect, executor.execute("EXPLAIN " + statement)); + + executor.execute(closeRule); + assertTrue(TestUtils.compareTables(executor.execute(optimizing), result)); + expect = + "ResultSets:\n" + + "+--------------------+-------------+------------------------------------------------------------------+\n" + + "| Logical Tree|Operator Type| Operator Info|\n" + + "+--------------------+-------------+------------------------------------------------------------------+\n" + + "|Union | Union|LeftOrder: t1.c2,t2.c2, RightOrder: t1.c2,t2.c2, isDistinct: false|\n" + + "| +--Reorder | Reorder| Order: t1.c2,t2.c2|\n" + + "| +--Project | Project| Patterns: t2.c2,t1.c2|\n" + + "| +--Select | Select| Filter: (t2.c1 == 1 && t1.c1 == 1)|\n" + + "| +--CrossJoin| CrossJoin| PrefixA: t1, PrefixB: t2|\n" + + "| +--Project| Project| Patterns: t1.*, Target DU: unit0000000002|\n" + + "| +--Project| Project| Patterns: t2.*, Target DU: unit0000000002|\n" + + "| +--Reorder | Reorder| Order: t1.c2,t2.c2|\n" + + "| +--Project | Project| Patterns: t2.c2,t1.c2|\n" + + "| +--Select | Select| Filter: (t2.c1 == 2 && t1.c1 == 2)|\n" + + "| +--CrossJoin| CrossJoin| PrefixA: t1, PrefixB: t2|\n" + + "| +--Project| Project| Patterns: t1.*, Target DU: unit0000000002|\n" + + "| +--Project| Project| Patterns: t2.*, Target DU: unit0000000002|\n" + + "+--------------------+-------------+------------------------------------------------------------------+\n" + + "Total line number = 13\n"; + assertEquals(expect, executor.execute("EXPLAIN " + statement)); + } } diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/TestUtils.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/TestUtils.java new file mode 100644 index 0000000000..8cc01bee91 --- /dev/null +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/TestUtils.java @@ -0,0 +1,66 @@ +package cn.edu.tsinghua.iginx.integration.tool; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +public class TestUtils { + /** + * 比较ResultSet的表格内容是否相等,不比较顺序。 + * + * @param table1 表格1 + * @param table2 表格2 + * @return 是否相等 + */ + public static boolean compareTables(String table1, String table2) { + List> list1 = parseTable(table1); + List> list2 = parseTable(table2); + + list1.sort(new ListComparator()); + list2.sort(new ListComparator()); + + return list1.equals(list2); + } + + /** + * 将ResultSet的表格内容解析为二维字符串列表。 + * + * @param table 表格字符串 + * @return 二维字符串列表 + */ + private static List> parseTable(String table) { + List> list = new ArrayList<>(); + String[] lines = table.split("\n"); + + for (String line : lines) { + if (line.startsWith("|") && line.endsWith("|")) { + String[] values = line.split("\\|"); + List row = new ArrayList<>(); + for (String value : values) { + value = value.trim(); + if (!value.isEmpty()) { + row.add(value); + } + } + if (!row.isEmpty()) { + list.add(row); + } + } + } + + return list; + } + + static class ListComparator implements Comparator> { + @Override + public int compare(List o1, List o2) { + for (int i = 0; i < o1.size(); i++) { + int comparison = o1.get(i).compareTo(o2.get(i)); + if (comparison != 0) { + return comparison; + } + } + return 0; + } + } +} From 3219f564be534eb1f3886fcda0939d9ee2692e91 Mon Sep 17 00:00:00 2001 From: Xu Yihao <48053143+Yihao-Xu@users.noreply.github.com> Date: Fri, 14 Jun 2024 09:06:01 +0800 Subject: [PATCH 038/138] fix(relational): fix concat function cannot apply more than 100 args (#350) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复关系对接层CONCAT无法处理超过100个参数的问题,对于超过100个参数的CONCAT,使用嵌套的方法来调用函数。 重构了关系对接层的代码,合并、删去了一些代码逻辑 添加了针对CONCAT的测试,对一个有1000个列的表进行查询 --- .../iginx/relational/RelationalStorage.java | 178 ++++++++++-------- .../meta/AbstractRelationalMeta.java | 6 +- .../relational/tools/FilterTransformer.java | 6 +- .../relational/tools/RelationSchema.java | 4 +- .../PostgreSQLCapacityExpansionIT.java | 73 ++++++- .../PostgreSQLHistoryDataGenerator.java | 19 +- 6 files changed, 192 insertions(+), 94 deletions(-) diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java index 484814477d..0a23801078 100644 --- a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java +++ b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java @@ -67,6 +67,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -471,13 +472,14 @@ else if (!tableNameToColumnNames.isEmpty()) { // 将columnNames中的列名加上tableName前缀 fullColumnNames.replaceAll( - s -> RelationSchema.getQuotFullName(tableName, s, relationalMeta.getQuote())); + s -> RelationSchema.getQuoteFullName(tableName, s, relationalMeta.getQuote())); fullColumnNamesList.add(fullColumnNames); } StringBuilder fullColumnNames = new StringBuilder(); fullColumnNames.append( - RelationSchema.getQuotFullName(tableNames.get(0), KEY_NAME, relationalMeta.getQuote())); + RelationSchema.getQuoteFullName( + tableNames.get(0), KEY_NAME, relationalMeta.getQuote())); for (List columnNames : fullColumnNamesList) { for (String columnName : columnNames) { fullColumnNames.append(", ").append(columnName); @@ -505,7 +507,7 @@ else if (!tableNameToColumnNames.isEmpty()) { String fullColumnNamesStr = fullColumnNames.toString(); String filterStr = filterTransformer.toString(filter); String orderByKey = - RelationSchema.getQuotFullName(tableNames.get(0), KEY_NAME, relationalMeta.getQuote()); + RelationSchema.getQuoteFullName(tableNames.get(0), KEY_NAME, relationalMeta.getQuote()); if (!relationalMeta.isSupportFullJoin()) { // 如果不支持full join,需要为left join + union模拟的full join表起别名,同时select、where、order by的部分都要调整 fullColumnNamesStr = fullColumnNamesStr.replaceAll("`\\.`", "."); @@ -570,11 +572,11 @@ private String getFullJoinTables(List tableNames, List> ful for (int j = 0; j < i; j++) { fullTableName .append( - RelationSchema.getQuotFullName( + RelationSchema.getQuoteFullName( tableNames.get(i), KEY_NAME, relationalMeta.getQuote())) .append(" = ") .append( - RelationSchema.getQuotFullName( + RelationSchema.getQuoteFullName( tableNames.get(j), KEY_NAME, relationalMeta.getQuote())); if (j != i - 1) { @@ -630,10 +632,43 @@ private String getFullJoinTables(List tableNames, List> ful return fullTableName.toString(); } + /** + * 通过columnNames构建concat语句,由于concat的参数个数有限,所以需要分批次嵌套concat + * 由于pg、mysql一张表最大都不能超过2000列,因此嵌套2层,可达到最大10000列,已满足需求。 + * + * @param columnNames 列名列表 + * @return concat语句 + */ + private String buildConcat(List columnNames) { + int n = columnNames.size(); + assert n > 0; + List> concatList = new ArrayList<>(); + for (int i = 0; i < n / 100 + 1; i++) { + List subList = columnNames.subList(i * 100, Math.min((i + 1) * 100, n)); + if (subList.size() == 0) { + continue; + } + concatList.add(subList); + } + + if (concatList.size() == 1) { + return String.format(" CONCAT(%s) ", String.join(", ", concatList.get(0))); + } + + StringBuilder concat = new StringBuilder(); + concat.append(" CONCAT("); + for (int i = 0; i < concatList.size(); i++) { + concat.append(String.format(" CONCAT(%s) ", String.join(", ", concatList.get(i)))); + if (i != concatList.size() - 1) { + concat.append(", "); + } + } + concat.append(") "); + return concat.toString(); + } + private String getDummyFullJoinTables( - List tableNames, - Map allColumnNameForTable, - List> fullColumnList) { + List tableNames, Map> allColumnNameForTable) { StringBuilder fullTableName = new StringBuilder(); if (relationalMeta.isSupportFullJoin()) { // table之间用FULL OUTER JOIN ON concat(table1所有列) = concat(table2所有列) @@ -646,14 +681,11 @@ private String getDummyFullJoinTables( .append(getQuotName(tableNames.get(i))) .append(" ON "); for (int j = 0; j < i; j++) { - fullTableName - .append("CONCAT(") - .append(allColumnNameForTable.get(tableNames.get(i))) - .append(")") - .append(" = ") - .append("CONCAT(") - .append(allColumnNameForTable.get(tableNames.get(j))) - .append(")"); + fullTableName.append( + String.format( + "%s = %s", + buildConcat(allColumnNameForTable.get(tableNames.get(i))), + buildConcat(allColumnNameForTable.get(tableNames.get(j))))); if (j != i - 1) { fullTableName.append(" AND "); } @@ -662,14 +694,13 @@ private String getDummyFullJoinTables( } } else { // 不支持全连接,就要用Left Join+Union来模拟全连接 - StringBuilder allColumns = new StringBuilder(); - fullColumnList.forEach( - columnList -> - columnList.forEach( - column -> - allColumns.append( - String.format("%s AS %s, ", column, column.replaceAll("`\\.`", "."))))); - allColumns.delete(allColumns.length() - 2, allColumns.length()); + char quote = relationalMeta.getQuote(); + String allColumns = + tableNames.stream() + .map(allColumnNameForTable::get) + .flatMap(List::stream) + .map(s -> s + " AS " + s.replaceAll(quote + "\\." + quote, ".")) + .collect(Collectors.joining(", ")); fullTableName.append("("); for (int i = 0; i < tableNames.size(); i++) { @@ -684,10 +715,10 @@ private String getDummyFullJoinTables( if (i != j) { fullTableName.append( String.format( - " LEFT JOIN %s ON CONCAT(%s) = CONCAT(%s)", + " LEFT JOIN %s ON %s = %s", getQuotName(tableNames.get(j)), - allColumnNameForTable.get(tableNames.get(i)), - allColumnNameForTable.get(tableNames.get(j)))); + buildConcat(allColumnNameForTable.get(tableNames.get(i))), + buildConcat(allColumnNameForTable.get(tableNames.get(j))))); } } if (i != tableNames.size() - 1) { @@ -878,21 +909,28 @@ private Filter cutFilterDatabaseNameForDummy(Filter filter, String databaseName) return filter; } - private Map getAllColumnNameForTable( + private Map> getAllColumnNameForTable( String databaseName, Map tableNameToColumnNames) throws SQLException { - Map allColumnNameForTable = new HashMap<>(); + Map> allColumnNameForTable = new HashMap<>(); for (Map.Entry entry : tableNameToColumnNames.entrySet()) { String tableName = entry.getKey(); - String columnNames = ""; List columnFieldList = getColumns(databaseName, tableName, "%"); for (ColumnField columnField : columnFieldList) { String columnName = columnField.columnName; - columnNames = - RelationSchema.getQuotFullName(tableName, columnName, relationalMeta.getQuote()); + if (allColumnNameForTable.containsKey(tableName)) { - columnNames = allColumnNameForTable.get(tableName) + ", " + columnNames; + allColumnNameForTable + .get(tableName) + .add( + RelationSchema.getQuoteFullName( + tableName, columnName, relationalMeta.getQuote())); + continue; } + + List columnNames = new ArrayList<>(); + columnNames.add( + RelationSchema.getQuoteFullName(tableName, columnName, relationalMeta.getQuote())); allColumnNameForTable.put(tableName, columnNames); } } @@ -927,29 +965,34 @@ private TaskExecuteResult executeProjectDummyWithFilter(Project project, Filter } connList.add(conn); + // 这里获取所有table的所有列名,用于concat时生成key列。 + Map> allColumnNameForTable = + getAllColumnNameForTable(databaseName, tableNameToColumnNames); + + // 如果table没有带通配符,那直接简单构建起查询语句即可 if (!filter.toString().contains("*") && !(tableNameToColumnNames.size() > 1 && filterContainsType(Arrays.asList(FilterType.Value, FilterType.Path), filter))) { - Map allColumnNameForTable = - getAllColumnNameForTable(databaseName, tableNameToColumnNames); + for (Map.Entry entry : splitEntry.getValue().entrySet()) { String tableName = entry.getKey(); String fullQuotColumnNames = getQuotColumnNames(entry.getValue()); List fullPathList = Arrays.asList(entry.getValue().split(", ")); fullPathList.replaceAll( - s -> RelationSchema.getQuotFullName(tableName, s, relationalMeta.getQuote())); + s -> RelationSchema.getQuoteFullName(tableName, s, relationalMeta.getQuote())); String filterStr = filterTransformer.toString( dummyFilterSetTrueByColumnNames( cutFilterDatabaseNameForDummy(filter.copy(), databaseName), fullPathList)); + String concatKey = buildConcat(fullPathList); statement = String.format( relationalMeta.getConcatQueryStatement(), - allColumnNameForTable.get(tableName), + concatKey, fullQuotColumnNames, getQuotName(tableName), filterStr.isEmpty() ? "" : "WHERE " + filterStr, - "Concat(" + allColumnNameForTable.get(tableName) + ")"); + concatKey); try { stmt = conn.createStatement(); @@ -967,7 +1010,7 @@ && filterContainsType(Arrays.asList(FilterType.Value, FilterType.Path), filter)) else if (!tableNameToColumnNames.isEmpty()) { List tableNames = new ArrayList<>(); List> fullColumnNamesList = new ArrayList<>(); - List> fullQuotColumnNamesList = new ArrayList<>(); + List> fullQuoteColumnNamesList = new ArrayList<>(); // 将columnNames中的列名加上tableName前缀,带JOIN的查询语句中需要用到 for (Map.Entry entry : tableNameToColumnNames.entrySet()) { @@ -980,40 +1023,16 @@ else if (!tableNameToColumnNames.isEmpty()) { List fullColumnNames = new ArrayList<>(Arrays.asList(entry.getValue().split(", "))); fullColumnNames.replaceAll( - s -> RelationSchema.getQuotFullName(tableName, s, relationalMeta.getQuote())); - fullQuotColumnNamesList.add(fullColumnNames); - } - - StringBuilder fullColumnNames = new StringBuilder(); - for (List columnNames : fullQuotColumnNamesList) { - for (String columnName : columnNames) { - fullColumnNames.append(columnName).append(", "); - } + s -> RelationSchema.getQuoteFullName(tableName, s, relationalMeta.getQuote())); + fullQuoteColumnNamesList.add(fullColumnNames); } - fullColumnNames.delete(fullColumnNames.length() - 2, fullColumnNames.length()); - - // 这里获取所有table的所有列名,用于concat时生成key列。 - Map allColumnNameForTable = - getAllColumnNameForTable(databaseName, tableNameToColumnNames); - StringBuilder allColumnNames = new StringBuilder(); - for (String tableName : tableNames) { - allColumnNames.append(allColumnNameForTable.get(tableName)).append(", "); - } - allColumnNames.delete(allColumnNames.length() - 2, allColumnNames.length()); - - String fullTableName = - getDummyFullJoinTables(tableNames, allColumnNameForTable, fullColumnNamesList); - Filter copyFilter = cutFilterDatabaseNameForDummy(filter.copy(), databaseName); + String fullTableName = getDummyFullJoinTables(tableNames, allColumnNameForTable); - copyFilter = + Filter copyFilter = dummyFilterSetTrueByColumnNames( - copyFilter, - Arrays.asList( - fullColumnNames - .toString() - .replace(String.valueOf(relationalMeta.getQuote()), "") - .split(", "))); + cutFilterDatabaseNameForDummy(filter.copy(), databaseName), + fullColumnNamesList.stream().flatMap(List::stream).collect(Collectors.toList())); // 对通配符做处理,将通配符替换成对应的列名 if (filterTransformer.toString(copyFilter).contains("*")) { @@ -1030,12 +1049,18 @@ else if (!tableNameToColumnNames.isEmpty()) { copyFilter = LogicalFilterUtils.mergeTrue(copyFilter); } - String fullColumnNamesStr = fullColumnNames.toString(); String filterStr = filterTransformer.toString(copyFilter); - String orderByKey = String.format("Concat(%s)", allColumnNames); + String orderByKey = + buildConcat( + fullQuoteColumnNamesList.stream() + .flatMap(List::stream) + .collect(Collectors.toList())); if (!relationalMeta.isSupportFullJoin()) { // 如果不支持full join,需要为left join + union模拟的full join表起别名,同时select、where、order by的部分都要调整 - fullColumnNamesStr = fullColumnNamesStr.replaceAll("`\\.`", "."); + char quote = relationalMeta.getQuote(); + fullQuoteColumnNamesList.forEach( + columnNames -> + columnNames.replaceAll(s -> s.replaceAll(quote + "\\." + quote, "."))); filterStr = filterStr.replaceAll("`\\.`", "."); filterStr = filterStr.replace( @@ -1046,8 +1071,13 @@ else if (!tableNameToColumnNames.isEmpty()) { statement = String.format( relationalMeta.getConcatQueryStatement(), - allColumnNames, - fullColumnNamesStr, + buildConcat( + fullQuoteColumnNamesList.stream() + .flatMap(List::stream) + .collect(Collectors.toList())), + fullQuoteColumnNamesList.stream() + .flatMap(List::stream) + .collect(Collectors.joining(", ")), fullTableName, filterStr.isEmpty() ? "" : "WHERE " + filterStr, orderByKey); diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/meta/AbstractRelationalMeta.java b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/meta/AbstractRelationalMeta.java index 8225037585..0e9c2bffd7 100644 --- a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/meta/AbstractRelationalMeta.java +++ b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/meta/AbstractRelationalMeta.java @@ -98,11 +98,7 @@ public String getQueryStatement() { * @return 通过concat生成key的query的SQL语句 */ public String getConcatQueryStatement() { - return "SELECT concat(%s) AS " - + getQuote() - + KEY_NAME - + getQuote() - + ", %s FROM %s %s ORDER BY %s"; + return "SELECT %s AS " + getQuote() + KEY_NAME + getQuote() + ", %s FROM %s %s ORDER BY %s"; } public String getCreateTableStatement() { diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/FilterTransformer.java b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/FilterTransformer.java index 19a3fc800f..ffbc5c1de4 100644 --- a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/FilterTransformer.java +++ b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/FilterTransformer.java @@ -90,7 +90,7 @@ private String toString(KeyFilter filter) { private String toString(ValueFilter filter) { RelationSchema schema = new RelationSchema(filter.getPath(), relationalMeta.getQuote()); - String path = schema.getQuotFullName(); + String path = schema.getQuoteFullName(); String op = isLikeOp(filter.getOp()) @@ -127,8 +127,8 @@ private String toString(OrFilter filter) { private String toString(PathFilter filter) { RelationSchema schemaA = new RelationSchema(filter.getPathA(), relationalMeta.getQuote()); RelationSchema schemaB = new RelationSchema(filter.getPathB(), relationalMeta.getQuote()); - String pathA = schemaA.getQuotFullName(); - String pathB = schemaB.getQuotFullName(); + String pathA = schemaA.getQuoteFullName(); + String pathB = schemaB.getQuoteFullName(); String op = Op.op2StrWithoutAndOr(filter.getOp()) diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/RelationSchema.java b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/RelationSchema.java index 052c245cf1..20b024f660 100644 --- a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/RelationSchema.java +++ b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/RelationSchema.java @@ -30,7 +30,7 @@ public RelationSchema(String path, boolean isDummy, char quote) { this.quote = quote; } - public static String getQuotFullName(String tableName, String columnName, char quote) { + public static String getQuoteFullName(String tableName, String columnName, char quote) { return getQuotName(tableName, quote) + SEPARATOR + getQuotName(columnName, quote); } @@ -50,7 +50,7 @@ public String getColumnName() { return columnName; } - public String getQuotFullName() { + public String getQuoteFullName() { return getQuotName(tableName, quote) + SEPARATOR + getQuotName(columnName, quote); } diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/postgresql/PostgreSQLCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/postgresql/PostgreSQLCapacityExpansionIT.java index 0ced1e22a1..7d5d52dc11 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/postgresql/PostgreSQLCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/postgresql/PostgreSQLCapacityExpansionIT.java @@ -7,6 +7,8 @@ import cn.edu.tsinghua.iginx.integration.tool.ConfLoader; import cn.edu.tsinghua.iginx.integration.tool.DBConf; import cn.edu.tsinghua.iginx.thrift.StorageEngineType; +import java.sql.Connection; +import java.sql.Statement; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -28,9 +30,14 @@ public PostgreSQLCapacityExpansionIT() { // wrong password situation cannot be tested because trust mode is used } - /** 执行一个简单查询1000次,测试是否会使连接池耗尽,来验证PG的dummy查询是否正确释放连接 */ @Override protected void testQuerySpecialHistoryData() { + testRepeatsQuery(); + testConcatFunction(); + } + + /** 执行一个简单查询1000次,测试是否会使连接池耗尽,来验证PG的dummy查询是否正确释放连接 */ + private void testRepeatsQuery() { String statement = "select * from ln;"; String expect = "ResultSets:\n" @@ -49,4 +56,68 @@ protected void testQuerySpecialHistoryData() { SQLTestTools.executeAndCompare(session, statement, expect); } } + + /** 创建一个1000列的表,进行查询,看concat函数是否会报错。 */ + protected void testConcatFunction() { + int cols = 1000; + // 用pg的session创建一个1000列的表 + String createTableStatement = "CREATE TABLE test_concat ("; + for (int i = 0; i < cols; i++) { + createTableStatement += "col" + i + " text,"; + } + createTableStatement = createTableStatement.substring(0, createTableStatement.length() - 1); + createTableStatement += ");"; + + StringBuilder insert1 = new StringBuilder(); + insert1.append("test_concat ("); + for (int i = 0; i < cols; i++) { + insert1.append("col" + i + ","); + } + insert1.deleteCharAt(insert1.length() - 1); + insert1.append(") "); + StringBuilder insert2 = new StringBuilder(); + insert2.append("("); + for (int i = 0; i < cols; i++) { + insert2.append("'test',"); + } + insert2.deleteCharAt(insert2.length() - 1); + insert2.append(");"); + String insertStatement = + String.format(PostgreSQLHistoryDataGenerator.INSERT_STATEMENT, insert1, insert2); + + try { + Connection connection = + PostgreSQLHistoryDataGenerator.connect(5432, true, null, "postgres", "postgres"); + Statement stmt = connection.createStatement(); + stmt.execute( + String.format(PostgreSQLHistoryDataGenerator.CREATE_DATABASE_STATEMENT, "test_concat")); + + Connection testConnection = + PostgreSQLHistoryDataGenerator.connect( + 5432, false, "test_concat", "postgres", "postgres"); + Statement testStmt = testConnection.createStatement(); + testStmt.execute(createTableStatement); + testStmt.execute(insertStatement); + + // 不用插入数据直接查,不报错即可,不需要比较结果 + String query = "SELECT col1 FROM test_concat.*;"; + String expect = + "ResultSets:\n" + + "+---------+----------------------------+\n" + + "| key|test_concat.test_concat.col1|\n" + + "+---------+----------------------------+\n" + + "|262526998| test|\n" + + "+---------+----------------------------+\n" + + "Total line number = 1\n"; + SQLTestTools.executeAndCompare(session, query, expect); + + testConnection.close(); + stmt.execute( + String.format(PostgreSQLHistoryDataGenerator.DROP_DATABASE_STATEMENT, "test_concat")); + connection.close(); + } catch (Exception e) { + LOGGER.error("create table failed", e); + assert false; + } + } } diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/postgresql/PostgreSQLHistoryDataGenerator.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/postgresql/PostgreSQLHistoryDataGenerator.java index 69d45ecc94..2571b08e14 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/postgresql/PostgreSQLHistoryDataGenerator.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/postgresql/PostgreSQLHistoryDataGenerator.java @@ -17,13 +17,13 @@ public class PostgreSQLHistoryDataGenerator extends BaseHistoryDataGenerator { private static final String QUERY_DATABASES_STATEMENT = "SELECT datname FROM pg_database;"; - private static final String CREATE_DATABASE_STATEMENT = "CREATE DATABASE \"%s\";"; + public static final String CREATE_DATABASE_STATEMENT = "CREATE DATABASE \"%s\";"; - private static final String CREATE_TABLE_STATEMENT = "CREATE TABLE %s (%s);"; + public static final String CREATE_TABLE_STATEMENT = "CREATE TABLE %s (%s);"; - private static final String INSERT_STATEMENT = "INSERT INTO %s VALUES %s;"; + public static final String INSERT_STATEMENT = "INSERT INTO %s VALUES %s;"; - private static final String DROP_DATABASE_STATEMENT = "DROP DATABASE \"%s\" WITH (FORCE);"; + public static final String DROP_DATABASE_STATEMENT = "DROP DATABASE \"%s\" WITH (FORCE);"; private static final String USERNAME = "postgres"; @@ -35,7 +35,8 @@ public PostgreSQLHistoryDataGenerator() { Constant.readOnlyPort = 5434; } - private Connection connect(int port, boolean useSystemDatabase, String databaseName) { + public static Connection connect( + int port, boolean useSystemDatabase, String databaseName, String username, String password) { try { String url; if (useSystemDatabase) { @@ -44,7 +45,7 @@ private Connection connect(int port, boolean useSystemDatabase, String databaseN url = String.format("jdbc:postgresql://127.0.0.1:%d/%s", port, databaseName); } Class.forName("org.postgresql.Driver"); - return DriverManager.getConnection(url, USERNAME, PASSWORD); + return DriverManager.getConnection(url, username, password); } catch (SQLException | ClassNotFoundException e) { throw new RuntimeException(e); } @@ -59,7 +60,7 @@ public void writeHistoryData( List> valuesList) { Connection connection = null; try { - connection = connect(port, true, null); + connection = connect(port, true, null, USERNAME, PASSWORD); if (connection == null) { LOGGER.error("cannot connect to 127.0.0.1:{}!", port); return; @@ -92,7 +93,7 @@ public void writeHistoryData( } stmt.close(); - Connection conn = connect(port, false, databaseName); + Connection conn = connect(port, false, databaseName, USERNAME, PASSWORD); stmt = conn.createStatement(); for (Map.Entry> item : entry.getValue().entrySet()) { String tableName = item.getKey(); @@ -161,7 +162,7 @@ public void writeHistoryData( public void clearHistoryDataForGivenPort(int port) { Connection conn = null; try { - conn = connect(port, true, null); + conn = connect(port, true, null, USERNAME, PASSWORD); Statement stmt = conn.createStatement(); ResultSet databaseSet = stmt.executeQuery(QUERY_DATABASES_STATEMENT); Statement dropDatabaseStatement = conn.createStatement(); From 9f6601cdca6cf082e8d59048a6c4be194bea744d Mon Sep 17 00:00:00 2001 From: RemHero <1104304963@qq.com> Date: Fri, 14 Jun 2024 10:46:46 +0800 Subject: [PATCH 039/138] fix --- .../tsinghua/iginx/filesystem/exec/LocalExecutor.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java index d7f2160a2a..6ca9527fd0 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java @@ -312,12 +312,13 @@ public TaskExecuteResult executeDeleteTask( return new TaskExecuteResult(null, null); } - boolean isPathMatchPattern(String path, Set pattern) { - if (pattern.isEmpty()) { + boolean isPathMatchPattern(String path, Set patterns) { + if (patterns.isEmpty()) { return true; } - for (String pathRegex : pattern) { - if (Pattern.matches(StringUtils.reformatPath(pathRegex), path)) { + for (String pattern : patterns) { + Pattern pathPattern = Pattern.compile(StringUtils.reformatPath(pattern)); + if (pathPattern.matcher(path).matches()) { return true; } } From 45b3ca59dafd07af70bc6b2c98c86928aada3d66 Mon Sep 17 00:00:00 2001 From: RemHero <1104304963@qq.com> Date: Fri, 14 Jun 2024 15:53:47 +0800 Subject: [PATCH 040/138] fix the code QL --- .../cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java index 6ca9527fd0..64999c18eb 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java @@ -317,8 +317,7 @@ boolean isPathMatchPattern(String path, Set patterns) { return true; } for (String pattern : patterns) { - Pattern pathPattern = Pattern.compile(StringUtils.reformatPath(pattern)); - if (pathPattern.matcher(path).matches()) { + if (StringUtils.match(path, pattern)) { return true; } } From 7771fc23135a26162e6c17ee389803040b25d47a Mon Sep 17 00:00:00 2001 From: RemHero <1104304963@qq.com> Date: Fri, 14 Jun 2024 16:16:52 +0800 Subject: [PATCH 041/138] foramt --- .../cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java | 1 - 1 file changed, 1 deletion(-) diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java index 64999c18eb..a08fde5285 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java @@ -37,7 +37,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import java.util.regex.Pattern; import org.slf4j.Logger; import org.slf4j.LoggerFactory; From 253c38bf22d5d5d09a9b309596368a1e1624cc79 Mon Sep 17 00:00:00 2001 From: Xu Yihao <48053143+Yihao-Xu@users.noreply.github.com> Date: Sat, 15 Jun 2024 10:53:50 +0800 Subject: [PATCH 042/138] feat(optimizer): Outer Join Eliminate Rule (#358) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR介绍 本次PR实现了OutJoinEliminate规则,能够做到以下优化: 当OutJoin上方仅涉及外表的列,并且被Distinct约束时,可以将OutJoin消除。 当OutJoin上方仅涉及外表的列,并且OutJoin在In或Exists子查询中时,可以将OutJoin消除。 详细性能测试见【PR文档】Out Join消除。 --- optimizer/pom.xml | 1 - .../iginx-optimizer-0.7.0-SNAPSHOT.jar | Bin 212055 -> 523231 bytes .../integration/func/sql/SQLSessionIT.java | 53 ++++++++++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/optimizer/pom.xml b/optimizer/pom.xml index 75bf60216a..b13681b4ab 100644 --- a/optimizer/pom.xml +++ b/optimizer/pom.xml @@ -93,7 +93,6 @@ - false ${java.home}/lib/rt.jar diff --git a/optimizer/src/main/resources/iginx-optimizer-0.7.0-SNAPSHOT.jar b/optimizer/src/main/resources/iginx-optimizer-0.7.0-SNAPSHOT.jar index 668020ee9dd019223a25d41e8f03869bbbf04227..57311a0eaf9fbda0068efcf6da8896b39a2dd647 100644 GIT binary patch delta 349424 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

bnf(;UDFGmYpOp)@oUM+b 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 #N{d!A=Vi5^b0}@{1X=$)$&2?k9~qpE^&2&_ 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 delta 35903 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 Date: Mon, 17 Jun 2024 14:51:46 +0800 Subject: [PATCH 043/138] rename --- .../tsinghua/iginx/engine/physical/storage/IStorage.java | 2 +- .../cn/edu/tsinghua/iginx/filesystem/FileSystemStorage.java | 4 ++-- .../cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java | 4 ++-- .../main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java | 4 ++-- .../java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java | 4 ++-- .../java/cn/edu/tsinghua/iginx/parquet/ParquetStorage.java | 4 ++-- .../main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java | 6 +++--- .../cn/edu/tsinghua/iginx/relational/RelationalStorage.java | 4 ++-- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/IStorage.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/IStorage.java index dda2f745f7..d967d323ba 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/IStorage.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/IStorage.java @@ -57,7 +57,7 @@ TaskExecuteResult executeProjectDummyWithSelect( TaskExecuteResult executeInsert(Insert insert, DataArea dataArea); /** 获取所有列信息 */ - List getColumns(Set pattern, TagFilter tagFilter) throws PhysicalException; + List getColumns(Set patterns, TagFilter tagFilter) throws PhysicalException; /** 获取指定前缀的数据边界 */ Pair getBoundaryOfStorage(String prefix) throws PhysicalException; diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/FileSystemStorage.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/FileSystemStorage.java index 6f31d9e666..d733b1b414 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/FileSystemStorage.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/FileSystemStorage.java @@ -151,9 +151,9 @@ public TaskExecuteResult executeDelete(Delete delete, DataArea dataArea) { } @Override - public List getColumns(Set pattern, TagFilter tagFilter) + public List getColumns(Set patterns, TagFilter tagFilter) throws PhysicalException { - return executor.getColumnsOfStorageUnit(WILDCARD, pattern, tagFilter); + return executor.getColumnsOfStorageUnit(WILDCARD, patterns, tagFilter); } @Override diff --git a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java index 0f91947422..37032de54f 100644 --- a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java +++ b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java @@ -231,7 +231,7 @@ private String findExtremeRecordPath( } @Override - public List getColumns(Set pattern, TagFilter tagFilter) { + public List getColumns(Set patterns, TagFilter tagFilter) { List timeseries = new ArrayList<>(); for (Bucket bucket : @@ -271,7 +271,7 @@ public List getColumns(Set pattern, TagFilter tagFilter) { path = bucket.getName() + "." + path; } // get columns by pattern - if (!isPathMatchPattern(path, pattern)) { + if (!isPathMatchPattern(path, patterns)) { continue; } // get columns by tag filter diff --git a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java b/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java index 092f4bcd6c..05cb5b995f 100644 --- a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java +++ b/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java @@ -192,10 +192,10 @@ public void release() throws PhysicalException { } @Override - public List getColumns(Set pattern, TagFilter tagFilter) + public List getColumns(Set patterns, TagFilter tagFilter) throws PhysicalException { List columns = new ArrayList<>(); - getColumns2StorageUnit(columns, null, pattern, tagFilter); + getColumns2StorageUnit(columns, null, patterns, tagFilter); return columns; } diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java index 4178ea2fab..f5dc5467b3 100644 --- a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java +++ b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java @@ -295,8 +295,8 @@ private static long getDuplicateKey(WriteError error) { } @Override - public List getColumns(Set pattern, TagFilter tagFilter) { - List patternList = new ArrayList<>(pattern); + public List getColumns(Set patterns, TagFilter tagFilter) { + List patternList = new ArrayList<>(patterns); if (patternList.isEmpty()) { patternList.add("*"); } diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/ParquetStorage.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/ParquetStorage.java index 6bc2298e71..f02d6f5c21 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/ParquetStorage.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/ParquetStorage.java @@ -176,9 +176,9 @@ public TaskExecuteResult executeInsert(Insert insert, DataArea dataArea) { } @Override - public List getColumns(Set pattern, TagFilter tagFilter) + public List getColumns(Set patterns, TagFilter tagFilter) throws PhysicalException { - return executor.getColumnsOfStorageUnit("*", pattern, tagFilter); + return executor.getColumnsOfStorageUnit("*", patterns, tagFilter); } @Override diff --git a/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java b/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java index abd7d16e78..b78ac6f896 100644 --- a/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java +++ b/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java @@ -467,11 +467,11 @@ public TaskExecuteResult executeInsert(Insert insert, DataArea dataArea) { } @Override - public List getColumns(Set pattern, TagFilter tagFilter) { + public List getColumns(Set patterns, TagFilter tagFilter) { try { List ret = new ArrayList<>(); - getIginxColumns(ret::add, pattern, tagFilter); - getDummyColumns(ret::add, pattern); + getIginxColumns(ret::add, patterns, tagFilter); + getDummyColumns(ret::add, patterns); return ret; } catch (PhysicalException e) { throw new IllegalStateException("get columns error", e); diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java index 30a56542f6..5ba973efcd 100644 --- a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java +++ b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java @@ -336,7 +336,7 @@ private boolean filterContainsType(List types, Filter filter) { } @Override - public List getColumns(Set pattern, TagFilter tagFilter) + public List getColumns(Set patterns, TagFilter tagFilter) throws RelationalTaskExecuteFailureException { List columns = new ArrayList<>(); Map extraParams = meta.getExtraParams(); @@ -367,7 +367,7 @@ public List getColumns(Set pattern, TagFilter tagFilter) } // get columns by pattern - if (!isPathMatchPattern(columnName, pattern)) { + if (!isPathMatchPattern(columnName, patterns)) { continue; } // get columns by tag filter From 389382db3960b7a2cd4f7178d7cdcd4cd11889f3 Mon Sep 17 00:00:00 2001 From: RemHero <1104304963@qq.com> Date: Mon, 17 Jun 2024 16:34:30 +0800 Subject: [PATCH 044/138] better IoTDB --- .../tsinghua/iginx/iotdb/IoTDBStorage.java | 105 ++++++++++-------- 1 file changed, 56 insertions(+), 49 deletions(-) diff --git a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java b/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java index 05cb5b995f..2ba5ff0396 100644 --- a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java +++ b/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java @@ -96,7 +96,9 @@ public class IoTDBStorage implements IStorage { private static final String DELETE_TIMESERIES_CLAUSE = "DELETE TIMESERIES %s"; - private static final String SHOW_TIMESERIES = "SHOW TIMESERIES"; + private static final String SHOW_TIMESERIES = "SHOW TIMESERIES root.%s"; + + private static final String SHOW_TIMESERIES_ALL = "SHOW TIMESERIES"; private static final String DOES_NOT_EXISTED = "does not exist"; @@ -214,61 +216,66 @@ boolean isPathMatchPattern(String path, Set pattern) { private void getColumns2StorageUnit( List columns, Map columns2StorageUnit, - Set pattern, + Set patterns, TagFilter tagFilter) throws PhysicalException { try { - SessionDataSetWrapper dataSet = sessionPool.executeQueryStatement(SHOW_TIMESERIES); - while (dataSet.hasNext()) { - RowRecord record = dataSet.next(); - if (record == null || record.getFields().size() < 4) { - continue; - } - String path = record.getFields().get(0).getStringValue(); - path = path.substring(5); // remove root. - boolean isDummy = true; - if (path.startsWith("unit")) { - path = path.substring(path.indexOf('.') + 1); - isDummy = false; + Iterator iterator = patterns.iterator(); + do { + String pattern = iterator.hasNext() ? iterator.next() : null; + SessionDataSetWrapper dataSet; + if (pattern != null) { + dataSet = sessionPool.executeQueryStatement(String.format(SHOW_TIMESERIES, pattern)); + } else { + dataSet = sessionPool.executeQueryStatement(SHOW_TIMESERIES_ALL); } - Pair> pair = TagKVUtils.splitFullName(path); - String dataTypeName = record.getFields().get(3).getStringValue(); + while (dataSet.hasNext()) { + RowRecord record = dataSet.next(); + if (record == null || record.getFields().size() < 4) { + continue; + } + String path = record.getFields().get(0).getStringValue(); + path = path.substring(5); // remove root. + boolean isDummy = true; + if (path.startsWith("unit")) { + path = path.substring(path.indexOf('.') + 1); + isDummy = false; + } + Pair> pair = TagKVUtils.splitFullName(path); + String dataTypeName = record.getFields().get(3).getStringValue(); - String fragment = isDummy ? "" : record.getFields().get(2).getStringValue().substring(5); - if (columns2StorageUnit != null) { - columns2StorageUnit.put(pair.k, fragment); - } - // get columns by pattern - if (!isPathMatchPattern(pair.k, pattern)) { - continue; - } - // get columns by tag filter - if (tagFilter != null && !TagKVUtils.match(pair.v, tagFilter)) { - continue; - } + String fragment = isDummy ? "" : record.getFields().get(2).getStringValue().substring(5); + if (columns2StorageUnit != null) { + columns2StorageUnit.put(pair.k, fragment); + } + // get columns by tag filter + if (tagFilter != null && !TagKVUtils.match(pair.v, tagFilter)) { + continue; + } - switch (dataTypeName) { - case "BOOLEAN": - columns.add(new Column(pair.k, DataType.BOOLEAN, pair.v, isDummy)); - break; - case "FLOAT": - columns.add(new Column(pair.k, DataType.FLOAT, pair.v, isDummy)); - break; - case "TEXT": - columns.add(new Column(pair.k, DataType.BINARY, pair.v, isDummy)); - break; - case "DOUBLE": - columns.add(new Column(pair.k, DataType.DOUBLE, pair.v, isDummy)); - break; - case "INT32": - columns.add(new Column(pair.k, DataType.INTEGER, pair.v, isDummy)); - break; - case "INT64": - columns.add(new Column(pair.k, DataType.LONG, pair.v, isDummy)); - break; + switch (dataTypeName) { + case "BOOLEAN": + columns.add(new Column(pair.k, DataType.BOOLEAN, pair.v, isDummy)); + break; + case "FLOAT": + columns.add(new Column(pair.k, DataType.FLOAT, pair.v, isDummy)); + break; + case "TEXT": + columns.add(new Column(pair.k, DataType.BINARY, pair.v, isDummy)); + break; + case "DOUBLE": + columns.add(new Column(pair.k, DataType.DOUBLE, pair.v, isDummy)); + break; + case "INT32": + columns.add(new Column(pair.k, DataType.INTEGER, pair.v, isDummy)); + break; + case "INT64": + columns.add(new Column(pair.k, DataType.LONG, pair.v, isDummy)); + break; + } } - } - dataSet.close(); + dataSet.close(); + } while (iterator.hasNext()); } catch (IoTDBConnectionException | StatementExecutionException e) { throw new IoTDBTaskExecuteFailureException("get time series failure: ", e); } From ca90fc20a53891adf379f1c4b1a68d667364b6c9 Mon Sep 17 00:00:00 2001 From: ZM <12236590+shinyano@users.noreply.github.com> Date: Tue, 18 Jun 2024 20:56:37 +0800 Subject: [PATCH 045/138] feat(influxdb&relational): show columns by pattern (#164) * for test * fix test * fix influxdb dummy show columns * fix relational dummy show columns * fix relational & format * restore tests * remove useless log --- .../iginx/influxdb/InfluxDBStorage.java | 79 +++++++++++- .../iginx/relational/RelationalStorage.java | 113 +++++++++++++----- 2 files changed, 162 insertions(+), 30 deletions(-) diff --git a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java index 37032de54f..38bfcd672b 100644 --- a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java +++ b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java @@ -96,6 +96,9 @@ public class InfluxDBStorage implements IStorage { private static final String SHOW_TIME_SERIES = "from(bucket:\"%s\") |> range(start: time(v: 0), stop: time(v: 9223372036854775807)) |> filter(fn: (r) => (r._measurement =~ /.*/ and r._field =~ /.+/)) |> first()"; + private static final String SHOW_TIME_SERIES_BY_PATTERN = + "from(bucket:\"%s\") |> range(start: time(v: 0), stop: time(v: 9223372036854775807)) |> filter(fn: (r) => (r._measurement =~ /%s/ and r._field =~ /%s/)) |> first()"; + private final StorageEngineMeta meta; private final InfluxDBClient client; @@ -233,7 +236,6 @@ private String findExtremeRecordPath( @Override public List getColumns(Set patterns, TagFilter tagFilter) { List timeseries = new ArrayList<>(); - for (Bucket bucket : client.getBucketsApi().findBucketsByOrgName(organization.getName())) { // get all the bucket // query all the series by querying all the data with first() @@ -251,8 +253,79 @@ public List getColumns(Set patterns, TagFilter tagFilter) { continue; } - String statement = String.format(SHOW_TIME_SERIES, bucket.getName()); - List tables = client.getQueryApi().query(statement, organization.getId()); + List tables = new ArrayList<>(); + String measPattern, fieldPattern, statement, bucketPattern; + // + List> patternPairs = new ArrayList<>(); + + if (patterns == null + || patterns.size() == 0 + || patterns.contains("*") + || patterns.contains("*.*")) { + statement = String.format(SHOW_TIME_SERIES, bucket.getName()); + tables = client.getQueryApi().query(statement, organization.getId()); + } else { + boolean thisBucketIsQueried = false; + for (String p : patterns) { + if (isDummy && !isUnit) { + bucketPattern = p.substring(0, p.indexOf(".")); + // dummy path starts with . + if (!Pattern.matches(StringUtils.reformatPath(bucketPattern), bucket.getName())) { + continue; + } + // * can match multiple layers. + if (p.startsWith("*.")) { + // match one layer first + p = p.substring(2); + if (p.contains(".")) { + // pattern *.xx.xx + patternPairs.add( + new Pair<>( + StringUtils.reformatPath(p.substring(0, p.indexOf("."))), + StringUtils.reformatPath(p.substring(p.indexOf(".") + 1)))); + } + // match multiple layers later. + p = "*.*." + p; + } + // remove . part from pattern + p = p.substring(p.indexOf(".") + 1); + } + thisBucketIsQueried = true; + + if (p.startsWith("*.")) { + // match one layer first + patternPairs.add( + new Pair<>( + StringUtils.reformatPath(p.substring(0, p.indexOf("."))), + StringUtils.reformatPath(p.substring(p.indexOf(".") + 1)))); + // match multiple layers + patternPairs.add( + new Pair<>(StringUtils.reformatPath("*"), StringUtils.reformatPath(p))); + } else if (p.equals("*")) { + patternPairs.add( + new Pair<>(StringUtils.reformatPath("*"), StringUtils.reformatPath("*"))); + } else if (p.contains(".")) { + patternPairs.add( + new Pair<>( + StringUtils.reformatPath(p.substring(0, p.indexOf("."))), + StringUtils.reformatPath(p.substring(p.indexOf(".") + 1)))); + } + for (Pair patternPair : patternPairs) { + measPattern = patternPair.k; + fieldPattern = patternPair.v; + // query time series based on pattern + statement = + String.format( + SHOW_TIME_SERIES_BY_PATTERN, bucket.getName(), measPattern, fieldPattern); + LOGGER.info("executing column query: {}", statement); + tables.addAll(client.getQueryApi().query(statement, organization.getId())); + } + } + // if bucket is dummy && all patterns do not match(.*), move on to next bucket + if (!thisBucketIsQueried) { + continue; + } + } for (FluxTable table : tables) { List column = table.getColumns(); diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java index 5ba973efcd..bcef47b68e 100644 --- a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java +++ b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java @@ -341,6 +341,14 @@ public List getColumns(Set patterns, TagFilter tagFilter) List columns = new ArrayList<>(); Map extraParams = meta.getExtraParams(); try { + // dummy pattern list + List patternList = new ArrayList<>(); + if (patterns == null || patterns.size() == 0) { + patternList = new ArrayList<>(Collections.singletonList("*.*")); + } + String colPattern; + + // non-dummy for (String databaseName : getDatabaseNames()) { if ((extraParams.get("has_data") == null || extraParams.get("has_data").equals("false")) && !databaseName.startsWith(DATABASE_PREFIX)) { @@ -348,38 +356,89 @@ public List getColumns(Set patterns, TagFilter tagFilter) } boolean isDummy = extraParams.get("has_data") != null - && extraParams.get("has_data").equalsIgnoreCase("true"); - - List tables = getTables(databaseName, "%"); - for (String tableName : tables) { - List columnFieldList = getColumns(databaseName, tableName, "%"); - for (ColumnField columnField : columnFieldList) { - String columnName = columnField.columnName; - String typeName = columnField.columnType; - if (columnName.equals(KEY_NAME)) { // key 列不显示 - continue; + && extraParams.get("has_data").equalsIgnoreCase("true") + && !databaseName.startsWith(DATABASE_PREFIX); + if (isDummy) { + // find pattern that match .* to avoid creating databases after. + if (patterns == null || patterns.size() == 0) { + continue; + } + for (String p : patterns) { + // dummy path starts with . + if (Pattern.matches( + StringUtils.reformatPath(p.substring(0, p.indexOf("."))), databaseName)) { + patternList.add(p); } - Pair> nameAndTags = splitFullName(columnName); - if (databaseName.startsWith(DATABASE_PREFIX)) { + } + continue; + } + + Map tableAndColPattern = new HashMap<>(); + + if (patterns != null && patterns.size() != 0) { + tableAndColPattern = splitAndMergeQueryPatterns(databaseName, new ArrayList<>(patterns)); + } else { + for (String table : getTables(databaseName, "%")) { + tableAndColPattern.put(table, "%"); + } + } + + for (String tableName : tableAndColPattern.keySet()) { + colPattern = tableAndColPattern.get(tableName); + for (String colName : colPattern.split(", ")) { + List columnFieldList = getColumns(databaseName, tableName, colName); + for (ColumnField columnField : columnFieldList) { + String columnName = columnField.columnName; + String typeName = columnField.columnType; + if (columnName.equals(KEY_NAME)) { // key 列不显示 + continue; + } + Pair> nameAndTags = splitFullName(columnName); columnName = tableName + SEPARATOR + nameAndTags.k; - } else { - columnName = databaseName + SEPARATOR + tableName + SEPARATOR + nameAndTags.k; + if (tagFilter != null && !TagKVUtils.match(nameAndTags.v, tagFilter)) { + continue; + } + columns.add( + new Column( + columnName, + relationalMeta.getDataTypeTransformer().fromEngineType(typeName), + nameAndTags.v, + isDummy)); } + } + } + } - // get columns by pattern - if (!isPathMatchPattern(columnName, patterns)) { - continue; - } - // get columns by tag filter - if (tagFilter != null && !TagKVUtils.match(nameAndTags.v, tagFilter)) { - continue; + // dummy + Map> dummyRes = splitAndMergeHistoryQueryPatterns(patternList); + Map table2cols; + // seemingly there are 4 nested loops, but it's only the consequence of special data structure + // and reused methods. + // the loops would not affect complexity + for (String databaseName : dummyRes.keySet()) { + table2cols = dummyRes.get(databaseName); + for (String tableName : table2cols.keySet()) { + colPattern = table2cols.get(tableName); + for (String colName : colPattern.split(", ")) { + List columnFieldList = getColumns(databaseName, tableName, colName); + for (ColumnField columnField : columnFieldList) { + String columnName = columnField.columnName; + String typeName = columnField.columnType; + if (columnName.equals(KEY_NAME)) { // key 列不显示 + continue; + } + Pair> nameAndTags = splitFullName(columnName); + columnName = databaseName + SEPARATOR + tableName + SEPARATOR + nameAndTags.k; + if (tagFilter != null && !TagKVUtils.match(nameAndTags.v, tagFilter)) { + continue; + } + columns.add( + new Column( + columnName, + relationalMeta.getDataTypeTransformer().fromEngineType(typeName), + nameAndTags.v, + true)); } - columns.add( - new Column( - columnName, - relationalMeta.getDataTypeTransformer().fromEngineType(typeName), - nameAndTags.v, - isDummy)); } } } From 38a92ba7d0d2b302b24211072d1ca250b9834607 Mon Sep 17 00:00:00 2001 From: RemHero <1104304963@qq.com> Date: Tue, 18 Jun 2024 21:15:03 +0800 Subject: [PATCH 046/138] fix IoTDB --- .../main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java b/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java index 2ba5ff0396..40c3ef7886 100644 --- a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java +++ b/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java @@ -157,7 +157,7 @@ public Pair getBoundaryOfStorage(String dataPrefix ColumnsInterval columnsInterval; try { if (dataPrefix == null || dataPrefix.isEmpty()) { - dataSet = sessionPool.executeQueryStatement(SHOW_TIMESERIES); + dataSet = sessionPool.executeQueryStatement(SHOW_TIMESERIES_ALL); while (dataSet.hasNext()) { record = dataSet.next(); if (record == null || record.getFields().size() < 4) { @@ -841,7 +841,7 @@ private List determineDeletePathList(String storageUnit, Delete delete) private List determinePathList(String storageUnit, List patterns) throws IoTDBConnectionException, StatementExecutionException { Set pathSet = new HashSet<>(); - String showColumns = SHOW_TIMESERIES; + String showColumns = SHOW_TIMESERIES_ALL; showColumns = storageUnit == null ? showColumns : showColumns + " " + PREFIX + storageUnit; SessionDataSetWrapper dataSet = sessionPool.executeQueryStatement(showColumns); while (dataSet.hasNext()) { From e443ec50ff49c139629fd23f101db1c6dee12280 Mon Sep 17 00:00:00 2001 From: RemHero <1104304963@qq.com> Date: Wed, 19 Jun 2024 15:17:40 +0800 Subject: [PATCH 047/138] fix IoTDB --- .../tsinghua/iginx/iotdb/IoTDBStorage.java | 123 ++++++++++-------- 1 file changed, 68 insertions(+), 55 deletions(-) diff --git a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java b/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java index 40c3ef7886..33f2da47ad 100644 --- a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java +++ b/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java @@ -96,7 +96,9 @@ public class IoTDBStorage implements IStorage { private static final String DELETE_TIMESERIES_CLAUSE = "DELETE TIMESERIES %s"; - private static final String SHOW_TIMESERIES = "SHOW TIMESERIES root.%s"; + private static final String SHOW_TIMESERIES_DUMMY = "SHOW TIMESERIES root.%s"; + + private static final String SHOW_TIMESERIES = "SHOW TIMESERIES root.*.%s"; private static final String SHOW_TIMESERIES_ALL = "SHOW TIMESERIES"; @@ -201,16 +203,61 @@ public List getColumns(Set patterns, TagFilter tagFilter) return columns; } - boolean isPathMatchPattern(String path, Set pattern) { - if (pattern.isEmpty()) { - return true; - } - for (String pathRegex : pattern) { - if (Pattern.matches(StringUtils.reformatPath(pathRegex), path)) { - return true; + private void getColumnsFromDataSet( + List columns, + Map columns2StorageUnit, + TagFilter tagFilter, + SessionDataSetWrapper dataSet) + throws PhysicalException { + try { + while (dataSet.hasNext()) { + RowRecord record = dataSet.next(); + if (record == null || record.getFields().size() < 4) { + continue; + } + String path = record.getFields().get(0).getStringValue(); + path = path.substring(5); // remove root. + boolean isDummy = true; + if (path.startsWith("unit")) { + path = path.substring(path.indexOf('.') + 1); + isDummy = false; + } + Pair> pair = TagKVUtils.splitFullName(path); + String dataTypeName = record.getFields().get(3).getStringValue(); + + String fragment = isDummy ? "" : record.getFields().get(2).getStringValue().substring(5); + if (columns2StorageUnit != null) { + columns2StorageUnit.put(pair.k, fragment); + } + // get columns by tag filter + if (tagFilter != null && !TagKVUtils.match(pair.v, tagFilter)) { + continue; + } + + switch (dataTypeName) { + case "BOOLEAN": + columns.add(new Column(pair.k, DataType.BOOLEAN, pair.v, isDummy)); + break; + case "FLOAT": + columns.add(new Column(pair.k, DataType.FLOAT, pair.v, isDummy)); + break; + case "TEXT": + columns.add(new Column(pair.k, DataType.BINARY, pair.v, isDummy)); + break; + case "DOUBLE": + columns.add(new Column(pair.k, DataType.DOUBLE, pair.v, isDummy)); + break; + case "INT32": + columns.add(new Column(pair.k, DataType.INTEGER, pair.v, isDummy)); + break; + case "INT64": + columns.add(new Column(pair.k, DataType.LONG, pair.v, isDummy)); + break; + } } + } catch (IoTDBConnectionException | StatementExecutionException e) { + throw new IoTDBTaskExecuteFailureException("get time series failure: ", e); } - return false; } private void getColumns2StorageUnit( @@ -224,57 +271,23 @@ private void getColumns2StorageUnit( do { String pattern = iterator.hasNext() ? iterator.next() : null; SessionDataSetWrapper dataSet; + LOGGER.debug("get time series: {}", pattern); if (pattern != null) { + LOGGER.debug("do show timeseries: {}", pattern); dataSet = sessionPool.executeQueryStatement(String.format(SHOW_TIMESERIES, pattern)); + getColumnsFromDataSet(columns, columns2StorageUnit, tagFilter, dataSet); + dataSet.close(); + + dataSet = + sessionPool.executeQueryStatement(String.format(SHOW_TIMESERIES_DUMMY, pattern)); + getColumnsFromDataSet(columns, columns2StorageUnit, tagFilter, dataSet); + dataSet.close(); } else { + LOGGER.debug("do show all timeseries"); dataSet = sessionPool.executeQueryStatement(SHOW_TIMESERIES_ALL); + getColumnsFromDataSet(columns, columns2StorageUnit, tagFilter, dataSet); + dataSet.close(); } - while (dataSet.hasNext()) { - RowRecord record = dataSet.next(); - if (record == null || record.getFields().size() < 4) { - continue; - } - String path = record.getFields().get(0).getStringValue(); - path = path.substring(5); // remove root. - boolean isDummy = true; - if (path.startsWith("unit")) { - path = path.substring(path.indexOf('.') + 1); - isDummy = false; - } - Pair> pair = TagKVUtils.splitFullName(path); - String dataTypeName = record.getFields().get(3).getStringValue(); - - String fragment = isDummy ? "" : record.getFields().get(2).getStringValue().substring(5); - if (columns2StorageUnit != null) { - columns2StorageUnit.put(pair.k, fragment); - } - // get columns by tag filter - if (tagFilter != null && !TagKVUtils.match(pair.v, tagFilter)) { - continue; - } - - switch (dataTypeName) { - case "BOOLEAN": - columns.add(new Column(pair.k, DataType.BOOLEAN, pair.v, isDummy)); - break; - case "FLOAT": - columns.add(new Column(pair.k, DataType.FLOAT, pair.v, isDummy)); - break; - case "TEXT": - columns.add(new Column(pair.k, DataType.BINARY, pair.v, isDummy)); - break; - case "DOUBLE": - columns.add(new Column(pair.k, DataType.DOUBLE, pair.v, isDummy)); - break; - case "INT32": - columns.add(new Column(pair.k, DataType.INTEGER, pair.v, isDummy)); - break; - case "INT64": - columns.add(new Column(pair.k, DataType.LONG, pair.v, isDummy)); - break; - } - } - dataSet.close(); } while (iterator.hasNext()); } catch (IoTDBConnectionException | StatementExecutionException e) { throw new IoTDBTaskExecuteFailureException("get time series failure: ", e); From 00f1d2cb32318c21d83c6640552069d75e856482 Mon Sep 17 00:00:00 2001 From: An Qi Date: Thu, 27 Jun 2024 17:12:09 +0800 Subject: [PATCH 048/138] change default config of log and file-permission (#361) --- conf/file-permission.properties | 160 +++++++++++++++++ conf/log4j2.properties | 35 ++++ core/src/assembly/server.xml | 7 - .../main/resources/file-permission.properties | 163 +----------------- core/src/main/resources/log4j2.properties | 17 -- 5 files changed, 199 insertions(+), 183 deletions(-) create mode 100644 conf/file-permission.properties create mode 100644 conf/log4j2.properties diff --git a/conf/file-permission.properties b/conf/file-permission.properties new file mode 100644 index 0000000000..e95a5a5592 --- /dev/null +++ b/conf/file-permission.properties @@ -0,0 +1,160 @@ +# This file is used to configure the accessType of the files in IGinX. +# +# +# Configuration format: +# ===================== +# +# Note: +# +# 1. If there is conflict between key, the first one will be used. +# 2. Charset should be UTF-8. +# 3. The configuration file is in the format of `properties`. +# 4. The key-value pair is separated by `=`. +# 5. The file is case-sensitive. +# +# Variable: +# +# The value of the key can contain variables, which will be replaced by the +# real value. Including: +# +# * `${}`: get the value of this configuration file. +# * `${env:}`: get the value of the environment variable. +# * `${sys:}`: get the value of the system property. +# +# more details: +# https://commons.apache.org/proper/commons-configuration/userguide/howto_basicfeatures.html#Variable_Interpolation +# +# +# Refresh Interval: +# ================= +# +# IGinX will refresh the accessType configuration file at a regular interval. +# The refresh interval can be configured by the `refreshInterval` key. +# The value is the interval in milliseconds. The default value is 5000. +# +# +# File access rule: +# ================= +# +# The file accessType rule is used to configure the accessType of the files +# in IGinX. The rule can be configured to allow or deny the file to be +# read/write/execute. The rule can be applied to the specific user and module. +# +# Rule Format: +# +# The rule is represented by 4 configuration items with the same prefix: +# +# ..include = +# ..read = true/false +# ..write = true/false +# ..execute = true/false +# +# where: +# * `` is the user name that the rule applies to. Specific users: +# + `default` means the default user. +# - All users first match the rules of specific users, if no match, +# then match the rules of the default user. +# + `root` means the root user. +# * `` is the name of the rule. +# + The name of the rule is used to distinguish different rules. +# * `include` means the file path pattern that the rule applies to. +# + this property is required. +# * `read/write/execute` means whether file can be read/written/executed. +# + this property is optional. +# + if read not set, the rule will be ignored when checking the read. +# Write and execute are the same. +# * `` is the pattern of the absolute file path. It can be: +# - `glob:`: matches the file path with the glob pattern. +# - `regex:`: matches the file path with the regex pattern. +# more details: +# https://docs.oracle.com/javase/8/docs/api/java/nio/file/FileSystem.html#getPathMatcher-java.lang.String- +# +# Rule Name: +# +# The rule name can be any string, but it should be unique for the same user. +# The rule name is used to distinguish different rules. Different modules +# determine the subset of rules used by filter. In details: +# +# * the default module uses rules starting with "default". +# + the rules of the default module is applied to all modules. +# * the udf module uses rules starting with "udf" +# * the transform module uses rules starting with "transformer". +# * the filesystem driver uses rules starting with "filesystem". +# +# Rule Application Order: +# 1. For the same user, the rules are applied in the order of the configuration +# file. The first rule that matches the file path will be used to determine +# whether the file can be read/written/executed. +# 2. If there is no read/write/execute for specific file when checking the rule, +# try to apply the next rule. +# 3. If there is no rule that matches the file path, the default user will +# be used. +# 4. If there is no rule that matches the file path for the default user, the +# default accessType will be used. Default accessType is `true`. +# +# Example: +# +# root.defaultRule.include=glob:** +# root.defaultRule.read=true +# root.defaultRule.write=true +# root.defaultRule.execute=true +# +# default.defaultRule.include=glob:**.parquet +# default.defaultRule.read=true +# +# default.defaultRule.include=glob:** +# default.defaultRule.read=false +# default.defaultRule.write=false +# default.defaultRule.execute=false +# +# in this example: all users can read all files. Only the root user can write +# and execute all files. The other users only can read the parquet files. +# +# +# Important Note: +# ============ +# +# Only the default user is supported currently. +# --------------------------------------------- +# +# Although the configuration file supports setting different permissions for +# different users, currently only the default user is supported, and the +# configuration of other users will be ignored. +# + +# the refresh interval of the accessType configuration file in milliseconds +refreshInterval=1000 + +# match all files for root user and default module +#root.defaultRule.include=glob:** +#root.defaultRule.read=true +#root.defaultRule.write=true +#root.defaultRule.execute=true + +# match iginx internal python files for default user and udf & transform module +default.transformerRule.include=glob:${env:IGINX_HOME}${sys:file.separator}udf_funcs${sys:file.separator}**.py +default.transformerRule.read=false +default.transformerRule.write=true +default.transformerRule.execute=true +default.udfTheRule.include=${default.transformerRule.include} +default.udfTheRule.read=${default.transformerRule.read} +default.udfTheRule.write=${default.transformerRule.write} +default.udfTheRule.execute=${default.transformerRule.execute} + +# match iginx internal system files for default user and default module +default.defaultFirstRule.include=glob:${env:IGINX_HOME}${sys:file.separator}**.{jar,properties,sh,bat} +default.defaultFirstRule.read=false +default.defaultFirstRule.write=false +default.defaultFirstRule.execute=false + +# match log files for default user and default module +default.default2ndRule.include=glob:${sys:user.dir}${sys:file.separator}logs${sys:file.separator}*.{log,log.gz} +default.default2ndRule.read=true +default.default2ndRule.write=false +default.default2ndRule.execute=false + +# match all files for default user and module +default.defaultLastRule.include=glob:** +default.defaultLastRule.read=true +default.defaultLastRule.write=true +default.defaultLastRule.execute=true diff --git a/conf/log4j2.properties b/conf/log4j2.properties new file mode 100644 index 0000000000..cc24c56f20 --- /dev/null +++ b/conf/log4j2.properties @@ -0,0 +1,35 @@ +# Update log configuration from file every 30 seconds +monitorInterval=30 + +# Define Appenders +#console +appender.console.name=ConsoleAppender +appender.console.type=Console +appender.console.target=SYSTEM_ERR +appender.console.layout.type=PatternLayout +appender.console.layout.pattern=%d %highlight{%-5p} [%t] - [%C.%M:%L] %m%n%ex +#rolling-file +appender.rolling.name=RollingFileAppender +appender.rolling.type=RollingFile +appender.rolling.fileName=logs/iginx-latest.log +appender.rolling.filePattern=logs/iginx-%d{yyyy-MM-dd}-%i.log.gz +appender.rolling.layout.type=PatternLayout +appender.rolling.layout.pattern=%d %-5p [%t] - [%C.%M:%L] %m%n%ex +appender.rolling.policies.type=Policies +appender.rolling.policies.time.type=TimeBasedTriggeringPolicy +appender.rolling.policies.time.interval=1 +appender.rolling.policies.time.modulate=true +appender.rolling.policies.size.type=SizeBasedTriggeringPolicy +appender.rolling.policies.size.size=100MB +appender.rolling.policies.startup.type=OnStartupTriggeringPolicy +appender.rolling.strategy.type=DefaultRolloverStrategy +appender.rolling.strategy.max=30 + +# Define Loggers +#root +rootLogger.level=warn +rootLogger.appenderRef.console.ref=ConsoleAppender +rootLogger.appenderRef.rolling.ref=RollingFileAppender +#iginx +logger.iginx.name=cn.edu.tsinghua.iginx +logger.iginx.level=info diff --git a/core/src/assembly/server.xml b/core/src/assembly/server.xml index a767d71a02..ba310d72e9 100644 --- a/core/src/assembly/server.xml +++ b/core/src/assembly/server.xml @@ -35,13 +35,6 @@ src/assembly/resources ${file.separator} - - src/main/resources - - *.properties - - conf - ../conf/ conf diff --git a/core/src/main/resources/file-permission.properties b/core/src/main/resources/file-permission.properties index e95a5a5592..cf4aa39370 100644 --- a/core/src/main/resources/file-permission.properties +++ b/core/src/main/resources/file-permission.properties @@ -1,160 +1,5 @@ -# This file is used to configure the accessType of the files in IGinX. -# -# -# Configuration format: -# ===================== -# -# Note: -# -# 1. If there is conflict between key, the first one will be used. -# 2. Charset should be UTF-8. -# 3. The configuration file is in the format of `properties`. -# 4. The key-value pair is separated by `=`. -# 5. The file is case-sensitive. -# -# Variable: -# -# The value of the key can contain variables, which will be replaced by the -# real value. Including: -# -# * `${}`: get the value of this configuration file. -# * `${env:}`: get the value of the environment variable. -# * `${sys:}`: get the value of the system property. -# -# more details: -# https://commons.apache.org/proper/commons-configuration/userguide/howto_basicfeatures.html#Variable_Interpolation -# -# -# Refresh Interval: -# ================= -# -# IGinX will refresh the accessType configuration file at a regular interval. -# The refresh interval can be configured by the `refreshInterval` key. -# The value is the interval in milliseconds. The default value is 5000. -# -# -# File access rule: -# ================= -# -# The file accessType rule is used to configure the accessType of the files -# in IGinX. The rule can be configured to allow or deny the file to be -# read/write/execute. The rule can be applied to the specific user and module. -# -# Rule Format: -# -# The rule is represented by 4 configuration items with the same prefix: -# -# ..include = -# ..read = true/false -# ..write = true/false -# ..execute = true/false -# -# where: -# * `` is the user name that the rule applies to. Specific users: -# + `default` means the default user. -# - All users first match the rules of specific users, if no match, -# then match the rules of the default user. -# + `root` means the root user. -# * `` is the name of the rule. -# + The name of the rule is used to distinguish different rules. -# * `include` means the file path pattern that the rule applies to. -# + this property is required. -# * `read/write/execute` means whether file can be read/written/executed. -# + this property is optional. -# + if read not set, the rule will be ignored when checking the read. -# Write and execute are the same. -# * `` is the pattern of the absolute file path. It can be: -# - `glob:`: matches the file path with the glob pattern. -# - `regex:`: matches the file path with the regex pattern. -# more details: -# https://docs.oracle.com/javase/8/docs/api/java/nio/file/FileSystem.html#getPathMatcher-java.lang.String- -# -# Rule Name: -# -# The rule name can be any string, but it should be unique for the same user. -# The rule name is used to distinguish different rules. Different modules -# determine the subset of rules used by filter. In details: -# -# * the default module uses rules starting with "default". -# + the rules of the default module is applied to all modules. -# * the udf module uses rules starting with "udf" -# * the transform module uses rules starting with "transformer". -# * the filesystem driver uses rules starting with "filesystem". -# -# Rule Application Order: -# 1. For the same user, the rules are applied in the order of the configuration -# file. The first rule that matches the file path will be used to determine -# whether the file can be read/written/executed. -# 2. If there is no read/write/execute for specific file when checking the rule, -# try to apply the next rule. -# 3. If there is no rule that matches the file path, the default user will -# be used. -# 4. If there is no rule that matches the file path for the default user, the -# default accessType will be used. Default accessType is `true`. -# -# Example: -# -# root.defaultRule.include=glob:** -# root.defaultRule.read=true -# root.defaultRule.write=true -# root.defaultRule.execute=true -# -# default.defaultRule.include=glob:**.parquet -# default.defaultRule.read=true -# -# default.defaultRule.include=glob:** -# default.defaultRule.read=false -# default.defaultRule.write=false -# default.defaultRule.execute=false -# -# in this example: all users can read all files. Only the root user can write -# and execute all files. The other users only can read the parquet files. -# -# -# Important Note: -# ============ -# -# Only the default user is supported currently. -# --------------------------------------------- -# -# Although the configuration file supports setting different permissions for -# different users, currently only the default user is supported, and the -# configuration of other users will be ignored. -# - -# the refresh interval of the accessType configuration file in milliseconds refreshInterval=1000 - -# match all files for root user and default module -#root.defaultRule.include=glob:** -#root.defaultRule.read=true -#root.defaultRule.write=true -#root.defaultRule.execute=true - -# match iginx internal python files for default user and udf & transform module -default.transformerRule.include=glob:${env:IGINX_HOME}${sys:file.separator}udf_funcs${sys:file.separator}**.py -default.transformerRule.read=false -default.transformerRule.write=true -default.transformerRule.execute=true -default.udfTheRule.include=${default.transformerRule.include} -default.udfTheRule.read=${default.transformerRule.read} -default.udfTheRule.write=${default.transformerRule.write} -default.udfTheRule.execute=${default.transformerRule.execute} - -# match iginx internal system files for default user and default module -default.defaultFirstRule.include=glob:${env:IGINX_HOME}${sys:file.separator}**.{jar,properties,sh,bat} -default.defaultFirstRule.read=false -default.defaultFirstRule.write=false -default.defaultFirstRule.execute=false - -# match log files for default user and default module -default.default2ndRule.include=glob:${sys:user.dir}${sys:file.separator}logs${sys:file.separator}*.{log,log.gz} -default.default2ndRule.read=true -default.default2ndRule.write=false -default.default2ndRule.execute=false - -# match all files for default user and module -default.defaultLastRule.include=glob:** -default.defaultLastRule.read=true -default.defaultLastRule.write=true -default.defaultLastRule.execute=true +default.defaultRule.include=glob:** +default.defaultRule.read=true +default.defaultRule.write=true +default.defaultRule.execute=true \ No newline at end of file diff --git a/core/src/main/resources/log4j2.properties b/core/src/main/resources/log4j2.properties index cc24c56f20..96207b646b 100644 --- a/core/src/main/resources/log4j2.properties +++ b/core/src/main/resources/log4j2.properties @@ -8,28 +8,11 @@ appender.console.type=Console appender.console.target=SYSTEM_ERR appender.console.layout.type=PatternLayout appender.console.layout.pattern=%d %highlight{%-5p} [%t] - [%C.%M:%L] %m%n%ex -#rolling-file -appender.rolling.name=RollingFileAppender -appender.rolling.type=RollingFile -appender.rolling.fileName=logs/iginx-latest.log -appender.rolling.filePattern=logs/iginx-%d{yyyy-MM-dd}-%i.log.gz -appender.rolling.layout.type=PatternLayout -appender.rolling.layout.pattern=%d %-5p [%t] - [%C.%M:%L] %m%n%ex -appender.rolling.policies.type=Policies -appender.rolling.policies.time.type=TimeBasedTriggeringPolicy -appender.rolling.policies.time.interval=1 -appender.rolling.policies.time.modulate=true -appender.rolling.policies.size.type=SizeBasedTriggeringPolicy -appender.rolling.policies.size.size=100MB -appender.rolling.policies.startup.type=OnStartupTriggeringPolicy -appender.rolling.strategy.type=DefaultRolloverStrategy -appender.rolling.strategy.max=30 # Define Loggers #root rootLogger.level=warn rootLogger.appenderRef.console.ref=ConsoleAppender -rootLogger.appenderRef.rolling.ref=RollingFileAppender #iginx logger.iginx.name=cn.edu.tsinghua.iginx logger.iginx.level=info From 65845d46071007a26f88979f9c06dfdc132b8542 Mon Sep 17 00:00:00 2001 From: ZM <12236590+shinyano@users.noreply.github.com> Date: Thu, 27 Jun 2024 17:13:09 +0800 Subject: [PATCH 049/138] feat(python): allow inserting dataframe (#357) User can use Session.insert_df(df: dataframe, prefix: str) to insert pandas.DataFrame data into IGinX. df: DataFrame data prefix(optional): if column names in df does not contain '.', a prefix is required. --- .github/actions/service/mysql/action.yml | 9 +++ session_py/iginx/iginx_pyclient/dataset.py | 79 ++++++++++++++++++- session_py/iginx/iginx_pyclient/session.py | 14 +++- .../iginx/iginx_pyclient/utils/byte_utils.py | 2 +- .../integration/func/session/PySessionIT.java | 30 ++++++- test/src/test/resources/pySessionIT/tests.py | 29 +++++++ 6 files changed, 159 insertions(+), 4 deletions(-) diff --git a/.github/actions/service/mysql/action.yml b/.github/actions/service/mysql/action.yml index 56f3c73c3a..da88544ba1 100644 --- a/.github/actions/service/mysql/action.yml +++ b/.github/actions/service/mysql/action.yml @@ -25,6 +25,15 @@ runs: echo "mysqlx = 0" >> $port.ini done + - if: runner.os == 'Windows' || runner.os == 'macOS' + name: Set Case Sensitivity + shell: bash + working-directory: ${{ github.action_path }} + run: | + for port in ${{ inputs.ports }}; do + echo "lower_case_table_names = 2" >> $port.ini + done + - name: Start mysql shell: bash working-directory: ${{ github.action_path }} diff --git a/session_py/iginx/iginx_pyclient/dataset.py b/session_py/iginx/iginx_pyclient/dataset.py index 11879a7c16..4ca6224caf 100644 --- a/session_py/iginx/iginx_pyclient/dataset.py +++ b/session_py/iginx/iginx_pyclient/dataset.py @@ -22,6 +22,84 @@ from .thrift.rpc.ttypes import SqlType, AggregateType, ExecuteSqlResp from .utils.bitmap import Bitmap from .utils.byte_utils import get_long_array, get_values_by_data_type, BytesParser +from .thrift.rpc.ttypes import DataType + +def map_dtype(dtype): + if pd.api.types.is_bool_dtype(dtype): + return DataType.BOOLEAN + elif pd.api.types.is_integer_dtype(dtype): + if dtype == 'int32': + return DataType.INTEGER + else: + return DataType.LONG + elif pd.api.types.is_float_dtype(dtype): + if dtype == 'float32': + return DataType.FLOAT + else: + return DataType.DOUBLE + elif pd.api.types.is_numeric_dtype(dtype): + return DataType.DOUBLE + else: + return DataType.BINARY # all other types are treated as BINARY + +# TODO: process NA values +def column_dataset_from_df(df: pd.DataFrame, prefix: str = ""): + # if no prefix is provided, the column names must contain at least one '.' except key. + column_list = df.columns.tolist() + if prefix == "": + for col in column_list: + if '.' not in col and col != 'key': + raise RuntimeError(f"The paths in data must contain '.' or prefix must be set") + else: + prefix = prefix + '.' + + if 'key' in column_list: + # examine key type + key_dtype = df['key'].dtype + valid_key = False + if key_dtype == 'int64': + valid_key = True + elif pd.api.types.is_integer_dtype(key_dtype): + df['key'] = df['key'].astype('int64') + valid_key = True + + if not valid_key: + raise RuntimeError(f"Invalid key type is provided. Required long/int but was %s.", df['key'].dtype) + key_list = df['key'].tolist() + df = df.drop(columns=['key']) + # if there is no key column in data, creat one + else: + key_list = list(range(len(df))) + + mapped_types = [map_dtype(dtype) for col, dtype in df.dtypes.items()] + values_list = [df[col].tolist() for col in df.columns] + column_list = [prefix + col for col in df.columns.tolist()] + return ColumnDataSet(column_list, mapped_types, key_list, values_list) + + +class ColumnDataSet(object): + def __init__(self, paths, types, keys, values_list): + self.__paths = paths + self.__types = types + self.__keys = keys + self.__values_list = values_list + + def get_insert_args(self): + return self.__paths, self.__keys, self.__values_list, self.__types + + def __str__(self): + column_names = ['key'] + self.__paths + num_rows = len(self.__keys) + columns = [self.__keys] + self.__values_list + output = [] + + output.append('\t'.join(column_names)) + + for i in range(num_rows): + row = [str(columns[j][i]) for j in range(len(columns))] + output.append('\t'.join(row)) + + return '\n'.join(output) class Point(object): @@ -100,7 +178,6 @@ def __str__(self): def to_df(self): has_key = self.__timestamps != [] - print(has_key) columns = ["key"] if has_key else [] for column in self.__paths: columns.append(str(column)) diff --git a/session_py/iginx/iginx_pyclient/session.py b/session_py/iginx/iginx_pyclient/session.py index 1a812f5519..175375d638 100644 --- a/session_py/iginx/iginx_pyclient/session.py +++ b/session_py/iginx/iginx_pyclient/session.py @@ -20,12 +20,13 @@ import os.path from datetime import datetime +import pandas as pd from thrift.protocol import TBinaryProtocol from thrift.transport import TSocket, TTransport from pathlib import Path from .cluster_info import ClusterInfo -from .dataset import QueryDataSet, AggregateQueryDataSet, StatementExecuteDataSet +from .dataset import column_dataset_from_df, QueryDataSet, AggregateQueryDataSet, StatementExecuteDataSet from .thrift.rpc.IService import Client from .thrift.rpc.ttypes import ( OpenSessionReq, @@ -405,6 +406,17 @@ def insert_non_aligned_column_records(self, paths, timestamps, values_list, data status = self.__client.insertNonAlignedColumnRecords(req) Session.verify_status(status) + def insert_df(self, df: pd.DataFrame, prefix: str = ""): + """ + insert dataframe data into IGinX + :param df: dataframe that contains data + :param prefix: (optional) path names in IGinX + must contain '.'. If columns in dataframe does not meet the requirement, a prefix can be used + """ + dataset = column_dataset_from_df(df, prefix) + paths, keys, value_list, type_list = dataset.get_insert_args() + self.insert_column_records(paths, keys, value_list, type_list) + def query(self, paths, start_time, end_time, timePrecision=None): req = QueryDataReq(sessionId=self.__session_id, paths=Session.merge_and_sort_paths(paths), startKey=start_time, endKey=end_time, timePrecision=timePrecision) diff --git a/session_py/iginx/iginx_pyclient/utils/byte_utils.py b/session_py/iginx/iginx_pyclient/utils/byte_utils.py index 9010056693..b083433380 100644 --- a/session_py/iginx/iginx_pyclient/utils/byte_utils.py +++ b/session_py/iginx/iginx_pyclient/utils/byte_utils.py @@ -190,7 +190,7 @@ def next(self, type): else: raise RuntimeError("unknown data type " + type) - def get_bytes_from_types(self, types, bitmap : Bitmap): + def get_bytes_from_types(self, types, bitmap: Bitmap): bytes_value = [] i = -1 for type in types: diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/PySessionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/PySessionIT.java index 8b8883b258..ca36b5cd24 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/PySessionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/PySessionIT.java @@ -46,7 +46,7 @@ public class PySessionIT { protected static String defaultTestPass = "root"; private static final Config config = ConfigDescriptor.getInstance().getConfig(); - private static String pythonCMD = "python"; + private static final String pythonCMD = config.getPythonCMD(); private static boolean isAbleToDelete = true; private static PythonInterpreter interpreter; @@ -375,6 +375,34 @@ public void testInsert() { assertEquals(expected, result); } + @Test + public void testInsertDF() { + String result = ""; + try { + logger.info("insert dataframe"); + result = runPythonScript("insertDF"); + logger.info(result); + } catch (IOException | InterruptedException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + // 检查Python脚本的输出是否符合预期 + String expected = + " key dftestdata.value1 dftestdata.value2 dftestdata.value3 dftestdata.value4\n" + + " 10 b'A' 1.1 b'B' 2.2\n" + + " 11 b'A' 1.1 b'B' 2.2\n" + + " 12 b'A' 1.1 b'B' 2.2\n" + + " 13 b'A' 1.1 b'B' 2.2\n" + + " 14 b'A' 1.1 b'B' 2.2\n" + + " 15 b'A' 1.1 b'B' 2.2\n" + + " 16 b'A' 1.1 b'B' 2.2\n" + + " 17 b'A' 1.1 b'B' 2.2\n" + + " 18 b'A' 1.1 b'B' 2.2\n" + + " 19 b'A' 1.1 b'B' 2.2\n"; + + assertEquals(expected, result); + } + @Test public void testDeleteRow() { if (!isAbleToDelete) { diff --git a/test/src/test/resources/pySessionIT/tests.py b/test/src/test/resources/pySessionIT/tests.py index 62efdb6bfd..caca95074b 100644 --- a/test/src/test/resources/pySessionIT/tests.py +++ b/test/src/test/resources/pySessionIT/tests.py @@ -395,6 +395,35 @@ def insertBaseDataset(self): return "" + def insertDF(self): + try: + import pandas as pd + data = { + 'key': list(range(10, 20)), + 'value1': ['A']*10, + 'value2': [1.1]*10 + } + + df = pd.DataFrame(data) + self.session.insert_df(df, "dftestdata") + data = { + 'key': list(range(10, 20)), + 'dftestdata.value3': ['B']*10, + 'dftestdata.value4': [2.2]*10 + } + + df = pd.DataFrame(data) + self.session.insert_df(df) + + dataset = self.session.query(["dftestdata.*"], 0, 1000) + pd.set_option('display.max_columns', None) + pd.set_option('display.max_rows', None) + retStr = dataset.to_df().to_string(index=False) + "\n" + return retStr + except Exception as e: + print(e) + exit(1) + def lastQuery(self): retStr = "" # 获取部分序列的最后一个数据点 From bdcf1fbe3e03b34808febc8fecb4a4524961aef3 Mon Sep 17 00:00:00 2001 From: shinyano <12236590+shinyano@users.noreply.github.com> Date: Fri, 28 Jun 2024 16:50:14 +0800 Subject: [PATCH 050/138] remove unused code --- .../tsinghua/iginx/influxdb/InfluxDBStorage.java | 16 ---------------- .../iginx/relational/RelationalStorage.java | 12 ------------ 2 files changed, 28 deletions(-) diff --git a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java index 38bfcd672b..0c91943fa2 100644 --- a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java +++ b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java @@ -343,10 +343,6 @@ public List getColumns(Set patterns, TagFilter tagFilter) { if (isDummy && !isUnit) { path = bucket.getName() + "." + path; } - // get columns by pattern - if (!isPathMatchPattern(path, patterns)) { - continue; - } // get columns by tag filter if (tagFilter != null && !TagKVUtils.match(tag, tagFilter)) { continue; @@ -384,18 +380,6 @@ public List getColumns(Set patterns, TagFilter tagFilter) { return timeseries; } - boolean isPathMatchPattern(String path, Set pattern) { - if (pattern == null || pattern.isEmpty()) { - return true; - } - for (String pathRegex : pattern) { - if (Pattern.matches(StringUtils.reformatPath(pathRegex), path)) { - return true; - } - } - return false; - } - @Override public void release() throws PhysicalException { client.close(); diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java index bcef47b68e..7eefd19c63 100644 --- a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java +++ b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java @@ -448,18 +448,6 @@ public List getColumns(Set patterns, TagFilter tagFilter) return columns; } - boolean isPathMatchPattern(String path, Set pattern) { - if (pattern == null || pattern.isEmpty()) { - return true; - } - for (String pathRegex : pattern) { - if (Pattern.matches(StringUtils.reformatPath(pathRegex), path)) { - return true; - } - } - return false; - } - @Override public TaskExecuteResult executeProject(Project project, DataArea dataArea) { KeyInterval keyInterval = dataArea.getKeyInterval(); From 193b1a2347f4f3194dc683636cbc3fa0ce16010c Mon Sep 17 00:00:00 2001 From: Yuqing Zhu Date: Sat, 29 Jun 2024 13:15:31 +0800 Subject: [PATCH 051/138] style: license changed from Apache 2.0 to GPL-3.0 (#365) * Update LICENSE from Apache 2.0 to GPL-3.0 * replacing apache 2.0 with GPL-3.0 * update copyright header for py, bat, and sh files * update copyright header for java and py files * update copyright in shell files * update copyright declaration in bat files * update license in thrift and antlr files * update the license badge in README --- .github/actions/dbLog/dbLog.sh | 18 + .../dataSources/filesystem_linux_windows.sh | 18 + .../scripts/dataSources/filesystem_macos.sh | 18 + .github/scripts/dataSources/influxdb.sh | 18 + .github/scripts/dataSources/influxdb_macos.sh | 18 + .../scripts/dataSources/influxdb_windows.sh | 18 + .github/scripts/dataSources/iotdb12.sh | 18 + .github/scripts/dataSources/iotdb12_macos.sh | 18 + .../scripts/dataSources/iotdb12_windows.sh | 18 + .../dataSources/mix_iotdb12_influxdb.sh | 18 + .../dataSources/mix_iotdb12_influxdb_macos.sh | 18 + .../mix_iotdb12_influxdb_windows.sh | 18 + .../dataSources/parquet_linux_windows.sh | 18 + .github/scripts/dataSources/parquet_macos.sh | 18 + .github/scripts/iginx/iginx.sh | 18 + .github/scripts/iginx/iginx_kill.sh | 18 + .github/scripts/iginx/iginx_macos.sh | 18 + .github/scripts/iginx/iginx_udf_path.sh | 18 + .github/scripts/iginx/iginx_windows.sh | 18 + .github/scripts/test/cli/test_infile.sh | 18 + .github/scripts/test/cli/test_infile_macos.sh | 18 + .../scripts/test/cli/test_infile_windows.sh | 18 + .github/scripts/test/cli/test_outfile.sh | 18 + .../scripts/test/cli/test_outfile_macos.sh | 18 + .../scripts/test/cli/test_outfile_windows.sh | 18 + .github/scripts/test/cli/test_py_register.sh | 18 + .../test/cli/test_py_register_macos.sh | 18 + .../test/cli/test_py_register_windows.sh | 18 + .github/scripts/test/cli/test_remote_udf.sh | 18 + .../scripts/test/cli/test_remote_udf_macos.sh | 18 + .../test/cli/test_remote_udf_windows.sh | 18 + .github/scripts/test/test_union.sh | 18 + LICENSE | 875 ++++++++++++++---- README.md | 2 +- .../antlr4/cn/edu/tsinghua/iginx/sql/Sql.g4 | 17 + .../resources/fast-deploy/clearAllData.bat | 17 + .../resources/fast-deploy/clearAllData.sh | 18 + .../resources/fast-deploy/runIGinXOn1Host.bat | 17 + .../resources/fast-deploy/runIGinXOn1Host.sh | 18 + .../fast-deploy/runIGinXOn1HostWithPemjax.bat | 17 + .../fast-deploy/runIGinXOn1HostWithPemjax.sh | 18 + .../resources/fast-deploy/stopIGinX.bat | 17 + .../resources/fast-deploy/stopIGinX.sh | 18 + .../src/assembly/resources/sbin/start_cli.bat | 28 +- .../src/assembly/resources/sbin/start_cli.sh | 45 +- .../tsinghua/iginx/client/IginxClient.java | 27 +- .../client/exception/ClientException.java | 27 +- .../assembly/resources/sbin/start_iginx.bat | 28 +- .../assembly/resources/sbin/start_iginx.sh | 27 +- .../java/cn/edu/tsinghua/iginx/Iginx.java | 27 +- .../cn/edu/tsinghua/iginx/IginxWorker.java | 27 +- .../iginx/auth/FilePermissionManager.java | 18 + .../tsinghua/iginx/auth/SessionManager.java | 27 +- .../edu/tsinghua/iginx/auth/UserManager.java | 27 +- .../iginx/auth/entity/FileAccessType.java | 18 + .../utils/FilePermissionRuleNameFilters.java | 18 + .../tsinghua/iginx/compaction/Compaction.java | 18 + .../iginx/compaction/CompactionManager.java | 18 + .../FragmentDeletionCompaction.java | 18 + .../iginx/compaction/InstantCompaction.java | 18 + .../LowAccessFragmentCompaction.java | 18 + .../LowWriteFragmentCompaction.java | 18 + .../cn/edu/tsinghua/iginx/conf/Config.java | 27 +- .../tsinghua/iginx/conf/ConfigDescriptor.java | 27 +- .../cn/edu/tsinghua/iginx/conf/Constants.java | 27 +- .../iginx/conf/FilePermissionConfig.java | 18 + .../cn/edu/tsinghua/iginx/conf/FileUtils.java | 18 + .../conf/entity/FilePermissionDescriptor.java | 18 + .../conf/parser/FilePermissionsParser.java | 18 + .../tsinghua/iginx/engine/ContextBuilder.java | 18 + .../iginx/engine/StatementBuilder.java | 18 + .../iginx/engine/StatementExecutor.java | 18 + .../logical/constraint/ConstraintChecker.java | 18 + .../constraint/ConstraintCheckerManager.java | 18 + .../constraint/NaiveConstraintChecker.java | 18 + .../logical/generator/AbstractGenerator.java | 18 + .../logical/generator/DeleteGenerator.java | 18 + .../logical/generator/GeneratorType.java | 18 + .../logical/generator/InsertGenerator.java | 18 + .../logical/generator/LogicalGenerator.java | 18 + .../logical/generator/QueryGenerator.java | 18 + .../generator/ShowColumnsGenerator.java | 18 + .../logical/optimizer/IRuleCollection.java | 18 + .../optimizer/LogicalOptimizerManager.java | 18 + .../engine/logical/optimizer/Optimizer.java | 18 + .../logical/utils/LogicalFilterUtils.java | 18 + .../iginx/engine/logical/utils/MetaUtils.java | 18 + .../engine/logical/utils/OperatorUtils.java | 18 + .../iginx/engine/logical/utils/PathUtils.java | 18 + .../iginx/engine/physical/PhysicalEngine.java | 27 +- .../engine/physical/PhysicalEngineImpl.java | 27 +- .../InvalidOperatorParameterException.java | 27 +- .../NonExecutablePhysicalTaskException.java | 27 +- .../exception/NonExistedStorageException.java | 27 +- .../NotSupportedOperatorException.java | 27 +- .../physical/exception/PhysicalException.java | 27 +- .../exception/PhysicalRuntimeException.java | 22 +- .../PhysicalTaskExecuteFailureException.java | 27 +- .../physical/exception/RowFetchException.java | 27 +- .../StorageInitializationException.java | 27 +- .../TooManyPhysicalTasksException.java | 27 +- .../UnexpectedOperatorException.java | 27 +- .../UnimplementedOperatorException.java | 27 +- .../memory/MemoryPhysicalTaskDispatcher.java | 27 +- .../execute/OperatorMemoryExecutor.java | 27 +- .../OperatorMemoryExecutorFactory.java | 27 +- .../engine/physical/memory/execute/Table.java | 27 +- .../naive/NaiveOperatorMemoryExecutor.java | 27 +- .../stream/AddSchemaPrefixLazyStream.java | 18 + .../execute/stream/BinaryLazyStream.java | 27 +- .../execute/stream/CrossJoinLazyStream.java | 18 + .../execute/stream/DistinctLazyStream.java | 18 + .../execute/stream/DownsampleLazyStream.java | 27 +- .../memory/execute/stream/EmptyRowStream.java | 27 +- .../execute/stream/ExceptLazyStream.java | 18 + .../execute/stream/GroupByLazyStream.java | 18 + .../stream/HashInnerJoinLazyStream.java | 18 + .../stream/HashMarkJoinLazyStream.java | 18 + .../stream/HashOuterJoinLazyStream.java | 18 + .../stream/HashSingleJoinLazyStream.java | 18 + .../execute/stream/IntersectLazyStream.java | 18 + .../memory/execute/stream/JoinLazyStream.java | 27 +- .../execute/stream/LimitLazyStream.java | 27 +- .../stream/MappingTransformLazyStream.java | 27 +- .../stream/NestedLoopInnerJoinLazyStream.java | 18 + .../stream/NestedLoopMarkJoinLazyStream.java | 18 + .../stream/NestedLoopOuterJoinLazyStream.java | 18 + .../NestedLoopSingleJoinLazyStream.java | 18 + .../execute/stream/PathUnionLazyStream.java | 27 +- .../execute/stream/ProjectLazyStream.java | 27 +- .../execute/stream/RenameLazyStream.java | 18 + .../execute/stream/ReorderLazyStream.java | 18 + .../stream/RowTransformLazyStream.java | 27 +- .../execute/stream/SelectLazyStream.java | 27 +- .../stream/SetTransformLazyStream.java | 27 +- .../memory/execute/stream/SortLazyStream.java | 27 +- .../SortedMergeInnerJoinLazyStream.java | 18 + .../SortedMergeOuterJoinLazyStream.java | 18 + .../stream/StreamOperatorMemoryExecutor.java | 27 +- .../execute/stream/UnaryLazyStream.java | 27 +- .../execute/stream/UnionAllLazyStream.java | 18 + .../stream/UnionDistinctLazyStream.java | 18 + .../stream/ValueToSelectedPathLazyStream.java | 18 + .../memory/execute/utils/ExprUtils.java | 18 + .../memory/execute/utils/FilterUtils.java | 27 +- .../memory/execute/utils/GroupByKey.java | 18 + .../memory/execute/utils/HeaderUtils.java | 18 + .../memory/execute/utils/RowUtils.java | 27 +- .../memory/queue/MemoryPhysicalTaskQueue.java | 27 +- .../queue/MemoryPhysicalTaskQueueImpl.java | 27 +- .../physical/optimizer/PhysicalOptimizer.java | 27 +- .../optimizer/PhysicalOptimizerManager.java | 27 +- .../physical/optimizer/ReplicaDispatcher.java | 27 +- .../engine/physical/storage/IStorage.java | 27 +- .../storage/StorageEngineClassLoader.java | 27 +- .../physical/storage/StorageManager.java | 27 +- .../physical/storage/domain/Column.java | 27 +- .../physical/storage/domain/ColumnKey.java | 18 + .../physical/storage/domain/DataArea.java | 18 + .../execute/StoragePhysicalTaskExecutor.java | 27 +- .../queue/StoragePhysicalTaskQueue.java | 27 +- .../storage/utils/ColumnKeyTranslator.java | 18 + .../physical/storage/utils/TagKVUtils.java | 18 + .../physical/task/AbstractPhysicalTask.java | 27 +- .../task/BinaryMemoryPhysicalTask.java | 27 +- .../task/CompletedFoldedPhysicalTask.java | 18 + .../task/FoldedMemoryPhysicalTask.java | 18 + .../physical/task/GlobalPhysicalTask.java | 27 +- .../engine/physical/task/Measurable.java | 18 + .../physical/task/MemoryPhysicalTask.java | 27 +- .../task/MultipleMemoryPhysicalTask.java | 18 + .../engine/physical/task/PhysicalTask.java | 27 +- .../physical/task/StoragePhysicalTask.java | 27 +- .../physical/task/TaskExecuteResult.java | 27 +- .../iginx/engine/physical/task/TaskType.java | 27 +- .../task/UnaryMemoryPhysicalTask.java | 18 + .../engine/physical/task/utils/TaskUtils.java | 18 + .../task/visitor/TaskInfoVisitor.java | 18 + .../physical/task/visitor/TaskVisitor.java | 18 + .../iginx/engine/shared/Constants.java | 27 +- .../iginx/engine/shared/KeyRange.java | 27 +- .../iginx/engine/shared/RequestContext.java | 18 + .../tsinghua/iginx/engine/shared/Result.java | 18 + .../shared/constraint/ConstraintManager.java | 27 +- .../engine/shared/data/ExecuteDetail.java | 18 + .../iginx/engine/shared/data/Value.java | 27 +- .../data/read/ClearEmptyRowStreamWrapper.java | 27 +- .../iginx/engine/shared/data/read/Field.java | 27 +- .../data/read/FilterRowStreamWrapper.java | 22 +- .../iginx/engine/shared/data/read/Header.java | 27 +- .../data/read/MergeFieldRowStreamWrapper.java | 18 + .../data/read/MergeTimeRowStreamWrapper.java | 18 + .../iginx/engine/shared/data/read/Row.java | 27 +- .../engine/shared/data/read/RowStream.java | 27 +- .../shared/data/read/RowStreamWrapper.java | 27 +- .../engine/shared/data/write/BitmapView.java | 27 +- .../shared/data/write/ColumnDataView.java | 27 +- .../engine/shared/data/write/DataView.java | 27 +- .../engine/shared/data/write/RawData.java | 18 + .../engine/shared/data/write/RawDataType.java | 18 + .../engine/shared/data/write/RowDataView.java | 27 +- .../StatementExecutionException.java | 27 +- .../engine/shared/expr/BaseExpression.java | 18 + .../engine/shared/expr/BinaryExpression.java | 18 + .../engine/shared/expr/BracketExpression.java | 18 + .../shared/expr/ConstantExpression.java | 18 + .../iginx/engine/shared/expr/Expression.java | 18 + .../engine/shared/expr/ExpressionVisitor.java | 18 + .../shared/expr/FromValueExpression.java | 18 + .../engine/shared/expr/FuncExpression.java | 18 + .../shared/expr/MultipleExpression.java | 18 + .../iginx/engine/shared/expr/Operator.java | 18 + .../engine/shared/expr/UnaryExpression.java | 18 + .../iginx/engine/shared/file/CSVFile.java | 18 + .../iginx/engine/shared/file/FileType.java | 18 + .../engine/shared/file/read/ImportCsv.java | 18 + .../engine/shared/file/read/ImportFile.java | 18 + .../shared/file/write/ExportByteStream.java | 18 + .../engine/shared/file/write/ExportCsv.java | 18 + .../engine/shared/file/write/ExportFile.java | 18 + .../engine/shared/function/Function.java | 27 +- .../engine/shared/function/FunctionCall.java | 27 +- .../shared/function/FunctionParams.java | 18 + .../engine/shared/function/FunctionType.java | 27 +- .../engine/shared/function/FunctionUtils.java | 18 + .../shared/function/MappingFunction.java | 27 +- .../engine/shared/function/MappingType.java | 27 +- .../shared/function/RowMappingFunction.java | 27 +- .../shared/function/SetMappingFunction.java | 27 +- .../function/manager/FunctionManager.java | 27 +- .../function/system/ArithmeticExpr.java | 18 + .../engine/shared/function/system/Avg.java | 27 +- .../engine/shared/function/system/Count.java | 27 +- .../engine/shared/function/system/First.java | 27 +- .../shared/function/system/FirstValue.java | 27 +- .../engine/shared/function/system/Last.java | 27 +- .../shared/function/system/LastValue.java | 27 +- .../engine/shared/function/system/Max.java | 27 +- .../engine/shared/function/system/Min.java | 27 +- .../engine/shared/function/system/Ratio.java | 18 + .../engine/shared/function/system/Sum.java | 27 +- .../function/system/utils/GroupByUtils.java | 27 +- .../function/system/utils/ValueUtils.java | 27 +- .../engine/shared/function/udf/UDAF.java | 18 + .../engine/shared/function/udf/UDSF.java | 18 + .../engine/shared/function/udf/UDTF.java | 18 + .../shared/function/udf/python/PyUDAF.java | 18 + .../shared/function/udf/python/PyUDSF.java | 18 + .../shared/function/udf/python/PyUDTF.java | 18 + .../shared/function/udf/utils/CheckUtils.java | 18 + .../shared/function/udf/utils/DataUtils.java | 18 + .../shared/function/udf/utils/RowUtils.java | 18 + .../operator/AbstractBinaryOperator.java | 27 +- .../engine/shared/operator/AbstractJoin.java | 18 + .../operator/AbstractMultipleOperator.java | 18 + .../shared/operator/AbstractOperator.java | 27 +- .../operator/AbstractUnaryOperator.java | 27 +- .../shared/operator/AddSchemaPrefix.java | 18 + .../shared/operator/BinaryOperator.java | 27 +- .../shared/operator/CombineNonQuery.java | 18 + .../engine/shared/operator/CrossJoin.java | 18 + .../iginx/engine/shared/operator/Delete.java | 18 + .../engine/shared/operator/Distinct.java | 18 + .../engine/shared/operator/Downsample.java | 27 +- .../iginx/engine/shared/operator/Except.java | 18 + .../shared/operator/FoldedOperator.java | 18 + .../iginx/engine/shared/operator/GroupBy.java | 18 + .../engine/shared/operator/InnerJoin.java | 18 + .../iginx/engine/shared/operator/Insert.java | 18 + .../engine/shared/operator/Intersect.java | 18 + .../iginx/engine/shared/operator/Join.java | 27 +- .../iginx/engine/shared/operator/Limit.java | 27 +- .../shared/operator/MappingTransform.java | 27 +- .../engine/shared/operator/MarkJoin.java | 18 + .../engine/shared/operator/Migration.java | 18 + .../shared/operator/MultipleOperator.java | 18 + .../engine/shared/operator/Operator.java | 27 +- .../engine/shared/operator/OuterJoin.java | 18 + .../engine/shared/operator/PathUnion.java | 27 +- .../iginx/engine/shared/operator/Project.java | 18 + .../operator/ProjectWaitingForPath.java | 18 + .../iginx/engine/shared/operator/Rename.java | 18 + .../iginx/engine/shared/operator/Reorder.java | 18 + .../engine/shared/operator/RowTransform.java | 27 +- .../iginx/engine/shared/operator/Select.java | 18 + .../engine/shared/operator/SetTransform.java | 27 +- .../engine/shared/operator/ShowColumns.java | 18 + .../engine/shared/operator/SingleJoin.java | 18 + .../iginx/engine/shared/operator/Sort.java | 27 +- .../engine/shared/operator/UnaryOperator.java | 27 +- .../iginx/engine/shared/operator/Union.java | 18 + .../shared/operator/ValueToSelectedPath.java | 18 + .../shared/operator/filter/AndFilter.java | 27 +- .../shared/operator/filter/BoolFilter.java | 18 + .../shared/operator/filter/ExprFilter.java | 18 + .../engine/shared/operator/filter/Filter.java | 27 +- .../shared/operator/filter/FilterType.java | 27 +- .../shared/operator/filter/FilterVisitor.java | 18 + .../shared/operator/filter/KeyFilter.java | 27 +- .../shared/operator/filter/NotFilter.java | 27 +- .../engine/shared/operator/filter/Op.java | 27 +- .../shared/operator/filter/OrFilter.java | 27 +- .../shared/operator/filter/PathFilter.java | 18 + .../shared/operator/filter/ValueFilter.java | 27 +- .../shared/operator/tag/AndTagFilter.java | 27 +- .../operator/tag/BasePreciseTagFilter.java | 18 + .../shared/operator/tag/BaseTagFilter.java | 27 +- .../shared/operator/tag/OrTagFilter.java | 27 +- .../shared/operator/tag/PreciseTagFilter.java | 18 + .../engine/shared/operator/tag/TagFilter.java | 27 +- .../shared/operator/tag/TagFilterType.java | 27 +- .../shared/operator/tag/WithoutTagFilter.java | 18 + .../engine/shared/operator/type/FuncType.java | 18 + .../shared/operator/type/JoinAlgType.java | 18 + .../shared/operator/type/OperatorType.java | 27 +- .../shared/operator/type/OuterJoinType.java | 18 + .../visitor/DeepFirstQueueVisitor.java | 18 + .../shared/operator/visitor/IndexVisitor.java | 18 + .../operator/visitor/OperatorInfoVisitor.java | 18 + .../operator/visitor/OperatorVisitor.java | 18 + .../operator/visitor/TreeInfoVisitor.java | 18 + .../processor/PostExecuteProcessor.java | 18 + .../processor/PostLogicalProcessor.java | 18 + .../shared/processor/PostParseProcessor.java | 18 + .../processor/PostPhysicalProcessor.java | 18 + .../shared/processor/PreExecuteProcessor.java | 18 + .../shared/processor/PreLogicalProcessor.java | 18 + .../shared/processor/PreParseProcessor.java | 18 + .../processor/PrePhysicalProcessor.java | 18 + .../engine/shared/processor/Processor.java | 18 + .../engine/shared/source/AbstractSource.java | 27 +- .../engine/shared/source/EmptySource.java | 18 + .../engine/shared/source/FragmentSource.java | 27 +- .../engine/shared/source/GlobalSource.java | 18 + .../engine/shared/source/OperatorSource.java | 27 +- .../iginx/engine/shared/source/Source.java | 27 +- .../engine/shared/source/SourceType.java | 27 +- .../iginx/exception/IginxException.java | 27 +- .../iginx/metadata/DefaultMetaManager.java | 27 +- .../tsinghua/iginx/metadata/IMetaManager.java | 27 +- .../iginx/metadata/MetaManagerMock.java | 18 + .../iginx/metadata/MetaManagerWrapper.java | 18 + .../metadata/cache/DefaultMetaCache.java | 27 +- .../iginx/metadata/cache/IMetaCache.java | 27 +- .../metadata/entity/ColumnsInterval.java | 27 +- .../iginx/metadata/entity/FragmentMeta.java | 54 +- .../iginx/metadata/entity/IginxMeta.java | 27 +- .../iginx/metadata/entity/KeyInterval.java | 27 +- .../metadata/entity/StorageEngineMeta.java | 27 +- .../metadata/entity/StorageUnitMeta.java | 27 +- .../metadata/entity/TransformTaskMeta.java | 18 + .../iginx/metadata/entity/UserMeta.java | 27 +- .../exception/MetaStorageException.java | 27 +- .../hook/EnableMonitorChangeHook.java | 27 +- .../metadata/hook/FragmentChangeHook.java | 27 +- .../iginx/metadata/hook/IginxChangeHook.java | 27 +- .../MaxActiveEndKeyStatisticsChangeHook.java | 27 +- .../hook/ReshardCounterChangeHook.java | 27 +- .../hook/ReshardStatusChangeHook.java | 27 +- .../hook/SchemaMappingChangeHook.java | 27 +- .../metadata/hook/StorageChangeHook.java | 27 +- .../hook/StorageEngineChangeHook.java | 27 +- .../metadata/hook/StorageUnitChangeHook.java | 27 +- .../iginx/metadata/hook/StorageUnitHook.java | 27 +- .../metadata/hook/TimeSeriesChangeHook.java | 18 + .../metadata/hook/TransformChangeHook.java | 18 + .../iginx/metadata/hook/UserChangeHook.java | 27 +- .../metadata/hook/VersionChangeHook.java | 18 + .../iginx/metadata/storage/IMetaStorage.java | 27 +- .../metadata/storage/constant/Constant.java | 18 + .../storage/etcd/ETCDMetaStorage.java | 27 +- .../storage/zk/ZooKeeperMetaStorage.java | 27 +- .../sync/proposal/ProposalListener.java | 18 + .../metadata/sync/proposal/SyncProposal.java | 18 + .../metadata/sync/proposal/SyncVote.java | 18 + .../metadata/sync/proposal/VoteListener.java | 18 + .../sync/protocol/ExecutionException.java | 18 + .../sync/protocol/NetworkException.java | 18 + .../metadata/sync/protocol/SyncProtocol.java | 18 + .../sync/protocol/VoteExpiredException.java | 18 + .../protocol/etcd/ETCDSyncProtocolImpl.java | 18 + .../zk/ZooKeeperSyncProtocolImpl.java | 18 + .../metadata/utils/ColumnsIntervalUtils.java | 18 + .../iginx/metadata/utils/FragmentUtils.java | 18 + .../iginx/metadata/utils/IdUtils.java | 18 + .../iginx/metadata/utils/ReshardStatus.java | 27 +- .../metadata/utils/StorageEngineUtils.java | 18 + .../migration/GreedyMigrationPolicy.java | 18 + .../iginx/migration/MigrationManager.java | 18 + .../migration/MigrationPhysicalExecutor.java | 18 + .../iginx/migration/MigrationPolicy.java | 18 + .../iginx/migration/MigrationTask.java | 18 + .../iginx/migration/MigrationType.java | 18 + .../iginx/migration/MigrationUtils.java | 18 + .../SimulationBasedMigrationPolicy.java | 18 + .../recover/MigrationExecuteTask.java | 18 + .../recover/MigrationExecuteType.java | 18 + .../migration/recover/MigrationLogger.java | 18 + .../recover/MigrationLoggerAnalyzer.java | 18 + .../iginx/monitor/HotSpotMonitor.java | 18 + .../edu/tsinghua/iginx/monitor/IMonitor.java | 18 + .../iginx/monitor/MonitorManager.java | 18 + .../iginx/monitor/RequestsMonitor.java | 18 + .../iginx/mqtt/BrokerAuthenticator.java | 27 +- .../iginx/mqtt/IPayloadFormatter.java | 27 +- .../iginx/mqtt/JsonPayloadFormatter.java | 27 +- .../edu/tsinghua/iginx/mqtt/MQTTService.java | 27 +- .../cn/edu/tsinghua/iginx/mqtt/Message.java | 27 +- .../iginx/mqtt/PayloadFormatManager.java | 27 +- .../tsinghua/iginx/mqtt/PublishHandler.java | 27 +- .../tsinghua/iginx/notice/EmailNotifier.java | 18 + .../tsinghua/iginx/policy/AbstractPolicy.java | 18 + .../cn/edu/tsinghua/iginx/policy/IPolicy.java | 18 + .../tsinghua/iginx/policy/PolicyManager.java | 18 + .../cn/edu/tsinghua/iginx/policy/Utils.java | 18 + .../policy/historical/HistoricalPolicy.java | 27 +- .../iginx/policy/naive/NaivePolicy.java | 18 + .../tsinghua/iginx/policy/naive/Sampler.java | 18 + .../iginx/policy/simple/ColumnCalDO.java | 18 + .../iginx/policy/simple/FragmentCreator.java | 18 + .../iginx/policy/simple/SimplePolicy.java | 18 + .../iginx/policy/test/KeyRangeTestPolicy.java | 18 + .../iginx/resource/QueryResourceManager.java | 27 +- .../iginx/resource/ResourceManager.java | 27 +- .../system/DefaultSystemMetricsService.java | 27 +- .../resource/system/SystemMetricsService.java | 27 +- .../tsinghua/iginx/rest/MetricsResource.java | 27 +- .../edu/tsinghua/iginx/rest/RestServer.java | 27 +- .../edu/tsinghua/iginx/rest/RestSession.java | 27 +- .../cn/edu/tsinghua/iginx/rest/RestUtils.java | 18 + .../tsinghua/iginx/rest/bean/Annotation.java | 18 + .../iginx/rest/bean/AnnotationLimit.java | 18 + .../edu/tsinghua/iginx/rest/bean/Metric.java | 27 +- .../edu/tsinghua/iginx/rest/bean/Query.java | 27 +- .../tsinghua/iginx/rest/bean/QueryMetric.java | 27 +- .../tsinghua/iginx/rest/bean/QueryResult.java | 27 +- .../iginx/rest/bean/QueryResultDataset.java | 27 +- .../iginx/rest/insert/DataPointsParser.java | 27 +- .../iginx/rest/insert/InsertWorker.java | 27 +- .../iginx/rest/query/QueryExecutor.java | 27 +- .../iginx/rest/query/QueryParser.java | 27 +- .../iginx/rest/query/aggregator/Filter.java | 27 +- .../query/aggregator/QueryAggregator.java | 27 +- .../query/aggregator/QueryAggregatorAvg.java | 27 +- .../aggregator/QueryAggregatorCount.java | 27 +- .../query/aggregator/QueryAggregatorDev.java | 27 +- .../query/aggregator/QueryAggregatorDiff.java | 27 +- .../query/aggregator/QueryAggregatorDiv.java | 27 +- .../aggregator/QueryAggregatorFilter.java | 27 +- .../aggregator/QueryAggregatorFirst.java | 27 +- .../query/aggregator/QueryAggregatorLast.java | 27 +- .../query/aggregator/QueryAggregatorMax.java | 27 +- .../query/aggregator/QueryAggregatorMin.java | 27 +- .../query/aggregator/QueryAggregatorNone.java | 27 +- .../aggregator/QueryAggregatorPercentile.java | 27 +- .../query/aggregator/QueryAggregatorRate.java | 27 +- .../aggregator/QueryAggregatorSampler.java | 27 +- .../aggregator/QueryAggregatorSaveAs.java | 27 +- .../query/aggregator/QueryAggregatorSum.java | 27 +- .../query/aggregator/QueryAggregatorType.java | 27 +- .../query/aggregator/QueryShowColumns.java | 27 +- .../tsinghua/iginx/sql/IginXSqlVisitor.java | 18 + .../edu/tsinghua/iginx/sql/SQLConstant.java | 18 + .../edu/tsinghua/iginx/sql/SQLParseError.java | 18 + .../sql/exception/SQLParserException.java | 18 + .../statement/AddStorageEngineStatement.java | 18 + .../sql/statement/CancelJobStatement.java | 18 + .../sql/statement/ClearDataStatement.java | 18 + .../CommitTransformJobStatement.java | 18 + .../iginx/sql/statement/CompactStatement.java | 18 + .../sql/statement/CountPointsStatement.java | 18 + .../iginx/sql/statement/DataStatement.java | 18 + .../sql/statement/DeleteColumnsStatement.java | 18 + .../iginx/sql/statement/DeleteStatement.java | 18 + .../sql/statement/DropTaskStatement.java | 18 + .../ExportFileFromSelectStatement.java | 18 + .../sql/statement/InsertFromCsvStatement.java | 18 + .../statement/InsertFromSelectStatement.java | 18 + .../iginx/sql/statement/InsertStatement.java | 18 + .../sql/statement/RegisterTaskStatement.java | 18 + .../RemoveHistoryDataSourceStatement.java | 18 + .../sql/statement/SetConfigStatement.java | 18 + .../sql/statement/SetRulesStatement.java | 18 + .../statement/ShowClusterInfoStatement.java | 18 + .../sql/statement/ShowColumnsStatement.java | 18 + .../sql/statement/ShowConfigStatement.java | 18 + .../statement/ShowEligibleJobStatement.java | 18 + .../sql/statement/ShowJobStatusStatement.java | 18 + .../statement/ShowRegisterTaskStatement.java | 18 + .../statement/ShowReplicationStatement.java | 18 + .../sql/statement/ShowRulesStatement.java | 18 + .../sql/statement/ShowSessionIDStatement.java | 18 + .../iginx/sql/statement/Statement.java | 18 + .../iginx/sql/statement/StatementType.java | 18 + .../iginx/sql/statement/SystemStatement.java | 18 + .../sql/statement/frompart/CteFromPart.java | 18 + .../sql/statement/frompart/FromPart.java | 18 + .../sql/statement/frompart/FromPartType.java | 18 + .../sql/statement/frompart/PathFromPart.java | 18 + .../frompart/ShowColumnsFromPart.java | 18 + .../statement/frompart/SubQueryFromPart.java | 18 + .../frompart/join/JoinCondition.java | 18 + .../sql/statement/frompart/join/JoinType.java | 18 + .../select/BinarySelectStatement.java | 18 + .../select/CommonTableExpression.java | 18 + .../sql/statement/select/SelectStatement.java | 18 + .../select/UnarySelectStatement.java | 18 + .../select/subclause/FromClause.java | 18 + .../select/subclause/GroupByClause.java | 18 + .../select/subclause/HavingClause.java | 18 + .../select/subclause/LimitClause.java | 18 + .../select/subclause/OrderByClause.java | 18 + .../select/subclause/SelectClause.java | 18 + .../select/subclause/WhereClause.java | 18 + .../iginx/sql/utils/ExpressionUtils.java | 18 + .../AbstractStageStatisticsCollector.java | 18 + .../ExecuteStatisticsCollector.java | 18 + .../IExecuteStatisticsCollector.java | 18 + .../ILogicalStatisticsCollector.java | 18 + .../statistics/IParseStatisticsCollector.java | 18 + .../IPhysicalStatisticsCollector.java | 18 + .../statistics/IStatisticsCollector.java | 18 + .../LogicalStatisticsCollector.java | 18 + .../statistics/ParseStatisticsCollector.java | 18 + .../PhysicalStatisticsCollector.java | 18 + .../tsinghua/iginx/statistics/Statistics.java | 18 + .../iginx/statistics/StatisticsCollector.java | 18 + .../tsinghua/iginx/transform/api/Checker.java | 18 + .../tsinghua/iginx/transform/api/Driver.java | 18 + .../tsinghua/iginx/transform/api/Reader.java | 18 + .../tsinghua/iginx/transform/api/Runner.java | 18 + .../tsinghua/iginx/transform/api/Stage.java | 18 + .../tsinghua/iginx/transform/api/Writer.java | 18 + .../iginx/transform/data/ArrowReader.java | 18 + .../iginx/transform/data/ArrowWriter.java | 18 + .../iginx/transform/data/BatchData.java | 18 + .../transform/data/CollectionWriter.java | 18 + .../iginx/transform/data/ExportWriter.java | 18 + .../iginx/transform/data/Exporter.java | 18 + .../transform/data/FileAppendWriter.java | 18 + .../iginx/transform/data/IginXWriter.java | 18 + .../iginx/transform/data/LogWriter.java | 18 + .../iginx/transform/data/PemjaReader.java | 18 + .../iginx/transform/data/PemjaWriter.java | 18 + .../iginx/transform/data/RowStreamReader.java | 18 + .../iginx/transform/data/SplitReader.java | 18 + .../iginx/transform/driver/IPCWorker.java | 18 + .../iginx/transform/driver/PemjaDriver.java | 18 + .../iginx/transform/driver/PemjaWorker.java | 18 + .../iginx/transform/driver/PythonDriver.java | 18 + .../exception/CreateWorkerException.java | 18 + .../exception/TransformException.java | 18 + .../exception/UnknownArgumentException.java | 18 + .../exception/UnknownDataFlowException.java | 18 + .../exception/WriteBatchException.java | 18 + .../transform/exec/BatchStageRunner.java | 18 + .../iginx/transform/exec/JobRunner.java | 18 + .../transform/exec/JobValidationChecker.java | 18 + .../transform/exec/StreamStageRunner.java | 18 + .../iginx/transform/exec/TaskManager.java | 18 + .../transform/exec/TransformJobManager.java | 18 + .../iginx/transform/pojo/BatchStage.java | 18 + .../iginx/transform/pojo/IginXTask.java | 18 + .../tsinghua/iginx/transform/pojo/Job.java | 18 + .../iginx/transform/pojo/PythonTask.java | 18 + .../iginx/transform/pojo/StreamStage.java | 18 + .../tsinghua/iginx/transform/pojo/Task.java | 18 + .../iginx/transform/pojo/TaskFactory.java | 18 + .../iginx/transform/utils/Constants.java | 18 + .../tsinghua/iginx/transform/utils/Mutex.java | 18 + .../iginx/transform/utils/RedirectLogger.java | 18 + .../iginx/transform/utils/TypeUtils.java | 18 + .../iginx/auth/FilePermissionManagerTest.java | 18 + .../LowAccessFragmentCompactionTest.java | 18 + .../LowWriteFragmentCompactionTest.java | 18 + .../iginx/compaction/PhysicalEngineMock.java | 18 + .../iginx/conf/FilePermissionConfigTest.java | 18 + .../logical/utils/LogicalFilterUtilsTest.java | 18 + .../engine/logical/utils/PathUtilsTest.java | 18 + .../AbstractOperatorMemoryExecutorTest.java | 27 +- .../NaiveOperatorMemoryExecutorTest.java | 27 +- .../StreamOperatorMemoryExecutorTest.java | 27 +- .../utils/ColumnKeyTranslatorTest.java | 18 + .../shared/function/system/MaxTest.java | 27 +- .../metadata/entity/ColumnsIntervalTest.java | 18 + .../iginx/metadata/entity/ExtraParamTest.java | 18 + .../iginx/notice/EmailNotifierTest.java | 18 + .../cn/edu/tsinghua/iginx/rest/ParseTest.java | 18 + .../tsinghua/iginx/sql/FilterVisitorTest.java | 18 + .../cn/edu/tsinghua/iginx/sql/ParseTest.java | 18 + .../cn/edu/tsinghua/iginx/sql/TestUtils.java | 18 + .../iginx/transform/YamlReadTest.java | 27 +- .../iginx/filesystem/FileSystemStorage.java | 27 +- ...FileSystemTaskExecuteFailureException.java | 27 +- .../exception/FilesystemException.java | 22 +- .../iginx/filesystem/exec/Executor.java | 18 + .../filesystem/exec/FileSystemManager.java | 18 + .../iginx/filesystem/exec/LocalExecutor.java | 18 + .../iginx/filesystem/exec/RemoteExecutor.java | 18 + .../filesystem/file/DefaultFileOperator.java | 18 + .../iginx/filesystem/file/IFileOperator.java | 18 + .../filesystem/file/entity/FileMeta.java | 18 + .../FileSystemHistoryQueryRowStream.java | 18 + .../entity/FileSystemQueryRowStream.java | 18 + .../query/entity/FileSystemResultTable.java | 18 + .../iginx/filesystem/query/entity/Record.java | 18 + .../filesystem/server/FileSystemServer.java | 18 + .../filesystem/server/FileSystemWorker.java | 18 + .../iginx/filesystem/shared/Constant.java | 18 + .../iginx/filesystem/shared/FileType.java | 18 + .../iginx/filesystem/tools/FilePathUtils.java | 18 + .../filesystem/tools/FilterTransformer.java | 18 + .../filesystem/tools/LimitedSizeMap.java | 18 + .../iginx/filesystem/tools/MemoryPool.java | 18 + .../iginx/influxdb/InfluxDBStorage.java | 27 +- .../influxdb/exception/InfluxDBException.java | 18 + .../InfluxDBTaskExecuteFailureException.java | 27 +- .../entity/InfluxDBHistoryQueryRowStream.java | 27 +- .../query/entity/InfluxDBQueryRowStream.java | 27 +- .../influxdb/query/entity/InfluxDBSchema.java | 27 +- .../influxdb/tools/DataTypeTransformer.java | 18 + .../influxdb/tools/FilterTransformer.java | 27 +- .../influxdb/tools/SchemaTransformer.java | 18 + .../iginx/influxdb/tools/TagFilterUtils.java | 18 + .../iginx/influxdb/tools/TimeUtils.java | 18 + .../tsinghua/iginx/iotdb/IoTDBStorage.java | 27 +- .../iginx/iotdb/exception/IoTDBException.java | 22 +- .../IoTDBTaskExecuteFailureException.java | 18 + .../query/entity/IoTDBQueryRowStream.java | 27 +- .../iotdb/tools/DataTypeTransformer.java | 27 +- .../iginx/iotdb/tools/DataViewWrapper.java | 27 +- .../iginx/iotdb/tools/FilterTransformer.java | 27 +- .../iginx/iotdb/tools/TagKVUtils.java | 27 +- .../iginx/mongodb/MongoDBStorage.java | 18 + .../iginx/mongodb/dummy/DummyQuery.java | 18 + .../iginx/mongodb/dummy/FilterUtils.java | 18 + .../iginx/mongodb/dummy/FindRowStream.java | 18 + .../iginx/mongodb/dummy/NameUtils.java | 18 + .../iginx/mongodb/dummy/PathTree.java | 18 + .../iginx/mongodb/dummy/QueryRowStream.java | 18 + .../iginx/mongodb/dummy/QueryUtils.java | 18 + .../iginx/mongodb/dummy/ResultColumn.java | 18 + .../iginx/mongodb/dummy/ResultRow.java | 18 + .../iginx/mongodb/dummy/ResultTable.java | 18 + .../iginx/mongodb/dummy/SampleQuery.java | 18 + .../iginx/mongodb/dummy/SchemaSample.java | 22 +- .../iginx/mongodb/dummy/TypeUtils.java | 18 + .../iginx/mongodb/entity/ColumnQuery.java | 18 + .../iginx/mongodb/entity/JoinQuery.java | 18 + .../iginx/mongodb/entity/SourceTable.java | 18 + .../iginx/mongodb/tools/FilterUtils.java | 18 + .../iginx/mongodb/tools/NameUtils.java | 18 + .../iginx/mongodb/tools/TypeUtils.java | 18 + .../iginx/mongodb/dummy/TypeUtilsTest.java | 18 + .../iginx/parquet/ParquetStorage.java | 22 +- .../tsinghua/iginx/parquet/db/Database.java | 22 +- .../iginx/parquet/db/ImmutableDatabase.java | 22 +- .../iginx/parquet/db/lsm/OneTierDB.java | 22 +- .../iginx/parquet/db/lsm/api/ReadWriter.java | 22 +- .../iginx/parquet/db/lsm/api/TableMeta.java | 18 + .../parquet/db/lsm/buffer/DataBuffer.java | 22 +- .../parquet/db/lsm/compact/Compactor.java | 22 +- .../parquet/db/lsm/table/DeletedTable.java | 22 +- .../db/lsm/table/DeletedTableMeta.java | 22 +- .../parquet/db/lsm/table/EmptyTable.java | 22 +- .../iginx/parquet/db/lsm/table/FileTable.java | 22 +- .../parquet/db/lsm/table/MemoryTable.java | 22 +- .../iginx/parquet/db/lsm/table/Table.java | 22 +- .../parquet/db/lsm/table/TableIndex.java | 22 +- .../parquet/db/lsm/table/TableStorage.java | 22 +- .../iginx/parquet/db/util/AreaSet.java | 22 +- .../parquet/db/util/SequenceGenerator.java | 22 +- .../db/util/iterator/AreaFilterScanner.java | 22 +- .../db/util/iterator/BatchPlaneScanner.java | 22 +- .../util/iterator/ColumnUnionRowScanner.java | 22 +- .../db/util/iterator/ConcatScanner.java | 22 +- .../db/util/iterator/EmptyScanner.java | 22 +- .../db/util/iterator/IteratorScanner.java | 22 +- .../db/util/iterator/RowUnionScanner.java | 22 +- .../parquet/db/util/iterator/Scanner.java | 22 +- .../parquet/db/util/iterator/SizeUtils.java | 22 +- .../tsinghua/iginx/parquet/exec/Executor.java | 22 +- .../iginx/parquet/exec/LocalExecutor.java | 22 +- .../iginx/parquet/exec/RemoteExecutor.java | 22 +- .../tsinghua/iginx/parquet/io/FileFormat.java | 22 +- .../tsinghua/iginx/parquet/io/FileIndex.java | 22 +- .../tsinghua/iginx/parquet/io/FileMeta.java | 22 +- .../tsinghua/iginx/parquet/io/FileReader.java | 22 +- .../tsinghua/iginx/parquet/io/FileWriter.java | 22 +- .../iginx/parquet/io/common/DataChunk.java | 22 +- .../iginx/parquet/io/common/DataChunks.java | 22 +- .../iginx/parquet/io/common/EmptyReader.java | 22 +- .../iginx/parquet/io/parquet/FilterUtils.java | 22 +- .../parquet/io/parquet/IGroupConverter.java | 22 +- .../parquet/io/parquet/IParquetReader.java | 22 +- .../parquet/io/parquet/IParquetWriter.java | 22 +- .../iginx/parquet/io/parquet/IRecord.java | 22 +- .../io/parquet/IRecordDematerializer.java | 22 +- .../io/parquet/IRecordMaterializer.java | 22 +- .../parquet/io/parquet/ProjectUtils.java | 22 +- .../iginx/parquet/manager/Manager.java | 22 +- .../parquet/manager/data/DataManager.java | 22 +- .../parquet/manager/data/DataViewWrapper.java | 22 +- .../manager/data/FilterRangeUtils.java | 22 +- .../parquet/manager/data/LongFormat.java | 22 +- .../parquet/manager/data/ObjectFormat.java | 22 +- .../manager/data/ParquetReadWriter.java | 18 + .../parquet/manager/data/ProjectUtils.java | 22 +- .../manager/data/ScannerRowStream.java | 22 +- .../parquet/manager/data/SerializeUtils.java | 22 +- .../iginx/parquet/manager/data/SizeUtils.java | 22 +- .../parquet/manager/data/StringFormat.java | 22 +- .../manager/data/TombstoneStorage.java | 22 +- .../iginx/parquet/manager/dummy/Column.java | 22 +- .../parquet/manager/dummy/DummyManager.java | 22 +- .../parquet/manager/dummy/EmptyManager.java | 22 +- .../iginx/parquet/manager/dummy/Field.java | 22 +- .../iginx/parquet/manager/dummy/Loader.java | 22 +- .../manager/dummy/NewQueryRowStream.java | 22 +- .../iginx/parquet/manager/dummy/Storer.java | 22 +- .../iginx/parquet/manager/dummy/Table.java | 22 +- .../parquet/manager/utils/RangeUtils.java | 18 + .../parquet/manager/utils/TagKVUtils.java | 18 + .../parquet/server/FilterTransformer.java | 22 +- .../iginx/parquet/server/ParquetServer.java | 22 +- .../iginx/parquet/server/ParquetWorker.java | 22 +- .../iginx/parquet/util/CachePool.java | 22 +- .../iginx/parquet/util/Constants.java | 22 +- .../iginx/parquet/util/ParseUtils.java | 22 +- .../tsinghua/iginx/parquet/util/Shared.java | 22 +- .../iginx/parquet/util/StorageProperties.java | 22 +- .../exception/InvalidFieldNameException.java | 22 +- .../util/exception/IsClosedException.java | 22 +- .../util/exception/NotIntegrityException.java | 22 +- .../util/exception/SchemaException.java | 22 +- .../util/exception/StorageException.java | 22 +- .../exception/StorageRuntimeException.java | 22 +- .../util/exception/TimeoutException.java | 22 +- .../exception/TypeConflictedException.java | 22 +- .../exception/UnsupportedFilterException.java | 22 +- .../db/common/utils/SerializeUtilsTest.java | 22 +- .../iginx/parquet/io/ParquetFormatIOTest.java | 18 + .../manager/data/FilterRangeUtilsTest.java | 22 +- .../tsinghua/iginx/redis/RedisStorage.java | 18 + .../tsinghua/iginx/redis/entity/Column.java | 18 + .../redis/entity/RedisQueryRowStream.java | 18 + .../tsinghua/iginx/redis/tools/DataCoder.java | 18 + .../iginx/redis/tools/DataTransformer.java | 18 + .../iginx/redis/tools/DataViewWrapper.java | 18 + .../iginx/redis/tools/FilterUtils.java | 18 + .../iginx/redis/tools/TagKVUtils.java | 27 +- .../iginx/relational/RelationalStorage.java | 27 +- .../transformer/IDataTypeTransformer.java | 18 + .../transformer/JDBCDataTypeTransformer.java | 18 + .../PostgreSQLDataTypeTransformer.java | 18 + .../exception/RelationalException.java | 18 + ...RelationalTaskExecuteFailureException.java | 18 + .../meta/AbstractRelationalMeta.java | 18 + .../iginx/relational/meta/JDBCMeta.java | 18 + .../iginx/relational/meta/PostgreSQLMeta.java | 27 +- .../query/entity/RelationQueryRowStream.java | 18 + .../iginx/relational/tools/ColumnField.java | 18 + .../iginx/relational/tools/Constants.java | 18 + .../relational/tools/FilterTransformer.java | 27 +- .../iginx/relational/tools/HashUtils.java | 18 + .../relational/tools/RelationSchema.java | 18 + .../iginx/relational/tools/TagKVUtils.java | 18 + docker/client/build-no-maven.bat | 17 + docker/client/build-no-maven.sh | 18 + docker/client/build.bat | 17 + docker/client/build.sh | 18 + docker/client/run_docker.bat | 17 + docker/client/run_docker.sh | 18 + .../build_and_run_iginx_docker.bat | 17 + docker/oneShot/build_and_run_iginx_docker.bat | 17 + .../onlyIginx-parquet/build_iginx_docker.bat | 17 + .../onlyIginx-parquet/build_iginx_docker.sh | 18 + docker/onlyIginx-parquet/run_iginx_docker.bat | 17 + docker/onlyIginx-parquet/run_iginx_docker.sh | 18 + docker/onlyIginx/build_iginx_docker.bat | 17 + docker/onlyIginx/run_iginx_docker.bat | 17 + .../session/IginXStreamSessionExample.java | 18 + .../iginx/session/InfluxDBSessionExample.java | 27 +- .../session/IoTDBAfterDilatationExample.java | 27 +- .../session/IoTDBBeforeDilatationExample.java | 27 +- .../iginx/session/IoTDBSessionExample.java | 27 +- .../session/IoTDBSessionPoolExample.java | 18 + .../iginx/session/NewSessionExample.java | 27 +- .../NewSessionNotSupportedQueryExample.java | 27 +- .../NewSessionNotSupportedWriteExample.java | 27 +- .../iginx/session/OpenTSDBSessionExample.java | 18 + .../iginx/session/ParquetServerExample.java | 18 + .../iginx/session/ParquetSessionExample.java | 18 + .../session/PostgreSQLSessionExample.java | 27 +- .../iginx/session/SQLSessionExample.java | 18 + .../iginx/session/TagKVSessionExample.java | 18 + .../session/TimescaleDBSessionExample.java | 27 +- .../iginx/session/TransformCompare.java | 18 + .../iginx/session/TransformExample.java | 18 + .../iginx/session/UDFCompareToSys.java | 18 + .../tsinghua/iginx/session/UDFExample.java | 18 + .../src/main/resources/transformer_add_one.py | 18 + example/src/main/resources/transformer_avg.py | 18 + .../src/main/resources/transformer_count.py | 18 + example/src/main/resources/transformer_max.py | 18 + example/src/main/resources/transformer_min.py | 18 + .../src/main/resources/transformer_row_sum.py | 18 + example/src/main/resources/transformer_sum.py | 18 + example/src/main/resources/udaf_count.py | 18 + example/src/main/resources/udtf_sin.py | 18 + .../cn/edu/tsinghua/iginx/jdbc/Config.java | 18 + .../cn/edu/tsinghua/iginx/jdbc/Constant.java | 18 + .../tsinghua/iginx/jdbc/IginXConnection.java | 18 + .../iginx/jdbc/IginXConnectionParams.java | 18 + .../tsinghua/iginx/jdbc/IginXDataSource.java | 18 + .../iginx/jdbc/IginXDatabaseMetadata.java | 18 + .../edu/tsinghua/iginx/jdbc/IginXDriver.java | 18 + .../iginx/jdbc/IginXPreparedStatement.java | 18 + .../iginx/jdbc/IginXResultMetadata.java | 18 + .../tsinghua/iginx/jdbc/IginXResultSet.java | 18 + .../tsinghua/iginx/jdbc/IginXStatement.java | 18 + .../iginx/jdbc/IginxUrlException.java | 18 + .../cn/edu/tsinghua/iginx/jdbc/Utils.java | 18 + jdbc/src/test/java/BatchTest.java | 18 + jdbc/src/test/java/ConnectionParamsTest.java | 18 + jdbc/src/test/java/ExampleTest.java | 18 + jdbc/src/test/java/PreparedStatementTest.java | 18 + jdbc/src/test/java/ResultMetadataTest.java | 18 + jdbc/src/test/java/ResultSetTest.java | 18 + jdbc/src/test/java/TestUtils.java | 18 + .../optimizer/FilterFragmentOptimizer.java | 18 + .../optimizer/FilterPushDownOptimizer.java | 18 + .../logical/optimizer/RemoveNotOptimizer.java | 18 + .../iginx/logical/optimizer/core/Operand.java | 18 + .../iginx/logical/optimizer/core/Planner.java | 18 + .../logical/optimizer/core/RuleCall.java | 18 + .../core/iterator/DeepFirstIterator.java | 18 + .../core/iterator/LeveledIterator.java | 18 + .../optimizer/core/iterator/MatchOrder.java | 18 + .../iterator/ReverseDeepFirstIterator.java | 18 + .../core/iterator/ReverseLeveledIterator.java | 18 + .../optimizer/core/iterator/TreeIterator.java | 18 + .../logical/optimizer/rbo/RBORuleCall.java | 18 + .../optimizer/rbo/RuleBasedOptimizer.java | 18 + .../optimizer/rbo/RuleBasedPlanner.java | 18 + .../optimizer/rules/ColumnPruningRule.java | 18 + .../rules/ConstantPropagationRule.java | 18 + .../rules/FilterConstantFoldingRule.java | 18 + .../rules/FilterJoinTransposeRule.java | 18 + .../FilterPushDownAddSchemaPrefixRule.java | 18 + .../rules/FilterPushDownGroupByRule.java | 18 + .../FilterPushDownPathUnionJoinRule.java | 18 + .../FilterPushDownProjectReorderSortRule.java | 18 + .../rules/FilterPushDownRenameRule.java | 18 + .../rules/FilterPushDownSelectRule.java | 18 + .../rules/FilterPushDownSetOpRule.java | 18 + .../rules/FilterPushDownTransformRule.java | 18 + .../FilterPushIntoJoinConditionRule.java | 18 + .../rules/FilterPushOutJoinConditionRule.java | 18 + .../rules/FragmentPruningByFilterRule.java | 18 + .../rules/FragmentPruningByPatternRule.java | 18 + .../rules/FunctionDistinctEliminateRule.java | 18 + .../rules/InExistsDistinctEliminateRule.java | 18 + .../optimizer/rules/NotFilterRemoveRule.java | 18 + .../RowTransformConstantFoldingRule.java | 18 + .../iginx/logical/optimizer/rules/Rule.java | 18 + .../optimizer/rules/RuleCollection.java | 18 + .../logical/optimizer/rules/RuleStrategy.java | 18 + .../naive/NaiveConstraintManager.java | 27 +- .../naive/NaivePhysicalOptimizer.java | 27 +- .../naive/NaiveReplicaDispatcher.java | 27 +- .../iginx/physical/optimizer/rule/Rule.java | 27 +- .../iginx/optimizer/IteratorTest.java | 18 + .../tsinghua/iginx/optimizer/OperandTest.java | 18 + .../edu/tsinghua/iginx/optimizer/RBOTest.java | 18 + .../iginx/optimizer/RBOTestUtils.java | 18 + .../tsinghua/iginx/optimizer/TreeBuilder.java | 18 + .../tsinghua/iginx/optimizer/TreePrinter.java | 18 + .../iginx/exception/SessionException.java | 27 +- .../cn/edu/tsinghua/iginx/pool/IginxInfo.java | 18 + .../edu/tsinghua/iginx/pool/SessionPool.java | 18 + .../tsinghua/iginx/session/ClusterInfo.java | 27 +- .../cn/edu/tsinghua/iginx/session/Column.java | 27 +- .../iginx/session/CurveMatchResult.java | 18 + .../cn/edu/tsinghua/iginx/session/Point.java | 27 +- .../tsinghua/iginx/session/QueryDataSet.java | 27 +- .../edu/tsinghua/iginx/session/Session.java | 27 +- .../session/SessionAggregateQueryDataSet.java | 18 + .../session/SessionExecuteSqlResult.java | 27 +- .../iginx/session/SessionQueryDataSet.java | 27 +- .../tsinghua/iginx/session_v2/Arguments.java | 27 +- .../iginx/session_v2/AsyncWriteClient.java | 27 +- .../iginx/session_v2/ClusterClient.java | 27 +- .../iginx/session_v2/DeleteClient.java | 27 +- .../iginx/session_v2/IginXClient.java | 27 +- .../iginx/session_v2/IginXClientFactory.java | 27 +- .../iginx/session_v2/IginXClientOptions.java | 27 +- .../iginx/session_v2/QueryClient.java | 27 +- .../iginx/session_v2/TransformClient.java | 18 + .../iginx/session_v2/UsersClient.java | 27 +- .../iginx/session_v2/WriteClient.java | 27 +- .../iginx/session_v2/annotations/Field.java | 27 +- .../session_v2/annotations/Measurement.java | 27 +- .../iginx/session_v2/domain/ClusterInfo.java | 27 +- .../iginx/session_v2/domain/Storage.java | 27 +- .../iginx/session_v2/domain/Task.java | 18 + .../iginx/session_v2/domain/Transform.java | 18 + .../iginx/session_v2/domain/User.java | 27 +- .../session_v2/exception/IginXException.java | 27 +- .../internal/AbstractFunctionClient.java | 27 +- .../internal/AsyncWriteClientImpl.java | 27 +- .../internal/ClusterClientImpl.java | 27 +- .../session_v2/internal/DeleteClientImpl.java | 27 +- .../session_v2/internal/IginXClientImpl.java | 27 +- .../internal/MeasurementMapper.java | 27 +- .../session_v2/internal/MeasurementUtils.java | 18 + .../session_v2/internal/QueryClientImpl.java | 27 +- .../session_v2/internal/ResultMapper.java | 27 +- .../internal/TransformClientImpl.java | 18 + .../session_v2/internal/UsersClientImpl.java | 27 +- .../session_v2/internal/WriteClientImpl.java | 27 +- .../session_v2/query/AggregateQuery.java | 27 +- .../session_v2/query/DownsampleQuery.java | 27 +- .../iginx/session_v2/query/IginXColumn.java | 27 +- .../iginx/session_v2/query/IginXHeader.java | 27 +- .../iginx/session_v2/query/IginXRecord.java | 27 +- .../iginx/session_v2/query/IginXTable.java | 27 +- .../iginx/session_v2/query/LastQuery.java | 27 +- .../iginx/session_v2/query/Query.java | 27 +- .../iginx/session_v2/query/SimpleQuery.java | 27 +- .../iginx/session_v2/write/Point.java | 27 +- .../iginx/session_v2/write/Record.java | 27 +- .../iginx/session_v2/write/Table.java | 27 +- .../edu/tsinghua/iginx/utils/StatusUtils.java | 27 +- session/src/test/java/ResultFormatTest.java | 18 + session_py/example.py | 29 +- session_py/file_example.py | 18 + session_py/iginx/iginx_pyclient/__init__.py | 28 +- .../iginx/iginx_pyclient/cluster_info.py | 28 +- session_py/iginx/iginx_pyclient/dataset.py | 28 +- session_py/iginx/iginx_pyclient/session.py | 28 +- .../iginx/iginx_pyclient/thrift/__init__.py | 18 + .../iginx_pyclient/thrift/rpc/IService.py | 18 + .../iginx_pyclient/thrift/rpc/__init__.py | 18 + .../iginx_pyclient/thrift/rpc/constants.py | 18 + .../iginx/iginx_pyclient/thrift/rpc/ttypes.py | 18 + .../iginx/iginx_pyclient/time_series.py | 28 +- .../iginx/iginx_pyclient/utils/__init__.py | 28 +- .../iginx/iginx_pyclient/utils/bitmap.py | 29 +- .../iginx/iginx_pyclient/utils/byte_utils.py | 29 +- session_py/iginx/setup.py | 18 + .../iginx/constant/GlobalConstant.java | 18 + .../exception/IginxRuntimeException.java | 18 + .../tsinghua/iginx/exception/StatusCode.java | 27 +- .../UnsupportedDataTypeException.java | 27 +- .../iginx/exception/package-info.java | 18 + .../cn/edu/tsinghua/iginx/utils/Bitmap.java | 27 +- .../edu/tsinghua/iginx/utils/ByteUtils.java | 27 +- .../cn/edu/tsinghua/iginx/utils/CSVUtils.java | 18 + .../tsinghua/iginx/utils/CheckedFunction.java | 27 +- .../iginx/utils/CompressionUtils.java | 18 + .../tsinghua/iginx/utils/CurveMatchUtils.java | 27 +- .../iginx/utils/DataTypeInferenceUtils.java | 27 +- .../tsinghua/iginx/utils/DataTypeUtils.java | 27 +- .../cn/edu/tsinghua/iginx/utils/EnvUtils.java | 27 +- .../cn/edu/tsinghua/iginx/utils/Escaper.java | 18 + .../iginx/utils/FileCompareUtils.java | 18 + .../edu/tsinghua/iginx/utils/FileReader.java | 18 + .../edu/tsinghua/iginx/utils/FileUtils.java | 18 + .../edu/tsinghua/iginx/utils/FormatUtils.java | 18 + .../edu/tsinghua/iginx/utils/HostUtils.java | 18 + .../edu/tsinghua/iginx/utils/JobFromYAML.java | 18 + .../edu/tsinghua/iginx/utils/JsonUtils.java | 18 + .../cn/edu/tsinghua/iginx/utils/Pair.java | 27 +- .../cn/edu/tsinghua/iginx/utils/RpcUtils.java | 27 +- .../tsinghua/iginx/utils/SerializeUtils.java | 27 +- .../edu/tsinghua/iginx/utils/ShellRunner.java | 18 + .../tsinghua/iginx/utils/SnowFlakeUtils.java | 27 +- .../edu/tsinghua/iginx/utils/SortUtils.java | 27 +- .../edu/tsinghua/iginx/utils/StringUtils.java | 27 +- .../edu/tsinghua/iginx/utils/TagKVUtils.java | 27 +- .../tsinghua/iginx/utils/TaskFromYAML.java | 18 + .../tsinghua/iginx/utils/ThriftConnPool.java | 18 + .../edu/tsinghua/iginx/utils/TimeUtils.java | 27 +- .../edu/tsinghua/iginx/utils/ValueUtils.java | 18 + .../edu/tsinghua/iginx/utils/YAMLReader.java | 18 + .../edu/tsinghua/iginx/utils/YAMLWriter.java | 18 + .../iginx/utils/CompressionUtilsTest.java | 18 + .../edu/tsinghua/iginx/utils/EscaperTest.java | 18 + .../tsinghua/iginx/utils/StringUtilsTest.java | 18 + .../iginx/shared/MockClassGenerator.java | 18 + .../integration/client/ExportFileIT.java | 18 + .../integration/client/ImportFileIT.java | 18 + .../integration/compaction/CompactionIT.java | 18 + .../integration/controller/Controller.java | 18 + .../controller/TestEnvironmentController.java | 18 + .../integration/datasource/DataSourceIT.java | 18 + .../expansion/BaseCapacityExpansionIT.java | 18 + .../expansion/BaseHistoryDataGenerator.java | 18 + .../expansion/constant/Constant.java | 18 + .../FileSystemCapacityExpansionIT.java | 18 + .../FileSystemHistoryDataGenerator.java | 18 + .../influxdb/InfluxDBCapacityExpansionIT.java | 18 + .../InfluxDBHistoryDataGenerator.java | 18 + .../iotdb/IoTDB12CapacityExpansionIT.java | 18 + .../iotdb/IoTDB12HistoryDataGenerator.java | 18 + .../mongodb/MongoDBCapacityExpansionIT.java | 18 + .../mongodb/MongoDBHistoryDataGenerator.java | 18 + .../mysql/MySQLCapacityExpansionIT.java | 18 + .../mysql/MySQLHistoryDataGenerator.java | 18 + .../parquet/ParquetCapacityExpansionIT.java | 18 + .../parquet/ParquetHistoryDataGenerator.java | 18 + .../PostgreSQLCapacityExpansionIT.java | 18 + .../PostgreSQLHistoryDataGenerator.java | 18 + .../redis/RedisCapacityExpansionIT.java | 18 + .../redis/RedisHistoryDataGenerator.java | 18 + .../expansion/utils/SQLTestTools.java | 18 + .../func/rest/RestAnnotationIT.java | 18 + .../iginx/integration/func/rest/RestIT.java | 18 + .../func/session/BaseSessionIT.java | 18 + .../func/session/InsertAPIType.java | 18 + .../func/session/NewSessionIT.java | 18 + .../integration/func/session/PySessionIT.java | 18 + .../func/session/SQLCompareIT.java | 18 + .../func/session/SessionConcurrencyIT.java | 18 + .../integration/func/session/SessionIT.java | 27 +- .../func/session/SessionPoolIT.java | 18 + .../integration/func/session/SessionV2IT.java | 18 + .../func/session/TestDataSection.java | 18 + .../integration/func/sql/SQLSessionIT.java | 18 + .../func/sql/SQLSessionPoolIT.java | 18 + .../iginx/integration/func/tag/TagIT.java | 18 + .../integration/func/udf/RemoteUDFIT.java | 18 + .../integration/func/udf/TransformIT.java | 27 +- .../iginx/integration/func/udf/UDFIT.java | 27 +- .../integration/func/udf/UDFTestTools.java | 18 + .../integration/mds/ETCDSyncProtocolTest.java | 18 + .../integration/mds/IMetaManagerTest.java | 27 +- .../iginx/integration/mds/RandomUtils.java | 18 + .../integration/mds/SyncProtocolTest.java | 18 + .../mds/ZooKeeperSyncProtocolTest.java | 18 + .../integration/other/FileLoaderTest.java | 18 + .../integration/other/TimePrecisionIT.java | 18 + .../iginx/integration/other/UDFPathIT.java | 18 + .../MixClusterShowColumnsRegressionTest.java | 18 + .../integration/tool/CombinedInsertTests.java | 18 + .../iginx/integration/tool/ConfLoader.java | 18 + .../iginx/integration/tool/DBConf.java | 18 + .../integration/tool/MultiConnection.java | 18 + .../iginx/integration/tool/SQLExecutor.java | 18 + .../iginx/integration/tool/TestUtils.java | 18 + test/src/test/resources/pySessionIT/tests.py | 29 +- .../transform/transformer_add_one.py | 18 + .../transform/transformer_row_sum.py | 18 + .../resources/transform/transformer_sleep.py | 18 + .../resources/transform/transformer_sum.py | 18 + test/src/test/resources/udf/mock_udf.py | 18 + .../test/resources/udf/my_module/__init__.py | 18 + .../resources/udf/my_module/dateutil_test.py | 18 + .../resources/udf/my_module/idle_classes.py | 18 + .../resources/udf/my_module/my_class_a.py | 18 + .../udf/my_module/sub_module/__init__.py | 18 + .../udf/my_module/sub_module/sub_class_a.py | 18 + thrift/src/main/proto/filesystem.thrift | 18 + thrift/src/main/proto/parquet.thrift | 18 + thrift/src/main/proto/rpc.thrift | 27 +- udf_funcs/python_scripts/class_loader.py | 18 + udf_funcs/python_scripts/constant.py | 18 + udf_funcs/python_scripts/py_worker.py | 18 + udf_funcs/python_scripts/transformer_apply.py | 18 + .../transformer_between_time.py | 18 + udf_funcs/python_scripts/transformer_bool.py | 18 + .../python_scripts/transformer_bottom.py | 18 + .../python_scripts/transformer_distinct.py | 18 + .../python_scripts/transformer_filter.py | 18 + udf_funcs/python_scripts/transformer_head.py | 18 + udf_funcs/python_scripts/transformer_loc.py | 18 + udf_funcs/python_scripts/transformer_mean.py | 18 + udf_funcs/python_scripts/transformer_skew.py | 18 + .../python_scripts/transformer_sortindex.py | 18 + .../python_scripts/transformer_spread.py | 18 + udf_funcs/python_scripts/udf_avg.py | 18 + udf_funcs/python_scripts/udf_count.py | 18 + udf_funcs/python_scripts/udf_max.py | 18 + udf_funcs/python_scripts/udf_max_with_key.py | 18 + udf_funcs/python_scripts/udf_min.py | 18 + udf_funcs/python_scripts/udf_sum.py | 18 + udf_funcs/python_scripts/udsf_reverse_rows.py | 18 + udf_funcs/python_scripts/udsf_transpose.py | 18 + .../python_scripts/udtf_column_expand.py | 18 + udf_funcs/python_scripts/udtf_cos.py | 18 + udf_funcs/python_scripts/udtf_key_add_one.py | 18 + udf_funcs/python_scripts/udtf_multiply.py | 18 + udf_funcs/python_scripts/udtf_pow.py | 18 + 1094 files changed, 18222 insertions(+), 5603 deletions(-) diff --git a/.github/actions/dbLog/dbLog.sh b/.github/actions/dbLog/dbLog.sh index 8b05915376..6a6b8f6feb 100644 --- a/.github/actions/dbLog/dbLog.sh +++ b/.github/actions/dbLog/dbLog.sh @@ -1,4 +1,22 @@ #!/bin/sh +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + # Only works on WindowsOS # all logs are stored in {DB_DIR_ROOT}/logs/db.log & {DB_DIR_ROOT}/logs/db-error.log(optional) diff --git a/.github/scripts/dataSources/filesystem_linux_windows.sh b/.github/scripts/dataSources/filesystem_linux_windows.sh index ea5a8a7ea9..938b5d410d 100644 --- a/.github/scripts/dataSources/filesystem_linux_windows.sh +++ b/.github/scripts/dataSources/filesystem_linux_windows.sh @@ -1,4 +1,22 @@ #!/bin/sh +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + set -e diff --git a/.github/scripts/dataSources/filesystem_macos.sh b/.github/scripts/dataSources/filesystem_macos.sh index 0882a84acd..b96aaa6068 100644 --- a/.github/scripts/dataSources/filesystem_macos.sh +++ b/.github/scripts/dataSources/filesystem_macos.sh @@ -1,4 +1,22 @@ #!/bin/sh +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + set -e diff --git a/.github/scripts/dataSources/influxdb.sh b/.github/scripts/dataSources/influxdb.sh index 9ca05856f8..879629574d 100644 --- a/.github/scripts/dataSources/influxdb.sh +++ b/.github/scripts/dataSources/influxdb.sh @@ -1,4 +1,22 @@ #!/bin/sh +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + set -e diff --git a/.github/scripts/dataSources/influxdb_macos.sh b/.github/scripts/dataSources/influxdb_macos.sh index 48138dbe3b..513562c313 100644 --- a/.github/scripts/dataSources/influxdb_macos.sh +++ b/.github/scripts/dataSources/influxdb_macos.sh @@ -1,4 +1,22 @@ #!/bin/sh +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + set -e diff --git a/.github/scripts/dataSources/influxdb_windows.sh b/.github/scripts/dataSources/influxdb_windows.sh index f3d1f2c8b5..ac5669b550 100644 --- a/.github/scripts/dataSources/influxdb_windows.sh +++ b/.github/scripts/dataSources/influxdb_windows.sh @@ -1,4 +1,22 @@ #!/bin/sh +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + set -e diff --git a/.github/scripts/dataSources/iotdb12.sh b/.github/scripts/dataSources/iotdb12.sh index 687dc55029..28d806af7f 100644 --- a/.github/scripts/dataSources/iotdb12.sh +++ b/.github/scripts/dataSources/iotdb12.sh @@ -1,4 +1,22 @@ #!/bin/sh +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + set -e diff --git a/.github/scripts/dataSources/iotdb12_macos.sh b/.github/scripts/dataSources/iotdb12_macos.sh index 4a611ce3b7..021ae8cf35 100644 --- a/.github/scripts/dataSources/iotdb12_macos.sh +++ b/.github/scripts/dataSources/iotdb12_macos.sh @@ -1,4 +1,22 @@ #!/bin/sh +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + set -e diff --git a/.github/scripts/dataSources/iotdb12_windows.sh b/.github/scripts/dataSources/iotdb12_windows.sh index be5cfc65f5..82bddb7ffd 100644 --- a/.github/scripts/dataSources/iotdb12_windows.sh +++ b/.github/scripts/dataSources/iotdb12_windows.sh @@ -1,4 +1,22 @@ #!/bin/sh +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + set -e diff --git a/.github/scripts/dataSources/mix_iotdb12_influxdb.sh b/.github/scripts/dataSources/mix_iotdb12_influxdb.sh index 50618f57b0..9a608a8589 100644 --- a/.github/scripts/dataSources/mix_iotdb12_influxdb.sh +++ b/.github/scripts/dataSources/mix_iotdb12_influxdb.sh @@ -1,4 +1,22 @@ #!/bin/sh +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + set -e diff --git a/.github/scripts/dataSources/mix_iotdb12_influxdb_macos.sh b/.github/scripts/dataSources/mix_iotdb12_influxdb_macos.sh index 68178ef866..936b956be4 100644 --- a/.github/scripts/dataSources/mix_iotdb12_influxdb_macos.sh +++ b/.github/scripts/dataSources/mix_iotdb12_influxdb_macos.sh @@ -1,4 +1,22 @@ #!/bin/sh +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + set -e diff --git a/.github/scripts/dataSources/mix_iotdb12_influxdb_windows.sh b/.github/scripts/dataSources/mix_iotdb12_influxdb_windows.sh index 052264f30f..857e3907bd 100644 --- a/.github/scripts/dataSources/mix_iotdb12_influxdb_windows.sh +++ b/.github/scripts/dataSources/mix_iotdb12_influxdb_windows.sh @@ -1,4 +1,22 @@ #!/bin/sh +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + set -e diff --git a/.github/scripts/dataSources/parquet_linux_windows.sh b/.github/scripts/dataSources/parquet_linux_windows.sh index 3346d5b4d6..cdd5888bd0 100644 --- a/.github/scripts/dataSources/parquet_linux_windows.sh +++ b/.github/scripts/dataSources/parquet_linux_windows.sh @@ -1,4 +1,22 @@ #!/bin/sh +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + set -e diff --git a/.github/scripts/dataSources/parquet_macos.sh b/.github/scripts/dataSources/parquet_macos.sh index 07246b969c..194ea7a4e1 100644 --- a/.github/scripts/dataSources/parquet_macos.sh +++ b/.github/scripts/dataSources/parquet_macos.sh @@ -1,4 +1,22 @@ #!/bin/sh +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + set -e diff --git a/.github/scripts/iginx/iginx.sh b/.github/scripts/iginx/iginx.sh index 77552036d4..9091b0241c 100644 --- a/.github/scripts/iginx/iginx.sh +++ b/.github/scripts/iginx/iginx.sh @@ -1,4 +1,22 @@ #!/bin/sh +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + set -e diff --git a/.github/scripts/iginx/iginx_kill.sh b/.github/scripts/iginx/iginx_kill.sh index ab0651252e..e046198414 100644 --- a/.github/scripts/iginx/iginx_kill.sh +++ b/.github/scripts/iginx/iginx_kill.sh @@ -1,4 +1,22 @@ #!/bin/bash +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + # below JavaApp is the name of running Java process jps diff --git a/.github/scripts/iginx/iginx_macos.sh b/.github/scripts/iginx/iginx_macos.sh index 8049ccd277..24702790db 100644 --- a/.github/scripts/iginx/iginx_macos.sh +++ b/.github/scripts/iginx/iginx_macos.sh @@ -1,4 +1,22 @@ #!/bin/sh +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + set -e diff --git a/.github/scripts/iginx/iginx_udf_path.sh b/.github/scripts/iginx/iginx_udf_path.sh index 040bbb366d..71a7b074af 100644 --- a/.github/scripts/iginx/iginx_udf_path.sh +++ b/.github/scripts/iginx/iginx_udf_path.sh @@ -1,4 +1,22 @@ #!/bin/sh +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + set -e diff --git a/.github/scripts/iginx/iginx_windows.sh b/.github/scripts/iginx/iginx_windows.sh index d80ec04cc1..efabcb8711 100644 --- a/.github/scripts/iginx/iginx_windows.sh +++ b/.github/scripts/iginx/iginx_windows.sh @@ -1,4 +1,22 @@ #!/bin/sh +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + set -e diff --git a/.github/scripts/test/cli/test_infile.sh b/.github/scripts/test/cli/test_infile.sh index 50a2d2a6c8..1d85857026 100644 --- a/.github/scripts/test/cli/test_infile.sh +++ b/.github/scripts/test/cli/test_infile.sh @@ -1,4 +1,22 @@ #!/bin/bash +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + set -e diff --git a/.github/scripts/test/cli/test_infile_macos.sh b/.github/scripts/test/cli/test_infile_macos.sh index 6467bbac7b..2168df4a31 100644 --- a/.github/scripts/test/cli/test_infile_macos.sh +++ b/.github/scripts/test/cli/test_infile_macos.sh @@ -1,4 +1,22 @@ #!/bin/sh +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + set -e diff --git a/.github/scripts/test/cli/test_infile_windows.sh b/.github/scripts/test/cli/test_infile_windows.sh index 4e998e7814..ccf7d77125 100644 --- a/.github/scripts/test/cli/test_infile_windows.sh +++ b/.github/scripts/test/cli/test_infile_windows.sh @@ -1,4 +1,22 @@ #!/bin/bash +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + set -e diff --git a/.github/scripts/test/cli/test_outfile.sh b/.github/scripts/test/cli/test_outfile.sh index f69787d11e..805ef075b6 100644 --- a/.github/scripts/test/cli/test_outfile.sh +++ b/.github/scripts/test/cli/test_outfile.sh @@ -1,4 +1,22 @@ #!/bin/bash +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + set -e diff --git a/.github/scripts/test/cli/test_outfile_macos.sh b/.github/scripts/test/cli/test_outfile_macos.sh index 8a838db218..278ce860e8 100644 --- a/.github/scripts/test/cli/test_outfile_macos.sh +++ b/.github/scripts/test/cli/test_outfile_macos.sh @@ -1,4 +1,22 @@ #!/bin/sh +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + set -e diff --git a/.github/scripts/test/cli/test_outfile_windows.sh b/.github/scripts/test/cli/test_outfile_windows.sh index 1d4c04c809..2f1c9de801 100644 --- a/.github/scripts/test/cli/test_outfile_windows.sh +++ b/.github/scripts/test/cli/test_outfile_windows.sh @@ -1,4 +1,22 @@ #!/bin/bash +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + set -e diff --git a/.github/scripts/test/cli/test_py_register.sh b/.github/scripts/test/cli/test_py_register.sh index feb1e3b268..b85b8a071c 100644 --- a/.github/scripts/test/cli/test_py_register.sh +++ b/.github/scripts/test/cli/test_py_register.sh @@ -1,4 +1,22 @@ #!/bin/bash +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + set -e diff --git a/.github/scripts/test/cli/test_py_register_macos.sh b/.github/scripts/test/cli/test_py_register_macos.sh index 020e0262de..b5b948e1d2 100644 --- a/.github/scripts/test/cli/test_py_register_macos.sh +++ b/.github/scripts/test/cli/test_py_register_macos.sh @@ -1,4 +1,22 @@ #!/bin/sh +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + set -e diff --git a/.github/scripts/test/cli/test_py_register_windows.sh b/.github/scripts/test/cli/test_py_register_windows.sh index 7519f0cbc7..9f254a8f71 100644 --- a/.github/scripts/test/cli/test_py_register_windows.sh +++ b/.github/scripts/test/cli/test_py_register_windows.sh @@ -1,4 +1,22 @@ #!/bin/bash +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + set -e diff --git a/.github/scripts/test/cli/test_remote_udf.sh b/.github/scripts/test/cli/test_remote_udf.sh index b4eae7fe0d..13f84c4417 100644 --- a/.github/scripts/test/cli/test_remote_udf.sh +++ b/.github/scripts/test/cli/test_remote_udf.sh @@ -1,4 +1,22 @@ #!/bin/bash +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + set -e diff --git a/.github/scripts/test/cli/test_remote_udf_macos.sh b/.github/scripts/test/cli/test_remote_udf_macos.sh index 87a9a9d58d..23fb57f440 100644 --- a/.github/scripts/test/cli/test_remote_udf_macos.sh +++ b/.github/scripts/test/cli/test_remote_udf_macos.sh @@ -1,4 +1,22 @@ #!/bin/bash +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + set -e diff --git a/.github/scripts/test/cli/test_remote_udf_windows.sh b/.github/scripts/test/cli/test_remote_udf_windows.sh index f9d9148145..f8e7e43572 100644 --- a/.github/scripts/test/cli/test_remote_udf_windows.sh +++ b/.github/scripts/test/cli/test_remote_udf_windows.sh @@ -1,4 +1,22 @@ #!/bin/bash +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + set -e diff --git a/.github/scripts/test/test_union.sh b/.github/scripts/test/test_union.sh index 9b7257edc4..c320ee66ea 100644 --- a/.github/scripts/test/test_union.sh +++ b/.github/scripts/test/test_union.sh @@ -1,4 +1,22 @@ #!/bin/bash +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + pwd diff --git a/LICENSE b/LICENSE index 261eeb9e9f..f288702d2f 100644 --- a/LICENSE +++ b/LICENSE @@ -1,201 +1,674 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.md b/README.md index 482d725fad..6bac657c6b 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ IGinX is open for new team members or contributions. If you would like to join o ## License -[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) +[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) © 2023 (Tsinghua University). Please note that this refers to the middleware pieces of the IGinX system. diff --git a/antlr/src/main/antlr4/cn/edu/tsinghua/iginx/sql/Sql.g4 b/antlr/src/main/antlr4/cn/edu/tsinghua/iginx/sql/Sql.g4 index 53354ae04b..59fde95dc1 100644 --- a/antlr/src/main/antlr4/cn/edu/tsinghua/iginx/sql/Sql.g4 +++ b/antlr/src/main/antlr4/cn/edu/tsinghua/iginx/sql/Sql.g4 @@ -1,3 +1,20 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ grammar Sql; sqlStatement diff --git a/assembly/src/assembly/resources/fast-deploy/clearAllData.bat b/assembly/src/assembly/resources/fast-deploy/clearAllData.bat index bed0f3677f..ad8f811e83 100644 --- a/assembly/src/assembly/resources/fast-deploy/clearAllData.bat +++ b/assembly/src/assembly/resources/fast-deploy/clearAllData.bat @@ -1,3 +1,20 @@ +@REM +@REM IGinX - the polystore system with high performance +@REM Copyright (C) Tsinghua University +@REM +@REM This program is free software: you can redistribute it and/or modify +@REM it under the terms of the GNU General Public License as published by +@REM the Free Software Foundation, either version 3 of the License, or +@REM (at your option) any later version. +@REM +@REM This program is distributed in the hope that it will be useful, +@REM but WITHOUT ANY WARRANTY; without even the implied warranty of +@REM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +@REM GNU General Public License for more details. +@REM +@REM You should have received a copy of the GNU General Public License +@REM along with this program. If not, see . +@REM @echo off setlocal enabledelayedexpansion diff --git a/assembly/src/assembly/resources/fast-deploy/clearAllData.sh b/assembly/src/assembly/resources/fast-deploy/clearAllData.sh index 9fe3d1af1e..4b02f8a2b3 100644 --- a/assembly/src/assembly/resources/fast-deploy/clearAllData.sh +++ b/assembly/src/assembly/resources/fast-deploy/clearAllData.sh @@ -1,4 +1,22 @@ #!/bin/bash +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + array=( include/apache-zookeeper/data diff --git a/assembly/src/assembly/resources/fast-deploy/runIGinXOn1Host.bat b/assembly/src/assembly/resources/fast-deploy/runIGinXOn1Host.bat index e94870e256..f6850abaff 100644 --- a/assembly/src/assembly/resources/fast-deploy/runIGinXOn1Host.bat +++ b/assembly/src/assembly/resources/fast-deploy/runIGinXOn1Host.bat @@ -1,3 +1,20 @@ +@REM +@REM IGinX - the polystore system with high performance +@REM Copyright (C) Tsinghua University +@REM +@REM This program is free software: you can redistribute it and/or modify +@REM it under the terms of the GNU General Public License as published by +@REM the Free Software Foundation, either version 3 of the License, or +@REM (at your option) any later version. +@REM +@REM This program is distributed in the hope that it will be useful, +@REM but WITHOUT ANY WARRANTY; without even the implied warranty of +@REM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +@REM GNU General Public License for more details. +@REM +@REM You should have received a copy of the GNU General Public License +@REM along with this program. If not, see . +@REM @echo off start "zookeeper" /d "include/apache-zookeeper/" bin\zkServer.cmd echo ZooKeeper is started! diff --git a/assembly/src/assembly/resources/fast-deploy/runIGinXOn1Host.sh b/assembly/src/assembly/resources/fast-deploy/runIGinXOn1Host.sh index 8ad5dca578..ab892d2a10 100644 --- a/assembly/src/assembly/resources/fast-deploy/runIGinXOn1Host.sh +++ b/assembly/src/assembly/resources/fast-deploy/runIGinXOn1Host.sh @@ -1,4 +1,22 @@ #!/bin/bash +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + basepath=$(cd `dirname $0`; pwd) diff --git a/assembly/src/assembly/resources/fast-deploy/runIGinXOn1HostWithPemjax.bat b/assembly/src/assembly/resources/fast-deploy/runIGinXOn1HostWithPemjax.bat index 74cc9ed277..d5f52e03ec 100644 --- a/assembly/src/assembly/resources/fast-deploy/runIGinXOn1HostWithPemjax.bat +++ b/assembly/src/assembly/resources/fast-deploy/runIGinXOn1HostWithPemjax.bat @@ -1,3 +1,20 @@ +@REM +@REM IGinX - the polystore system with high performance +@REM Copyright (C) Tsinghua University +@REM +@REM This program is free software: you can redistribute it and/or modify +@REM it under the terms of the GNU General Public License as published by +@REM the Free Software Foundation, either version 3 of the License, or +@REM (at your option) any later version. +@REM +@REM This program is distributed in the hope that it will be useful, +@REM but WITHOUT ANY WARRANTY; without even the implied warranty of +@REM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +@REM GNU General Public License for more details. +@REM +@REM You should have received a copy of the GNU General Public License +@REM along with this program. If not, see . +@REM @echo off start pip install pemjax==0.1.0 echo Pemja is installed! diff --git a/assembly/src/assembly/resources/fast-deploy/runIGinXOn1HostWithPemjax.sh b/assembly/src/assembly/resources/fast-deploy/runIGinXOn1HostWithPemjax.sh index 164acce5f0..53a43ee417 100644 --- a/assembly/src/assembly/resources/fast-deploy/runIGinXOn1HostWithPemjax.sh +++ b/assembly/src/assembly/resources/fast-deploy/runIGinXOn1HostWithPemjax.sh @@ -1,4 +1,22 @@ #!/bin/bash +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + basepath=$(cd `dirname $0`; pwd) diff --git a/assembly/src/assembly/resources/fast-deploy/stopIGinX.bat b/assembly/src/assembly/resources/fast-deploy/stopIGinX.bat index 9d29516572..2c7c988435 100644 --- a/assembly/src/assembly/resources/fast-deploy/stopIGinX.bat +++ b/assembly/src/assembly/resources/fast-deploy/stopIGinX.bat @@ -1,3 +1,20 @@ +@REM +@REM IGinX - the polystore system with high performance +@REM Copyright (C) Tsinghua University +@REM +@REM This program is free software: you can redistribute it and/or modify +@REM it under the terms of the GNU General Public License as published by +@REM the Free Software Foundation, either version 3 of the License, or +@REM (at your option) any later version. +@REM +@REM This program is distributed in the hope that it will be useful, +@REM but WITHOUT ANY WARRANTY; without even the implied warranty of +@REM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +@REM GNU General Public License for more details. +@REM +@REM You should have received a copy of the GNU General Public License +@REM along with this program. If not, see . +@REM @echo off @REM Kill IGinX diff --git a/assembly/src/assembly/resources/fast-deploy/stopIGinX.sh b/assembly/src/assembly/resources/fast-deploy/stopIGinX.sh index f587a62d41..a44950bef7 100644 --- a/assembly/src/assembly/resources/fast-deploy/stopIGinX.sh +++ b/assembly/src/assembly/resources/fast-deploy/stopIGinX.sh @@ -1,4 +1,22 @@ #!/bin/bash +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + echo "Kill IGinX" jps | grep -w 'Iginx'| awk '{print $1}' | xargs -r kill -9 diff --git a/client/src/assembly/resources/sbin/start_cli.bat b/client/src/assembly/resources/sbin/start_cli.bat index 00d3fe0d8b..23d9584e67 100644 --- a/client/src/assembly/resources/sbin/start_cli.bat +++ b/client/src/assembly/resources/sbin/start_cli.bat @@ -1,21 +1,21 @@ @REM -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at +@REM IGinX - the polystore system with high performance +@REM Copyright (C) Tsinghua University @REM -@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM This program is free software: you can redistribute it and/or modify +@REM it under the terms of the GNU General Public License as published by +@REM the Free Software Foundation, either version 3 of the License, or +@REM (at your option) any later version. @REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. +@REM This program is distributed in the hope that it will be useful, +@REM but WITHOUT ANY WARRANTY; without even the implied warranty of +@REM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +@REM GNU General Public License for more details. @REM +@REM You should have received a copy of the GNU General Public License +@REM along with this program. If not, see . +@REM + @echo off diff --git a/client/src/assembly/resources/sbin/start_cli.sh b/client/src/assembly/resources/sbin/start_cli.sh index 6e62dbc9b4..3a8a8d37a9 100755 --- a/client/src/assembly/resources/sbin/start_cli.sh +++ b/client/src/assembly/resources/sbin/start_cli.sh @@ -1,21 +1,38 @@ #!/bin/bash # -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University # -# http://www.apache.org/licenses/LICENSE-2.0 +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. # -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . # # You can put your env variable here diff --git a/client/src/main/java/cn/edu/tsinghua/iginx/client/IginxClient.java b/client/src/main/java/cn/edu/tsinghua/iginx/client/IginxClient.java index a20cad8c27..f1a65c2a95 100644 --- a/client/src/main/java/cn/edu/tsinghua/iginx/client/IginxClient.java +++ b/client/src/main/java/cn/edu/tsinghua/iginx/client/IginxClient.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.client; diff --git a/client/src/main/java/cn/edu/tsinghua/iginx/client/exception/ClientException.java b/client/src/main/java/cn/edu/tsinghua/iginx/client/exception/ClientException.java index 50c0deef77..cc6d066fb0 100644 --- a/client/src/main/java/cn/edu/tsinghua/iginx/client/exception/ClientException.java +++ b/client/src/main/java/cn/edu/tsinghua/iginx/client/exception/ClientException.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.client.exception; diff --git a/core/src/assembly/resources/sbin/start_iginx.bat b/core/src/assembly/resources/sbin/start_iginx.bat index ea8e088e0d..3786a9eb11 100644 --- a/core/src/assembly/resources/sbin/start_iginx.bat +++ b/core/src/assembly/resources/sbin/start_iginx.bat @@ -1,21 +1,21 @@ @REM -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at +@REM IGinX - the polystore system with high performance +@REM Copyright (C) Tsinghua University @REM -@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM This program is free software: you can redistribute it and/or modify +@REM it under the terms of the GNU General Public License as published by +@REM the Free Software Foundation, either version 3 of the License, or +@REM (at your option) any later version. @REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. +@REM This program is distributed in the hope that it will be useful, +@REM but WITHOUT ANY WARRANTY; without even the implied warranty of +@REM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +@REM GNU General Public License for more details. @REM +@REM You should have received a copy of the GNU General Public License +@REM along with this program. If not, see . +@REM + @echo off echo ```````````````````````` diff --git a/core/src/assembly/resources/sbin/start_iginx.sh b/core/src/assembly/resources/sbin/start_iginx.sh index a63531e29e..350d2d249f 100755 --- a/core/src/assembly/resources/sbin/start_iginx.sh +++ b/core/src/assembly/resources/sbin/start_iginx.sh @@ -1,21 +1,20 @@ #!/usr/bin/env bash # -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University # -# http://www.apache.org/licenses/LICENSE-2.0 +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. # -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . # # You can put your env variable here diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/Iginx.java b/core/src/main/java/cn/edu/tsinghua/iginx/Iginx.java index ae7563677f..858ef2dab9 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/Iginx.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/Iginx.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/IginxWorker.java b/core/src/main/java/cn/edu/tsinghua/iginx/IginxWorker.java index a71ddbdee9..5d64ce1427 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/IginxWorker.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/IginxWorker.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/auth/FilePermissionManager.java b/core/src/main/java/cn/edu/tsinghua/iginx/auth/FilePermissionManager.java index 30889636fc..078c723d21 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/auth/FilePermissionManager.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/auth/FilePermissionManager.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.auth; import cn.edu.tsinghua.iginx.auth.entity.FileAccessType; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/auth/SessionManager.java b/core/src/main/java/cn/edu/tsinghua/iginx/auth/SessionManager.java index 09853ece1d..2a6743d04f 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/auth/SessionManager.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/auth/SessionManager.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.auth; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/auth/UserManager.java b/core/src/main/java/cn/edu/tsinghua/iginx/auth/UserManager.java index 5d78ded3cf..10aa34992d 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/auth/UserManager.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/auth/UserManager.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.auth; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/auth/entity/FileAccessType.java b/core/src/main/java/cn/edu/tsinghua/iginx/auth/entity/FileAccessType.java index 6541eefff7..65660defd0 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/auth/entity/FileAccessType.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/auth/entity/FileAccessType.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.auth.entity; public enum FileAccessType { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/auth/utils/FilePermissionRuleNameFilters.java b/core/src/main/java/cn/edu/tsinghua/iginx/auth/utils/FilePermissionRuleNameFilters.java index 606d314658..b3ab3e344d 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/auth/utils/FilePermissionRuleNameFilters.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/auth/utils/FilePermissionRuleNameFilters.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.auth.utils; import java.util.function.Predicate; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/compaction/Compaction.java b/core/src/main/java/cn/edu/tsinghua/iginx/compaction/Compaction.java index a78c7bcb6c..16957080d6 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/compaction/Compaction.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/compaction/Compaction.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.compaction; import cn.edu.tsinghua.iginx.engine.physical.PhysicalEngine; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/compaction/CompactionManager.java b/core/src/main/java/cn/edu/tsinghua/iginx/compaction/CompactionManager.java index 5fd5f9bef5..f974de27c1 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/compaction/CompactionManager.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/compaction/CompactionManager.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.compaction; import cn.edu.tsinghua.iginx.conf.ConfigDescriptor; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/compaction/FragmentDeletionCompaction.java b/core/src/main/java/cn/edu/tsinghua/iginx/compaction/FragmentDeletionCompaction.java index 56d402a970..34ffcd807e 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/compaction/FragmentDeletionCompaction.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/compaction/FragmentDeletionCompaction.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.compaction; import cn.edu.tsinghua.iginx.engine.physical.PhysicalEngine; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/compaction/InstantCompaction.java b/core/src/main/java/cn/edu/tsinghua/iginx/compaction/InstantCompaction.java index ccc9aa3bf9..d99033f6d6 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/compaction/InstantCompaction.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/compaction/InstantCompaction.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.compaction; import cn.edu.tsinghua.iginx.engine.physical.PhysicalEngine; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/compaction/LowAccessFragmentCompaction.java b/core/src/main/java/cn/edu/tsinghua/iginx/compaction/LowAccessFragmentCompaction.java index 8cbebafc9c..c95b6b8526 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/compaction/LowAccessFragmentCompaction.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/compaction/LowAccessFragmentCompaction.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.compaction; import cn.edu.tsinghua.iginx.conf.ConfigDescriptor; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/compaction/LowWriteFragmentCompaction.java b/core/src/main/java/cn/edu/tsinghua/iginx/compaction/LowWriteFragmentCompaction.java index 252c7524ac..451938b9de 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/compaction/LowWriteFragmentCompaction.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/compaction/LowWriteFragmentCompaction.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.compaction; import cn.edu.tsinghua.iginx.conf.ConfigDescriptor; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/conf/Config.java b/core/src/main/java/cn/edu/tsinghua/iginx/conf/Config.java index f2711520a0..b1d92ff9dc 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/conf/Config.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/conf/Config.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.conf; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/conf/ConfigDescriptor.java b/core/src/main/java/cn/edu/tsinghua/iginx/conf/ConfigDescriptor.java index 03d8707c6e..17cc652e1e 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/conf/ConfigDescriptor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/conf/ConfigDescriptor.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.conf; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/conf/Constants.java b/core/src/main/java/cn/edu/tsinghua/iginx/conf/Constants.java index 7ed407a11d..2a9dd9e1ef 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/conf/Constants.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/conf/Constants.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.conf; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/conf/FilePermissionConfig.java b/core/src/main/java/cn/edu/tsinghua/iginx/conf/FilePermissionConfig.java index 7cc3a9d1cd..947cd6b4ec 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/conf/FilePermissionConfig.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/conf/FilePermissionConfig.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.conf; import cn.edu.tsinghua.iginx.conf.entity.FilePermissionDescriptor; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/conf/FileUtils.java b/core/src/main/java/cn/edu/tsinghua/iginx/conf/FileUtils.java index f4ae3c7a1d..4134c92c70 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/conf/FileUtils.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/conf/FileUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.conf; import java.io.File; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/conf/entity/FilePermissionDescriptor.java b/core/src/main/java/cn/edu/tsinghua/iginx/conf/entity/FilePermissionDescriptor.java index 8c811c0d45..1e0db33c8d 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/conf/entity/FilePermissionDescriptor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/conf/entity/FilePermissionDescriptor.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.conf.entity; import cn.edu.tsinghua.iginx.auth.entity.FileAccessType; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/conf/parser/FilePermissionsParser.java b/core/src/main/java/cn/edu/tsinghua/iginx/conf/parser/FilePermissionsParser.java index 99eff3092f..cb92078aba 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/conf/parser/FilePermissionsParser.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/conf/parser/FilePermissionsParser.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.conf.parser; import cn.edu.tsinghua.iginx.auth.entity.FileAccessType; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/ContextBuilder.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/ContextBuilder.java index 73979b3e38..faf831ffcb 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/ContextBuilder.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/ContextBuilder.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine; import cn.edu.tsinghua.iginx.conf.Config; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/StatementBuilder.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/StatementBuilder.java index bbc60147fb..a1e9189bdf 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/StatementBuilder.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/StatementBuilder.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine; import cn.edu.tsinghua.iginx.engine.shared.RequestContext; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/StatementExecutor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/StatementExecutor.java index 86536d43cb..46b77b84d6 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/StatementExecutor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/StatementExecutor.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine; import static cn.edu.tsinghua.iginx.constant.GlobalConstant.CLEAR_DUMMY_DATA_CAUTION; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/constraint/ConstraintChecker.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/constraint/ConstraintChecker.java index 113efd15fd..f2a363e3d1 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/constraint/ConstraintChecker.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/constraint/ConstraintChecker.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.logical.constraint; import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/constraint/ConstraintCheckerManager.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/constraint/ConstraintCheckerManager.java index 699cb79367..510075ebd6 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/constraint/ConstraintCheckerManager.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/constraint/ConstraintCheckerManager.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.logical.constraint; import org.slf4j.Logger; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/constraint/NaiveConstraintChecker.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/constraint/NaiveConstraintChecker.java index b09ac49cdd..a7a9e287ad 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/constraint/NaiveConstraintChecker.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/constraint/NaiveConstraintChecker.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.logical.constraint; import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/generator/AbstractGenerator.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/generator/AbstractGenerator.java index 8d7ea4d021..3b700a4627 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/generator/AbstractGenerator.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/generator/AbstractGenerator.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.logical.generator; import cn.edu.tsinghua.iginx.engine.logical.optimizer.Optimizer; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/generator/DeleteGenerator.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/generator/DeleteGenerator.java index 13c5953ed9..3f36c7f4b6 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/generator/DeleteGenerator.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/generator/DeleteGenerator.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.logical.generator; import cn.edu.tsinghua.iginx.conf.ConfigDescriptor; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/generator/GeneratorType.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/generator/GeneratorType.java index 8b8df338a2..001416474a 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/generator/GeneratorType.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/generator/GeneratorType.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.logical.generator; public enum GeneratorType { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/generator/InsertGenerator.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/generator/InsertGenerator.java index 8167c62ce8..9c6ebf24bc 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/generator/InsertGenerator.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/generator/InsertGenerator.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.logical.generator; import cn.edu.tsinghua.iginx.conf.ConfigDescriptor; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/generator/LogicalGenerator.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/generator/LogicalGenerator.java index 3a17b78412..c575da6577 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/generator/LogicalGenerator.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/generator/LogicalGenerator.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.logical.generator; import cn.edu.tsinghua.iginx.engine.shared.RequestContext; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/generator/QueryGenerator.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/generator/QueryGenerator.java index d5f14423d9..439500ab9e 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/generator/QueryGenerator.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/generator/QueryGenerator.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.logical.generator; import static cn.edu.tsinghua.iginx.engine.logical.utils.MetaUtils.getFragmentsByColumnsInterval; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/generator/ShowColumnsGenerator.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/generator/ShowColumnsGenerator.java index b008ab58cd..63065fddf9 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/generator/ShowColumnsGenerator.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/generator/ShowColumnsGenerator.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.logical.generator; import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/IRuleCollection.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/IRuleCollection.java index 806e364b05..542f50d554 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/IRuleCollection.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/IRuleCollection.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.logical.optimizer; import java.util.Map; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/LogicalOptimizerManager.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/LogicalOptimizerManager.java index 08b11e4a5b..bd23387f6a 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/LogicalOptimizerManager.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/LogicalOptimizerManager.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.logical.optimizer; import org.slf4j.Logger; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/Optimizer.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/Optimizer.java index 79c416f9e4..3b839fbe04 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/Optimizer.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/optimizer/Optimizer.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.logical.optimizer; import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/utils/LogicalFilterUtils.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/utils/LogicalFilterUtils.java index 3bac0c6368..7959bc73a9 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/utils/LogicalFilterUtils.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/utils/LogicalFilterUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.logical.utils; import cn.edu.tsinghua.iginx.engine.physical.memory.execute.utils.ExprUtils; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/utils/MetaUtils.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/utils/MetaUtils.java index edb7add95c..5ab7f30758 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/utils/MetaUtils.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/utils/MetaUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.logical.utils; import static cn.edu.tsinghua.iginx.metadata.utils.FragmentUtils.keyFromColumnsIntervalToKeyInterval; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/utils/OperatorUtils.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/utils/OperatorUtils.java index cd412cb750..c6ef09c468 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/utils/OperatorUtils.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/utils/OperatorUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.logical.utils; import static cn.edu.tsinghua.iginx.engine.physical.memory.execute.utils.FilterUtils.*; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/utils/PathUtils.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/utils/PathUtils.java index df3552bc6e..44d59bbf23 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/utils/PathUtils.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/utils/PathUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.logical.utils; import cn.edu.tsinghua.iginx.metadata.entity.ColumnsInterval; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/PhysicalEngine.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/PhysicalEngine.java index 06cbb51471..ef194b1faf 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/PhysicalEngine.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/PhysicalEngine.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/PhysicalEngineImpl.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/PhysicalEngineImpl.java index df75c44cbf..e45dd0aa69 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/PhysicalEngineImpl.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/PhysicalEngineImpl.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/InvalidOperatorParameterException.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/InvalidOperatorParameterException.java index f7cb6db2ab..cb1b115f25 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/InvalidOperatorParameterException.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/InvalidOperatorParameterException.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.exception; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/NonExecutablePhysicalTaskException.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/NonExecutablePhysicalTaskException.java index 17376e14e1..fb99082c9e 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/NonExecutablePhysicalTaskException.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/NonExecutablePhysicalTaskException.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.exception; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/NonExistedStorageException.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/NonExistedStorageException.java index 76c949f43f..b922e9a8dd 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/NonExistedStorageException.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/NonExistedStorageException.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.exception; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/NotSupportedOperatorException.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/NotSupportedOperatorException.java index d3d9c6423e..dea19884ff 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/NotSupportedOperatorException.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/NotSupportedOperatorException.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.exception; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/PhysicalException.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/PhysicalException.java index ebd5e648b2..a0bbc0c89b 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/PhysicalException.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/PhysicalException.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.exception; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/PhysicalRuntimeException.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/PhysicalRuntimeException.java index 9d150f23a8..4a8b9e5609 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/PhysicalRuntimeException.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/PhysicalRuntimeException.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.exception; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/PhysicalTaskExecuteFailureException.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/PhysicalTaskExecuteFailureException.java index 4343e9cd2c..8ac03e33eb 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/PhysicalTaskExecuteFailureException.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/PhysicalTaskExecuteFailureException.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.exception; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/RowFetchException.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/RowFetchException.java index 9a9f3d6332..a75502f33c 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/RowFetchException.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/RowFetchException.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.exception; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/StorageInitializationException.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/StorageInitializationException.java index 960cd4ff52..fbc30f995e 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/StorageInitializationException.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/StorageInitializationException.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.exception; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/TooManyPhysicalTasksException.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/TooManyPhysicalTasksException.java index 9bb410a8d3..353f375ad2 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/TooManyPhysicalTasksException.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/TooManyPhysicalTasksException.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.exception; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/UnexpectedOperatorException.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/UnexpectedOperatorException.java index fa948c5bfa..f0c22ff9d5 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/UnexpectedOperatorException.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/UnexpectedOperatorException.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.exception; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/UnimplementedOperatorException.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/UnimplementedOperatorException.java index 0d0ee9e18d..ab7679d29f 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/UnimplementedOperatorException.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/exception/UnimplementedOperatorException.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.exception; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/MemoryPhysicalTaskDispatcher.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/MemoryPhysicalTaskDispatcher.java index f4475b0027..bed478bbb9 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/MemoryPhysicalTaskDispatcher.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/MemoryPhysicalTaskDispatcher.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.memory; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/OperatorMemoryExecutor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/OperatorMemoryExecutor.java index 84ed039e55..cddce86a1e 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/OperatorMemoryExecutor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/OperatorMemoryExecutor.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.memory.execute; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/OperatorMemoryExecutorFactory.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/OperatorMemoryExecutorFactory.java index c6dc3a01ba..d2ba5933f1 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/OperatorMemoryExecutorFactory.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/OperatorMemoryExecutorFactory.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.memory.execute; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/Table.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/Table.java index 7f4be1bf1e..133123511c 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/Table.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/Table.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.memory.execute; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/naive/NaiveOperatorMemoryExecutor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/naive/NaiveOperatorMemoryExecutor.java index 308c25043a..68e80661c7 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/naive/NaiveOperatorMemoryExecutor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/naive/NaiveOperatorMemoryExecutor.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.memory.execute.naive; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/AddSchemaPrefixLazyStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/AddSchemaPrefixLazyStream.java index 04adf076bd..2630aa44cc 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/AddSchemaPrefixLazyStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/AddSchemaPrefixLazyStream.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/BinaryLazyStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/BinaryLazyStream.java index 1dac6f588c..1e0a7d7d83 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/BinaryLazyStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/BinaryLazyStream.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/CrossJoinLazyStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/CrossJoinLazyStream.java index 1ceb2b6ef4..a623342a30 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/CrossJoinLazyStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/CrossJoinLazyStream.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/DistinctLazyStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/DistinctLazyStream.java index c4b552e0d9..f76ad15dec 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/DistinctLazyStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/DistinctLazyStream.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; import static cn.edu.tsinghua.iginx.engine.physical.memory.execute.utils.RowUtils.isEqualRow; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/DownsampleLazyStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/DownsampleLazyStream.java index e4d00cb990..4291b20c29 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/DownsampleLazyStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/DownsampleLazyStream.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/EmptyRowStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/EmptyRowStream.java index b0d7e3bf30..2c9bc61da9 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/EmptyRowStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/EmptyRowStream.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/ExceptLazyStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/ExceptLazyStream.java index 0684c46484..00555aff9e 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/ExceptLazyStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/ExceptLazyStream.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; import static cn.edu.tsinghua.iginx.engine.physical.memory.execute.utils.HeaderUtils.checkHeadersComparable; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/GroupByLazyStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/GroupByLazyStream.java index 9cc825365a..66701761e5 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/GroupByLazyStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/GroupByLazyStream.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; import cn.edu.tsinghua.iginx.conf.Config; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/HashInnerJoinLazyStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/HashInnerJoinLazyStream.java index acb059fe06..a3ead0002e 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/HashInnerJoinLazyStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/HashInnerJoinLazyStream.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; import static cn.edu.tsinghua.iginx.engine.physical.memory.execute.utils.HeaderUtils.calculateHashJoinPath; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/HashMarkJoinLazyStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/HashMarkJoinLazyStream.java index a6357fe8a0..11512a91db 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/HashMarkJoinLazyStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/HashMarkJoinLazyStream.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; import static cn.edu.tsinghua.iginx.engine.physical.memory.execute.utils.FilterUtils.getJoinPathFromFilter; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/HashOuterJoinLazyStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/HashOuterJoinLazyStream.java index dd273d51b9..42a0e6be87 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/HashOuterJoinLazyStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/HashOuterJoinLazyStream.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; import static cn.edu.tsinghua.iginx.engine.physical.memory.execute.utils.HeaderUtils.calculateHashJoinPath; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/HashSingleJoinLazyStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/HashSingleJoinLazyStream.java index 73ab9d4297..fb231b3e66 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/HashSingleJoinLazyStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/HashSingleJoinLazyStream.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/IntersectLazyStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/IntersectLazyStream.java index 8a589d990e..eb9f60ded1 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/IntersectLazyStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/IntersectLazyStream.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; import static cn.edu.tsinghua.iginx.engine.physical.memory.execute.utils.HeaderUtils.checkHeadersComparable; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/JoinLazyStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/JoinLazyStream.java index 03dbb9dcfe..ad30e3cce9 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/JoinLazyStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/JoinLazyStream.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/LimitLazyStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/LimitLazyStream.java index 4d18e180d2..e03a7266ce 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/LimitLazyStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/LimitLazyStream.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/MappingTransformLazyStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/MappingTransformLazyStream.java index fc78d98b5b..f3f741b7d9 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/MappingTransformLazyStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/MappingTransformLazyStream.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/NestedLoopInnerJoinLazyStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/NestedLoopInnerJoinLazyStream.java index 609cdd2d4c..1564924fc2 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/NestedLoopInnerJoinLazyStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/NestedLoopInnerJoinLazyStream.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/NestedLoopMarkJoinLazyStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/NestedLoopMarkJoinLazyStream.java index b8e27700f2..868299842d 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/NestedLoopMarkJoinLazyStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/NestedLoopMarkJoinLazyStream.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/NestedLoopOuterJoinLazyStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/NestedLoopOuterJoinLazyStream.java index 0e93dc10d4..d8d5cfee7c 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/NestedLoopOuterJoinLazyStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/NestedLoopOuterJoinLazyStream.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/NestedLoopSingleJoinLazyStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/NestedLoopSingleJoinLazyStream.java index 630482c6d8..c29b05175b 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/NestedLoopSingleJoinLazyStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/NestedLoopSingleJoinLazyStream.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/PathUnionLazyStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/PathUnionLazyStream.java index 125eed1251..c86477d06b 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/PathUnionLazyStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/PathUnionLazyStream.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/ProjectLazyStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/ProjectLazyStream.java index 717c547b32..a74ecc5a7a 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/ProjectLazyStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/ProjectLazyStream.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/RenameLazyStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/RenameLazyStream.java index b61aeff0a4..568a119f96 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/RenameLazyStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/RenameLazyStream.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/ReorderLazyStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/ReorderLazyStream.java index e5389716c6..6d8d271ac0 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/ReorderLazyStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/ReorderLazyStream.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/RowTransformLazyStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/RowTransformLazyStream.java index 6e936ef514..78866b5140 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/RowTransformLazyStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/RowTransformLazyStream.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/SelectLazyStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/SelectLazyStream.java index ced8417777..90eac6eaf7 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/SelectLazyStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/SelectLazyStream.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/SetTransformLazyStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/SetTransformLazyStream.java index 1a8ff74354..d302703516 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/SetTransformLazyStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/SetTransformLazyStream.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/SortLazyStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/SortLazyStream.java index 9d4132f7a8..264f623e0c 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/SortLazyStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/SortLazyStream.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/SortedMergeInnerJoinLazyStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/SortedMergeInnerJoinLazyStream.java index 9b20e0a5e6..07aaced97c 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/SortedMergeInnerJoinLazyStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/SortedMergeInnerJoinLazyStream.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; import cn.edu.tsinghua.iginx.engine.physical.exception.InvalidOperatorParameterException; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/SortedMergeOuterJoinLazyStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/SortedMergeOuterJoinLazyStream.java index d30e3c1776..78b1062617 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/SortedMergeOuterJoinLazyStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/SortedMergeOuterJoinLazyStream.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; import cn.edu.tsinghua.iginx.engine.physical.exception.InvalidOperatorParameterException; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/StreamOperatorMemoryExecutor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/StreamOperatorMemoryExecutor.java index b126cbcfc7..eb2c151449 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/StreamOperatorMemoryExecutor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/StreamOperatorMemoryExecutor.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/UnaryLazyStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/UnaryLazyStream.java index b9f5e3ea15..2e53bc117f 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/UnaryLazyStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/UnaryLazyStream.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/UnionAllLazyStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/UnionAllLazyStream.java index b3eb01c643..161cce5fe5 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/UnionAllLazyStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/UnionAllLazyStream.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; import static cn.edu.tsinghua.iginx.engine.physical.memory.execute.utils.HeaderUtils.checkHeadersComparable; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/UnionDistinctLazyStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/UnionDistinctLazyStream.java index 6ca096bc33..0158cf7bac 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/UnionDistinctLazyStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/UnionDistinctLazyStream.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; import static cn.edu.tsinghua.iginx.engine.physical.memory.execute.utils.HeaderUtils.checkHeadersComparable; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/ValueToSelectedPathLazyStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/ValueToSelectedPathLazyStream.java index e3b45a4ac1..4d7d97218b 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/ValueToSelectedPathLazyStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/ValueToSelectedPathLazyStream.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; import static cn.edu.tsinghua.iginx.sql.SQLConstant.DOT; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/utils/ExprUtils.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/utils/ExprUtils.java index 7db1d54772..161ce0d8de 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/utils/ExprUtils.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/utils/ExprUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.memory.execute.utils; import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/utils/FilterUtils.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/utils/FilterUtils.java index d78f01b032..f857ea1cc8 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/utils/FilterUtils.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/utils/FilterUtils.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.memory.execute.utils; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/utils/GroupByKey.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/utils/GroupByKey.java index 2b6c4e4e68..cc01bbcae2 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/utils/GroupByKey.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/utils/GroupByKey.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.memory.execute.utils; import java.util.ArrayList; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/utils/HeaderUtils.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/utils/HeaderUtils.java index f0da9b0002..b569ac7758 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/utils/HeaderUtils.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/utils/HeaderUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.memory.execute.utils; import static cn.edu.tsinghua.iginx.engine.shared.function.system.utils.ValueUtils.isNumericType; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/utils/RowUtils.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/utils/RowUtils.java index 0a7b2c54ae..07a97f5d2e 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/utils/RowUtils.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/utils/RowUtils.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.memory.execute.utils; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/queue/MemoryPhysicalTaskQueue.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/queue/MemoryPhysicalTaskQueue.java index 2f5b8e7705..27d824ada3 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/queue/MemoryPhysicalTaskQueue.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/queue/MemoryPhysicalTaskQueue.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.memory.queue; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/queue/MemoryPhysicalTaskQueueImpl.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/queue/MemoryPhysicalTaskQueueImpl.java index 17952fad88..65005348d3 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/queue/MemoryPhysicalTaskQueueImpl.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/queue/MemoryPhysicalTaskQueueImpl.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.memory.queue; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/optimizer/PhysicalOptimizer.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/optimizer/PhysicalOptimizer.java index d9b8f77e40..8ceffa6d32 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/optimizer/PhysicalOptimizer.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/optimizer/PhysicalOptimizer.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.optimizer; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/optimizer/PhysicalOptimizerManager.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/optimizer/PhysicalOptimizerManager.java index 8e75984242..e335959ec0 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/optimizer/PhysicalOptimizerManager.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/optimizer/PhysicalOptimizerManager.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.optimizer; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/optimizer/ReplicaDispatcher.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/optimizer/ReplicaDispatcher.java index 3d3cddbacd..a691323dd6 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/optimizer/ReplicaDispatcher.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/optimizer/ReplicaDispatcher.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.optimizer; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/IStorage.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/IStorage.java index b2d83e47c7..0a1068f50a 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/IStorage.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/IStorage.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.storage; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/StorageEngineClassLoader.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/StorageEngineClassLoader.java index 4eec0860a4..8ee468e4fd 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/StorageEngineClassLoader.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/StorageEngineClassLoader.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.storage; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/StorageManager.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/StorageManager.java index 4ecf7e58c1..4823983360 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/StorageManager.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/StorageManager.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.storage; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/domain/Column.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/domain/Column.java index 1adcf33f8b..accf53af7d 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/domain/Column.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/domain/Column.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.storage.domain; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/domain/ColumnKey.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/domain/ColumnKey.java index 09379e589c..3b7f50d382 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/domain/ColumnKey.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/domain/ColumnKey.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.storage.domain; import java.util.*; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/domain/DataArea.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/domain/DataArea.java index b60eda7580..9ba8de6f2e 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/domain/DataArea.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/domain/DataArea.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.storage.domain; import cn.edu.tsinghua.iginx.metadata.entity.KeyInterval; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java index 074e5f1834..05fbe2cb51 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.storage.execute; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/queue/StoragePhysicalTaskQueue.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/queue/StoragePhysicalTaskQueue.java index 7fc371d2c2..cb5fa5fb3c 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/queue/StoragePhysicalTaskQueue.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/queue/StoragePhysicalTaskQueue.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.storage.queue; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/utils/ColumnKeyTranslator.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/utils/ColumnKeyTranslator.java index cf3d2b2025..2e6f7fa972 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/utils/ColumnKeyTranslator.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/utils/ColumnKeyTranslator.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.storage.utils; import cn.edu.tsinghua.iginx.engine.physical.storage.domain.ColumnKey; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/utils/TagKVUtils.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/utils/TagKVUtils.java index 2202931d68..2acb04a057 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/utils/TagKVUtils.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/utils/TagKVUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.storage.utils; import cn.edu.tsinghua.iginx.engine.shared.operator.tag.*; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/AbstractPhysicalTask.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/AbstractPhysicalTask.java index 30a31be860..32727aa5ff 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/AbstractPhysicalTask.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/AbstractPhysicalTask.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.task; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/BinaryMemoryPhysicalTask.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/BinaryMemoryPhysicalTask.java index f92df4aa45..1152970171 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/BinaryMemoryPhysicalTask.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/BinaryMemoryPhysicalTask.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.task; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/CompletedFoldedPhysicalTask.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/CompletedFoldedPhysicalTask.java index 179982d791..8f24ad52de 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/CompletedFoldedPhysicalTask.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/CompletedFoldedPhysicalTask.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.task; import cn.edu.tsinghua.iginx.engine.shared.RequestContext; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/FoldedMemoryPhysicalTask.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/FoldedMemoryPhysicalTask.java index 5a240f3e53..434633184c 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/FoldedMemoryPhysicalTask.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/FoldedMemoryPhysicalTask.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.task; import static cn.edu.tsinghua.iginx.engine.logical.utils.MetaUtils.getFragmentsByColumnsInterval; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/GlobalPhysicalTask.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/GlobalPhysicalTask.java index a6054b42b6..409628d41a 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/GlobalPhysicalTask.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/GlobalPhysicalTask.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.task; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/Measurable.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/Measurable.java index df53ac9fcd..e173fead78 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/Measurable.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/Measurable.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.task; public interface Measurable { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/MemoryPhysicalTask.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/MemoryPhysicalTask.java index e218ba69ea..2bcb274cd6 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/MemoryPhysicalTask.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/MemoryPhysicalTask.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.task; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/MultipleMemoryPhysicalTask.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/MultipleMemoryPhysicalTask.java index 265de1b718..92c7f67f7b 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/MultipleMemoryPhysicalTask.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/MultipleMemoryPhysicalTask.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.task; import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/PhysicalTask.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/PhysicalTask.java index f5a4a9e62d..2e5a3177cc 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/PhysicalTask.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/PhysicalTask.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.task; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/StoragePhysicalTask.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/StoragePhysicalTask.java index 91972369d7..5fd3c1159a 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/StoragePhysicalTask.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/StoragePhysicalTask.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.task; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/TaskExecuteResult.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/TaskExecuteResult.java index 02f73466d0..fc5f87742a 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/TaskExecuteResult.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/TaskExecuteResult.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.task; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/TaskType.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/TaskType.java index fbfee578fa..944d27350d 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/TaskType.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/TaskType.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.task; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/UnaryMemoryPhysicalTask.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/UnaryMemoryPhysicalTask.java index d871066948..8240947cf1 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/UnaryMemoryPhysicalTask.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/UnaryMemoryPhysicalTask.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.task; import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/utils/TaskUtils.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/utils/TaskUtils.java index 276e26cd32..ea72b82bd4 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/utils/TaskUtils.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/utils/TaskUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.task.utils; import cn.edu.tsinghua.iginx.engine.physical.task.BinaryMemoryPhysicalTask; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/visitor/TaskInfoVisitor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/visitor/TaskInfoVisitor.java index 7208d8d8dc..020150cfd2 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/visitor/TaskInfoVisitor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/visitor/TaskInfoVisitor.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.task.visitor; import cn.edu.tsinghua.iginx.engine.physical.task.BinaryMemoryPhysicalTask; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/visitor/TaskVisitor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/visitor/TaskVisitor.java index 4a1eb3d259..b82c3d2205 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/visitor/TaskVisitor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/task/visitor/TaskVisitor.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.task.visitor; import cn.edu.tsinghua.iginx.engine.physical.task.BinaryMemoryPhysicalTask; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/Constants.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/Constants.java index d9608367a0..20fe07f2c8 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/Constants.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/Constants.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/KeyRange.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/KeyRange.java index 35000ca367..83656eccac 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/KeyRange.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/KeyRange.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/RequestContext.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/RequestContext.java index 293e2b431c..c9bb244ae9 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/RequestContext.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/RequestContext.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared; import cn.edu.tsinghua.iginx.engine.physical.task.PhysicalTask; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/Result.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/Result.java index 67d0a3cf41..37c4239667 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/Result.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/Result.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared; import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/constraint/ConstraintManager.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/constraint/ConstraintManager.java index 6f88d8573f..f61d34cbc2 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/constraint/ConstraintManager.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/constraint/ConstraintManager.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.constraint; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/ExecuteDetail.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/ExecuteDetail.java index 563bf12a99..98223b3a64 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/ExecuteDetail.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/ExecuteDetail.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.data; import java.util.List; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/Value.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/Value.java index c9b4c10e02..3cffd7cf4b 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/Value.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/Value.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.data; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/ClearEmptyRowStreamWrapper.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/ClearEmptyRowStreamWrapper.java index a867c26cc8..d6106c0003 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/ClearEmptyRowStreamWrapper.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/ClearEmptyRowStreamWrapper.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.data.read; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/Field.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/Field.java index afb1c18e7d..4ebfc7a12c 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/Field.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/Field.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.data.read; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/FilterRowStreamWrapper.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/FilterRowStreamWrapper.java index ded35cfecb..4e51e0f271 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/FilterRowStreamWrapper.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/FilterRowStreamWrapper.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.data.read; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/Header.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/Header.java index f7d9f8534b..e224a26fbb 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/Header.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/Header.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.data.read; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/MergeFieldRowStreamWrapper.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/MergeFieldRowStreamWrapper.java index 3f1a0ad77e..4a207c4858 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/MergeFieldRowStreamWrapper.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/MergeFieldRowStreamWrapper.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.data.read; import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/MergeTimeRowStreamWrapper.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/MergeTimeRowStreamWrapper.java index 3694be599e..ddd592d982 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/MergeTimeRowStreamWrapper.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/MergeTimeRowStreamWrapper.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.data.read; import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/Row.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/Row.java index cbee7591de..77a33bcc2c 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/Row.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/Row.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.data.read; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/RowStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/RowStream.java index dbb3dbac86..782fcbde9e 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/RowStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/RowStream.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.data.read; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/RowStreamWrapper.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/RowStreamWrapper.java index 71a5ae617d..c1b088924b 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/RowStreamWrapper.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/RowStreamWrapper.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.data.read; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/write/BitmapView.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/write/BitmapView.java index a902cf9991..9c43e422eb 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/write/BitmapView.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/write/BitmapView.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.data.write; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/write/ColumnDataView.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/write/ColumnDataView.java index ed7928f08b..14cc789164 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/write/ColumnDataView.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/write/ColumnDataView.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.data.write; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/write/DataView.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/write/DataView.java index 179cbb361c..e3b5f2644f 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/write/DataView.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/write/DataView.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.data.write; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/write/RawData.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/write/RawData.java index 587e1187d1..f3926b80cf 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/write/RawData.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/write/RawData.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.data.write; import cn.edu.tsinghua.iginx.thrift.DataType; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/write/RawDataType.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/write/RawDataType.java index aec570d6de..7b74e1063b 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/write/RawDataType.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/write/RawDataType.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.data.write; public enum RawDataType { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/write/RowDataView.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/write/RowDataView.java index 379f8963dd..b0acb1d81f 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/write/RowDataView.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/write/RowDataView.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.data.write; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/exception/StatementExecutionException.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/exception/StatementExecutionException.java index 1c02083dd5..48c8392adc 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/exception/StatementExecutionException.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/exception/StatementExecutionException.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.exception; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/BaseExpression.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/BaseExpression.java index 22a040b4b0..4d7240f2da 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/BaseExpression.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/BaseExpression.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.expr; public class BaseExpression implements Expression { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/BinaryExpression.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/BinaryExpression.java index ec230c75c7..9b5dc92226 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/BinaryExpression.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/BinaryExpression.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.expr; public class BinaryExpression implements Expression { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/BracketExpression.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/BracketExpression.java index de69413d9f..4ee402ef12 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/BracketExpression.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/BracketExpression.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.expr; public class BracketExpression implements Expression { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/ConstantExpression.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/ConstantExpression.java index 9a276f08d5..4377c4ec78 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/ConstantExpression.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/ConstantExpression.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.expr; public class ConstantExpression implements Expression { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/Expression.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/Expression.java index 930981c3b1..0260761ce4 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/Expression.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/Expression.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.expr; public interface Expression { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/ExpressionVisitor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/ExpressionVisitor.java index 53658a175c..0537836302 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/ExpressionVisitor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/ExpressionVisitor.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.expr; public interface ExpressionVisitor { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/FromValueExpression.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/FromValueExpression.java index bef0169155..9134b21561 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/FromValueExpression.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/FromValueExpression.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.expr; import cn.edu.tsinghua.iginx.sql.statement.select.SelectStatement; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/FuncExpression.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/FuncExpression.java index bcd357ffd8..14fc68c9ea 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/FuncExpression.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/FuncExpression.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.expr; import cn.edu.tsinghua.iginx.engine.shared.function.FunctionUtils; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/MultipleExpression.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/MultipleExpression.java index 2179f79757..2df31649bf 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/MultipleExpression.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/MultipleExpression.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.expr; import java.util.List; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/Operator.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/Operator.java index d3e8876408..3ea2def34c 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/Operator.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/Operator.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.expr; public enum Operator { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/UnaryExpression.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/UnaryExpression.java index 2164d791dd..e3ad98fb39 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/UnaryExpression.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/UnaryExpression.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.expr; public class UnaryExpression implements Expression { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/file/CSVFile.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/file/CSVFile.java index 10d168dda1..0881537a9c 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/file/CSVFile.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/file/CSVFile.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.file; import cn.edu.tsinghua.iginx.utils.CSVUtils; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/file/FileType.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/file/FileType.java index 742ddfdc7c..d014c40e15 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/file/FileType.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/file/FileType.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.file; public enum FileType { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/file/read/ImportCsv.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/file/read/ImportCsv.java index bd09c8067f..1f540dfb69 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/file/read/ImportCsv.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/file/read/ImportCsv.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.file.read; import cn.edu.tsinghua.iginx.engine.shared.file.CSVFile; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/file/read/ImportFile.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/file/read/ImportFile.java index 1066dc5026..b4544890ec 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/file/read/ImportFile.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/file/read/ImportFile.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.file.read; import cn.edu.tsinghua.iginx.engine.shared.file.FileType; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/file/write/ExportByteStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/file/write/ExportByteStream.java index f83bb63610..86942a68dc 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/file/write/ExportByteStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/file/write/ExportByteStream.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.file.write; import cn.edu.tsinghua.iginx.engine.shared.file.FileType; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/file/write/ExportCsv.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/file/write/ExportCsv.java index 9ef752b127..253d7a16c6 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/file/write/ExportCsv.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/file/write/ExportCsv.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.file.write; import cn.edu.tsinghua.iginx.engine.shared.file.CSVFile; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/file/write/ExportFile.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/file/write/ExportFile.java index 8b53644bf1..791ce16b73 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/file/write/ExportFile.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/file/write/ExportFile.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.file.write; import cn.edu.tsinghua.iginx.engine.shared.file.FileType; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/Function.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/Function.java index 163ea3e348..3fa9d887dd 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/Function.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/Function.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.function; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/FunctionCall.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/FunctionCall.java index 201e57790b..0713e56422 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/FunctionCall.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/FunctionCall.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.function; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/FunctionParams.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/FunctionParams.java index 947645a351..0fa0bf2f01 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/FunctionParams.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/FunctionParams.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.function; import cn.edu.tsinghua.iginx.engine.shared.expr.Expression; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/FunctionType.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/FunctionType.java index 2ca683a519..c03ef8f525 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/FunctionType.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/FunctionType.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.function; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/FunctionUtils.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/FunctionUtils.java index cf0edb7e65..8d7e7ae571 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/FunctionUtils.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/FunctionUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.function; import static cn.edu.tsinghua.iginx.utils.DataTypeUtils.isWholeNumber; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/MappingFunction.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/MappingFunction.java index 43b8f1f2aa..1ccece57d4 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/MappingFunction.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/MappingFunction.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.function; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/MappingType.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/MappingType.java index b8bb17c047..a449452030 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/MappingType.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/MappingType.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.function; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/RowMappingFunction.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/RowMappingFunction.java index 95972d8f0c..de2b2eadf1 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/RowMappingFunction.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/RowMappingFunction.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.function; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/SetMappingFunction.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/SetMappingFunction.java index 45f227b932..3aded20a5e 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/SetMappingFunction.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/SetMappingFunction.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.function; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/manager/FunctionManager.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/manager/FunctionManager.java index ba74d76572..c3d89886fa 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/manager/FunctionManager.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/manager/FunctionManager.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.function.manager; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/ArithmeticExpr.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/ArithmeticExpr.java index f3502f413f..6580c3daa1 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/ArithmeticExpr.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/ArithmeticExpr.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.function.system; import cn.edu.tsinghua.iginx.engine.physical.memory.execute.utils.ExprUtils; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/Avg.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/Avg.java index 043c08a23a..acba2fe4b4 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/Avg.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/Avg.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.function.system; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/Count.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/Count.java index baf7dbe337..5cb698ad9d 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/Count.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/Count.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.function.system; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/First.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/First.java index 6ca685a957..1a3d32611c 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/First.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/First.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.function.system; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/FirstValue.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/FirstValue.java index efc120d819..690b43d8d2 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/FirstValue.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/FirstValue.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.function.system; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/Last.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/Last.java index 09a2cd5657..672cc68ead 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/Last.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/Last.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.function.system; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/LastValue.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/LastValue.java index 77e626a0cc..d57c79560b 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/LastValue.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/LastValue.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.function.system; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/Max.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/Max.java index 8e9b0e7621..dafe2ceaad 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/Max.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/Max.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.function.system; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/Min.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/Min.java index 9952778dd6..bd234e950d 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/Min.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/Min.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.function.system; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/Ratio.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/Ratio.java index 9539f9964b..42e6ccbf5b 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/Ratio.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/Ratio.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.function.system; import cn.edu.tsinghua.iginx.engine.shared.data.Value; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/Sum.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/Sum.java index 606c66fb32..71986e0710 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/Sum.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/Sum.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.function.system; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/utils/GroupByUtils.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/utils/GroupByUtils.java index de8c6db186..1770ef61b5 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/utils/GroupByUtils.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/utils/GroupByUtils.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.function.system.utils; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/utils/ValueUtils.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/utils/ValueUtils.java index 1e7c4a6e94..773f5c6070 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/utils/ValueUtils.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/system/utils/ValueUtils.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.function.system.utils; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/UDAF.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/UDAF.java index 70f679ab05..12a5b24e0d 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/UDAF.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/UDAF.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.function.udf; import cn.edu.tsinghua.iginx.engine.shared.function.SetMappingFunction; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/UDSF.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/UDSF.java index 9aa87b8c90..cc278938ce 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/UDSF.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/UDSF.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.function.udf; import cn.edu.tsinghua.iginx.engine.shared.function.MappingFunction; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/UDTF.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/UDTF.java index 78cbdeba38..2ddc562991 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/UDTF.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/UDTF.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.function.udf; import cn.edu.tsinghua.iginx.engine.shared.function.RowMappingFunction; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/python/PyUDAF.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/python/PyUDAF.java index 9c24c5a20d..c44b470515 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/python/PyUDAF.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/python/PyUDAF.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.function.udf.python; import static cn.edu.tsinghua.iginx.engine.shared.Constants.UDF_CLASS; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/python/PyUDSF.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/python/PyUDSF.java index 36da7166ab..210f8d1211 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/python/PyUDSF.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/python/PyUDSF.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.function.udf.python; import static cn.edu.tsinghua.iginx.engine.shared.Constants.UDF_CLASS; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/python/PyUDTF.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/python/PyUDTF.java index 3b4d89b114..4ed1701161 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/python/PyUDTF.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/python/PyUDTF.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.function.udf.python; import static cn.edu.tsinghua.iginx.engine.shared.Constants.UDF_CLASS; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/utils/CheckUtils.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/utils/CheckUtils.java index a5789729f0..701f27e855 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/utils/CheckUtils.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/utils/CheckUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.function.udf.utils; import cn.edu.tsinghua.iginx.engine.shared.function.FunctionParams; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/utils/DataUtils.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/utils/DataUtils.java index b2bf283aa4..ad244952d0 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/utils/DataUtils.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/utils/DataUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.function.udf.utils; import cn.edu.tsinghua.iginx.engine.physical.memory.execute.Table; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/utils/RowUtils.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/utils/RowUtils.java index 06165f5d3e..59daec650c 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/utils/RowUtils.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/function/udf/utils/RowUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.function.udf.utils; import cn.edu.tsinghua.iginx.engine.physical.memory.execute.Table; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/AbstractBinaryOperator.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/AbstractBinaryOperator.java index 6466ec0464..b77a725fdb 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/AbstractBinaryOperator.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/AbstractBinaryOperator.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.operator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/AbstractJoin.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/AbstractJoin.java index 762f105e03..ce481dfc9e 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/AbstractJoin.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/AbstractJoin.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator; import cn.edu.tsinghua.iginx.engine.shared.operator.type.JoinAlgType; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/AbstractMultipleOperator.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/AbstractMultipleOperator.java index 954a07f84e..d63774cb8e 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/AbstractMultipleOperator.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/AbstractMultipleOperator.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator; import cn.edu.tsinghua.iginx.engine.shared.operator.type.OperatorType; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/AbstractOperator.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/AbstractOperator.java index 4ee81b0022..9c06b2b21a 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/AbstractOperator.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/AbstractOperator.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.operator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/AbstractUnaryOperator.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/AbstractUnaryOperator.java index c30e06c9a9..18d9713876 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/AbstractUnaryOperator.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/AbstractUnaryOperator.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.operator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/AddSchemaPrefix.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/AddSchemaPrefix.java index 461a3e7a9c..c33ca326c9 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/AddSchemaPrefix.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/AddSchemaPrefix.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator; import cn.edu.tsinghua.iginx.engine.shared.operator.type.OperatorType; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/BinaryOperator.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/BinaryOperator.java index 4ad30c2a1d..ee2adfa05b 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/BinaryOperator.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/BinaryOperator.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.operator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/CombineNonQuery.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/CombineNonQuery.java index 2b7f163fe9..b69d4f69ca 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/CombineNonQuery.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/CombineNonQuery.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator; import cn.edu.tsinghua.iginx.engine.shared.operator.type.OperatorType; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/CrossJoin.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/CrossJoin.java index 962796b97f..4a272a6371 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/CrossJoin.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/CrossJoin.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator; import cn.edu.tsinghua.iginx.engine.shared.operator.type.JoinAlgType; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Delete.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Delete.java index 96c2e692f8..448131187d 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Delete.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Delete.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator; import cn.edu.tsinghua.iginx.engine.shared.KeyRange; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Distinct.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Distinct.java index 5fe46ebc85..311062969f 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Distinct.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Distinct.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator; import cn.edu.tsinghua.iginx.engine.shared.operator.type.OperatorType; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Downsample.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Downsample.java index 24ca783c72..03414af68d 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Downsample.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Downsample.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.operator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Except.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Except.java index e11032f886..0eb29b76f2 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Except.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Except.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator; import cn.edu.tsinghua.iginx.engine.shared.operator.type.OperatorType; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/FoldedOperator.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/FoldedOperator.java index 2b1a60e298..b39e832ab7 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/FoldedOperator.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/FoldedOperator.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator; import cn.edu.tsinghua.iginx.engine.shared.operator.type.OperatorType; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/GroupBy.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/GroupBy.java index 766b24c3bf..1af269b5f9 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/GroupBy.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/GroupBy.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator; import cn.edu.tsinghua.iginx.engine.shared.function.FunctionCall; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/InnerJoin.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/InnerJoin.java index f5ec0f683e..50400907c3 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/InnerJoin.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/InnerJoin.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator; import static cn.edu.tsinghua.iginx.engine.shared.operator.type.JoinAlgType.chooseJoinAlg; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Insert.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Insert.java index 18545b76dc..dcdf292868 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Insert.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Insert.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator; import cn.edu.tsinghua.iginx.engine.shared.data.write.DataView; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Intersect.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Intersect.java index 1471701daf..1914114709 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Intersect.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Intersect.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator; import cn.edu.tsinghua.iginx.engine.shared.operator.type.OperatorType; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Join.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Join.java index c4b1e307d9..11752b836a 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Join.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Join.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.operator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Limit.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Limit.java index 9c17a51757..473cb42e78 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Limit.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Limit.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.operator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/MappingTransform.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/MappingTransform.java index e00feb5321..d40e0bc8c2 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/MappingTransform.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/MappingTransform.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.operator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/MarkJoin.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/MarkJoin.java index e111d5d807..e2322644a9 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/MarkJoin.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/MarkJoin.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator; import static cn.edu.tsinghua.iginx.engine.shared.operator.type.JoinAlgType.chooseJoinAlg; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Migration.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Migration.java index 95dfb6a898..ace8c354e4 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Migration.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Migration.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator; import cn.edu.tsinghua.iginx.engine.shared.operator.type.OperatorType; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/MultipleOperator.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/MultipleOperator.java index cd1132c68c..6d658406d9 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/MultipleOperator.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/MultipleOperator.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator; import cn.edu.tsinghua.iginx.engine.shared.source.Source; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Operator.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Operator.java index 93162f9c62..147bd4fb95 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Operator.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Operator.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.operator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/OuterJoin.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/OuterJoin.java index 62e752f94d..2a2ea3f3b7 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/OuterJoin.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/OuterJoin.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Filter; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/PathUnion.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/PathUnion.java index 7fd7345477..56434a6bf4 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/PathUnion.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/PathUnion.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.operator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Project.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Project.java index 7e13d257d8..8282eb5a75 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Project.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Project.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator; import cn.edu.tsinghua.iginx.engine.shared.operator.tag.TagFilter; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/ProjectWaitingForPath.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/ProjectWaitingForPath.java index cffe981363..346d0120e8 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/ProjectWaitingForPath.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/ProjectWaitingForPath.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator; import cn.edu.tsinghua.iginx.engine.shared.operator.type.OperatorType; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Rename.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Rename.java index 9d88bc56ce..0539de7378 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Rename.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Rename.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator; import cn.edu.tsinghua.iginx.engine.shared.operator.type.OperatorType; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Reorder.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Reorder.java index e594b87c63..c451366e9d 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Reorder.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Reorder.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator; import cn.edu.tsinghua.iginx.engine.shared.function.FunctionUtils; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/RowTransform.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/RowTransform.java index f0acc74d43..4705c83437 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/RowTransform.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/RowTransform.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.operator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Select.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Select.java index 13354a378b..531db819e4 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Select.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Select.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Filter; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/SetTransform.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/SetTransform.java index 9aa2ddcb77..336d018a57 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/SetTransform.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/SetTransform.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.operator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/ShowColumns.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/ShowColumns.java index 9b0daf1f1d..69fc49f842 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/ShowColumns.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/ShowColumns.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator; import cn.edu.tsinghua.iginx.engine.shared.operator.tag.TagFilter; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/SingleJoin.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/SingleJoin.java index 7636a82d1b..773c7fd09f 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/SingleJoin.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/SingleJoin.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator; import static cn.edu.tsinghua.iginx.engine.shared.operator.type.JoinAlgType.chooseJoinAlg; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Sort.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Sort.java index 6d2f512309..dbee447e64 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Sort.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Sort.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.operator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/UnaryOperator.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/UnaryOperator.java index 39bf9da77f..8ffbe5a80a 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/UnaryOperator.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/UnaryOperator.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.operator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Union.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Union.java index bf69c88f4f..c5d4d55ea4 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Union.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Union.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator; import cn.edu.tsinghua.iginx.engine.shared.operator.type.OperatorType; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/ValueToSelectedPath.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/ValueToSelectedPath.java index 10943627fe..6775bf3b7d 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/ValueToSelectedPath.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/ValueToSelectedPath.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator; import cn.edu.tsinghua.iginx.engine.shared.operator.type.OperatorType; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/AndFilter.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/AndFilter.java index 54644f91a1..51e79a08f7 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/AndFilter.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/AndFilter.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.operator.filter; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/BoolFilter.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/BoolFilter.java index 4081b340e4..3d103aa79d 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/BoolFilter.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/BoolFilter.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator.filter; import java.util.Objects; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/ExprFilter.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/ExprFilter.java index cc8b78f44d..bd7746065e 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/ExprFilter.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/ExprFilter.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator.filter; import cn.edu.tsinghua.iginx.engine.shared.expr.Expression; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/Filter.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/Filter.java index f63f52cd37..69fb910cf6 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/Filter.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/Filter.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.operator.filter; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/FilterType.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/FilterType.java index 3c66321206..fa6c8601c7 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/FilterType.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/FilterType.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.operator.filter; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/FilterVisitor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/FilterVisitor.java index 108913a628..75b7fe8ebf 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/FilterVisitor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/FilterVisitor.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator.filter; public interface FilterVisitor { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/KeyFilter.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/KeyFilter.java index be3a89bdf1..ff8298f0a2 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/KeyFilter.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/KeyFilter.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.operator.filter; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/NotFilter.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/NotFilter.java index 6f6a0bf09f..31902831ce 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/NotFilter.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/NotFilter.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.operator.filter; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/Op.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/Op.java index 73d8cd878f..770d931ea0 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/Op.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/Op.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.operator.filter; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/OrFilter.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/OrFilter.java index fbf8809b05..f8e63ffa50 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/OrFilter.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/OrFilter.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.operator.filter; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/PathFilter.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/PathFilter.java index 7bb19d168f..ef689230f2 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/PathFilter.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/PathFilter.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator.filter; import java.util.Objects; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/ValueFilter.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/ValueFilter.java index 09a4998d35..8c38e3f7d3 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/ValueFilter.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/filter/ValueFilter.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.operator.filter; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/tag/AndTagFilter.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/tag/AndTagFilter.java index 56ec19c4c6..9eb747e559 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/tag/AndTagFilter.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/tag/AndTagFilter.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.operator.tag; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/tag/BasePreciseTagFilter.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/tag/BasePreciseTagFilter.java index e031344da1..04b909b2b3 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/tag/BasePreciseTagFilter.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/tag/BasePreciseTagFilter.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator.tag; import java.util.Map; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/tag/BaseTagFilter.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/tag/BaseTagFilter.java index 865c162d85..1713a5d062 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/tag/BaseTagFilter.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/tag/BaseTagFilter.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.operator.tag; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/tag/OrTagFilter.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/tag/OrTagFilter.java index 65e3b8cced..2a9598aec9 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/tag/OrTagFilter.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/tag/OrTagFilter.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.operator.tag; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/tag/PreciseTagFilter.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/tag/PreciseTagFilter.java index d890b49117..d9960c856a 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/tag/PreciseTagFilter.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/tag/PreciseTagFilter.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator.tag; import java.util.ArrayList; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/tag/TagFilter.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/tag/TagFilter.java index 171a32032d..7cb3792876 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/tag/TagFilter.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/tag/TagFilter.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.operator.tag; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/tag/TagFilterType.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/tag/TagFilterType.java index 7600b9c0f8..5db040c8f7 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/tag/TagFilterType.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/tag/TagFilterType.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.operator.tag; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/tag/WithoutTagFilter.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/tag/WithoutTagFilter.java index 83f001e361..9b805bc65d 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/tag/WithoutTagFilter.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/tag/WithoutTagFilter.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator.tag; public class WithoutTagFilter implements TagFilter { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/type/FuncType.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/type/FuncType.java index 809b6d2f30..995d69d32f 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/type/FuncType.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/type/FuncType.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator.type; public enum FuncType { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/type/JoinAlgType.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/type/JoinAlgType.java index f1e8fd0e87..dea2bc5bf5 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/type/JoinAlgType.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/type/JoinAlgType.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator.type; import cn.edu.tsinghua.iginx.engine.physical.memory.execute.utils.FilterUtils; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/type/OperatorType.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/type/OperatorType.java index cbf9ee3dbc..c697f3e2e3 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/type/OperatorType.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/type/OperatorType.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.operator.type; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/type/OuterJoinType.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/type/OuterJoinType.java index e2c35eb62c..f650c269c9 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/type/OuterJoinType.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/type/OuterJoinType.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator.type; public enum OuterJoinType { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/visitor/DeepFirstQueueVisitor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/visitor/DeepFirstQueueVisitor.java index 3b2b11c2a5..191e510e08 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/visitor/DeepFirstQueueVisitor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/visitor/DeepFirstQueueVisitor.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator.visitor; import cn.edu.tsinghua.iginx.engine.shared.operator.BinaryOperator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/visitor/IndexVisitor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/visitor/IndexVisitor.java index 8da7c2e967..93099a1c06 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/visitor/IndexVisitor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/visitor/IndexVisitor.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator.visitor; import cn.edu.tsinghua.iginx.engine.shared.operator.BinaryOperator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/visitor/OperatorInfoVisitor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/visitor/OperatorInfoVisitor.java index d021729df3..a76658f8e5 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/visitor/OperatorInfoVisitor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/visitor/OperatorInfoVisitor.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator.visitor; import cn.edu.tsinghua.iginx.engine.shared.operator.BinaryOperator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/visitor/OperatorVisitor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/visitor/OperatorVisitor.java index db19ffa6de..e636650099 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/visitor/OperatorVisitor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/visitor/OperatorVisitor.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator.visitor; import cn.edu.tsinghua.iginx.engine.shared.operator.BinaryOperator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/visitor/TreeInfoVisitor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/visitor/TreeInfoVisitor.java index d0f21f0e39..1f5b0cdee4 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/visitor/TreeInfoVisitor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/visitor/TreeInfoVisitor.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.operator.visitor; import cn.edu.tsinghua.iginx.engine.shared.operator.BinaryOperator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/PostExecuteProcessor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/PostExecuteProcessor.java index e7ef303e30..c7ab490688 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/PostExecuteProcessor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/PostExecuteProcessor.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.processor; public interface PostExecuteProcessor extends Processor {} diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/PostLogicalProcessor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/PostLogicalProcessor.java index 0fd4ed5c2f..2172f0eed6 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/PostLogicalProcessor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/PostLogicalProcessor.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.processor; public interface PostLogicalProcessor extends Processor {} diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/PostParseProcessor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/PostParseProcessor.java index a7197b99c5..425d53ae81 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/PostParseProcessor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/PostParseProcessor.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.processor; public interface PostParseProcessor extends Processor {} diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/PostPhysicalProcessor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/PostPhysicalProcessor.java index ea0c04858e..9d03887836 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/PostPhysicalProcessor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/PostPhysicalProcessor.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.processor; public interface PostPhysicalProcessor extends Processor {} diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/PreExecuteProcessor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/PreExecuteProcessor.java index ec7101963c..6153755987 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/PreExecuteProcessor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/PreExecuteProcessor.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.processor; public interface PreExecuteProcessor extends Processor {} diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/PreLogicalProcessor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/PreLogicalProcessor.java index 6def269021..f61afdb718 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/PreLogicalProcessor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/PreLogicalProcessor.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.processor; public interface PreLogicalProcessor extends Processor {} diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/PreParseProcessor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/PreParseProcessor.java index 02a6bf4db1..60040b7fc1 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/PreParseProcessor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/PreParseProcessor.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.processor; public interface PreParseProcessor extends Processor {} diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/PrePhysicalProcessor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/PrePhysicalProcessor.java index 59b515b282..9f3f808db4 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/PrePhysicalProcessor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/PrePhysicalProcessor.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.processor; public interface PrePhysicalProcessor extends Processor {} diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/Processor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/Processor.java index 3a25b03966..d40491a30c 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/Processor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/processor/Processor.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.processor; import cn.edu.tsinghua.iginx.engine.shared.RequestContext; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/source/AbstractSource.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/source/AbstractSource.java index 84604867a9..d4d024ef5c 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/source/AbstractSource.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/source/AbstractSource.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.source; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/source/EmptySource.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/source/EmptySource.java index d91888d779..0bf4126f4f 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/source/EmptySource.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/source/EmptySource.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.source; public class EmptySource implements Source { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/source/FragmentSource.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/source/FragmentSource.java index 3c4254c466..b488e20b7e 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/source/FragmentSource.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/source/FragmentSource.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.source; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/source/GlobalSource.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/source/GlobalSource.java index ad178a8623..8032b613d3 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/source/GlobalSource.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/source/GlobalSource.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.shared.source; public class GlobalSource extends AbstractSource { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/source/OperatorSource.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/source/OperatorSource.java index 9972b2ba59..6dc74a16d0 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/source/OperatorSource.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/source/OperatorSource.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.source; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/source/Source.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/source/Source.java index d848017d3e..163ec34339 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/source/Source.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/source/Source.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.source; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/source/SourceType.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/source/SourceType.java index c207473c74..fb2a9eb2e4 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/source/SourceType.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/source/SourceType.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.source; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/exception/IginxException.java b/core/src/main/java/cn/edu/tsinghua/iginx/exception/IginxException.java index 87a051f3d2..cc37c09724 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/exception/IginxException.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/exception/IginxException.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.exception; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/DefaultMetaManager.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/DefaultMetaManager.java index 356e28be5e..baf2a41d5b 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/DefaultMetaManager.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/DefaultMetaManager.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.metadata; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/IMetaManager.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/IMetaManager.java index f47a37dbff..8a9c1a3f52 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/IMetaManager.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/IMetaManager.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.metadata; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/MetaManagerMock.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/MetaManagerMock.java index 4fac461607..3438c7a002 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/MetaManagerMock.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/MetaManagerMock.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.metadata; import cn.edu.tsinghua.iginx.metadata.entity.*; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/MetaManagerWrapper.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/MetaManagerWrapper.java index aeab5a637e..69fd0bc6b6 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/MetaManagerWrapper.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/MetaManagerWrapper.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.metadata; import cn.edu.tsinghua.iginx.conf.ConfigDescriptor; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/cache/DefaultMetaCache.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/cache/DefaultMetaCache.java index f0cddafb90..c62a5a35fd 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/cache/DefaultMetaCache.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/cache/DefaultMetaCache.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.metadata.cache; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/cache/IMetaCache.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/cache/IMetaCache.java index 350f575c4d..083b022140 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/cache/IMetaCache.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/cache/IMetaCache.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.metadata.cache; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/ColumnsInterval.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/ColumnsInterval.java index 6686eff59c..36d9b1c10e 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/ColumnsInterval.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/ColumnsInterval.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.metadata.entity; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/FragmentMeta.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/FragmentMeta.java index 67815532d9..bdb8205510 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/FragmentMeta.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/FragmentMeta.java @@ -1,38 +1,36 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.metadata.entity; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/IginxMeta.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/IginxMeta.java index baaa00b901..6e5011d62f 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/IginxMeta.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/IginxMeta.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.metadata.entity; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/KeyInterval.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/KeyInterval.java index a4b9be393c..ed54d672cd 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/KeyInterval.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/KeyInterval.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.metadata.entity; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/StorageEngineMeta.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/StorageEngineMeta.java index 689b317d79..2be914f2d3 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/StorageEngineMeta.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/StorageEngineMeta.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.metadata.entity; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/StorageUnitMeta.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/StorageUnitMeta.java index bcfa84763e..8f5bb698f0 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/StorageUnitMeta.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/StorageUnitMeta.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.metadata.entity; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/TransformTaskMeta.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/TransformTaskMeta.java index eff7f4abc2..24055fea9f 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/TransformTaskMeta.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/TransformTaskMeta.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.metadata.entity; import cn.edu.tsinghua.iginx.thrift.UDFType; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/UserMeta.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/UserMeta.java index 74ed4081d5..cab0a919f1 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/UserMeta.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/UserMeta.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.metadata.entity; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/exception/MetaStorageException.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/exception/MetaStorageException.java index 0741a10b6b..c6dc8e64ec 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/exception/MetaStorageException.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/exception/MetaStorageException.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.metadata.exception; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/EnableMonitorChangeHook.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/EnableMonitorChangeHook.java index fe68217cba..95f2e37072 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/EnableMonitorChangeHook.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/EnableMonitorChangeHook.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.metadata.hook; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/FragmentChangeHook.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/FragmentChangeHook.java index 9811cb561e..70def91f30 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/FragmentChangeHook.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/FragmentChangeHook.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.metadata.hook; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/IginxChangeHook.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/IginxChangeHook.java index 7c1e3c2c6e..fcddf7ef26 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/IginxChangeHook.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/IginxChangeHook.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.metadata.hook; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/MaxActiveEndKeyStatisticsChangeHook.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/MaxActiveEndKeyStatisticsChangeHook.java index 16c146842f..8c67c8d340 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/MaxActiveEndKeyStatisticsChangeHook.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/MaxActiveEndKeyStatisticsChangeHook.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.metadata.hook; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/ReshardCounterChangeHook.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/ReshardCounterChangeHook.java index dbb54c60c6..99cb403b19 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/ReshardCounterChangeHook.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/ReshardCounterChangeHook.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.metadata.hook; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/ReshardStatusChangeHook.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/ReshardStatusChangeHook.java index 47314c00ae..c3c2e2a63c 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/ReshardStatusChangeHook.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/ReshardStatusChangeHook.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.metadata.hook; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/SchemaMappingChangeHook.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/SchemaMappingChangeHook.java index 46cbfa1597..109cc878ee 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/SchemaMappingChangeHook.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/SchemaMappingChangeHook.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.metadata.hook; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/StorageChangeHook.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/StorageChangeHook.java index c7c8adee7d..f17ac27db6 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/StorageChangeHook.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/StorageChangeHook.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.metadata.hook; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/StorageEngineChangeHook.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/StorageEngineChangeHook.java index 75e914886c..0466112d07 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/StorageEngineChangeHook.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/StorageEngineChangeHook.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.metadata.hook; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/StorageUnitChangeHook.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/StorageUnitChangeHook.java index faa07a88a7..2469958a0e 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/StorageUnitChangeHook.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/StorageUnitChangeHook.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.metadata.hook; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/StorageUnitHook.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/StorageUnitHook.java index 74ee074672..9ae348fc13 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/StorageUnitHook.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/StorageUnitHook.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.metadata.hook; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/TimeSeriesChangeHook.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/TimeSeriesChangeHook.java index f74a120aac..63e7b9acdc 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/TimeSeriesChangeHook.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/TimeSeriesChangeHook.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.metadata.hook; public interface TimeSeriesChangeHook { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/TransformChangeHook.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/TransformChangeHook.java index 2030f10d67..61e8cc8f95 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/TransformChangeHook.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/TransformChangeHook.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.metadata.hook; import cn.edu.tsinghua.iginx.metadata.entity.TransformTaskMeta; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/UserChangeHook.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/UserChangeHook.java index 2745f817f0..9cf1a0639d 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/UserChangeHook.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/UserChangeHook.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.metadata.hook; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/VersionChangeHook.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/VersionChangeHook.java index a8b5f262ec..8a83308ad8 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/VersionChangeHook.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/hook/VersionChangeHook.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.metadata.hook; public interface VersionChangeHook { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/storage/IMetaStorage.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/storage/IMetaStorage.java index b8d4bff2f1..728ebfcd37 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/storage/IMetaStorage.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/storage/IMetaStorage.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.metadata.storage; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/storage/constant/Constant.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/storage/constant/Constant.java index b7b6dcfa0a..d186bb97e6 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/storage/constant/Constant.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/storage/constant/Constant.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.metadata.storage.constant; public class Constant { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/storage/etcd/ETCDMetaStorage.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/storage/etcd/ETCDMetaStorage.java index cfb420dcad..30e582acad 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/storage/etcd/ETCDMetaStorage.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/storage/etcd/ETCDMetaStorage.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.metadata.storage.etcd; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/storage/zk/ZooKeeperMetaStorage.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/storage/zk/ZooKeeperMetaStorage.java index a84944e4ff..aae1bc1ae2 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/storage/zk/ZooKeeperMetaStorage.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/storage/zk/ZooKeeperMetaStorage.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.metadata.storage.zk; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/proposal/ProposalListener.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/proposal/ProposalListener.java index a28d18bec4..de9d81e940 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/proposal/ProposalListener.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/proposal/ProposalListener.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.metadata.sync.proposal; public interface ProposalListener { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/proposal/SyncProposal.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/proposal/SyncProposal.java index 4a0969bae7..7dfdedd80d 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/proposal/SyncProposal.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/proposal/SyncProposal.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.metadata.sync.proposal; public class SyncProposal { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/proposal/SyncVote.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/proposal/SyncVote.java index 0cc3fc9951..b421e341cd 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/proposal/SyncVote.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/proposal/SyncVote.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.metadata.sync.proposal; public class SyncVote { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/proposal/VoteListener.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/proposal/VoteListener.java index e1fc200ad8..cbff39a55b 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/proposal/VoteListener.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/proposal/VoteListener.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.metadata.sync.proposal; public interface VoteListener { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/protocol/ExecutionException.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/protocol/ExecutionException.java index cccd0f37ff..a240c327f8 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/protocol/ExecutionException.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/protocol/ExecutionException.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.metadata.sync.protocol; public class ExecutionException extends Exception { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/protocol/NetworkException.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/protocol/NetworkException.java index 219f573b5b..8cacb3c714 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/protocol/NetworkException.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/protocol/NetworkException.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.metadata.sync.protocol; public class NetworkException extends Exception { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/protocol/SyncProtocol.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/protocol/SyncProtocol.java index 8752c8faac..3790256d27 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/protocol/SyncProtocol.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/protocol/SyncProtocol.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.metadata.sync.protocol; import cn.edu.tsinghua.iginx.metadata.sync.proposal.ProposalListener; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/protocol/VoteExpiredException.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/protocol/VoteExpiredException.java index aa69423a78..a78e0f4713 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/protocol/VoteExpiredException.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/protocol/VoteExpiredException.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.metadata.sync.protocol; public class VoteExpiredException extends Exception { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/protocol/etcd/ETCDSyncProtocolImpl.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/protocol/etcd/ETCDSyncProtocolImpl.java index a2111e2218..fc56388cd7 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/protocol/etcd/ETCDSyncProtocolImpl.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/protocol/etcd/ETCDSyncProtocolImpl.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.metadata.sync.protocol.etcd; import cn.edu.tsinghua.iginx.metadata.sync.proposal.ProposalListener; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/protocol/zk/ZooKeeperSyncProtocolImpl.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/protocol/zk/ZooKeeperSyncProtocolImpl.java index 5e39eaa3cf..284e58ab9d 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/protocol/zk/ZooKeeperSyncProtocolImpl.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/sync/protocol/zk/ZooKeeperSyncProtocolImpl.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.metadata.sync.protocol.zk; import cn.edu.tsinghua.iginx.metadata.sync.proposal.ProposalListener; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/utils/ColumnsIntervalUtils.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/utils/ColumnsIntervalUtils.java index ddc85698ab..db887f1471 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/utils/ColumnsIntervalUtils.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/utils/ColumnsIntervalUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.metadata.utils; import cn.edu.tsinghua.iginx.metadata.entity.ColumnsInterval; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/utils/FragmentUtils.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/utils/FragmentUtils.java index 009f8a439a..b508fa78c0 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/utils/FragmentUtils.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/utils/FragmentUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.metadata.utils; import cn.edu.tsinghua.iginx.metadata.entity.ColumnsInterval; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/utils/IdUtils.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/utils/IdUtils.java index d6181c3245..b28feef207 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/utils/IdUtils.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/utils/IdUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.metadata.utils; import static cn.edu.tsinghua.iginx.conf.Constants.LENGTH_OF_SEQUENCE_NUMBER; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/utils/ReshardStatus.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/utils/ReshardStatus.java index 9a4d25eab2..cd78980b3c 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/utils/ReshardStatus.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/utils/ReshardStatus.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.metadata.utils; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/utils/StorageEngineUtils.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/utils/StorageEngineUtils.java index 7130b56892..b2e35b8abc 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/utils/StorageEngineUtils.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/utils/StorageEngineUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.metadata.utils; import static cn.edu.tsinghua.iginx.conf.Constants.*; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/migration/GreedyMigrationPolicy.java b/core/src/main/java/cn/edu/tsinghua/iginx/migration/GreedyMigrationPolicy.java index 3e02552b12..1135e4e028 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/migration/GreedyMigrationPolicy.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/migration/GreedyMigrationPolicy.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.migration; import cn.edu.tsinghua.iginx.metadata.entity.FragmentMeta; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/migration/MigrationManager.java b/core/src/main/java/cn/edu/tsinghua/iginx/migration/MigrationManager.java index d7300a0188..2e401a8f2f 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/migration/MigrationManager.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/migration/MigrationManager.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.migration; import cn.edu.tsinghua.iginx.conf.ConfigDescriptor; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/migration/MigrationPhysicalExecutor.java b/core/src/main/java/cn/edu/tsinghua/iginx/migration/MigrationPhysicalExecutor.java index f9b7f141f4..0ef8412bcc 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/migration/MigrationPhysicalExecutor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/migration/MigrationPhysicalExecutor.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.migration; import cn.edu.tsinghua.iginx.conf.ConfigDescriptor; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/migration/MigrationPolicy.java b/core/src/main/java/cn/edu/tsinghua/iginx/migration/MigrationPolicy.java index ed17816ccb..97f7dd20ff 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/migration/MigrationPolicy.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/migration/MigrationPolicy.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.migration; import cn.edu.tsinghua.iginx.conf.Config; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/migration/MigrationTask.java b/core/src/main/java/cn/edu/tsinghua/iginx/migration/MigrationTask.java index 198ab8b975..514e69f808 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/migration/MigrationTask.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/migration/MigrationTask.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.migration; import cn.edu.tsinghua.iginx.metadata.entity.FragmentMeta; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/migration/MigrationType.java b/core/src/main/java/cn/edu/tsinghua/iginx/migration/MigrationType.java index ddaa2870b4..33be62cd1a 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/migration/MigrationType.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/migration/MigrationType.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.migration; public enum MigrationType { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/migration/MigrationUtils.java b/core/src/main/java/cn/edu/tsinghua/iginx/migration/MigrationUtils.java index ba1a2d7144..387b04d29b 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/migration/MigrationUtils.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/migration/MigrationUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.migration; import java.util.Collection; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/migration/SimulationBasedMigrationPolicy.java b/core/src/main/java/cn/edu/tsinghua/iginx/migration/SimulationBasedMigrationPolicy.java index 72c7c439f9..e5547f743e 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/migration/SimulationBasedMigrationPolicy.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/migration/SimulationBasedMigrationPolicy.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.migration; import cn.edu.tsinghua.iginx.metadata.entity.FragmentMeta; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/migration/recover/MigrationExecuteTask.java b/core/src/main/java/cn/edu/tsinghua/iginx/migration/recover/MigrationExecuteTask.java index fa68c44b18..6319c7a161 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/migration/recover/MigrationExecuteTask.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/migration/recover/MigrationExecuteTask.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.migration.recover; import cn.edu.tsinghua.iginx.metadata.entity.FragmentMeta; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/migration/recover/MigrationExecuteType.java b/core/src/main/java/cn/edu/tsinghua/iginx/migration/recover/MigrationExecuteType.java index 760b27232e..be1b2ea346 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/migration/recover/MigrationExecuteType.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/migration/recover/MigrationExecuteType.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.migration.recover; public enum MigrationExecuteType { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/migration/recover/MigrationLogger.java b/core/src/main/java/cn/edu/tsinghua/iginx/migration/recover/MigrationLogger.java index be1a9c4136..b016a6c299 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/migration/recover/MigrationLogger.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/migration/recover/MigrationLogger.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.migration.recover; import cn.edu.tsinghua.iginx.migration.MigrationTask; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/migration/recover/MigrationLoggerAnalyzer.java b/core/src/main/java/cn/edu/tsinghua/iginx/migration/recover/MigrationLoggerAnalyzer.java index 96c928f11a..a1cea1e480 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/migration/recover/MigrationLoggerAnalyzer.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/migration/recover/MigrationLoggerAnalyzer.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.migration.recover; import static cn.edu.tsinghua.iginx.migration.recover.MigrationLogger.MIGRATION_EXECUTE_TASK_END; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/monitor/HotSpotMonitor.java b/core/src/main/java/cn/edu/tsinghua/iginx/monitor/HotSpotMonitor.java index 586d6ca945..08e02bcbd5 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/monitor/HotSpotMonitor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/monitor/HotSpotMonitor.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.monitor; import cn.edu.tsinghua.iginx.conf.ConfigDescriptor; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/monitor/IMonitor.java b/core/src/main/java/cn/edu/tsinghua/iginx/monitor/IMonitor.java index 2b0ca31c26..8b5753fd5f 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/monitor/IMonitor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/monitor/IMonitor.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.monitor; public interface IMonitor { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/monitor/MonitorManager.java b/core/src/main/java/cn/edu/tsinghua/iginx/monitor/MonitorManager.java index 72307fea18..8a18f413a1 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/monitor/MonitorManager.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/monitor/MonitorManager.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.monitor; import cn.edu.tsinghua.iginx.compaction.CompactionManager; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/monitor/RequestsMonitor.java b/core/src/main/java/cn/edu/tsinghua/iginx/monitor/RequestsMonitor.java index 5e3eb899cf..0d7b77feff 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/monitor/RequestsMonitor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/monitor/RequestsMonitor.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.monitor; import cn.edu.tsinghua.iginx.conf.ConfigDescriptor; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/mqtt/BrokerAuthenticator.java b/core/src/main/java/cn/edu/tsinghua/iginx/mqtt/BrokerAuthenticator.java index 3a6c74af04..c1d4e2f1c4 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/mqtt/BrokerAuthenticator.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/mqtt/BrokerAuthenticator.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.mqtt; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/mqtt/IPayloadFormatter.java b/core/src/main/java/cn/edu/tsinghua/iginx/mqtt/IPayloadFormatter.java index 71bd9e2b46..390b10a014 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/mqtt/IPayloadFormatter.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/mqtt/IPayloadFormatter.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.mqtt; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/mqtt/JsonPayloadFormatter.java b/core/src/main/java/cn/edu/tsinghua/iginx/mqtt/JsonPayloadFormatter.java index 6b5e991742..8d75e19f2b 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/mqtt/JsonPayloadFormatter.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/mqtt/JsonPayloadFormatter.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.mqtt; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/mqtt/MQTTService.java b/core/src/main/java/cn/edu/tsinghua/iginx/mqtt/MQTTService.java index 9af969cf02..0bac762728 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/mqtt/MQTTService.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/mqtt/MQTTService.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.mqtt; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/mqtt/Message.java b/core/src/main/java/cn/edu/tsinghua/iginx/mqtt/Message.java index 3a93fa7fba..4fd3042e34 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/mqtt/Message.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/mqtt/Message.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.mqtt; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/mqtt/PayloadFormatManager.java b/core/src/main/java/cn/edu/tsinghua/iginx/mqtt/PayloadFormatManager.java index d6c29baa59..f054fde751 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/mqtt/PayloadFormatManager.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/mqtt/PayloadFormatManager.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.mqtt; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/mqtt/PublishHandler.java b/core/src/main/java/cn/edu/tsinghua/iginx/mqtt/PublishHandler.java index 6e7073c33f..4366ef3460 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/mqtt/PublishHandler.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/mqtt/PublishHandler.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.mqtt; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/notice/EmailNotifier.java b/core/src/main/java/cn/edu/tsinghua/iginx/notice/EmailNotifier.java index 72bfa22149..8bc6ade0c2 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/notice/EmailNotifier.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/notice/EmailNotifier.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.notice; import cn.edu.tsinghua.iginx.conf.Config; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/policy/AbstractPolicy.java b/core/src/main/java/cn/edu/tsinghua/iginx/policy/AbstractPolicy.java index a9643f1f04..1b426a0922 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/policy/AbstractPolicy.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/policy/AbstractPolicy.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.policy; import cn.edu.tsinghua.iginx.metadata.IMetaManager; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/policy/IPolicy.java b/core/src/main/java/cn/edu/tsinghua/iginx/policy/IPolicy.java index 7df5602b8c..d693ef58ef 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/policy/IPolicy.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/policy/IPolicy.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.policy; import cn.edu.tsinghua.iginx.metadata.IMetaManager; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/policy/PolicyManager.java b/core/src/main/java/cn/edu/tsinghua/iginx/policy/PolicyManager.java index e502257687..d86372fceb 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/policy/PolicyManager.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/policy/PolicyManager.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.policy; import cn.edu.tsinghua.iginx.metadata.DefaultMetaManager; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/policy/Utils.java b/core/src/main/java/cn/edu/tsinghua/iginx/policy/Utils.java index 185b2b8944..53f3033b54 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/policy/Utils.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/policy/Utils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.policy; import cn.edu.tsinghua.iginx.conf.Constants; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/policy/historical/HistoricalPolicy.java b/core/src/main/java/cn/edu/tsinghua/iginx/policy/historical/HistoricalPolicy.java index bdebb5e47b..10e698483d 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/policy/historical/HistoricalPolicy.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/policy/historical/HistoricalPolicy.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.policy.historical; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/policy/naive/NaivePolicy.java b/core/src/main/java/cn/edu/tsinghua/iginx/policy/naive/NaivePolicy.java index 471b9e0e67..f8aea68416 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/policy/naive/NaivePolicy.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/policy/naive/NaivePolicy.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.policy.naive; import cn.edu.tsinghua.iginx.conf.ConfigDescriptor; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/policy/naive/Sampler.java b/core/src/main/java/cn/edu/tsinghua/iginx/policy/naive/Sampler.java index 711d8cec51..431d9fce16 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/policy/naive/Sampler.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/policy/naive/Sampler.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.policy.naive; import java.util.*; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/policy/simple/ColumnCalDO.java b/core/src/main/java/cn/edu/tsinghua/iginx/policy/simple/ColumnCalDO.java index 10cb853cb2..2afb07a2fa 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/policy/simple/ColumnCalDO.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/policy/simple/ColumnCalDO.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.policy.simple; import lombok.Data; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/policy/simple/FragmentCreator.java b/core/src/main/java/cn/edu/tsinghua/iginx/policy/simple/FragmentCreator.java index b894a25fc5..0525865bfe 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/policy/simple/FragmentCreator.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/policy/simple/FragmentCreator.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.policy.simple; import cn.edu.tsinghua.iginx.conf.Config; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/policy/simple/SimplePolicy.java b/core/src/main/java/cn/edu/tsinghua/iginx/policy/simple/SimplePolicy.java index 4661c366ef..324c5bfd01 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/policy/simple/SimplePolicy.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/policy/simple/SimplePolicy.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.policy.simple; import cn.edu.tsinghua.iginx.conf.Config; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/policy/test/KeyRangeTestPolicy.java b/core/src/main/java/cn/edu/tsinghua/iginx/policy/test/KeyRangeTestPolicy.java index 71e211f8f8..482423aaa4 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/policy/test/KeyRangeTestPolicy.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/policy/test/KeyRangeTestPolicy.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + /** 该Policy是为了测试而写的,不要在生产环境中使用 该Policy会生成KeyRange不同的Fragment,用于测试。 */ package cn.edu.tsinghua.iginx.policy.test; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/resource/QueryResourceManager.java b/core/src/main/java/cn/edu/tsinghua/iginx/resource/QueryResourceManager.java index cf415bb1e5..e7b3d635ca 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/resource/QueryResourceManager.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/resource/QueryResourceManager.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.resource; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/resource/ResourceManager.java b/core/src/main/java/cn/edu/tsinghua/iginx/resource/ResourceManager.java index 0e03d54114..faf2befe35 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/resource/ResourceManager.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/resource/ResourceManager.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.resource; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/resource/system/DefaultSystemMetricsService.java b/core/src/main/java/cn/edu/tsinghua/iginx/resource/system/DefaultSystemMetricsService.java index 2a48dfe77e..b9b4dcaf18 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/resource/system/DefaultSystemMetricsService.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/resource/system/DefaultSystemMetricsService.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.resource.system; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/resource/system/SystemMetricsService.java b/core/src/main/java/cn/edu/tsinghua/iginx/resource/system/SystemMetricsService.java index 9def741047..3a44a03d03 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/resource/system/SystemMetricsService.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/resource/system/SystemMetricsService.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.resource.system; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/MetricsResource.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/MetricsResource.java index 5def01525b..6d8c5bb66b 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/MetricsResource.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/MetricsResource.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.rest; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/RestServer.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/RestServer.java index df7e7b40ad..cf0f43ceff 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/RestServer.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/RestServer.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.rest; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/RestSession.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/RestSession.java index 65ae5d9fb0..b5fe2068fe 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/RestSession.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/RestSession.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.rest; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/RestUtils.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/RestUtils.java index d820d59a16..6f50593233 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/RestUtils.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/RestUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.rest; import cn.edu.tsinghua.iginx.session.SessionQueryDataSet; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/bean/Annotation.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/bean/Annotation.java index 8e2e870380..e75f9a654b 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/bean/Annotation.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/bean/Annotation.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.rest.bean; import com.fasterxml.jackson.databind.JsonNode; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/bean/AnnotationLimit.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/bean/AnnotationLimit.java index 8be17ac846..609157764b 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/bean/AnnotationLimit.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/bean/AnnotationLimit.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.rest.bean; import java.util.*; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/bean/Metric.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/bean/Metric.java index b1aaeee04d..b13c927186 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/bean/Metric.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/bean/Metric.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.rest.bean; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/bean/Query.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/bean/Query.java index 123f5327e1..0af8e5fcb1 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/bean/Query.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/bean/Query.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.rest.bean; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/bean/QueryMetric.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/bean/QueryMetric.java index 194b797783..07a3b5dfbe 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/bean/QueryMetric.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/bean/QueryMetric.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.rest.bean; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/bean/QueryResult.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/bean/QueryResult.java index c7d2357286..f05ce37fb3 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/bean/QueryResult.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/bean/QueryResult.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.rest.bean; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/bean/QueryResultDataset.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/bean/QueryResultDataset.java index bc222318b4..60d93181fc 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/bean/QueryResultDataset.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/bean/QueryResultDataset.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.rest.bean; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/insert/DataPointsParser.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/insert/DataPointsParser.java index df9ecc6310..44a5e4146f 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/insert/DataPointsParser.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/insert/DataPointsParser.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.rest.insert; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/insert/InsertWorker.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/insert/InsertWorker.java index 05a871932c..2beaa32fbc 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/insert/InsertWorker.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/insert/InsertWorker.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.rest.insert; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/QueryExecutor.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/QueryExecutor.java index 37a89456c7..81559fb414 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/QueryExecutor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/QueryExecutor.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.rest.query; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/QueryParser.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/QueryParser.java index 7926134a61..459b88ee69 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/QueryParser.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/QueryParser.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.rest.query; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/Filter.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/Filter.java index 4f5da3f17d..b351d78ad5 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/Filter.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/Filter.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.rest.query.aggregator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregator.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregator.java index 16a47ad6a7..98cf57913e 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregator.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregator.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.rest.query.aggregator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorAvg.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorAvg.java index 11105b3096..b102b17241 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorAvg.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorAvg.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.rest.query.aggregator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorCount.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorCount.java index e949c4f047..0b6b6a4399 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorCount.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorCount.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.rest.query.aggregator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorDev.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorDev.java index 029cb5c61e..3c77712706 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorDev.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorDev.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.rest.query.aggregator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorDiff.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorDiff.java index 4406bc193b..ee72c3ca5c 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorDiff.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorDiff.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.rest.query.aggregator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorDiv.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorDiv.java index b9b6b83da4..574d7654cd 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorDiv.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorDiv.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.rest.query.aggregator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorFilter.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorFilter.java index 462c7b6888..ad2225dc83 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorFilter.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorFilter.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.rest.query.aggregator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorFirst.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorFirst.java index 48b73c40da..a09b6d2fc6 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorFirst.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorFirst.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.rest.query.aggregator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorLast.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorLast.java index 1526a0babf..4cc112a0bb 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorLast.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorLast.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.rest.query.aggregator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorMax.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorMax.java index 50c065ef99..e122ac759f 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorMax.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorMax.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.rest.query.aggregator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorMin.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorMin.java index e919b3c66b..8ab41b0817 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorMin.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorMin.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.rest.query.aggregator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorNone.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorNone.java index 171a358bae..51961d0a48 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorNone.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorNone.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.rest.query.aggregator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorPercentile.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorPercentile.java index 9684a198a2..4daf1cd00f 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorPercentile.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorPercentile.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.rest.query.aggregator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorRate.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorRate.java index 33c2f068e9..26385e635b 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorRate.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorRate.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.rest.query.aggregator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorSampler.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorSampler.java index a5c2d0f9cd..111a60d9db 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorSampler.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorSampler.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.rest.query.aggregator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorSaveAs.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorSaveAs.java index 74c5924790..e21df27f77 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorSaveAs.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorSaveAs.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.rest.query.aggregator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorSum.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorSum.java index 78c34532da..c82489b3cd 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorSum.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorSum.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.rest.query.aggregator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorType.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorType.java index 82da56ddad..e756c418d2 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorType.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryAggregatorType.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.rest.query.aggregator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryShowColumns.java b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryShowColumns.java index 2272bf3f54..0ab1083800 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryShowColumns.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/rest/query/aggregator/QueryShowColumns.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.rest.query.aggregator; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/IginXSqlVisitor.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/IginXSqlVisitor.java index 5bc65bf4a7..30f916b73a 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/IginXSqlVisitor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/IginXSqlVisitor.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql; import static cn.edu.tsinghua.iginx.constant.GlobalConstant.KEY_MAX_VAL; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/SQLConstant.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/SQLConstant.java index cfbdd1e72f..7c0093d987 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/SQLConstant.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/SQLConstant.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql; public class SQLConstant { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/SQLParseError.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/SQLParseError.java index 0fc2b3b2b7..3d936031ad 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/SQLParseError.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/SQLParseError.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql; import org.antlr.v4.runtime.BaseErrorListener; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/exception/SQLParserException.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/exception/SQLParserException.java index 3c986d351d..d86e7f1b41 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/exception/SQLParserException.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/exception/SQLParserException.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.exception; public class SQLParserException extends RuntimeException { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/AddStorageEngineStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/AddStorageEngineStatement.java index 8a12eb5946..e3e433feac 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/AddStorageEngineStatement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/AddStorageEngineStatement.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement; import cn.edu.tsinghua.iginx.IginxWorker; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/CancelJobStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/CancelJobStatement.java index 8cb032ed6d..51b22e74d6 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/CancelJobStatement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/CancelJobStatement.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement; import cn.edu.tsinghua.iginx.IginxWorker; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ClearDataStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ClearDataStatement.java index e941b4f09c..7d74986336 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ClearDataStatement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ClearDataStatement.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement; public class ClearDataStatement extends DataStatement { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/CommitTransformJobStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/CommitTransformJobStatement.java index 7b0d89f7ca..216c894581 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/CommitTransformJobStatement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/CommitTransformJobStatement.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement; import cn.edu.tsinghua.iginx.engine.shared.RequestContext; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/CompactStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/CompactStatement.java index 754367b47a..31b5ff9671 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/CompactStatement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/CompactStatement.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement; import cn.edu.tsinghua.iginx.compaction.CompactionManager; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/CountPointsStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/CountPointsStatement.java index 5ad50b1ba9..b74a2b0147 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/CountPointsStatement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/CountPointsStatement.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement; public class CountPointsStatement extends DataStatement { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/DataStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/DataStatement.java index cf84f7a607..ff16efcc46 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/DataStatement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/DataStatement.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement; public abstract class DataStatement extends Statement {} diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/DeleteColumnsStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/DeleteColumnsStatement.java index 07d76b6bc9..5b6c9f26d5 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/DeleteColumnsStatement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/DeleteColumnsStatement.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement; import cn.edu.tsinghua.iginx.engine.shared.operator.tag.TagFilter; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/DeleteStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/DeleteStatement.java index 120e50b8a3..f12db217a4 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/DeleteStatement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/DeleteStatement.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement; import cn.edu.tsinghua.iginx.engine.logical.utils.LogicalFilterUtils; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/DropTaskStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/DropTaskStatement.java index 7f45240994..5dbcae57ed 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/DropTaskStatement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/DropTaskStatement.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement; import cn.edu.tsinghua.iginx.IginxWorker; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ExportFileFromSelectStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ExportFileFromSelectStatement.java index f88559d8b8..96323a8e68 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ExportFileFromSelectStatement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ExportFileFromSelectStatement.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement; import cn.edu.tsinghua.iginx.engine.shared.file.FileType; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/InsertFromCsvStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/InsertFromCsvStatement.java index 6fb684f414..d7b65e444d 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/InsertFromCsvStatement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/InsertFromCsvStatement.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement; import cn.edu.tsinghua.iginx.engine.shared.file.read.ImportFile; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/InsertFromSelectStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/InsertFromSelectStatement.java index 475bb6cf3f..4d8d80f445 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/InsertFromSelectStatement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/InsertFromSelectStatement.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement; import cn.edu.tsinghua.iginx.sql.statement.select.SelectStatement; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/InsertStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/InsertStatement.java index 8ed4d95987..7728b8e4fa 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/InsertStatement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/InsertStatement.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement; import cn.edu.tsinghua.iginx.engine.shared.data.write.RawData; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/RegisterTaskStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/RegisterTaskStatement.java index f8461b9145..69d7d43a04 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/RegisterTaskStatement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/RegisterTaskStatement.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement; import cn.edu.tsinghua.iginx.IginxWorker; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/RemoveHistoryDataSourceStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/RemoveHistoryDataSourceStatement.java index 9306783112..cc962ea43c 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/RemoveHistoryDataSourceStatement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/RemoveHistoryDataSourceStatement.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement; import cn.edu.tsinghua.iginx.IginxWorker; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/SetConfigStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/SetConfigStatement.java index bd8d110911..4c7a474985 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/SetConfigStatement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/SetConfigStatement.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement; import cn.edu.tsinghua.iginx.conf.Config; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/SetRulesStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/SetRulesStatement.java index db13fb3cca..f7a9235e60 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/SetRulesStatement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/SetRulesStatement.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement; import cn.edu.tsinghua.iginx.IginxWorker; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowClusterInfoStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowClusterInfoStatement.java index df902eda64..fa5dd1ce85 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowClusterInfoStatement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowClusterInfoStatement.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement; import cn.edu.tsinghua.iginx.IginxWorker; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowColumnsStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowColumnsStatement.java index ebc69d3b20..19eea0ebc9 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowColumnsStatement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowColumnsStatement.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement; import cn.edu.tsinghua.iginx.engine.shared.operator.tag.TagFilter; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowConfigStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowConfigStatement.java index a5221df0eb..b69ef3da0b 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowConfigStatement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowConfigStatement.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement; import cn.edu.tsinghua.iginx.conf.Config; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowEligibleJobStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowEligibleJobStatement.java index 2d38f30995..d877c44c9f 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowEligibleJobStatement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowEligibleJobStatement.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement; import cn.edu.tsinghua.iginx.IginxWorker; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowJobStatusStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowJobStatusStatement.java index c0e5b0280d..06348630bc 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowJobStatusStatement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowJobStatusStatement.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement; import cn.edu.tsinghua.iginx.IginxWorker; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowRegisterTaskStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowRegisterTaskStatement.java index d8932c0615..e02e2e75ac 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowRegisterTaskStatement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowRegisterTaskStatement.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement; import cn.edu.tsinghua.iginx.IginxWorker; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowReplicationStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowReplicationStatement.java index a28d3074cd..a9ccf435d0 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowReplicationStatement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowReplicationStatement.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement; import cn.edu.tsinghua.iginx.conf.ConfigDescriptor; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowRulesStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowRulesStatement.java index 75e59a5bfb..9198ddc19c 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowRulesStatement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowRulesStatement.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement; import cn.edu.tsinghua.iginx.IginxWorker; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowSessionIDStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowSessionIDStatement.java index 25a50e5211..a3c0647afa 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowSessionIDStatement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/ShowSessionIDStatement.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement; import cn.edu.tsinghua.iginx.IginxWorker; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/Statement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/Statement.java index d5ff6af936..ee0a81c76f 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/Statement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/Statement.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement; public abstract class Statement { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/StatementType.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/StatementType.java index 8f1d5ef319..7130308932 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/StatementType.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/StatementType.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement; public enum StatementType { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/SystemStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/SystemStatement.java index df29cc0a6d..a95d887adf 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/SystemStatement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/SystemStatement.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement; import cn.edu.tsinghua.iginx.engine.shared.RequestContext; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/CteFromPart.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/CteFromPart.java index 1f09dba85e..1b63e0126a 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/CteFromPart.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/CteFromPart.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement.frompart; import static cn.edu.tsinghua.iginx.engine.shared.Constants.ALL_PATH_SUFFIX; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/FromPart.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/FromPart.java index 2897f1cac6..a7a66ebf47 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/FromPart.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/FromPart.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement.frompart; import cn.edu.tsinghua.iginx.sql.statement.frompart.join.JoinCondition; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/FromPartType.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/FromPartType.java index bfe9e57ffb..e74891f72a 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/FromPartType.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/FromPartType.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement.frompart; public enum FromPartType { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/PathFromPart.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/PathFromPart.java index eee60ac70a..5f2dd9360e 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/PathFromPart.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/PathFromPart.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement.frompart; import static cn.edu.tsinghua.iginx.engine.shared.Constants.ALL_PATH_SUFFIX; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/ShowColumnsFromPart.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/ShowColumnsFromPart.java index 27f07ad587..8c18b32d48 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/ShowColumnsFromPart.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/ShowColumnsFromPart.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement.frompart; import cn.edu.tsinghua.iginx.engine.shared.Constants; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/SubQueryFromPart.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/SubQueryFromPart.java index 866b4b8019..ed45058b51 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/SubQueryFromPart.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/SubQueryFromPart.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement.frompart; import cn.edu.tsinghua.iginx.engine.shared.Constants; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/join/JoinCondition.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/join/JoinCondition.java index 382c94aba8..5e41d38f14 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/join/JoinCondition.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/join/JoinCondition.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement.frompart.join; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Filter; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/join/JoinType.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/join/JoinType.java index 0e3deaefc1..54969f25e6 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/join/JoinType.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/join/JoinType.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement.frompart.join; public enum JoinType { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/BinarySelectStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/BinarySelectStatement.java index a92c46156c..aec06e51b8 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/BinarySelectStatement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/BinarySelectStatement.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement.select; import cn.edu.tsinghua.iginx.engine.shared.expr.Expression; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/CommonTableExpression.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/CommonTableExpression.java index c8b5f486d0..52a1438823 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/CommonTableExpression.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/CommonTableExpression.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement.select; import cn.edu.tsinghua.iginx.engine.shared.expr.Expression; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/SelectStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/SelectStatement.java index e47eb95730..10a9eba5c8 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/SelectStatement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/SelectStatement.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement.select; import cn.edu.tsinghua.iginx.engine.shared.expr.Expression; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/UnarySelectStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/UnarySelectStatement.java index 16c4280dda..c78b28063d 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/UnarySelectStatement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/UnarySelectStatement.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement.select; import static cn.edu.tsinghua.iginx.sql.SQLConstant.DOT; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/subclause/FromClause.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/subclause/FromClause.java index 87b53cbd69..8b076818f9 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/subclause/FromClause.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/subclause/FromClause.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement.select.subclause; import cn.edu.tsinghua.iginx.sql.statement.frompart.FromPart; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/subclause/GroupByClause.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/subclause/GroupByClause.java index ac85f4ebe0..017c1b82de 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/subclause/GroupByClause.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/subclause/GroupByClause.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement.select.subclause; import cn.edu.tsinghua.iginx.sql.statement.select.UnarySelectStatement.QueryType; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/subclause/HavingClause.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/subclause/HavingClause.java index fb7bbf6106..4effb9ce21 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/subclause/HavingClause.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/subclause/HavingClause.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement.select.subclause; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Filter; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/subclause/LimitClause.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/subclause/LimitClause.java index 6bd6803d7b..9dd5398185 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/subclause/LimitClause.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/subclause/LimitClause.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement.select.subclause; public class LimitClause { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/subclause/OrderByClause.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/subclause/OrderByClause.java index 09ddd44771..4ec70e4605 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/subclause/OrderByClause.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/subclause/OrderByClause.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement.select.subclause; import java.util.ArrayList; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/subclause/SelectClause.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/subclause/SelectClause.java index b61e2f309b..bb07872366 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/subclause/SelectClause.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/subclause/SelectClause.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement.select.subclause; import cn.edu.tsinghua.iginx.engine.shared.expr.Expression; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/subclause/WhereClause.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/subclause/WhereClause.java index 9b992ad56e..00434d9da6 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/subclause/WhereClause.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/subclause/WhereClause.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.statement.select.subclause; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Filter; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/utils/ExpressionUtils.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/utils/ExpressionUtils.java index a242cc2fa4..fd77a34777 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/utils/ExpressionUtils.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/utils/ExpressionUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql.utils; import cn.edu.tsinghua.iginx.engine.shared.expr.BinaryExpression; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/statistics/AbstractStageStatisticsCollector.java b/core/src/main/java/cn/edu/tsinghua/iginx/statistics/AbstractStageStatisticsCollector.java index 098d24197f..024b685226 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/statistics/AbstractStageStatisticsCollector.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/statistics/AbstractStageStatisticsCollector.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.statistics; import cn.edu.tsinghua.iginx.engine.shared.RequestContext; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/statistics/ExecuteStatisticsCollector.java b/core/src/main/java/cn/edu/tsinghua/iginx/statistics/ExecuteStatisticsCollector.java index e8b49fc60f..dd4a880e30 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/statistics/ExecuteStatisticsCollector.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/statistics/ExecuteStatisticsCollector.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.statistics; import cn.edu.tsinghua.iginx.engine.shared.Result; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/statistics/IExecuteStatisticsCollector.java b/core/src/main/java/cn/edu/tsinghua/iginx/statistics/IExecuteStatisticsCollector.java index 1286c089ef..9a6c7883b2 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/statistics/IExecuteStatisticsCollector.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/statistics/IExecuteStatisticsCollector.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.statistics; import cn.edu.tsinghua.iginx.engine.shared.processor.PostExecuteProcessor; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/statistics/ILogicalStatisticsCollector.java b/core/src/main/java/cn/edu/tsinghua/iginx/statistics/ILogicalStatisticsCollector.java index 9c969da0dc..78a2f0b4a5 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/statistics/ILogicalStatisticsCollector.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/statistics/ILogicalStatisticsCollector.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.statistics; import cn.edu.tsinghua.iginx.engine.shared.processor.PostLogicalProcessor; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/statistics/IParseStatisticsCollector.java b/core/src/main/java/cn/edu/tsinghua/iginx/statistics/IParseStatisticsCollector.java index 6ce9bd25ff..ae1dc8b36d 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/statistics/IParseStatisticsCollector.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/statistics/IParseStatisticsCollector.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.statistics; import cn.edu.tsinghua.iginx.engine.shared.processor.PostParseProcessor; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/statistics/IPhysicalStatisticsCollector.java b/core/src/main/java/cn/edu/tsinghua/iginx/statistics/IPhysicalStatisticsCollector.java index 20e2996f9b..685b4eabc3 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/statistics/IPhysicalStatisticsCollector.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/statistics/IPhysicalStatisticsCollector.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.statistics; import cn.edu.tsinghua.iginx.engine.shared.processor.PostPhysicalProcessor; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/statistics/IStatisticsCollector.java b/core/src/main/java/cn/edu/tsinghua/iginx/statistics/IStatisticsCollector.java index f1a98d3295..0c3de7a791 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/statistics/IStatisticsCollector.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/statistics/IStatisticsCollector.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.statistics; public interface IStatisticsCollector diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/statistics/LogicalStatisticsCollector.java b/core/src/main/java/cn/edu/tsinghua/iginx/statistics/LogicalStatisticsCollector.java index 31d782fda2..430f892a87 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/statistics/LogicalStatisticsCollector.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/statistics/LogicalStatisticsCollector.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.statistics; import cn.edu.tsinghua.iginx.engine.shared.processor.PostLogicalProcessor; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/statistics/ParseStatisticsCollector.java b/core/src/main/java/cn/edu/tsinghua/iginx/statistics/ParseStatisticsCollector.java index 977ae3894d..ccb31eca68 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/statistics/ParseStatisticsCollector.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/statistics/ParseStatisticsCollector.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.statistics; import cn.edu.tsinghua.iginx.engine.shared.processor.PostParseProcessor; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/statistics/PhysicalStatisticsCollector.java b/core/src/main/java/cn/edu/tsinghua/iginx/statistics/PhysicalStatisticsCollector.java index 23d9ac0d77..f2c2719348 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/statistics/PhysicalStatisticsCollector.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/statistics/PhysicalStatisticsCollector.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.statistics; import cn.edu.tsinghua.iginx.engine.shared.processor.PostPhysicalProcessor; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/statistics/Statistics.java b/core/src/main/java/cn/edu/tsinghua/iginx/statistics/Statistics.java index 599d771516..b93d32d907 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/statistics/Statistics.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/statistics/Statistics.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.statistics; import cn.edu.tsinghua.iginx.engine.shared.RequestContext; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/statistics/StatisticsCollector.java b/core/src/main/java/cn/edu/tsinghua/iginx/statistics/StatisticsCollector.java index ba63ce0568..afd481f870 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/statistics/StatisticsCollector.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/statistics/StatisticsCollector.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.statistics; import cn.edu.tsinghua.iginx.conf.ConfigDescriptor; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/api/Checker.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/api/Checker.java index 02839241e8..ef01135f0f 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/api/Checker.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/api/Checker.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.api; import cn.edu.tsinghua.iginx.transform.pojo.Job; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/api/Driver.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/api/Driver.java index ed883d305b..d759876153 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/api/Driver.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/api/Driver.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.api; import cn.edu.tsinghua.iginx.transform.driver.IPCWorker; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/api/Reader.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/api/Reader.java index 0fe283f03b..a5559c65d9 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/api/Reader.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/api/Reader.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.api; import cn.edu.tsinghua.iginx.transform.data.BatchData; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/api/Runner.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/api/Runner.java index 79b96848a4..c7097610ee 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/api/Runner.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/api/Runner.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.api; import cn.edu.tsinghua.iginx.transform.exception.TransformException; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/api/Stage.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/api/Stage.java index 86b6692ed0..f5fec0f5a8 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/api/Stage.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/api/Stage.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.api; import cn.edu.tsinghua.iginx.thrift.DataFlowType; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/api/Writer.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/api/Writer.java index 5b4e5f4cec..d9e12a244e 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/api/Writer.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/api/Writer.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.api; import cn.edu.tsinghua.iginx.transform.data.BatchData; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/ArrowReader.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/ArrowReader.java index c828003c91..9dc490580c 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/ArrowReader.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/ArrowReader.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.data; import cn.edu.tsinghua.iginx.engine.shared.data.read.Header; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/ArrowWriter.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/ArrowWriter.java index 79227d09a7..1714c6d88f 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/ArrowWriter.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/ArrowWriter.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.data; import cn.edu.tsinghua.iginx.conf.Config; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/BatchData.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/BatchData.java index 18efc3dfb5..f4a473d8ab 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/BatchData.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/BatchData.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.data; import cn.edu.tsinghua.iginx.engine.shared.data.read.Header; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/CollectionWriter.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/CollectionWriter.java index ab874d94d5..1dde14fd81 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/CollectionWriter.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/CollectionWriter.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.data; import cn.edu.tsinghua.iginx.engine.shared.data.read.Row; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/ExportWriter.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/ExportWriter.java index 7b54bf2974..72f3d7ae05 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/ExportWriter.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/ExportWriter.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.data; import cn.edu.tsinghua.iginx.transform.api.Writer; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/Exporter.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/Exporter.java index 2e16b31f69..7408118e30 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/Exporter.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/Exporter.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.data; import cn.edu.tsinghua.iginx.transform.utils.Mutex; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/FileAppendWriter.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/FileAppendWriter.java index 3b45d467b5..8f9eea77eb 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/FileAppendWriter.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/FileAppendWriter.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.data; import cn.edu.tsinghua.iginx.auth.FilePermissionManager; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/IginXWriter.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/IginXWriter.java index ecff9a8edb..c81108f4c9 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/IginXWriter.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/IginXWriter.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.data; import cn.edu.tsinghua.iginx.engine.ContextBuilder; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/LogWriter.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/LogWriter.java index e26e6f8f2f..8049aed459 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/LogWriter.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/LogWriter.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.data; import cn.edu.tsinghua.iginx.constant.GlobalConstant; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/PemjaReader.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/PemjaReader.java index e547260133..ebe432a54a 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/PemjaReader.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/PemjaReader.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.data; import cn.edu.tsinghua.iginx.engine.shared.data.read.Field; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/PemjaWriter.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/PemjaWriter.java index c1223f8675..e7536d444f 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/PemjaWriter.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/PemjaWriter.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.data; import cn.edu.tsinghua.iginx.transform.api.Writer; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/RowStreamReader.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/RowStreamReader.java index e4237c9f56..cf7d7cc77c 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/RowStreamReader.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/RowStreamReader.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.data; import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/SplitReader.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/SplitReader.java index 1100c588a1..465a5f58db 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/SplitReader.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/SplitReader.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.data; import cn.edu.tsinghua.iginx.engine.shared.data.read.Header; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/driver/IPCWorker.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/driver/IPCWorker.java index c3476aab24..cb6a563ce0 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/driver/IPCWorker.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/driver/IPCWorker.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.driver; import cn.edu.tsinghua.iginx.conf.Config; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/driver/PemjaDriver.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/driver/PemjaDriver.java index f63356241a..ac9329561d 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/driver/PemjaDriver.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/driver/PemjaDriver.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.driver; import cn.edu.tsinghua.iginx.conf.Config; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/driver/PemjaWorker.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/driver/PemjaWorker.java index 9112bfba7b..06b3b31e5c 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/driver/PemjaWorker.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/driver/PemjaWorker.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.driver; import static cn.edu.tsinghua.iginx.transform.utils.Constants.UDF_CLASS; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/driver/PythonDriver.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/driver/PythonDriver.java index a22f8ceca5..7ca9fe8b58 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/driver/PythonDriver.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/driver/PythonDriver.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.driver; import cn.edu.tsinghua.iginx.conf.Config; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/exception/CreateWorkerException.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/exception/CreateWorkerException.java index 9f18171b78..ffc40d43b6 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/exception/CreateWorkerException.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/exception/CreateWorkerException.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.exception; public class CreateWorkerException extends TransformException { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/exception/TransformException.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/exception/TransformException.java index 056a2bb996..3e384da994 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/exception/TransformException.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/exception/TransformException.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.exception; public class TransformException extends Exception { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/exception/UnknownArgumentException.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/exception/UnknownArgumentException.java index b366e370b4..344eff4550 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/exception/UnknownArgumentException.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/exception/UnknownArgumentException.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.exception; public class UnknownArgumentException extends TransformException { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/exception/UnknownDataFlowException.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/exception/UnknownDataFlowException.java index 95d325bd21..71949376b1 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/exception/UnknownDataFlowException.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/exception/UnknownDataFlowException.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.exception; import cn.edu.tsinghua.iginx.thrift.DataFlowType; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/exception/WriteBatchException.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/exception/WriteBatchException.java index 6e194f71e0..9de96f644d 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/exception/WriteBatchException.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/exception/WriteBatchException.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.exception; public class WriteBatchException extends TransformException { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/BatchStageRunner.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/BatchStageRunner.java index 85fb21fa9a..d186a2faad 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/BatchStageRunner.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/BatchStageRunner.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.exec; import cn.edu.tsinghua.iginx.transform.api.Runner; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/JobRunner.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/JobRunner.java index 6871c2686f..aa388b269f 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/JobRunner.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/JobRunner.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.exec; import cn.edu.tsinghua.iginx.thrift.DataFlowType; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/JobValidationChecker.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/JobValidationChecker.java index a37367e03b..4cef4756f9 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/JobValidationChecker.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/JobValidationChecker.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.exec; import cn.edu.tsinghua.iginx.thrift.DataFlowType; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/StreamStageRunner.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/StreamStageRunner.java index 8e51a5135d..d10f301699 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/StreamStageRunner.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/StreamStageRunner.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.exec; import cn.edu.tsinghua.iginx.conf.Config; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/TaskManager.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/TaskManager.java index 506583a435..63b4998901 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/TaskManager.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/TaskManager.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.exec; public class TaskManager {} diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/TransformJobManager.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/TransformJobManager.java index 63fc1ca2d2..64ec4051f2 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/TransformJobManager.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/TransformJobManager.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.exec; import cn.edu.tsinghua.iginx.conf.Config; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/BatchStage.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/BatchStage.java index 436daf29e4..4a8f7189af 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/BatchStage.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/BatchStage.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.pojo; import cn.edu.tsinghua.iginx.thrift.DataFlowType; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/IginXTask.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/IginXTask.java index 3c7a287577..f0ce7d4f2e 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/IginXTask.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/IginXTask.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.pojo; import cn.edu.tsinghua.iginx.thrift.TaskInfo; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/Job.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/Job.java index d2f71812d9..8a42a0bf1f 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/Job.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/Job.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.pojo; import cn.edu.tsinghua.iginx.thrift.*; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/PythonTask.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/PythonTask.java index 5dd94ba237..42b10a44ca 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/PythonTask.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/PythonTask.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.pojo; import cn.edu.tsinghua.iginx.thrift.DataFlowType; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/StreamStage.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/StreamStage.java index 6a8bba7829..8cf2a4e530 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/StreamStage.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/StreamStage.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.pojo; import cn.edu.tsinghua.iginx.thrift.DataFlowType; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/Task.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/Task.java index 218a96af48..7026da763a 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/Task.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/Task.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.pojo; import cn.edu.tsinghua.iginx.thrift.DataFlowType; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/TaskFactory.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/TaskFactory.java index 72e4141811..77dd82f434 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/TaskFactory.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/TaskFactory.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.pojo; import cn.edu.tsinghua.iginx.thrift.TaskInfo; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/utils/Constants.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/utils/Constants.java index d5a0abdbe9..53d3eb49d9 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/utils/Constants.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/utils/Constants.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.utils; import java.util.HashMap; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/utils/Mutex.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/utils/Mutex.java index 0a796e57d0..2d88bf1585 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/utils/Mutex.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/utils/Mutex.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.utils; import org.slf4j.Logger; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/utils/RedirectLogger.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/utils/RedirectLogger.java index e9fe35f067..bf4916983c 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/utils/RedirectLogger.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/utils/RedirectLogger.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.utils; import java.io.InputStream; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/utils/TypeUtils.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/utils/TypeUtils.java index 2d1191461e..7c62485dea 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/utils/TypeUtils.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/utils/TypeUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.transform.utils; import cn.edu.tsinghua.iginx.thrift.DataType; diff --git a/core/src/test/java/cn/edu/tsinghua/iginx/auth/FilePermissionManagerTest.java b/core/src/test/java/cn/edu/tsinghua/iginx/auth/FilePermissionManagerTest.java index 849af83d5c..703ff28fcb 100644 --- a/core/src/test/java/cn/edu/tsinghua/iginx/auth/FilePermissionManagerTest.java +++ b/core/src/test/java/cn/edu/tsinghua/iginx/auth/FilePermissionManagerTest.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.auth; import static cn.edu.tsinghua.iginx.auth.utils.FilePermissionRuleNameFilters.defaultRules; diff --git a/core/src/test/java/cn/edu/tsinghua/iginx/compaction/LowAccessFragmentCompactionTest.java b/core/src/test/java/cn/edu/tsinghua/iginx/compaction/LowAccessFragmentCompactionTest.java index 22c479f6de..d7c9a1d1d7 100644 --- a/core/src/test/java/cn/edu/tsinghua/iginx/compaction/LowAccessFragmentCompactionTest.java +++ b/core/src/test/java/cn/edu/tsinghua/iginx/compaction/LowAccessFragmentCompactionTest.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.compaction; import static org.junit.Assert.assertEquals; diff --git a/core/src/test/java/cn/edu/tsinghua/iginx/compaction/LowWriteFragmentCompactionTest.java b/core/src/test/java/cn/edu/tsinghua/iginx/compaction/LowWriteFragmentCompactionTest.java index b0e2019418..7163a81e81 100644 --- a/core/src/test/java/cn/edu/tsinghua/iginx/compaction/LowWriteFragmentCompactionTest.java +++ b/core/src/test/java/cn/edu/tsinghua/iginx/compaction/LowWriteFragmentCompactionTest.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.compaction; import static org.junit.Assert.assertEquals; diff --git a/core/src/test/java/cn/edu/tsinghua/iginx/compaction/PhysicalEngineMock.java b/core/src/test/java/cn/edu/tsinghua/iginx/compaction/PhysicalEngineMock.java index 0a4ea4f510..a5e9c375bf 100644 --- a/core/src/test/java/cn/edu/tsinghua/iginx/compaction/PhysicalEngineMock.java +++ b/core/src/test/java/cn/edu/tsinghua/iginx/compaction/PhysicalEngineMock.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.compaction; import cn.edu.tsinghua.iginx.engine.physical.PhysicalEngine; diff --git a/core/src/test/java/cn/edu/tsinghua/iginx/conf/FilePermissionConfigTest.java b/core/src/test/java/cn/edu/tsinghua/iginx/conf/FilePermissionConfigTest.java index df0ea46eac..2c59afaa35 100644 --- a/core/src/test/java/cn/edu/tsinghua/iginx/conf/FilePermissionConfigTest.java +++ b/core/src/test/java/cn/edu/tsinghua/iginx/conf/FilePermissionConfigTest.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.conf; import static org.junit.Assert.*; diff --git a/core/src/test/java/cn/edu/tsinghua/iginx/engine/logical/utils/LogicalFilterUtilsTest.java b/core/src/test/java/cn/edu/tsinghua/iginx/engine/logical/utils/LogicalFilterUtilsTest.java index 32ac842d6a..4ed699fe19 100644 --- a/core/src/test/java/cn/edu/tsinghua/iginx/engine/logical/utils/LogicalFilterUtilsTest.java +++ b/core/src/test/java/cn/edu/tsinghua/iginx/engine/logical/utils/LogicalFilterUtilsTest.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.logical.utils; import static org.junit.Assert.assertEquals; diff --git a/core/src/test/java/cn/edu/tsinghua/iginx/engine/logical/utils/PathUtilsTest.java b/core/src/test/java/cn/edu/tsinghua/iginx/engine/logical/utils/PathUtilsTest.java index 6feb53be8f..f181be96f5 100644 --- a/core/src/test/java/cn/edu/tsinghua/iginx/engine/logical/utils/PathUtilsTest.java +++ b/core/src/test/java/cn/edu/tsinghua/iginx/engine/logical/utils/PathUtilsTest.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.logical.utils; import static org.junit.Assert.assertEquals; diff --git a/core/src/test/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/AbstractOperatorMemoryExecutorTest.java b/core/src/test/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/AbstractOperatorMemoryExecutorTest.java index c22fae8d52..7c08858257 100644 --- a/core/src/test/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/AbstractOperatorMemoryExecutorTest.java +++ b/core/src/test/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/AbstractOperatorMemoryExecutorTest.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.memory.execute; diff --git a/core/src/test/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/naive/NaiveOperatorMemoryExecutorTest.java b/core/src/test/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/naive/NaiveOperatorMemoryExecutorTest.java index 43116ae09c..33b17da65d 100644 --- a/core/src/test/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/naive/NaiveOperatorMemoryExecutorTest.java +++ b/core/src/test/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/naive/NaiveOperatorMemoryExecutorTest.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.memory.execute.naive; diff --git a/core/src/test/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/StreamOperatorMemoryExecutorTest.java b/core/src/test/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/StreamOperatorMemoryExecutorTest.java index b59fca864b..d64f43bc5f 100644 --- a/core/src/test/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/StreamOperatorMemoryExecutorTest.java +++ b/core/src/test/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/StreamOperatorMemoryExecutorTest.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream; diff --git a/core/src/test/java/cn/edu/tsinghua/iginx/engine/physical/storage/utils/ColumnKeyTranslatorTest.java b/core/src/test/java/cn/edu/tsinghua/iginx/engine/physical/storage/utils/ColumnKeyTranslatorTest.java index edb1a30b64..bd10ccf245 100644 --- a/core/src/test/java/cn/edu/tsinghua/iginx/engine/physical/storage/utils/ColumnKeyTranslatorTest.java +++ b/core/src/test/java/cn/edu/tsinghua/iginx/engine/physical/storage/utils/ColumnKeyTranslatorTest.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.engine.physical.storage.utils; import cn.edu.tsinghua.iginx.engine.physical.storage.domain.ColumnKey; diff --git a/core/src/test/java/cn/edu/tsinghua/iginx/engine/shared/function/system/MaxTest.java b/core/src/test/java/cn/edu/tsinghua/iginx/engine/shared/function/system/MaxTest.java index 857b6f61f5..c4b3fedc91 100644 --- a/core/src/test/java/cn/edu/tsinghua/iginx/engine/shared/function/system/MaxTest.java +++ b/core/src/test/java/cn/edu/tsinghua/iginx/engine/shared/function/system/MaxTest.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.engine.shared.function.system; diff --git a/core/src/test/java/cn/edu/tsinghua/iginx/metadata/entity/ColumnsIntervalTest.java b/core/src/test/java/cn/edu/tsinghua/iginx/metadata/entity/ColumnsIntervalTest.java index eb37113512..2653ca2033 100644 --- a/core/src/test/java/cn/edu/tsinghua/iginx/metadata/entity/ColumnsIntervalTest.java +++ b/core/src/test/java/cn/edu/tsinghua/iginx/metadata/entity/ColumnsIntervalTest.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.metadata.entity; import static org.junit.Assert.*; diff --git a/core/src/test/java/cn/edu/tsinghua/iginx/metadata/entity/ExtraParamTest.java b/core/src/test/java/cn/edu/tsinghua/iginx/metadata/entity/ExtraParamTest.java index ee28df15c5..b8ea99bd67 100644 --- a/core/src/test/java/cn/edu/tsinghua/iginx/metadata/entity/ExtraParamTest.java +++ b/core/src/test/java/cn/edu/tsinghua/iginx/metadata/entity/ExtraParamTest.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.metadata.entity; import static cn.edu.tsinghua.iginx.metadata.utils.StorageEngineUtils.checkEmbeddedStorageExtraParams; diff --git a/core/src/test/java/cn/edu/tsinghua/iginx/notice/EmailNotifierTest.java b/core/src/test/java/cn/edu/tsinghua/iginx/notice/EmailNotifierTest.java index be4e4dbc77..f8b8ccdab8 100644 --- a/core/src/test/java/cn/edu/tsinghua/iginx/notice/EmailNotifierTest.java +++ b/core/src/test/java/cn/edu/tsinghua/iginx/notice/EmailNotifierTest.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.notice; import static org.junit.Assert.*; diff --git a/core/src/test/java/cn/edu/tsinghua/iginx/rest/ParseTest.java b/core/src/test/java/cn/edu/tsinghua/iginx/rest/ParseTest.java index 820d758641..f5e3b2e962 100644 --- a/core/src/test/java/cn/edu/tsinghua/iginx/rest/ParseTest.java +++ b/core/src/test/java/cn/edu/tsinghua/iginx/rest/ParseTest.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.rest; import static org.junit.Assert.assertEquals; diff --git a/core/src/test/java/cn/edu/tsinghua/iginx/sql/FilterVisitorTest.java b/core/src/test/java/cn/edu/tsinghua/iginx/sql/FilterVisitorTest.java index 20a028826d..00e07e5681 100644 --- a/core/src/test/java/cn/edu/tsinghua/iginx/sql/FilterVisitorTest.java +++ b/core/src/test/java/cn/edu/tsinghua/iginx/sql/FilterVisitorTest.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.AndFilter; diff --git a/core/src/test/java/cn/edu/tsinghua/iginx/sql/ParseTest.java b/core/src/test/java/cn/edu/tsinghua/iginx/sql/ParseTest.java index e8211f82e5..023c056d7d 100644 --- a/core/src/test/java/cn/edu/tsinghua/iginx/sql/ParseTest.java +++ b/core/src/test/java/cn/edu/tsinghua/iginx/sql/ParseTest.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql; import static org.junit.Assert.assertEquals; diff --git a/core/src/test/java/cn/edu/tsinghua/iginx/sql/TestUtils.java b/core/src/test/java/cn/edu/tsinghua/iginx/sql/TestUtils.java index a3a2d81bc4..08cd7d2532 100644 --- a/core/src/test/java/cn/edu/tsinghua/iginx/sql/TestUtils.java +++ b/core/src/test/java/cn/edu/tsinghua/iginx/sql/TestUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.sql; import cn.edu.tsinghua.iginx.engine.shared.operator.BinaryOperator; diff --git a/core/src/test/java/cn/edu/tsinghua/iginx/transform/YamlReadTest.java b/core/src/test/java/cn/edu/tsinghua/iginx/transform/YamlReadTest.java index 00271a7a95..c4a0b065b4 100644 --- a/core/src/test/java/cn/edu/tsinghua/iginx/transform/YamlReadTest.java +++ b/core/src/test/java/cn/edu/tsinghua/iginx/transform/YamlReadTest.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.transform; diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/FileSystemStorage.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/FileSystemStorage.java index 9c32e4fd9d..c6acfab070 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/FileSystemStorage.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/FileSystemStorage.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.filesystem; diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exception/FileSystemTaskExecuteFailureException.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exception/FileSystemTaskExecuteFailureException.java index 79e4784e8f..c4d49acb99 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exception/FileSystemTaskExecuteFailureException.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exception/FileSystemTaskExecuteFailureException.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.filesystem.exception; diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exception/FilesystemException.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exception/FilesystemException.java index c4b5c77333..67965145aa 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exception/FilesystemException.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exception/FilesystemException.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.filesystem.exception; diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/Executor.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/Executor.java index 5c59a40c50..32ab4d6a1a 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/Executor.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/Executor.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.filesystem.exec; import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java index 436fca62d2..da9f0c9f4f 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.filesystem.exec; import static cn.edu.tsinghua.iginx.engine.logical.utils.PathUtils.MAX_CHAR; diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java index e7510fb036..eb50648f61 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.filesystem.exec; import static cn.edu.tsinghua.iginx.engine.logical.utils.LogicalFilterUtils.getKeyRangesFromFilter; diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/RemoteExecutor.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/RemoteExecutor.java index 32c9c31087..4ba054d5fb 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/RemoteExecutor.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/RemoteExecutor.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.filesystem.exec; import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/file/DefaultFileOperator.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/file/DefaultFileOperator.java index d4a5b50e6f..dd74903eb9 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/file/DefaultFileOperator.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/file/DefaultFileOperator.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.filesystem.file; import static cn.edu.tsinghua.iginx.filesystem.shared.Constant.*; diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/file/IFileOperator.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/file/IFileOperator.java index 3294dfa815..8b12f5e267 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/file/IFileOperator.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/file/IFileOperator.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.filesystem.file; import cn.edu.tsinghua.iginx.filesystem.file.entity.FileMeta; diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/file/entity/FileMeta.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/file/entity/FileMeta.java index fb115db556..64ed8a3fb4 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/file/entity/FileMeta.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/file/entity/FileMeta.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.filesystem.file.entity; import static cn.edu.tsinghua.iginx.filesystem.shared.Constant.MAGIC_NUMBER; diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/FileSystemHistoryQueryRowStream.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/FileSystemHistoryQueryRowStream.java index e5550132fc..e7c2a969fc 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/FileSystemHistoryQueryRowStream.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/FileSystemHistoryQueryRowStream.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.filesystem.query.entity; import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/FileSystemQueryRowStream.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/FileSystemQueryRowStream.java index 6639fa9cc2..53d6475f19 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/FileSystemQueryRowStream.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/FileSystemQueryRowStream.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.filesystem.query.entity; import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/FileSystemResultTable.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/FileSystemResultTable.java index c1e2f659dd..cc349b5f35 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/FileSystemResultTable.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/FileSystemResultTable.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.filesystem.query.entity; import cn.edu.tsinghua.iginx.thrift.DataType; diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/Record.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/Record.java index 373e44dae3..27686a6018 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/Record.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/Record.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.filesystem.query.entity; import cn.edu.tsinghua.iginx.engine.shared.data.Value; diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/server/FileSystemServer.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/server/FileSystemServer.java index 4b0d15a869..749a4653d0 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/server/FileSystemServer.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/server/FileSystemServer.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.filesystem.server; import cn.edu.tsinghua.iginx.conf.Config; diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/server/FileSystemWorker.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/server/FileSystemWorker.java index 73383ae362..9980330ee8 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/server/FileSystemWorker.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/server/FileSystemWorker.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.filesystem.server; import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/shared/Constant.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/shared/Constant.java index 7cc5afefa7..28b28644ce 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/shared/Constant.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/shared/Constant.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.filesystem.shared; import java.nio.charset.Charset; diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/shared/FileType.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/shared/FileType.java index 6bbb4dace8..0691c8b659 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/shared/FileType.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/shared/FileType.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.filesystem.shared; public enum FileType { diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/FilePathUtils.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/FilePathUtils.java index 95a04f610d..745e6d7046 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/FilePathUtils.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/FilePathUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.filesystem.tools; import static cn.edu.tsinghua.iginx.filesystem.shared.Constant.*; diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/FilterTransformer.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/FilterTransformer.java index bbc33239c4..fb42abaff0 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/FilterTransformer.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/FilterTransformer.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.filesystem.tools; import static cn.edu.tsinghua.iginx.engine.shared.operator.filter.Op.*; diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/LimitedSizeMap.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/LimitedSizeMap.java index 298c6ba840..068d501a56 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/LimitedSizeMap.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/LimitedSizeMap.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.filesystem.tools; import java.util.LinkedHashMap; diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/MemoryPool.java b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/MemoryPool.java index 62af9b6a95..77ee08d6df 100644 --- a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/MemoryPool.java +++ b/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/MemoryPool.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.filesystem.tools; import java.util.Queue; diff --git a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java index ece91da52a..1311e3ac46 100644 --- a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java +++ b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.influxdb; diff --git a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/exception/InfluxDBException.java b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/exception/InfluxDBException.java index 084e4dbfe8..7b29d0e133 100644 --- a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/exception/InfluxDBException.java +++ b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/exception/InfluxDBException.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.influxdb.exception; import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; diff --git a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/exception/InfluxDBTaskExecuteFailureException.java b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/exception/InfluxDBTaskExecuteFailureException.java index 1c72331792..2cc741fff8 100644 --- a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/exception/InfluxDBTaskExecuteFailureException.java +++ b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/exception/InfluxDBTaskExecuteFailureException.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.influxdb.exception; diff --git a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/query/entity/InfluxDBHistoryQueryRowStream.java b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/query/entity/InfluxDBHistoryQueryRowStream.java index cbb85dcf6f..46d5fb6adf 100644 --- a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/query/entity/InfluxDBHistoryQueryRowStream.java +++ b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/query/entity/InfluxDBHistoryQueryRowStream.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.influxdb.query.entity; diff --git a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/query/entity/InfluxDBQueryRowStream.java b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/query/entity/InfluxDBQueryRowStream.java index 913db4e56b..c6eeefa5b2 100644 --- a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/query/entity/InfluxDBQueryRowStream.java +++ b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/query/entity/InfluxDBQueryRowStream.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.influxdb.query.entity; diff --git a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/query/entity/InfluxDBSchema.java b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/query/entity/InfluxDBSchema.java index 86d6e0b95b..7dec918481 100644 --- a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/query/entity/InfluxDBSchema.java +++ b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/query/entity/InfluxDBSchema.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.influxdb.query.entity; diff --git a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/DataTypeTransformer.java b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/DataTypeTransformer.java index a56dd54e6f..fe4d60953a 100644 --- a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/DataTypeTransformer.java +++ b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/DataTypeTransformer.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.influxdb.tools; import static cn.edu.tsinghua.iginx.thrift.DataType.BINARY; diff --git a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/FilterTransformer.java b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/FilterTransformer.java index ba080f671e..f4c4891e0c 100644 --- a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/FilterTransformer.java +++ b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/FilterTransformer.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.influxdb.tools; diff --git a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/SchemaTransformer.java b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/SchemaTransformer.java index 217b9c6783..cf652fa953 100644 --- a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/SchemaTransformer.java +++ b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/SchemaTransformer.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.influxdb.tools; import static cn.edu.tsinghua.iginx.influxdb.tools.DataTypeTransformer.fromInfluxDB; diff --git a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/TagFilterUtils.java b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/TagFilterUtils.java index aa478f6253..d75f35efbe 100644 --- a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/TagFilterUtils.java +++ b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/TagFilterUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.influxdb.tools; import cn.edu.tsinghua.iginx.engine.shared.operator.tag.*; diff --git a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/TimeUtils.java b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/TimeUtils.java index 10a3f9e018..c1a036ff34 100644 --- a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/TimeUtils.java +++ b/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/TimeUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.influxdb.tools; import java.time.Instant; diff --git a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java b/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java index 74be91517d..62e1a35b44 100644 --- a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java +++ b/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.iotdb; diff --git a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/exception/IoTDBException.java b/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/exception/IoTDBException.java index 75796b76d9..a838b0fc21 100644 --- a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/exception/IoTDBException.java +++ b/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/exception/IoTDBException.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.iotdb.exception; diff --git a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/exception/IoTDBTaskExecuteFailureException.java b/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/exception/IoTDBTaskExecuteFailureException.java index af7cec29fe..4bdb056ee5 100644 --- a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/exception/IoTDBTaskExecuteFailureException.java +++ b/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/exception/IoTDBTaskExecuteFailureException.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.iotdb.exception; import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalTaskExecuteFailureException; diff --git a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/query/entity/IoTDBQueryRowStream.java b/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/query/entity/IoTDBQueryRowStream.java index ad4e0baf79..c7427655de 100644 --- a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/query/entity/IoTDBQueryRowStream.java +++ b/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/query/entity/IoTDBQueryRowStream.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.iotdb.query.entity; diff --git a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/DataTypeTransformer.java b/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/DataTypeTransformer.java index d8c3f14272..bdf312acda 100644 --- a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/DataTypeTransformer.java +++ b/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/DataTypeTransformer.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.iotdb.tools; diff --git a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/DataViewWrapper.java b/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/DataViewWrapper.java index 5ae6578e65..7746f7c039 100644 --- a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/DataViewWrapper.java +++ b/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/DataViewWrapper.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.iotdb.tools; diff --git a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/FilterTransformer.java b/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/FilterTransformer.java index b948bef5ef..27d1b8322c 100644 --- a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/FilterTransformer.java +++ b/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/FilterTransformer.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.iotdb.tools; diff --git a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/TagKVUtils.java b/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/TagKVUtils.java index 1893703f46..18fa42916a 100644 --- a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/TagKVUtils.java +++ b/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/TagKVUtils.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.iotdb.tools; diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java index 2dde3d2ca8..e55c72de5b 100644 --- a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java +++ b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.mongodb; import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/DummyQuery.java b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/DummyQuery.java index 1588ec5fe5..938835248b 100644 --- a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/DummyQuery.java +++ b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/DummyQuery.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.mongodb.dummy; import cn.edu.tsinghua.iginx.engine.shared.data.read.RowStream; diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/FilterUtils.java b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/FilterUtils.java index 07e05b8004..0c24841be6 100644 --- a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/FilterUtils.java +++ b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/FilterUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.mongodb.dummy; import static com.mongodb.client.model.Filters.*; diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/FindRowStream.java b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/FindRowStream.java index 3c985187e4..a9ec690449 100644 --- a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/FindRowStream.java +++ b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/FindRowStream.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.mongodb.dummy; import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/NameUtils.java b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/NameUtils.java index 927c392979..840e07de9e 100644 --- a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/NameUtils.java +++ b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/NameUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.mongodb.dummy; class NameUtils { diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/PathTree.java b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/PathTree.java index 0a82168510..59f8d6747f 100644 --- a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/PathTree.java +++ b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/PathTree.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.mongodb.dummy; import cn.edu.tsinghua.iginx.mongodb.tools.NameUtils; diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/QueryRowStream.java b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/QueryRowStream.java index 646dafa8fb..beeb79c25c 100644 --- a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/QueryRowStream.java +++ b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/QueryRowStream.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.mongodb.dummy; import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/QueryUtils.java b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/QueryUtils.java index e0970e238b..d6221925e2 100644 --- a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/QueryUtils.java +++ b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/QueryUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.mongodb.dummy; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Filter; diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/ResultColumn.java b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/ResultColumn.java index 600a5acddc..c197c94e40 100644 --- a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/ResultColumn.java +++ b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/ResultColumn.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.mongodb.dummy; import cn.edu.tsinghua.iginx.thrift.DataType; diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/ResultRow.java b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/ResultRow.java index 7c6ae252e7..2b231a841e 100644 --- a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/ResultRow.java +++ b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/ResultRow.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.mongodb.dummy; import static java.util.AbstractMap.SimpleImmutableEntry; diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/ResultTable.java b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/ResultTable.java index 46b8471def..21514ffeeb 100644 --- a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/ResultTable.java +++ b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/ResultTable.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.mongodb.dummy; import cn.edu.tsinghua.iginx.thrift.DataType; diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/SampleQuery.java b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/SampleQuery.java index e7c338a3a2..21feb5a5e6 100644 --- a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/SampleQuery.java +++ b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/SampleQuery.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.mongodb.dummy; import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/SchemaSample.java b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/SchemaSample.java index 50c5393ceb..d9da918fd3 100644 --- a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/SchemaSample.java +++ b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/SchemaSample.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.mongodb.dummy; diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/TypeUtils.java b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/TypeUtils.java index 1ae75248a4..1644289403 100644 --- a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/TypeUtils.java +++ b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/TypeUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.mongodb.dummy; import cn.edu.tsinghua.iginx.engine.shared.data.Value; diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/entity/ColumnQuery.java b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/entity/ColumnQuery.java index 4b8e9addc6..b06a9d6c50 100644 --- a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/entity/ColumnQuery.java +++ b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/entity/ColumnQuery.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.mongodb.entity; import cn.edu.tsinghua.iginx.engine.shared.data.read.Field; diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/entity/JoinQuery.java b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/entity/JoinQuery.java index 23eff1d5a0..5dff770071 100644 --- a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/entity/JoinQuery.java +++ b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/entity/JoinQuery.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.mongodb.entity; import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/entity/SourceTable.java b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/entity/SourceTable.java index 402a32516a..871bc179db 100644 --- a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/entity/SourceTable.java +++ b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/entity/SourceTable.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.mongodb.entity; import cn.edu.tsinghua.iginx.engine.shared.data.read.Field; diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/tools/FilterUtils.java b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/tools/FilterUtils.java index 35b119712e..d8d6d2491c 100644 --- a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/tools/FilterUtils.java +++ b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/tools/FilterUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.mongodb.tools; import static com.mongodb.client.model.Filters.*; diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/tools/NameUtils.java b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/tools/NameUtils.java index 5871b82b20..12b7848ab4 100644 --- a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/tools/NameUtils.java +++ b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/tools/NameUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.mongodb.tools; import cn.edu.tsinghua.iginx.engine.physical.storage.domain.ColumnKey; diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/tools/TypeUtils.java b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/tools/TypeUtils.java index 970afa472e..7feae6169e 100644 --- a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/tools/TypeUtils.java +++ b/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/tools/TypeUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.mongodb.tools; import cn.edu.tsinghua.iginx.thrift.DataType; diff --git a/dataSources/mongodb/src/test/java/cn/edu/tsinghua/iginx/mongodb/dummy/TypeUtilsTest.java b/dataSources/mongodb/src/test/java/cn/edu/tsinghua/iginx/mongodb/dummy/TypeUtilsTest.java index 33b7364ce9..01249ee43c 100644 --- a/dataSources/mongodb/src/test/java/cn/edu/tsinghua/iginx/mongodb/dummy/TypeUtilsTest.java +++ b/dataSources/mongodb/src/test/java/cn/edu/tsinghua/iginx/mongodb/dummy/TypeUtilsTest.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.mongodb.dummy; import org.bson.*; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/ParquetStorage.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/ParquetStorage.java index d39b62d931..f8783f700e 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/ParquetStorage.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/ParquetStorage.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/Database.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/Database.java index d34e68e53a..ea8b3f1072 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/Database.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/Database.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.db; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/ImmutableDatabase.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/ImmutableDatabase.java index b8f4fcbb8a..e32b9108ce 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/ImmutableDatabase.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/ImmutableDatabase.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.db; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/OneTierDB.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/OneTierDB.java index 8df4b6b1ea..f93fa6d7d8 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/OneTierDB.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/OneTierDB.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.db.lsm; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/api/ReadWriter.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/api/ReadWriter.java index 3c80d625f5..8e251d7c6a 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/api/ReadWriter.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/api/ReadWriter.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.db.lsm.api; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/api/TableMeta.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/api/TableMeta.java index 99ba2944d1..65665fce2b 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/api/TableMeta.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/api/TableMeta.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.parquet.db.lsm.api; import com.google.common.collect.Range; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/DataBuffer.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/DataBuffer.java index ef6435c51e..e0d70a2bf3 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/DataBuffer.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/DataBuffer.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.db.lsm.buffer; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/compact/Compactor.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/compact/Compactor.java index 1bd1413de3..2515d35dcc 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/compact/Compactor.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/compact/Compactor.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.db.lsm.compact; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/DeletedTable.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/DeletedTable.java index 6dd9d85fb5..aa509cd156 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/DeletedTable.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/DeletedTable.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.db.lsm.table; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/DeletedTableMeta.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/DeletedTableMeta.java index a6a32ec8d1..8c3faa27f7 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/DeletedTableMeta.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/DeletedTableMeta.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.db.lsm.table; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/EmptyTable.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/EmptyTable.java index 20091f459e..3b1b29bd50 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/EmptyTable.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/EmptyTable.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.db.lsm.table; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/FileTable.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/FileTable.java index 19c3e719a7..3b6bdac830 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/FileTable.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/FileTable.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.db.lsm.table; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/MemoryTable.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/MemoryTable.java index 4bc6590c62..39d22d9661 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/MemoryTable.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/MemoryTable.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.db.lsm.table; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/Table.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/Table.java index 8a5b2370bc..e00584d5b7 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/Table.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/Table.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.db.lsm.table; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/TableIndex.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/TableIndex.java index fe3afd87e0..73c5d8d727 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/TableIndex.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/TableIndex.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.db.lsm.table; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/TableStorage.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/TableStorage.java index 42bdfbd9b3..4c93860bf6 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/TableStorage.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/TableStorage.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.db.lsm.table; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/AreaSet.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/AreaSet.java index ff0908a3e7..5d4c87bd35 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/AreaSet.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/AreaSet.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.db.util; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/SequenceGenerator.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/SequenceGenerator.java index 01f15c52ea..ac1013bf38 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/SequenceGenerator.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/SequenceGenerator.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.db.util; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/AreaFilterScanner.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/AreaFilterScanner.java index b20e7830e0..9204a5b27a 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/AreaFilterScanner.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/AreaFilterScanner.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.db.util.iterator; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/BatchPlaneScanner.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/BatchPlaneScanner.java index 66e26a751a..a8fbb4e20b 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/BatchPlaneScanner.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/BatchPlaneScanner.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.db.util.iterator; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/ColumnUnionRowScanner.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/ColumnUnionRowScanner.java index 429880b056..b0227c2e35 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/ColumnUnionRowScanner.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/ColumnUnionRowScanner.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.db.util.iterator; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/ConcatScanner.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/ConcatScanner.java index 1afe3017dc..b0f9538811 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/ConcatScanner.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/ConcatScanner.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.db.util.iterator; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/EmptyScanner.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/EmptyScanner.java index 4df8b9f5e0..145e1a42e0 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/EmptyScanner.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/EmptyScanner.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.db.util.iterator; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/IteratorScanner.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/IteratorScanner.java index bdaa269e3c..b55908e6d6 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/IteratorScanner.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/IteratorScanner.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.db.util.iterator; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/RowUnionScanner.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/RowUnionScanner.java index a8f34162cc..8d4d15c8eb 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/RowUnionScanner.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/RowUnionScanner.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.db.util.iterator; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/Scanner.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/Scanner.java index c01fab50d7..2644383429 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/Scanner.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/Scanner.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.db.util.iterator; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/SizeUtils.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/SizeUtils.java index a1940a0f52..4bfb3cf177 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/SizeUtils.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/SizeUtils.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.db.util.iterator; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/Executor.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/Executor.java index 16ed980af1..9b1b8e1dde 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/Executor.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/Executor.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.exec; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java index 175811369a..04f4e53223 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.exec; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java index 2bae22e064..4abbe370c8 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.exec; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileFormat.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileFormat.java index b0f8cdef9e..cd18e98120 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileFormat.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileFormat.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.io; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileIndex.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileIndex.java index 8353a5db65..b131949830 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileIndex.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileIndex.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.io; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileMeta.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileMeta.java index 42a234f097..10fd4ef2d7 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileMeta.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileMeta.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.io; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileReader.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileReader.java index 1391a01d40..fe7fd214e5 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileReader.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileReader.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.io; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileWriter.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileWriter.java index 9f0509c65f..141a7001b4 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileWriter.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileWriter.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.io; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/DataChunk.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/DataChunk.java index 1c7ffc217e..5802384ad4 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/DataChunk.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/DataChunk.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.io.common; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/DataChunks.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/DataChunks.java index 047543c3d2..313559d275 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/DataChunks.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/DataChunks.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.io.common; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/EmptyReader.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/EmptyReader.java index b9de15f41b..c9e6b69eb4 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/EmptyReader.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/EmptyReader.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.io.common; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/FilterUtils.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/FilterUtils.java index d50364fe32..10a5676860 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/FilterUtils.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/FilterUtils.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.io.parquet; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IGroupConverter.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IGroupConverter.java index 4385f3ce32..9603000871 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IGroupConverter.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IGroupConverter.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.io.parquet; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IParquetReader.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IParquetReader.java index dc47c96014..aef812f893 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IParquetReader.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IParquetReader.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.io.parquet; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IParquetWriter.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IParquetWriter.java index 7e7aa90086..f99b9dd424 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IParquetWriter.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IParquetWriter.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.io.parquet; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IRecord.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IRecord.java index 2504a50918..5a69ebf25a 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IRecord.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IRecord.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.io.parquet; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IRecordDematerializer.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IRecordDematerializer.java index d64d6adfaf..2c753bffed 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IRecordDematerializer.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IRecordDematerializer.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.io.parquet; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IRecordMaterializer.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IRecordMaterializer.java index d1e809e66f..e6808a0d3c 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IRecordMaterializer.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IRecordMaterializer.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.io.parquet; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/ProjectUtils.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/ProjectUtils.java index 0cba9c8696..7a54d3b0f0 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/ProjectUtils.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/ProjectUtils.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.io.parquet; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/Manager.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/Manager.java index e072f50b2b..94aec17ac1 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/Manager.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/Manager.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.manager; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/DataManager.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/DataManager.java index bbe4a16527..e0a326f1e4 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/DataManager.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/DataManager.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.manager.data; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/DataViewWrapper.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/DataViewWrapper.java index d1650919a6..24bb6c1f2a 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/DataViewWrapper.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/DataViewWrapper.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.manager.data; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/FilterRangeUtils.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/FilterRangeUtils.java index b1e25d96da..7d268a5e37 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/FilterRangeUtils.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/FilterRangeUtils.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.manager.data; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/LongFormat.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/LongFormat.java index 0a3d9a3930..8d7e166a4f 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/LongFormat.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/LongFormat.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.manager.data; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ObjectFormat.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ObjectFormat.java index 538ca3d9b8..a67d3878b3 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ObjectFormat.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ObjectFormat.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.manager.data; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ParquetReadWriter.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ParquetReadWriter.java index 351373c6d5..f6fea28117 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ParquetReadWriter.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ParquetReadWriter.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.parquet.manager.data; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.AndFilter; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ProjectUtils.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ProjectUtils.java index 613146041c..799f3d9810 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ProjectUtils.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ProjectUtils.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.manager.data; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ScannerRowStream.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ScannerRowStream.java index dd02c08600..e86102a56a 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ScannerRowStream.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ScannerRowStream.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.manager.data; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/SerializeUtils.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/SerializeUtils.java index 95222d6eec..4341052f78 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/SerializeUtils.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/SerializeUtils.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.manager.data; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/SizeUtils.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/SizeUtils.java index 3c205ba400..4cc8f14494 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/SizeUtils.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/SizeUtils.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.manager.data; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/StringFormat.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/StringFormat.java index 21f0130f1d..7963d81eaf 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/StringFormat.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/StringFormat.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.manager.data; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/TombstoneStorage.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/TombstoneStorage.java index 7e2fbadd5a..7bb6cee8c4 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/TombstoneStorage.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/TombstoneStorage.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.manager.data; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Column.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Column.java index abc460a87e..fa393f3b41 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Column.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Column.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.manager.dummy; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/DummyManager.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/DummyManager.java index 24afeaddee..df6f748ed0 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/DummyManager.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/DummyManager.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.manager.dummy; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/EmptyManager.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/EmptyManager.java index cbc6daf1b6..288119484e 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/EmptyManager.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/EmptyManager.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.manager.dummy; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Field.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Field.java index dc2bfb50c3..db2c57c838 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Field.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Field.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.manager.dummy; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Loader.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Loader.java index f3a1f67b6b..c6af146fae 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Loader.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Loader.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.manager.dummy; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/NewQueryRowStream.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/NewQueryRowStream.java index 08bed34b4b..34a038e0d4 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/NewQueryRowStream.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/NewQueryRowStream.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.manager.dummy; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Storer.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Storer.java index b1278eaa37..da74ee87e5 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Storer.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Storer.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.manager.dummy; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Table.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Table.java index 6dad70d6ec..ce3348d8ca 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Table.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Table.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.manager.dummy; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/utils/RangeUtils.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/utils/RangeUtils.java index 38f89068ea..2f24acba31 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/utils/RangeUtils.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/utils/RangeUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.parquet.manager.utils; import cn.edu.tsinghua.iginx.metadata.entity.KeyInterval; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/utils/TagKVUtils.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/utils/TagKVUtils.java index 36dca6da5d..280ca35540 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/utils/TagKVUtils.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/utils/TagKVUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.parquet.manager.utils; import cn.edu.tsinghua.iginx.engine.physical.storage.domain.ColumnKey; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/FilterTransformer.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/FilterTransformer.java index bce5c1cd14..9c04d60b41 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/FilterTransformer.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/FilterTransformer.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.server; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetServer.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetServer.java index 25d5734309..8030a4a2eb 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetServer.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetServer.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.server; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetWorker.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetWorker.java index 3201bbf694..14cf525e34 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetWorker.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetWorker.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.server; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/CachePool.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/CachePool.java index e25c496768..5a37ca181c 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/CachePool.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/CachePool.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.util; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/Constants.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/Constants.java index 4193891785..9f0f13c55d 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/Constants.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/Constants.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.util; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/ParseUtils.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/ParseUtils.java index ca839e3b15..12eba3c385 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/ParseUtils.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/ParseUtils.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.util; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/Shared.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/Shared.java index d4b6ddf327..c2b27b5516 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/Shared.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/Shared.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.util; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/StorageProperties.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/StorageProperties.java index 5538ccd92a..c1f57be2a7 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/StorageProperties.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/StorageProperties.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.util; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/InvalidFieldNameException.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/InvalidFieldNameException.java index 46926c296c..7b7adf0b8b 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/InvalidFieldNameException.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/InvalidFieldNameException.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.util.exception; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/IsClosedException.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/IsClosedException.java index 158e1f1cc7..0b494a64f0 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/IsClosedException.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/IsClosedException.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.util.exception; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/NotIntegrityException.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/NotIntegrityException.java index 3344488d22..e5599890fe 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/NotIntegrityException.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/NotIntegrityException.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.util.exception; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/SchemaException.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/SchemaException.java index a7885cd98d..61edfc7c16 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/SchemaException.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/SchemaException.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.util.exception; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/StorageException.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/StorageException.java index 6b1376ddb0..9670a96b99 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/StorageException.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/StorageException.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.util.exception; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/StorageRuntimeException.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/StorageRuntimeException.java index 26b95af0aa..354e9b882c 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/StorageRuntimeException.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/StorageRuntimeException.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.util.exception; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/TimeoutException.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/TimeoutException.java index 83014cf257..42dc9b4738 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/TimeoutException.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/TimeoutException.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.util.exception; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/TypeConflictedException.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/TypeConflictedException.java index 18f2ccfd71..9ea3f3fa8e 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/TypeConflictedException.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/TypeConflictedException.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.util.exception; diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/UnsupportedFilterException.java b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/UnsupportedFilterException.java index ca96d70995..ec066b7031 100644 --- a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/UnsupportedFilterException.java +++ b/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/UnsupportedFilterException.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.util.exception; diff --git a/dataSources/parquet/src/test/java/cn/edu/tsinghua/iginx/parquet/db/common/utils/SerializeUtilsTest.java b/dataSources/parquet/src/test/java/cn/edu/tsinghua/iginx/parquet/db/common/utils/SerializeUtilsTest.java index b8fc070952..ed1824a888 100644 --- a/dataSources/parquet/src/test/java/cn/edu/tsinghua/iginx/parquet/db/common/utils/SerializeUtilsTest.java +++ b/dataSources/parquet/src/test/java/cn/edu/tsinghua/iginx/parquet/db/common/utils/SerializeUtilsTest.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.db.common.utils; diff --git a/dataSources/parquet/src/test/java/cn/edu/tsinghua/iginx/parquet/io/ParquetFormatIOTest.java b/dataSources/parquet/src/test/java/cn/edu/tsinghua/iginx/parquet/io/ParquetFormatIOTest.java index 9cbeeae82a..89b3dfefeb 100644 --- a/dataSources/parquet/src/test/java/cn/edu/tsinghua/iginx/parquet/io/ParquetFormatIOTest.java +++ b/dataSources/parquet/src/test/java/cn/edu/tsinghua/iginx/parquet/io/ParquetFormatIOTest.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.parquet.io; import static org.junit.Assert.assertEquals; diff --git a/dataSources/parquet/src/test/java/cn/edu/tsinghua/iginx/parquet/manager/data/FilterRangeUtilsTest.java b/dataSources/parquet/src/test/java/cn/edu/tsinghua/iginx/parquet/manager/data/FilterRangeUtilsTest.java index 5605222c38..1d4b53b33f 100644 --- a/dataSources/parquet/src/test/java/cn/edu/tsinghua/iginx/parquet/manager/data/FilterRangeUtilsTest.java +++ b/dataSources/parquet/src/test/java/cn/edu/tsinghua/iginx/parquet/manager/data/FilterRangeUtilsTest.java @@ -1,17 +1,19 @@ /* - * Copyright 2024 IGinX of Tsinghua University + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.parquet.manager.data; diff --git a/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java b/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java index 831a7b9c1c..b49c280ea9 100644 --- a/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java +++ b/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.redis; import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; diff --git a/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/entity/Column.java b/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/entity/Column.java index 4cb3770b9d..8edb0d2c7b 100644 --- a/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/entity/Column.java +++ b/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/entity/Column.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.redis.entity; import cn.edu.tsinghua.iginx.thrift.DataType; diff --git a/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/entity/RedisQueryRowStream.java b/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/entity/RedisQueryRowStream.java index b7761a6045..7cb9789ce5 100644 --- a/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/entity/RedisQueryRowStream.java +++ b/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/entity/RedisQueryRowStream.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.redis.entity; import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; diff --git a/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/DataCoder.java b/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/DataCoder.java index e964a11f40..323b20d8df 100644 --- a/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/DataCoder.java +++ b/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/DataCoder.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.redis.tools; public class DataCoder { diff --git a/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/DataTransformer.java b/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/DataTransformer.java index 605fab83b8..37b3d96274 100644 --- a/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/DataTransformer.java +++ b/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/DataTransformer.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.redis.tools; import cn.edu.tsinghua.iginx.thrift.DataType; diff --git a/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/DataViewWrapper.java b/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/DataViewWrapper.java index ed0993074c..30d26730b4 100644 --- a/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/DataViewWrapper.java +++ b/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/DataViewWrapper.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.redis.tools; import cn.edu.tsinghua.iginx.engine.shared.data.write.BitmapView; diff --git a/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/FilterUtils.java b/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/FilterUtils.java index 5c815c44b5..3ad3a615ea 100644 --- a/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/FilterUtils.java +++ b/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/FilterUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.redis.tools; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.AndFilter; diff --git a/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/TagKVUtils.java b/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/TagKVUtils.java index c42ffba5d3..23c2d3c1d8 100644 --- a/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/TagKVUtils.java +++ b/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/TagKVUtils.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.redis.tools; diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java index 0a23801078..bf26cf354b 100644 --- a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java +++ b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.relational; diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/datatype/transformer/IDataTypeTransformer.java b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/datatype/transformer/IDataTypeTransformer.java index bdf0530397..8a31b66e8e 100644 --- a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/datatype/transformer/IDataTypeTransformer.java +++ b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/datatype/transformer/IDataTypeTransformer.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.relational.datatype.transformer; import cn.edu.tsinghua.iginx.thrift.DataType; diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/datatype/transformer/JDBCDataTypeTransformer.java b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/datatype/transformer/JDBCDataTypeTransformer.java index be6b23cc35..8aa6951c0c 100644 --- a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/datatype/transformer/JDBCDataTypeTransformer.java +++ b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/datatype/transformer/JDBCDataTypeTransformer.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.relational.datatype.transformer; import cn.edu.tsinghua.iginx.thrift.DataType; diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/datatype/transformer/PostgreSQLDataTypeTransformer.java b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/datatype/transformer/PostgreSQLDataTypeTransformer.java index 33b512390a..dde7c4e4e0 100644 --- a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/datatype/transformer/PostgreSQLDataTypeTransformer.java +++ b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/datatype/transformer/PostgreSQLDataTypeTransformer.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.relational.datatype.transformer; import static cn.edu.tsinghua.iginx.thrift.DataType.*; diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/exception/RelationalException.java b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/exception/RelationalException.java index 2b3bd398f3..92a0f3ea93 100644 --- a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/exception/RelationalException.java +++ b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/exception/RelationalException.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.relational.exception; import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/exception/RelationalTaskExecuteFailureException.java b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/exception/RelationalTaskExecuteFailureException.java index 3c588a5e4c..d6bb3c297c 100644 --- a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/exception/RelationalTaskExecuteFailureException.java +++ b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/exception/RelationalTaskExecuteFailureException.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.relational.exception; import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalTaskExecuteFailureException; diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/meta/AbstractRelationalMeta.java b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/meta/AbstractRelationalMeta.java index 0e9c2bffd7..5bedbf4dc6 100644 --- a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/meta/AbstractRelationalMeta.java +++ b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/meta/AbstractRelationalMeta.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.relational.meta; import static cn.edu.tsinghua.iginx.relational.tools.Constants.KEY_NAME; diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/meta/JDBCMeta.java b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/meta/JDBCMeta.java index 66204a301c..5b752c80a0 100644 --- a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/meta/JDBCMeta.java +++ b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/meta/JDBCMeta.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.relational.meta; import cn.edu.tsinghua.iginx.metadata.entity.StorageEngineMeta; diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/meta/PostgreSQLMeta.java b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/meta/PostgreSQLMeta.java index 108001d1cb..b6b63e28f9 100644 --- a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/meta/PostgreSQLMeta.java +++ b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/meta/PostgreSQLMeta.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.relational.meta; diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/query/entity/RelationQueryRowStream.java b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/query/entity/RelationQueryRowStream.java index b7d7a3a0f5..bd9345551e 100644 --- a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/query/entity/RelationQueryRowStream.java +++ b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/query/entity/RelationQueryRowStream.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.relational.query.entity; import static cn.edu.tsinghua.iginx.constant.GlobalConstant.SEPARATOR; diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/ColumnField.java b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/ColumnField.java index ca8bc0e0cc..fae79399fe 100644 --- a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/ColumnField.java +++ b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/ColumnField.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.relational.tools; public class ColumnField { diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/Constants.java b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/Constants.java index e7e7cca55f..4a154f3743 100644 --- a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/Constants.java +++ b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/Constants.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.relational.tools; import java.util.HashMap; diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/FilterTransformer.java b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/FilterTransformer.java index ffbc5c1de4..d1e5c95396 100644 --- a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/FilterTransformer.java +++ b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/FilterTransformer.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.relational.tools; diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/HashUtils.java b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/HashUtils.java index 45c3845a60..4c549f5ee4 100644 --- a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/HashUtils.java +++ b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/HashUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.relational.tools; public class HashUtils { diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/RelationSchema.java b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/RelationSchema.java index 20b024f660..5bc755d668 100644 --- a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/RelationSchema.java +++ b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/RelationSchema.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.relational.tools; import static cn.edu.tsinghua.iginx.constant.GlobalConstant.SEPARATOR; diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/TagKVUtils.java b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/TagKVUtils.java index d84b3c8b43..8f6c0b318d 100644 --- a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/TagKVUtils.java +++ b/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/TagKVUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.relational.tools; import static cn.edu.tsinghua.iginx.relational.tools.Constants.*; diff --git a/docker/client/build-no-maven.bat b/docker/client/build-no-maven.bat index 497ce80c6e..f5dee8b5a8 100644 --- a/docker/client/build-no-maven.bat +++ b/docker/client/build-no-maven.bat @@ -1 +1,18 @@ +@REM +@REM IGinX - the polystore system with high performance +@REM Copyright (C) Tsinghua University +@REM +@REM This program is free software: you can redistribute it and/or modify +@REM it under the terms of the GNU General Public License as published by +@REM the Free Software Foundation, either version 3 of the License, or +@REM (at your option) any later version. +@REM +@REM This program is distributed in the hope that it will be useful, +@REM but WITHOUT ANY WARRANTY; without even the implied warranty of +@REM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +@REM GNU General Public License for more details. +@REM +@REM You should have received a copy of the GNU General Public License +@REM along with this program. If not, see . +@REM docker build --file Dockerfile-no-maven-windows -t iginx-client:0.7.0-SNAPSHOT ../../client \ No newline at end of file diff --git a/docker/client/build-no-maven.sh b/docker/client/build-no-maven.sh index 9e4f8c1829..7556c27c53 100644 --- a/docker/client/build-no-maven.sh +++ b/docker/client/build-no-maven.sh @@ -1,2 +1,20 @@ #!/bin/bash +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + docker build --file Dockerfile-no-maven -t iginx-client:0.7.0-SNAPSHOT ../../client \ No newline at end of file diff --git a/docker/client/build.bat b/docker/client/build.bat index b3220791a7..e5f14cbc2b 100644 --- a/docker/client/build.bat +++ b/docker/client/build.bat @@ -1 +1,18 @@ +@REM +@REM IGinX - the polystore system with high performance +@REM Copyright (C) Tsinghua University +@REM +@REM This program is free software: you can redistribute it and/or modify +@REM it under the terms of the GNU General Public License as published by +@REM the Free Software Foundation, either version 3 of the License, or +@REM (at your option) any later version. +@REM +@REM This program is distributed in the hope that it will be useful, +@REM but WITHOUT ANY WARRANTY; without even the implied warranty of +@REM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +@REM GNU General Public License for more details. +@REM +@REM You should have received a copy of the GNU General Public License +@REM along with this program. If not, see . +@REM docker build --file Dockerfile -t iginx-client:0.7.0-SNAPSHOT ../../client \ No newline at end of file diff --git a/docker/client/build.sh b/docker/client/build.sh index 7e39502357..86cafa869f 100644 --- a/docker/client/build.sh +++ b/docker/client/build.sh @@ -1,2 +1,20 @@ #!/bin/bash +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + docker build --file Dockerfile -t iginx-client:0.7.0-SNAPSHOT ../../client \ No newline at end of file diff --git a/docker/client/run_docker.bat b/docker/client/run_docker.bat index c96c3488e7..971720bc04 100644 --- a/docker/client/run_docker.bat +++ b/docker/client/run_docker.bat @@ -1,3 +1,20 @@ +@REM +@REM IGinX - the polystore system with high performance +@REM Copyright (C) Tsinghua University +@REM +@REM This program is free software: you can redistribute it and/or modify +@REM it under the terms of the GNU General Public License as published by +@REM the Free Software Foundation, either version 3 of the License, or +@REM (at your option) any later version. +@REM +@REM This program is distributed in the hope that it will be useful, +@REM but WITHOUT ANY WARRANTY; without even the implied warranty of +@REM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +@REM GNU General Public License for more details. +@REM +@REM You should have received a copy of the GNU General Public License +@REM along with this program. If not, see . +@REM @echo off setlocal enabledelayedexpansion diff --git a/docker/client/run_docker.sh b/docker/client/run_docker.sh index 26af3060d2..1aac13254e 100644 --- a/docker/client/run_docker.sh +++ b/docker/client/run_docker.sh @@ -1,4 +1,22 @@ #!/bin/bash +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + datadir="$(pwd)/data" name="iginx-client" diff --git a/docker/oneShot-parquet/build_and_run_iginx_docker.bat b/docker/oneShot-parquet/build_and_run_iginx_docker.bat index 3178b9fdc3..994cee100d 100644 --- a/docker/oneShot-parquet/build_and_run_iginx_docker.bat +++ b/docker/oneShot-parquet/build_and_run_iginx_docker.bat @@ -1 +1,18 @@ +@REM +@REM IGinX - the polystore system with high performance +@REM Copyright (C) Tsinghua University +@REM +@REM This program is free software: you can redistribute it and/or modify +@REM it under the terms of the GNU General Public License as published by +@REM the Free Software Foundation, either version 3 of the License, or +@REM (at your option) any later version. +@REM +@REM This program is distributed in the hope that it will be useful, +@REM but WITHOUT ANY WARRANTY; without even the implied warranty of +@REM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +@REM GNU General Public License for more details. +@REM +@REM You should have received a copy of the GNU General Public License +@REM along with this program. If not, see . +@REM docker compose up --build --detach \ No newline at end of file diff --git a/docker/oneShot/build_and_run_iginx_docker.bat b/docker/oneShot/build_and_run_iginx_docker.bat index 3178b9fdc3..994cee100d 100644 --- a/docker/oneShot/build_and_run_iginx_docker.bat +++ b/docker/oneShot/build_and_run_iginx_docker.bat @@ -1 +1,18 @@ +@REM +@REM IGinX - the polystore system with high performance +@REM Copyright (C) Tsinghua University +@REM +@REM This program is free software: you can redistribute it and/or modify +@REM it under the terms of the GNU General Public License as published by +@REM the Free Software Foundation, either version 3 of the License, or +@REM (at your option) any later version. +@REM +@REM This program is distributed in the hope that it will be useful, +@REM but WITHOUT ANY WARRANTY; without even the implied warranty of +@REM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +@REM GNU General Public License for more details. +@REM +@REM You should have received a copy of the GNU General Public License +@REM along with this program. If not, see . +@REM docker compose up --build --detach \ No newline at end of file diff --git a/docker/onlyIginx-parquet/build_iginx_docker.bat b/docker/onlyIginx-parquet/build_iginx_docker.bat index d08f72dac8..773a4d6c87 100644 --- a/docker/onlyIginx-parquet/build_iginx_docker.bat +++ b/docker/onlyIginx-parquet/build_iginx_docker.bat @@ -1 +1,18 @@ +@REM +@REM IGinX - the polystore system with high performance +@REM Copyright (C) Tsinghua University +@REM +@REM This program is free software: you can redistribute it and/or modify +@REM it under the terms of the GNU General Public License as published by +@REM the Free Software Foundation, either version 3 of the License, or +@REM (at your option) any later version. +@REM +@REM This program is distributed in the hope that it will be useful, +@REM but WITHOUT ANY WARRANTY; without even the implied warranty of +@REM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +@REM GNU General Public License for more details. +@REM +@REM You should have received a copy of the GNU General Public License +@REM along with this program. If not, see . +@REM docker build --file Dockerfile-iginx -t iginx:0.7.0-SNAPSHOT ../.. \ No newline at end of file diff --git a/docker/onlyIginx-parquet/build_iginx_docker.sh b/docker/onlyIginx-parquet/build_iginx_docker.sh index 46acb2af5a..8293ed7620 100644 --- a/docker/onlyIginx-parquet/build_iginx_docker.sh +++ b/docker/onlyIginx-parquet/build_iginx_docker.sh @@ -1,2 +1,20 @@ #!/bin/bash +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + docker build --file Dockerfile-iginx -t iginx:0.7.0-SNAPSHOT ../.. \ No newline at end of file diff --git a/docker/onlyIginx-parquet/run_iginx_docker.bat b/docker/onlyIginx-parquet/run_iginx_docker.bat index 173b980e57..fd656462e8 100644 --- a/docker/onlyIginx-parquet/run_iginx_docker.bat +++ b/docker/onlyIginx-parquet/run_iginx_docker.bat @@ -1,3 +1,20 @@ +@REM +@REM IGinX - the polystore system with high performance +@REM Copyright (C) Tsinghua University +@REM +@REM This program is free software: you can redistribute it and/or modify +@REM it under the terms of the GNU General Public License as published by +@REM the Free Software Foundation, either version 3 of the License, or +@REM (at your option) any later version. +@REM +@REM This program is distributed in the hope that it will be useful, +@REM but WITHOUT ANY WARRANTY; without even the implied warranty of +@REM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +@REM GNU General Public License for more details. +@REM +@REM You should have received a copy of the GNU General Public License +@REM along with this program. If not, see . +@REM @echo off cd /d %~dp0 setlocal EnableDelayedExpansion diff --git a/docker/onlyIginx-parquet/run_iginx_docker.sh b/docker/onlyIginx-parquet/run_iginx_docker.sh index 8b54fb4e87..9982b9ede5 100644 --- a/docker/onlyIginx-parquet/run_iginx_docker.sh +++ b/docker/onlyIginx-parquet/run_iginx_docker.sh @@ -1,4 +1,22 @@ #!/bin/bash +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + # workdir: $IGINX_HOME/docker/onlyiginx-parquet # work descripition: diff --git a/docker/onlyIginx/build_iginx_docker.bat b/docker/onlyIginx/build_iginx_docker.bat index d08f72dac8..773a4d6c87 100644 --- a/docker/onlyIginx/build_iginx_docker.bat +++ b/docker/onlyIginx/build_iginx_docker.bat @@ -1 +1,18 @@ +@REM +@REM IGinX - the polystore system with high performance +@REM Copyright (C) Tsinghua University +@REM +@REM This program is free software: you can redistribute it and/or modify +@REM it under the terms of the GNU General Public License as published by +@REM the Free Software Foundation, either version 3 of the License, or +@REM (at your option) any later version. +@REM +@REM This program is distributed in the hope that it will be useful, +@REM but WITHOUT ANY WARRANTY; without even the implied warranty of +@REM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +@REM GNU General Public License for more details. +@REM +@REM You should have received a copy of the GNU General Public License +@REM along with this program. If not, see . +@REM docker build --file Dockerfile-iginx -t iginx:0.7.0-SNAPSHOT ../.. \ No newline at end of file diff --git a/docker/onlyIginx/run_iginx_docker.bat b/docker/onlyIginx/run_iginx_docker.bat index 3ca78a712c..2322b2b11b 100644 --- a/docker/onlyIginx/run_iginx_docker.bat +++ b/docker/onlyIginx/run_iginx_docker.bat @@ -1,3 +1,20 @@ +@REM +@REM IGinX - the polystore system with high performance +@REM Copyright (C) Tsinghua University +@REM +@REM This program is free software: you can redistribute it and/or modify +@REM it under the terms of the GNU General Public License as published by +@REM the Free Software Foundation, either version 3 of the License, or +@REM (at your option) any later version. +@REM +@REM This program is distributed in the hope that it will be useful, +@REM but WITHOUT ANY WARRANTY; without even the implied warranty of +@REM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +@REM GNU General Public License for more details. +@REM +@REM You should have received a copy of the GNU General Public License +@REM along with this program. If not, see . +@REM @echo off set "current_dir=%CD%" @REM 将路径中的单反斜线替换为双反斜线 diff --git a/example/src/main/java/cn/edu/tsinghua/iginx/session/IginXStreamSessionExample.java b/example/src/main/java/cn/edu/tsinghua/iginx/session/IginXStreamSessionExample.java index dbcc45db57..4982b500a3 100644 --- a/example/src/main/java/cn/edu/tsinghua/iginx/session/IginXStreamSessionExample.java +++ b/example/src/main/java/cn/edu/tsinghua/iginx/session/IginXStreamSessionExample.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.session; import cn.edu.tsinghua.iginx.thrift.DataType; diff --git a/example/src/main/java/cn/edu/tsinghua/iginx/session/InfluxDBSessionExample.java b/example/src/main/java/cn/edu/tsinghua/iginx/session/InfluxDBSessionExample.java index 8c04a18e77..c94b77b068 100644 --- a/example/src/main/java/cn/edu/tsinghua/iginx/session/InfluxDBSessionExample.java +++ b/example/src/main/java/cn/edu/tsinghua/iginx/session/InfluxDBSessionExample.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session; diff --git a/example/src/main/java/cn/edu/tsinghua/iginx/session/IoTDBAfterDilatationExample.java b/example/src/main/java/cn/edu/tsinghua/iginx/session/IoTDBAfterDilatationExample.java index b9f04a6a52..96e45ddaa6 100644 --- a/example/src/main/java/cn/edu/tsinghua/iginx/session/IoTDBAfterDilatationExample.java +++ b/example/src/main/java/cn/edu/tsinghua/iginx/session/IoTDBAfterDilatationExample.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session; diff --git a/example/src/main/java/cn/edu/tsinghua/iginx/session/IoTDBBeforeDilatationExample.java b/example/src/main/java/cn/edu/tsinghua/iginx/session/IoTDBBeforeDilatationExample.java index f248cbd411..48b6755e19 100644 --- a/example/src/main/java/cn/edu/tsinghua/iginx/session/IoTDBBeforeDilatationExample.java +++ b/example/src/main/java/cn/edu/tsinghua/iginx/session/IoTDBBeforeDilatationExample.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session; diff --git a/example/src/main/java/cn/edu/tsinghua/iginx/session/IoTDBSessionExample.java b/example/src/main/java/cn/edu/tsinghua/iginx/session/IoTDBSessionExample.java index 6cc6fb6429..832e37cf0b 100644 --- a/example/src/main/java/cn/edu/tsinghua/iginx/session/IoTDBSessionExample.java +++ b/example/src/main/java/cn/edu/tsinghua/iginx/session/IoTDBSessionExample.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session; diff --git a/example/src/main/java/cn/edu/tsinghua/iginx/session/IoTDBSessionPoolExample.java b/example/src/main/java/cn/edu/tsinghua/iginx/session/IoTDBSessionPoolExample.java index 601e97f206..0cb10d224f 100644 --- a/example/src/main/java/cn/edu/tsinghua/iginx/session/IoTDBSessionPoolExample.java +++ b/example/src/main/java/cn/edu/tsinghua/iginx/session/IoTDBSessionPoolExample.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.session; import cn.edu.tsinghua.iginx.exception.SessionException; diff --git a/example/src/main/java/cn/edu/tsinghua/iginx/session/NewSessionExample.java b/example/src/main/java/cn/edu/tsinghua/iginx/session/NewSessionExample.java index fa94688c5e..d49d83d56b 100644 --- a/example/src/main/java/cn/edu/tsinghua/iginx/session/NewSessionExample.java +++ b/example/src/main/java/cn/edu/tsinghua/iginx/session/NewSessionExample.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session; diff --git a/example/src/main/java/cn/edu/tsinghua/iginx/session/NewSessionNotSupportedQueryExample.java b/example/src/main/java/cn/edu/tsinghua/iginx/session/NewSessionNotSupportedQueryExample.java index 2e5bf69e3d..0031467e13 100644 --- a/example/src/main/java/cn/edu/tsinghua/iginx/session/NewSessionNotSupportedQueryExample.java +++ b/example/src/main/java/cn/edu/tsinghua/iginx/session/NewSessionNotSupportedQueryExample.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session; diff --git a/example/src/main/java/cn/edu/tsinghua/iginx/session/NewSessionNotSupportedWriteExample.java b/example/src/main/java/cn/edu/tsinghua/iginx/session/NewSessionNotSupportedWriteExample.java index 481220bed4..a5d7939b14 100644 --- a/example/src/main/java/cn/edu/tsinghua/iginx/session/NewSessionNotSupportedWriteExample.java +++ b/example/src/main/java/cn/edu/tsinghua/iginx/session/NewSessionNotSupportedWriteExample.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session; diff --git a/example/src/main/java/cn/edu/tsinghua/iginx/session/OpenTSDBSessionExample.java b/example/src/main/java/cn/edu/tsinghua/iginx/session/OpenTSDBSessionExample.java index f1d7c570c8..c24f7f1ca1 100644 --- a/example/src/main/java/cn/edu/tsinghua/iginx/session/OpenTSDBSessionExample.java +++ b/example/src/main/java/cn/edu/tsinghua/iginx/session/OpenTSDBSessionExample.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.session; import cn.edu.tsinghua.iginx.exception.SessionException; diff --git a/example/src/main/java/cn/edu/tsinghua/iginx/session/ParquetServerExample.java b/example/src/main/java/cn/edu/tsinghua/iginx/session/ParquetServerExample.java index ee31bfcae1..63a066c6c8 100644 --- a/example/src/main/java/cn/edu/tsinghua/iginx/session/ParquetServerExample.java +++ b/example/src/main/java/cn/edu/tsinghua/iginx/session/ParquetServerExample.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.session; import cn.edu.tsinghua.iginx.exception.SessionException; diff --git a/example/src/main/java/cn/edu/tsinghua/iginx/session/ParquetSessionExample.java b/example/src/main/java/cn/edu/tsinghua/iginx/session/ParquetSessionExample.java index a4a39846d0..60ccda6bbe 100644 --- a/example/src/main/java/cn/edu/tsinghua/iginx/session/ParquetSessionExample.java +++ b/example/src/main/java/cn/edu/tsinghua/iginx/session/ParquetSessionExample.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.session; import cn.edu.tsinghua.iginx.exception.SessionException; diff --git a/example/src/main/java/cn/edu/tsinghua/iginx/session/PostgreSQLSessionExample.java b/example/src/main/java/cn/edu/tsinghua/iginx/session/PostgreSQLSessionExample.java index fddc870791..058842ffce 100644 --- a/example/src/main/java/cn/edu/tsinghua/iginx/session/PostgreSQLSessionExample.java +++ b/example/src/main/java/cn/edu/tsinghua/iginx/session/PostgreSQLSessionExample.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session; diff --git a/example/src/main/java/cn/edu/tsinghua/iginx/session/SQLSessionExample.java b/example/src/main/java/cn/edu/tsinghua/iginx/session/SQLSessionExample.java index 6b539c6de8..396204fce7 100644 --- a/example/src/main/java/cn/edu/tsinghua/iginx/session/SQLSessionExample.java +++ b/example/src/main/java/cn/edu/tsinghua/iginx/session/SQLSessionExample.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.session; import cn.edu.tsinghua.iginx.exception.SessionException; diff --git a/example/src/main/java/cn/edu/tsinghua/iginx/session/TagKVSessionExample.java b/example/src/main/java/cn/edu/tsinghua/iginx/session/TagKVSessionExample.java index af66050836..3a56d64d6c 100644 --- a/example/src/main/java/cn/edu/tsinghua/iginx/session/TagKVSessionExample.java +++ b/example/src/main/java/cn/edu/tsinghua/iginx/session/TagKVSessionExample.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.session; import cn.edu.tsinghua.iginx.exception.SessionException; diff --git a/example/src/main/java/cn/edu/tsinghua/iginx/session/TimescaleDBSessionExample.java b/example/src/main/java/cn/edu/tsinghua/iginx/session/TimescaleDBSessionExample.java index a09d81cfe9..6e119cbfc0 100644 --- a/example/src/main/java/cn/edu/tsinghua/iginx/session/TimescaleDBSessionExample.java +++ b/example/src/main/java/cn/edu/tsinghua/iginx/session/TimescaleDBSessionExample.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session; diff --git a/example/src/main/java/cn/edu/tsinghua/iginx/session/TransformCompare.java b/example/src/main/java/cn/edu/tsinghua/iginx/session/TransformCompare.java index e8fa6b582f..6b5fa3ca32 100644 --- a/example/src/main/java/cn/edu/tsinghua/iginx/session/TransformCompare.java +++ b/example/src/main/java/cn/edu/tsinghua/iginx/session/TransformCompare.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.session; import cn.edu.tsinghua.iginx.exception.SessionException; diff --git a/example/src/main/java/cn/edu/tsinghua/iginx/session/TransformExample.java b/example/src/main/java/cn/edu/tsinghua/iginx/session/TransformExample.java index 0c0a8df6f9..e40f0ac9eb 100644 --- a/example/src/main/java/cn/edu/tsinghua/iginx/session/TransformExample.java +++ b/example/src/main/java/cn/edu/tsinghua/iginx/session/TransformExample.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.session; import cn.edu.tsinghua.iginx.exception.SessionException; diff --git a/example/src/main/java/cn/edu/tsinghua/iginx/session/UDFCompareToSys.java b/example/src/main/java/cn/edu/tsinghua/iginx/session/UDFCompareToSys.java index 2f46a097f7..c5e480fe40 100644 --- a/example/src/main/java/cn/edu/tsinghua/iginx/session/UDFCompareToSys.java +++ b/example/src/main/java/cn/edu/tsinghua/iginx/session/UDFCompareToSys.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.session; import cn.edu.tsinghua.iginx.exception.SessionException; diff --git a/example/src/main/java/cn/edu/tsinghua/iginx/session/UDFExample.java b/example/src/main/java/cn/edu/tsinghua/iginx/session/UDFExample.java index 24047bb5c1..7c5f1b5515 100644 --- a/example/src/main/java/cn/edu/tsinghua/iginx/session/UDFExample.java +++ b/example/src/main/java/cn/edu/tsinghua/iginx/session/UDFExample.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.session; import cn.edu.tsinghua.iginx.exception.SessionException; diff --git a/example/src/main/resources/transformer_add_one.py b/example/src/main/resources/transformer_add_one.py index 6315786272..4fe45d624a 100644 --- a/example/src/main/resources/transformer_add_one.py +++ b/example/src/main/resources/transformer_add_one.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + import pandas as pd diff --git a/example/src/main/resources/transformer_avg.py b/example/src/main/resources/transformer_avg.py index dbd319c3d9..90e78e8f8b 100644 --- a/example/src/main/resources/transformer_avg.py +++ b/example/src/main/resources/transformer_avg.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + import pandas as pd diff --git a/example/src/main/resources/transformer_count.py b/example/src/main/resources/transformer_count.py index e2ab063333..259d6ef1da 100644 --- a/example/src/main/resources/transformer_count.py +++ b/example/src/main/resources/transformer_count.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + import pandas as pd diff --git a/example/src/main/resources/transformer_max.py b/example/src/main/resources/transformer_max.py index 594ce29a15..5ad89df329 100644 --- a/example/src/main/resources/transformer_max.py +++ b/example/src/main/resources/transformer_max.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + import pandas as pd diff --git a/example/src/main/resources/transformer_min.py b/example/src/main/resources/transformer_min.py index 31003e10e4..8e886ba5a3 100644 --- a/example/src/main/resources/transformer_min.py +++ b/example/src/main/resources/transformer_min.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + import pandas as pd diff --git a/example/src/main/resources/transformer_row_sum.py b/example/src/main/resources/transformer_row_sum.py index fea1fcff92..0f38eabba1 100644 --- a/example/src/main/resources/transformer_row_sum.py +++ b/example/src/main/resources/transformer_row_sum.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + import pandas as pd import numpy as np diff --git a/example/src/main/resources/transformer_sum.py b/example/src/main/resources/transformer_sum.py index 63dea29ddb..e4ef01dd18 100644 --- a/example/src/main/resources/transformer_sum.py +++ b/example/src/main/resources/transformer_sum.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + import pandas as pd diff --git a/example/src/main/resources/udaf_count.py b/example/src/main/resources/udaf_count.py index b8884e7b3c..623278fe94 100644 --- a/example/src/main/resources/udaf_count.py +++ b/example/src/main/resources/udaf_count.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + class UDFCount: def __init__(self): pass diff --git a/example/src/main/resources/udtf_sin.py b/example/src/main/resources/udtf_sin.py index b66329b91c..51cf539c44 100644 --- a/example/src/main/resources/udtf_sin.py +++ b/example/src/main/resources/udtf_sin.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + import math diff --git a/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/Config.java b/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/Config.java index 52673440a8..95ee63baf3 100644 --- a/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/Config.java +++ b/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/Config.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.jdbc; public class Config { diff --git a/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/Constant.java b/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/Constant.java index 0c6be18ffd..e307079037 100644 --- a/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/Constant.java +++ b/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/Constant.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.jdbc; public class Constant { diff --git a/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXConnection.java b/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXConnection.java index da87be06cb..e5bf0bf5bd 100644 --- a/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXConnection.java +++ b/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXConnection.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.jdbc; import cn.edu.tsinghua.iginx.exception.SessionException; diff --git a/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXConnectionParams.java b/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXConnectionParams.java index 2d1f281f01..3d8e036c06 100644 --- a/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXConnectionParams.java +++ b/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXConnectionParams.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.jdbc; public class IginXConnectionParams { diff --git a/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXDataSource.java b/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXDataSource.java index e7a17c459d..82c8fc47e0 100644 --- a/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXDataSource.java +++ b/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXDataSource.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.jdbc; import cn.edu.tsinghua.iginx.exception.SessionException; diff --git a/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXDatabaseMetadata.java b/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXDatabaseMetadata.java index 115fd725ab..2f98301fe1 100644 --- a/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXDatabaseMetadata.java +++ b/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXDatabaseMetadata.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.jdbc; import cn.edu.tsinghua.iginx.session.Session; diff --git a/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXDriver.java b/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXDriver.java index b66f9fb876..5b60685ab6 100644 --- a/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXDriver.java +++ b/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXDriver.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.jdbc; import java.sql.*; diff --git a/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXPreparedStatement.java b/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXPreparedStatement.java index a4c3035490..11df856441 100644 --- a/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXPreparedStatement.java +++ b/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXPreparedStatement.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.jdbc; import cn.edu.tsinghua.iginx.session.Session; diff --git a/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXResultMetadata.java b/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXResultMetadata.java index 40a1e20a6f..19cb84b0c4 100644 --- a/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXResultMetadata.java +++ b/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXResultMetadata.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.jdbc; import cn.edu.tsinghua.iginx.thrift.DataType; diff --git a/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXResultSet.java b/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXResultSet.java index 7beb610ad2..0d947d1e0c 100644 --- a/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXResultSet.java +++ b/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXResultSet.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.jdbc; import cn.edu.tsinghua.iginx.constant.GlobalConstant; diff --git a/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXStatement.java b/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXStatement.java index 8b95433f24..0252120ab2 100644 --- a/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXStatement.java +++ b/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginXStatement.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.jdbc; import cn.edu.tsinghua.iginx.exception.SessionException; diff --git a/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginxUrlException.java b/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginxUrlException.java index a83df88b58..26321f3d27 100644 --- a/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginxUrlException.java +++ b/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/IginxUrlException.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.jdbc; import java.sql.SQLException; diff --git a/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/Utils.java b/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/Utils.java index e69c1a4cc4..f64653c850 100644 --- a/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/Utils.java +++ b/jdbc/src/main/java/cn/edu/tsinghua/iginx/jdbc/Utils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.jdbc; import java.sql.Date; diff --git a/jdbc/src/test/java/BatchTest.java b/jdbc/src/test/java/BatchTest.java index 4568232f6d..a967a66fb6 100644 --- a/jdbc/src/test/java/BatchTest.java +++ b/jdbc/src/test/java/BatchTest.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + import cn.edu.tsinghua.iginx.jdbc.IginXStatement; import java.sql.SQLException; import java.util.ArrayList; diff --git a/jdbc/src/test/java/ConnectionParamsTest.java b/jdbc/src/test/java/ConnectionParamsTest.java index 7bcc302e7e..fb898160fa 100644 --- a/jdbc/src/test/java/ConnectionParamsTest.java +++ b/jdbc/src/test/java/ConnectionParamsTest.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + import static org.junit.Assert.assertEquals; import cn.edu.tsinghua.iginx.jdbc.Config; diff --git a/jdbc/src/test/java/ExampleTest.java b/jdbc/src/test/java/ExampleTest.java index 2a28406772..801ce32737 100644 --- a/jdbc/src/test/java/ExampleTest.java +++ b/jdbc/src/test/java/ExampleTest.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + import cn.edu.tsinghua.iginx.jdbc.IginXPreparedStatement; import java.sql.*; import org.apache.commons.lang3.RandomStringUtils; diff --git a/jdbc/src/test/java/PreparedStatementTest.java b/jdbc/src/test/java/PreparedStatementTest.java index 9a54307891..f2bb27cb5f 100644 --- a/jdbc/src/test/java/PreparedStatementTest.java +++ b/jdbc/src/test/java/PreparedStatementTest.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + import cn.edu.tsinghua.iginx.jdbc.IginXPreparedStatement; import java.sql.SQLException; import org.junit.Assert; diff --git a/jdbc/src/test/java/ResultMetadataTest.java b/jdbc/src/test/java/ResultMetadataTest.java index c699a50203..c2daabe903 100644 --- a/jdbc/src/test/java/ResultMetadataTest.java +++ b/jdbc/src/test/java/ResultMetadataTest.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; diff --git a/jdbc/src/test/java/ResultSetTest.java b/jdbc/src/test/java/ResultSetTest.java index f19fd32c1f..70b052602d 100644 --- a/jdbc/src/test/java/ResultSetTest.java +++ b/jdbc/src/test/java/ResultSetTest.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + import cn.edu.tsinghua.iginx.constant.GlobalConstant; import java.sql.ResultSet; import java.sql.SQLException; diff --git a/jdbc/src/test/java/TestUtils.java b/jdbc/src/test/java/TestUtils.java index 499661cebd..74f29b727a 100644 --- a/jdbc/src/test/java/TestUtils.java +++ b/jdbc/src/test/java/TestUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + import cn.edu.tsinghua.iginx.jdbc.IginXResultSet; import cn.edu.tsinghua.iginx.session.SessionExecuteSqlResult; import cn.edu.tsinghua.iginx.thrift.DataType; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/FilterFragmentOptimizer.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/FilterFragmentOptimizer.java index 099ebd3d08..4a06563683 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/FilterFragmentOptimizer.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/FilterFragmentOptimizer.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer; import cn.edu.tsinghua.iginx.engine.logical.optimizer.Optimizer; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/FilterPushDownOptimizer.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/FilterPushDownOptimizer.java index 924dd3316c..73aed98b46 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/FilterPushDownOptimizer.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/FilterPushDownOptimizer.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer; import cn.edu.tsinghua.iginx.engine.logical.optimizer.Optimizer; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/RemoveNotOptimizer.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/RemoveNotOptimizer.java index a0d3bf9002..5e536fc5db 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/RemoveNotOptimizer.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/RemoveNotOptimizer.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer; import cn.edu.tsinghua.iginx.engine.logical.optimizer.Optimizer; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/Operand.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/Operand.java index b2966c78bf..90fdf6d8e8 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/Operand.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/Operand.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer.core; import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/Planner.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/Planner.java index 9b9380980e..7f17c1065d 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/Planner.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/Planner.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer.core; import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/RuleCall.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/RuleCall.java index efefd6f160..bfc882038e 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/RuleCall.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/RuleCall.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer.core; import cn.edu.tsinghua.iginx.engine.shared.operator.BinaryOperator; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/DeepFirstIterator.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/DeepFirstIterator.java index 25e0091ba0..bb955e4697 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/DeepFirstIterator.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/DeepFirstIterator.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer.core.iterator; import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/LeveledIterator.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/LeveledIterator.java index d76fe1905b..4e1cb6cd8f 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/LeveledIterator.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/LeveledIterator.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer.core.iterator; import cn.edu.tsinghua.iginx.engine.shared.operator.BinaryOperator; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/MatchOrder.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/MatchOrder.java index 96f0ec8922..2484b42354 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/MatchOrder.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/MatchOrder.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer.core.iterator; public enum MatchOrder { diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/ReverseDeepFirstIterator.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/ReverseDeepFirstIterator.java index 8e6d323e0d..f0d2a43855 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/ReverseDeepFirstIterator.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/ReverseDeepFirstIterator.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer.core.iterator; import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/ReverseLeveledIterator.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/ReverseLeveledIterator.java index c42f720463..fa107bdab5 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/ReverseLeveledIterator.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/ReverseLeveledIterator.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer.core.iterator; import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/TreeIterator.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/TreeIterator.java index c226fc2c03..ce43a192b0 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/TreeIterator.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/core/iterator/TreeIterator.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer.core.iterator; import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rbo/RBORuleCall.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rbo/RBORuleCall.java index 1298ad240f..89727fa48a 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rbo/RBORuleCall.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rbo/RBORuleCall.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer.rbo; import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rbo/RuleBasedOptimizer.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rbo/RuleBasedOptimizer.java index aae3b09b6e..c22f303922 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rbo/RuleBasedOptimizer.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rbo/RuleBasedOptimizer.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer.rbo; import cn.edu.tsinghua.iginx.engine.logical.optimizer.Optimizer; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rbo/RuleBasedPlanner.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rbo/RuleBasedPlanner.java index 5aa212dec5..ac700b3753 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rbo/RuleBasedPlanner.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rbo/RuleBasedPlanner.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer.rbo; import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/ColumnPruningRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/ColumnPruningRule.java index 573815ffbf..4eb237fb74 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/ColumnPruningRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/ColumnPruningRule.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer.rules; import static cn.edu.tsinghua.iginx.engine.logical.utils.PathUtils.*; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/ConstantPropagationRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/ConstantPropagationRule.java index b578662561..ffda74db40 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/ConstantPropagationRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/ConstantPropagationRule.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer.rules; import cn.edu.tsinghua.iginx.engine.logical.utils.LogicalFilterUtils; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterConstantFoldingRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterConstantFoldingRule.java index 70a2c15fd9..075f0c9753 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterConstantFoldingRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterConstantFoldingRule.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer.rules; import cn.edu.tsinghua.iginx.engine.logical.utils.LogicalFilterUtils; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterJoinTransposeRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterJoinTransposeRule.java index bd26369a56..107090b3f2 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterJoinTransposeRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterJoinTransposeRule.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer.rules; import cn.edu.tsinghua.iginx.engine.shared.operator.AbstractJoin; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownAddSchemaPrefixRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownAddSchemaPrefixRule.java index 0ebf6eeb8e..5aeda23cb9 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownAddSchemaPrefixRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownAddSchemaPrefixRule.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer.rules; import cn.edu.tsinghua.iginx.engine.shared.expr.*; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownGroupByRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownGroupByRule.java index 1c5e13f439..eaf6e90545 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownGroupByRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownGroupByRule.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer.rules; import cn.edu.tsinghua.iginx.engine.logical.utils.LogicalFilterUtils; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownPathUnionJoinRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownPathUnionJoinRule.java index cc045cc3ad..354f80307b 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownPathUnionJoinRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownPathUnionJoinRule.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer.rules; import cn.edu.tsinghua.iginx.engine.logical.utils.LogicalFilterUtils; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownProjectReorderSortRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownProjectReorderSortRule.java index 9d44733996..b6fdc7e391 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownProjectReorderSortRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownProjectReorderSortRule.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer.rules; import cn.edu.tsinghua.iginx.engine.shared.operator.*; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownRenameRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownRenameRule.java index 01c248c08a..e3d94d2211 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownRenameRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownRenameRule.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer.rules; import cn.edu.tsinghua.iginx.engine.logical.utils.PathUtils; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownSelectRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownSelectRule.java index 27663a0e8f..241b73a719 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownSelectRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownSelectRule.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer.rules; import cn.edu.tsinghua.iginx.engine.logical.utils.LogicalFilterUtils; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownSetOpRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownSetOpRule.java index 935707782d..05cd0be93c 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownSetOpRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownSetOpRule.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer.rules; import cn.edu.tsinghua.iginx.engine.shared.Constants; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownTransformRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownTransformRule.java index c69e11bd29..4d8387ae7e 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownTransformRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownTransformRule.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer.rules; import cn.edu.tsinghua.iginx.engine.logical.utils.LogicalFilterUtils; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushIntoJoinConditionRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushIntoJoinConditionRule.java index 99124f28a9..d358597e2e 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushIntoJoinConditionRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushIntoJoinConditionRule.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer.rules; import cn.edu.tsinghua.iginx.engine.physical.memory.execute.utils.FilterUtils; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushOutJoinConditionRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushOutJoinConditionRule.java index 2480e36edf..4a93ff3a82 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushOutJoinConditionRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushOutJoinConditionRule.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer.rules; import cn.edu.tsinghua.iginx.engine.logical.utils.LogicalFilterUtils; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FragmentPruningByFilterRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FragmentPruningByFilterRule.java index 9dad7ff188..ab1dc4eb22 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FragmentPruningByFilterRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FragmentPruningByFilterRule.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer.rules; import cn.edu.tsinghua.iginx.engine.logical.utils.LogicalFilterUtils; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FragmentPruningByPatternRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FragmentPruningByPatternRule.java index 23a08832cf..3af23df73a 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FragmentPruningByPatternRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FragmentPruningByPatternRule.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer.rules; import cn.edu.tsinghua.iginx.engine.shared.operator.*; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FunctionDistinctEliminateRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FunctionDistinctEliminateRule.java index ab6518e5b7..bfa94abf97 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FunctionDistinctEliminateRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FunctionDistinctEliminateRule.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer.rules; import cn.edu.tsinghua.iginx.engine.shared.function.FunctionCall; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/InExistsDistinctEliminateRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/InExistsDistinctEliminateRule.java index 9408ae86fc..bd3ee246eb 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/InExistsDistinctEliminateRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/InExistsDistinctEliminateRule.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer.rules; import cn.edu.tsinghua.iginx.engine.shared.operator.AbstractJoin; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/NotFilterRemoveRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/NotFilterRemoveRule.java index 6c4b00d962..8cd0454f3e 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/NotFilterRemoveRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/NotFilterRemoveRule.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer.rules; import cn.edu.tsinghua.iginx.engine.logical.utils.LogicalFilterUtils; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/RowTransformConstantFoldingRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/RowTransformConstantFoldingRule.java index 499154b87b..d98665c811 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/RowTransformConstantFoldingRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/RowTransformConstantFoldingRule.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer.rules; import cn.edu.tsinghua.iginx.engine.physical.memory.execute.utils.ExprUtils; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/Rule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/Rule.java index ccea39df2e..465bf528b9 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/Rule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/Rule.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer.rules; import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/RuleCollection.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/RuleCollection.java index 517e14a6c7..c2cb7b56b9 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/RuleCollection.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/RuleCollection.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer.rules; import cn.edu.tsinghua.iginx.conf.Config; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/RuleStrategy.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/RuleStrategy.java index 761e34e82b..91bc1cbbd0 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/RuleStrategy.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/RuleStrategy.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.logical.optimizer.rules; public enum RuleStrategy { diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/physical/optimizer/naive/NaiveConstraintManager.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/physical/optimizer/naive/NaiveConstraintManager.java index 5887797ba4..23f3767608 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/physical/optimizer/naive/NaiveConstraintManager.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/physical/optimizer/naive/NaiveConstraintManager.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.physical.optimizer.naive; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/physical/optimizer/naive/NaivePhysicalOptimizer.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/physical/optimizer/naive/NaivePhysicalOptimizer.java index 2450a17cfb..5b3b34de84 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/physical/optimizer/naive/NaivePhysicalOptimizer.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/physical/optimizer/naive/NaivePhysicalOptimizer.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.physical.optimizer.naive; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/physical/optimizer/naive/NaiveReplicaDispatcher.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/physical/optimizer/naive/NaiveReplicaDispatcher.java index 0537878559..3f0ffa1fe7 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/physical/optimizer/naive/NaiveReplicaDispatcher.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/physical/optimizer/naive/NaiveReplicaDispatcher.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.physical.optimizer.naive; diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/physical/optimizer/rule/Rule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/physical/optimizer/rule/Rule.java index 37e9e2b4d8..e06a64edc1 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/physical/optimizer/rule/Rule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/physical/optimizer/rule/Rule.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.physical.optimizer.rule; diff --git a/optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/IteratorTest.java b/optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/IteratorTest.java index dfcf058cea..04e85b60af 100644 --- a/optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/IteratorTest.java +++ b/optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/IteratorTest.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.optimizer; import cn.edu.tsinghua.iginx.engine.shared.operator.InnerJoin; diff --git a/optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/OperandTest.java b/optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/OperandTest.java index aeebada545..ab4f4bbecb 100644 --- a/optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/OperandTest.java +++ b/optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/OperandTest.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.optimizer; import static cn.edu.tsinghua.iginx.logical.optimizer.rules.Rule.any; diff --git a/optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/RBOTest.java b/optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/RBOTest.java index a9df7870a6..b082cfb121 100644 --- a/optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/RBOTest.java +++ b/optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/RBOTest.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.optimizer; import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; diff --git a/optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/RBOTestUtils.java b/optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/RBOTestUtils.java index a4e3c01e26..0fceff9f87 100644 --- a/optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/RBOTestUtils.java +++ b/optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/RBOTestUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.optimizer; import cn.edu.tsinghua.iginx.logical.optimizer.rules.RuleCollection; diff --git a/optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/TreeBuilder.java b/optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/TreeBuilder.java index f7547e6c25..31a444bb16 100644 --- a/optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/TreeBuilder.java +++ b/optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/TreeBuilder.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.optimizer; import cn.edu.tsinghua.iginx.engine.shared.Constants; diff --git a/optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/TreePrinter.java b/optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/TreePrinter.java index 1264db082d..65e0ba5487 100644 --- a/optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/TreePrinter.java +++ b/optimizer/src/test/java/cn/edu/tsinghua/iginx/optimizer/TreePrinter.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.optimizer; import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/exception/SessionException.java b/session/src/main/java/cn/edu/tsinghua/iginx/exception/SessionException.java index a46e454a13..8f13d10bc0 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/exception/SessionException.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/exception/SessionException.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.exception; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/pool/IginxInfo.java b/session/src/main/java/cn/edu/tsinghua/iginx/pool/IginxInfo.java index 11829d6a2f..d5b004c191 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/pool/IginxInfo.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/pool/IginxInfo.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.pool; public class IginxInfo { diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/pool/SessionPool.java b/session/src/main/java/cn/edu/tsinghua/iginx/pool/SessionPool.java index 68f6dcd133..e292601853 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/pool/SessionPool.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/pool/SessionPool.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.pool; import static cn.edu.tsinghua.iginx.constant.GlobalConstant.KEY_MAX_VAL; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session/ClusterInfo.java b/session/src/main/java/cn/edu/tsinghua/iginx/session/ClusterInfo.java index fecfdfe5f3..55916b1149 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session/ClusterInfo.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session/ClusterInfo.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session/Column.java b/session/src/main/java/cn/edu/tsinghua/iginx/session/Column.java index e1db46dbf1..c1aab542ab 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session/Column.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session/Column.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session/CurveMatchResult.java b/session/src/main/java/cn/edu/tsinghua/iginx/session/CurveMatchResult.java index 762331a1f0..077a880b42 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session/CurveMatchResult.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session/CurveMatchResult.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.session; public class CurveMatchResult { diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session/Point.java b/session/src/main/java/cn/edu/tsinghua/iginx/session/Point.java index 40628ea06f..4e849c7fc0 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session/Point.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session/Point.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session/QueryDataSet.java b/session/src/main/java/cn/edu/tsinghua/iginx/session/QueryDataSet.java index 948248f9b2..7cd0d6b22c 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session/QueryDataSet.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session/QueryDataSet.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session/Session.java b/session/src/main/java/cn/edu/tsinghua/iginx/session/Session.java index c7215fc5fd..100e1341a6 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session/Session.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session/Session.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session/SessionAggregateQueryDataSet.java b/session/src/main/java/cn/edu/tsinghua/iginx/session/SessionAggregateQueryDataSet.java index 456df5f747..809403ca61 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session/SessionAggregateQueryDataSet.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session/SessionAggregateQueryDataSet.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.session; import static cn.edu.tsinghua.iginx.utils.ByteUtils.getLongArrayFromByteBuffer; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session/SessionExecuteSqlResult.java b/session/src/main/java/cn/edu/tsinghua/iginx/session/SessionExecuteSqlResult.java index 453a5de818..c3a02c3ae3 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session/SessionExecuteSqlResult.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session/SessionExecuteSqlResult.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session/SessionQueryDataSet.java b/session/src/main/java/cn/edu/tsinghua/iginx/session/SessionQueryDataSet.java index cc3fa2653d..ee2f281913 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session/SessionQueryDataSet.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session/SessionQueryDataSet.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/Arguments.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/Arguments.java index b74524ad5b..28fe266314 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/Arguments.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/Arguments.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/AsyncWriteClient.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/AsyncWriteClient.java index aa6a7ddf7d..91642be2fc 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/AsyncWriteClient.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/AsyncWriteClient.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/ClusterClient.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/ClusterClient.java index 2ba4dd4acf..ddc094902a 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/ClusterClient.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/ClusterClient.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/DeleteClient.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/DeleteClient.java index 632f9546d1..84aa16a53b 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/DeleteClient.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/DeleteClient.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/IginXClient.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/IginXClient.java index e9197623c9..d65b479892 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/IginXClient.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/IginXClient.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/IginXClientFactory.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/IginXClientFactory.java index b5e4080836..f759985a17 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/IginXClientFactory.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/IginXClientFactory.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/IginXClientOptions.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/IginXClientOptions.java index f4cafe2137..ab83f4b5f0 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/IginXClientOptions.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/IginXClientOptions.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/QueryClient.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/QueryClient.java index 946932de1c..6130983192 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/QueryClient.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/QueryClient.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/TransformClient.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/TransformClient.java index 5c2de90c11..982b5dc81c 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/TransformClient.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/TransformClient.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.session_v2; import cn.edu.tsinghua.iginx.session_v2.domain.Transform; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/UsersClient.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/UsersClient.java index a746e11b97..9544f25da3 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/UsersClient.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/UsersClient.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/WriteClient.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/WriteClient.java index b3e594ba47..b89c443206 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/WriteClient.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/WriteClient.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/annotations/Field.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/annotations/Field.java index b48b595330..1d1d6a429f 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/annotations/Field.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/annotations/Field.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2.annotations; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/annotations/Measurement.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/annotations/Measurement.java index 75e823eb5c..bce8e68988 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/annotations/Measurement.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/annotations/Measurement.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2.annotations; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/domain/ClusterInfo.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/domain/ClusterInfo.java index cb873c3864..a83f31cca0 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/domain/ClusterInfo.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/domain/ClusterInfo.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2.domain; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/domain/Storage.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/domain/Storage.java index c367e5de8c..4334cb5785 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/domain/Storage.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/domain/Storage.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2.domain; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/domain/Task.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/domain/Task.java index 91d5154ba0..c21f8726d2 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/domain/Task.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/domain/Task.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.session_v2.domain; import cn.edu.tsinghua.iginx.session_v2.Arguments; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/domain/Transform.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/domain/Transform.java index 7d876c18ff..662fd8ee49 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/domain/Transform.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/domain/Transform.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.session_v2.domain; import cn.edu.tsinghua.iginx.session_v2.Arguments; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/domain/User.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/domain/User.java index 799f2eae28..7615e62b28 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/domain/User.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/domain/User.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2.domain; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/exception/IginXException.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/exception/IginXException.java index 63eeaa1e48..324c2a7495 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/exception/IginXException.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/exception/IginXException.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2.exception; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/AbstractFunctionClient.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/AbstractFunctionClient.java index 3a97cdd2ab..941dc977f9 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/AbstractFunctionClient.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/AbstractFunctionClient.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2.internal; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/AsyncWriteClientImpl.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/AsyncWriteClientImpl.java index 25cd74ca29..9e564d6bc2 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/AsyncWriteClientImpl.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/AsyncWriteClientImpl.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2.internal; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/ClusterClientImpl.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/ClusterClientImpl.java index b012af02c1..ee31303489 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/ClusterClientImpl.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/ClusterClientImpl.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2.internal; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/DeleteClientImpl.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/DeleteClientImpl.java index 20dc720e60..f74574018c 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/DeleteClientImpl.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/DeleteClientImpl.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2.internal; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/IginXClientImpl.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/IginXClientImpl.java index 4b1e05e96f..b18259a01d 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/IginXClientImpl.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/IginXClientImpl.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2.internal; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/MeasurementMapper.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/MeasurementMapper.java index c28e9a35fd..ee466670a4 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/MeasurementMapper.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/MeasurementMapper.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2.internal; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/MeasurementUtils.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/MeasurementUtils.java index 4e44dfe832..c50fb98cb6 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/MeasurementUtils.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/MeasurementUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.session_v2.internal; import java.util.ArrayList; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/QueryClientImpl.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/QueryClientImpl.java index ab3c037779..284558e342 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/QueryClientImpl.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/QueryClientImpl.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2.internal; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/ResultMapper.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/ResultMapper.java index 2e9a311435..08323ca044 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/ResultMapper.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/ResultMapper.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2.internal; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/TransformClientImpl.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/TransformClientImpl.java index 419c770d09..892e96928e 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/TransformClientImpl.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/TransformClientImpl.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.session_v2.internal; import cn.edu.tsinghua.iginx.exception.SessionException; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/UsersClientImpl.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/UsersClientImpl.java index dcad9c0dc2..eed5b062dd 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/UsersClientImpl.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/UsersClientImpl.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2.internal; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/WriteClientImpl.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/WriteClientImpl.java index 1c09a8a6df..fc068a0ebf 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/WriteClientImpl.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/internal/WriteClientImpl.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2.internal; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/AggregateQuery.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/AggregateQuery.java index 0ead2e9c85..d87b497f3f 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/AggregateQuery.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/AggregateQuery.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2.query; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/DownsampleQuery.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/DownsampleQuery.java index 359a085b55..073d86dbdb 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/DownsampleQuery.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/DownsampleQuery.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2.query; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/IginXColumn.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/IginXColumn.java index bed65ab57e..86d9e72e3b 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/IginXColumn.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/IginXColumn.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2.query; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/IginXHeader.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/IginXHeader.java index 4f025fdf15..a1d1a7669f 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/IginXHeader.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/IginXHeader.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2.query; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/IginXRecord.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/IginXRecord.java index 5fde058f0e..8c5cc8c31f 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/IginXRecord.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/IginXRecord.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2.query; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/IginXTable.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/IginXTable.java index e2c9cdc34d..93106d35a5 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/IginXTable.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/IginXTable.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2.query; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/LastQuery.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/LastQuery.java index dd51cc8490..c8d795f377 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/LastQuery.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/LastQuery.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2.query; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/Query.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/Query.java index 3900923c40..73daae5208 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/Query.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/Query.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2.query; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/SimpleQuery.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/SimpleQuery.java index 5a231771d6..465e8967ed 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/SimpleQuery.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/query/SimpleQuery.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2.query; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/write/Point.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/write/Point.java index 6d91df640b..d31b5df320 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/write/Point.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/write/Point.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2.write; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/write/Record.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/write/Record.java index aef2a80aeb..a274877f27 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/write/Record.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/write/Record.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2.write; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/write/Table.java b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/write/Table.java index 24475a0bed..9993ae0eb9 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/write/Table.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session_v2/write/Table.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.session_v2.write; diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/utils/StatusUtils.java b/session/src/main/java/cn/edu/tsinghua/iginx/utils/StatusUtils.java index 62e1926a2f..788e9c8893 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/utils/StatusUtils.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/utils/StatusUtils.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.utils; diff --git a/session/src/test/java/ResultFormatTest.java b/session/src/test/java/ResultFormatTest.java index fcf7bd8285..218b0b5a62 100644 --- a/session/src/test/java/ResultFormatTest.java +++ b/session/src/test/java/ResultFormatTest.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + import static org.junit.Assert.assertEquals; import cn.edu.tsinghua.iginx.session.SessionExecuteSqlResult; diff --git a/session_py/example.py b/session_py/example.py index 1a207cf9ce..01ca135ecf 100644 --- a/session_py/example.py +++ b/session_py/example.py @@ -1,20 +1,21 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University # -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. # +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + import pandas as pd from iginx_pyclient.session import Session diff --git a/session_py/file_example.py b/session_py/file_example.py index 6735ef1365..b7d6c9ae07 100644 --- a/session_py/file_example.py +++ b/session_py/file_example.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + """ A simple example on how to manipulate file with IGinX """ diff --git a/session_py/iginx/iginx_pyclient/__init__.py b/session_py/iginx/iginx_pyclient/__init__.py index 2a1e720805..2482c22e8a 100644 --- a/session_py/iginx/iginx_pyclient/__init__.py +++ b/session_py/iginx/iginx_pyclient/__init__.py @@ -1,17 +1,17 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University # -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . # diff --git a/session_py/iginx/iginx_pyclient/cluster_info.py b/session_py/iginx/iginx_pyclient/cluster_info.py index 11c47e70d3..608769b762 100644 --- a/session_py/iginx/iginx_pyclient/cluster_info.py +++ b/session_py/iginx/iginx_pyclient/cluster_info.py @@ -1,19 +1,19 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University # -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . # from .thrift.rpc.ttypes import StorageEngineType diff --git a/session_py/iginx/iginx_pyclient/dataset.py b/session_py/iginx/iginx_pyclient/dataset.py index 4ca6224caf..f80047cce1 100644 --- a/session_py/iginx/iginx_pyclient/dataset.py +++ b/session_py/iginx/iginx_pyclient/dataset.py @@ -1,19 +1,19 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University # -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . # from enum import Enum diff --git a/session_py/iginx/iginx_pyclient/session.py b/session_py/iginx/iginx_pyclient/session.py index 175375d638..0e328b6744 100644 --- a/session_py/iginx/iginx_pyclient/session.py +++ b/session_py/iginx/iginx_pyclient/session.py @@ -1,19 +1,19 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University # -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . # import csv import logging diff --git a/session_py/iginx/iginx_pyclient/thrift/__init__.py b/session_py/iginx/iginx_pyclient/thrift/__init__.py index e69de29bb2..02225d5e15 100644 --- a/session_py/iginx/iginx_pyclient/thrift/__init__.py +++ b/session_py/iginx/iginx_pyclient/thrift/__init__.py @@ -0,0 +1,18 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + diff --git a/session_py/iginx/iginx_pyclient/thrift/rpc/IService.py b/session_py/iginx/iginx_pyclient/thrift/rpc/IService.py index d19e949dde..358925678d 100644 --- a/session_py/iginx/iginx_pyclient/thrift/rpc/IService.py +++ b/session_py/iginx/iginx_pyclient/thrift/rpc/IService.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + # # Autogenerated by Thrift Compiler (0.16.0) # diff --git a/session_py/iginx/iginx_pyclient/thrift/rpc/__init__.py b/session_py/iginx/iginx_pyclient/thrift/rpc/__init__.py index cc24d07ca3..9ed5ba1cbb 100644 --- a/session_py/iginx/iginx_pyclient/thrift/rpc/__init__.py +++ b/session_py/iginx/iginx_pyclient/thrift/rpc/__init__.py @@ -1 +1,19 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + __all__ = ['ttypes', 'constants', 'IService'] diff --git a/session_py/iginx/iginx_pyclient/thrift/rpc/constants.py b/session_py/iginx/iginx_pyclient/thrift/rpc/constants.py index 82c674e052..a4d9713781 100644 --- a/session_py/iginx/iginx_pyclient/thrift/rpc/constants.py +++ b/session_py/iginx/iginx_pyclient/thrift/rpc/constants.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + # # Autogenerated by Thrift Compiler (0.16.0) # diff --git a/session_py/iginx/iginx_pyclient/thrift/rpc/ttypes.py b/session_py/iginx/iginx_pyclient/thrift/rpc/ttypes.py index 0e820c0567..0498f488bf 100644 --- a/session_py/iginx/iginx_pyclient/thrift/rpc/ttypes.py +++ b/session_py/iginx/iginx_pyclient/thrift/rpc/ttypes.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + # # Autogenerated by Thrift Compiler (0.16.0) # diff --git a/session_py/iginx/iginx_pyclient/time_series.py b/session_py/iginx/iginx_pyclient/time_series.py index 1cf4cf9d64..3d340d5f94 100644 --- a/session_py/iginx/iginx_pyclient/time_series.py +++ b/session_py/iginx/iginx_pyclient/time_series.py @@ -1,19 +1,19 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University # -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . # from .thrift.rpc.ttypes import DataType diff --git a/session_py/iginx/iginx_pyclient/utils/__init__.py b/session_py/iginx/iginx_pyclient/utils/__init__.py index 4b8ee97fad..cc3b5d49eb 100644 --- a/session_py/iginx/iginx_pyclient/utils/__init__.py +++ b/session_py/iginx/iginx_pyclient/utils/__init__.py @@ -1,17 +1,17 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University # -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . # \ No newline at end of file diff --git a/session_py/iginx/iginx_pyclient/utils/bitmap.py b/session_py/iginx/iginx_pyclient/utils/bitmap.py index e27f4125df..af9a40d4fc 100644 --- a/session_py/iginx/iginx_pyclient/utils/bitmap.py +++ b/session_py/iginx/iginx_pyclient/utils/bitmap.py @@ -1,21 +1,20 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University # -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . # - class Bitmap(object): BIT_UTIL = [1, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 6, 1 << 7] diff --git a/session_py/iginx/iginx_pyclient/utils/byte_utils.py b/session_py/iginx/iginx_pyclient/utils/byte_utils.py index b083433380..10ed177254 100644 --- a/session_py/iginx/iginx_pyclient/utils/byte_utils.py +++ b/session_py/iginx/iginx_pyclient/utils/byte_utils.py @@ -1,21 +1,20 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University # -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . # - import struct from .bitmap import Bitmap diff --git a/session_py/iginx/setup.py b/session_py/iginx/setup.py index 6aabea4ba8..0eaa72f64f 100644 --- a/session_py/iginx/setup.py +++ b/session_py/iginx/setup.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + import io import os import sys diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/constant/GlobalConstant.java b/shared/src/main/java/cn/edu/tsinghua/iginx/constant/GlobalConstant.java index fb9927bdfa..41b9327b6f 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/constant/GlobalConstant.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/constant/GlobalConstant.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.constant; public class GlobalConstant { diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/exception/IginxRuntimeException.java b/shared/src/main/java/cn/edu/tsinghua/iginx/exception/IginxRuntimeException.java index 8db3c68488..10de2baca9 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/exception/IginxRuntimeException.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/exception/IginxRuntimeException.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + /* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/exception/StatusCode.java b/shared/src/main/java/cn/edu/tsinghua/iginx/exception/StatusCode.java index 2dcdf4836d..e5aa81971f 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/exception/StatusCode.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/exception/StatusCode.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.exception; diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/exception/UnsupportedDataTypeException.java b/shared/src/main/java/cn/edu/tsinghua/iginx/exception/UnsupportedDataTypeException.java index 9665d97ce9..b850c93e93 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/exception/UnsupportedDataTypeException.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/exception/UnsupportedDataTypeException.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.exception; diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/exception/package-info.java b/shared/src/main/java/cn/edu/tsinghua/iginx/exception/package-info.java index 8e523880b3..4108ad30eb 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/exception/package-info.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/exception/package-info.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + /** * IGinX异常处理规范。 * diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/Bitmap.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/Bitmap.java index b02ae40ded..8638cba727 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/Bitmap.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/Bitmap.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.utils; diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/ByteUtils.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/ByteUtils.java index 626229346b..b966d9c35b 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/ByteUtils.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/ByteUtils.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.utils; diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/CSVUtils.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/CSVUtils.java index 1978c94e89..25636093b3 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/CSVUtils.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/CSVUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.utils; import cn.edu.tsinghua.iginx.thrift.ExportCSV; diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/CheckedFunction.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/CheckedFunction.java index 39842e55e6..7c59d906cf 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/CheckedFunction.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/CheckedFunction.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.utils; diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/CompressionUtils.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/CompressionUtils.java index da7fd16174..2edf585817 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/CompressionUtils.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/CompressionUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.utils; import java.io.*; diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/CurveMatchUtils.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/CurveMatchUtils.java index ca1c38d158..3ca544db76 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/CurveMatchUtils.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/CurveMatchUtils.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.utils; diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/DataTypeInferenceUtils.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/DataTypeInferenceUtils.java index 8bc61c2ef1..07c6662f5a 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/DataTypeInferenceUtils.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/DataTypeInferenceUtils.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.utils; diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/DataTypeUtils.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/DataTypeUtils.java index b144e217d5..ea0efd44b8 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/DataTypeUtils.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/DataTypeUtils.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.utils; diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/EnvUtils.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/EnvUtils.java index a94d924851..77214db983 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/EnvUtils.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/EnvUtils.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.utils; diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/Escaper.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/Escaper.java index 3dcd250d39..6f9c7011a6 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/Escaper.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/Escaper.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.utils; import java.text.ParseException; diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/FileCompareUtils.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/FileCompareUtils.java index a86a777c25..31a0492d30 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/FileCompareUtils.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/FileCompareUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.utils; import java.io.BufferedReader; diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/FileReader.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/FileReader.java index 9d680823de..4dc17b00bb 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/FileReader.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/FileReader.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.utils; import java.io.*; diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/FileUtils.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/FileUtils.java index 03bc5a7446..4e7496538c 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/FileUtils.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/FileUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.utils; import java.io.File; diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/FormatUtils.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/FormatUtils.java index 28a4ecd991..4bfef95735 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/FormatUtils.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/FormatUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.utils; import java.text.SimpleDateFormat; diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/HostUtils.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/HostUtils.java index e714b8186d..31adc88681 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/HostUtils.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/HostUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.utils; import java.net.Inet4Address; diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/JobFromYAML.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/JobFromYAML.java index bc758c2a0d..e6b1de01ce 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/JobFromYAML.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/JobFromYAML.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.utils; import java.util.List; diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/JsonUtils.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/JsonUtils.java index edbb6ff952..5669ea211b 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/JsonUtils.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/JsonUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.utils; import com.alibaba.fastjson2.JSON; diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/Pair.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/Pair.java index d15d0dd292..05158f9982 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/Pair.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/Pair.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.utils; diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/RpcUtils.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/RpcUtils.java index 69f524bbc1..078fa94303 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/RpcUtils.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/RpcUtils.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.utils; diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/SerializeUtils.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/SerializeUtils.java index 9d75ffb1fb..733cee3ae5 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/SerializeUtils.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/SerializeUtils.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.utils; diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/ShellRunner.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/ShellRunner.java index 4be241aaa4..efd9f5a21c 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/ShellRunner.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/ShellRunner.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.utils; import java.io.BufferedReader; diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/SnowFlakeUtils.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/SnowFlakeUtils.java index 01ffbdd71d..5f305f2cd9 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/SnowFlakeUtils.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/SnowFlakeUtils.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.utils; diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/SortUtils.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/SortUtils.java index 10c05386f9..d59ecb2fae 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/SortUtils.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/SortUtils.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.utils; diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java index 0453342c2a..da98f07251 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.utils; diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/TagKVUtils.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/TagKVUtils.java index fc8ca48ed8..317c462805 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/TagKVUtils.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/TagKVUtils.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.utils; diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/TaskFromYAML.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/TaskFromYAML.java index 9a52bf75bb..5d3bfdf87d 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/TaskFromYAML.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/TaskFromYAML.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.utils; import java.util.List; diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/ThriftConnPool.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/ThriftConnPool.java index da9695d2a2..1dc2782e2f 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/ThriftConnPool.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/ThriftConnPool.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.utils; import java.time.Duration; diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/TimeUtils.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/TimeUtils.java index 9c1efcabee..c15497430b 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/TimeUtils.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/TimeUtils.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.utils; diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/ValueUtils.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/ValueUtils.java index 2346fad6a9..d57568d19b 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/ValueUtils.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/ValueUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.utils; public class ValueUtils { diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/YAMLReader.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/YAMLReader.java index 46bd13abe6..a75b2066e0 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/YAMLReader.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/YAMLReader.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.utils; import java.io.*; diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/YAMLWriter.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/YAMLWriter.java index cf8a9c5283..35f774c945 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/YAMLWriter.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/YAMLWriter.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.utils; import java.io.BufferedWriter; diff --git a/shared/src/test/java/cn/edu/tsinghua/iginx/utils/CompressionUtilsTest.java b/shared/src/test/java/cn/edu/tsinghua/iginx/utils/CompressionUtilsTest.java index cdf145a76e..dcc269ccbc 100644 --- a/shared/src/test/java/cn/edu/tsinghua/iginx/utils/CompressionUtilsTest.java +++ b/shared/src/test/java/cn/edu/tsinghua/iginx/utils/CompressionUtilsTest.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.utils; import static org.junit.Assert.fail; diff --git a/shared/src/test/java/cn/edu/tsinghua/iginx/utils/EscaperTest.java b/shared/src/test/java/cn/edu/tsinghua/iginx/utils/EscaperTest.java index 87bf1d4265..78926dd14c 100644 --- a/shared/src/test/java/cn/edu/tsinghua/iginx/utils/EscaperTest.java +++ b/shared/src/test/java/cn/edu/tsinghua/iginx/utils/EscaperTest.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.utils; import static org.junit.Assert.*; diff --git a/shared/src/test/java/cn/edu/tsinghua/iginx/utils/StringUtilsTest.java b/shared/src/test/java/cn/edu/tsinghua/iginx/utils/StringUtilsTest.java index 90cad48265..ab7e707ae6 100644 --- a/shared/src/test/java/cn/edu/tsinghua/iginx/utils/StringUtilsTest.java +++ b/shared/src/test/java/cn/edu/tsinghua/iginx/utils/StringUtilsTest.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.utils; import static org.junit.Assert.assertEquals; diff --git a/test/src/main/java/cn/edu/tsinghua/iginx/shared/MockClassGenerator.java b/test/src/main/java/cn/edu/tsinghua/iginx/shared/MockClassGenerator.java index 48a62d6b56..b7c933fabd 100644 --- a/test/src/main/java/cn/edu/tsinghua/iginx/shared/MockClassGenerator.java +++ b/test/src/main/java/cn/edu/tsinghua/iginx/shared/MockClassGenerator.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.shared; import cn.edu.tsinghua.iginx.conf.Constants; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/client/ExportFileIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/client/ExportFileIT.java index 0497d370da..95a93bfad1 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/client/ExportFileIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/client/ExportFileIT.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.client; import static org.junit.Assert.assertEquals; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/client/ImportFileIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/client/ImportFileIT.java index d040dd4cdb..5bc50d2ea4 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/client/ImportFileIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/client/ImportFileIT.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.client; import cn.edu.tsinghua.iginx.exception.SessionException; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/compaction/CompactionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/compaction/CompactionIT.java index 636ad9b3af..087faf9ffa 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/compaction/CompactionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/compaction/CompactionIT.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.compaction; import static org.junit.Assert.assertEquals; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/controller/Controller.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/controller/Controller.java index b5231a1d69..d62a87cda1 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/controller/Controller.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/controller/Controller.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.controller; import static cn.edu.tsinghua.iginx.constant.GlobalConstant.CLEAR_DUMMY_DATA_CAUTION; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/controller/TestEnvironmentController.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/controller/TestEnvironmentController.java index 41aff1d677..b1dda6b233 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/controller/TestEnvironmentController.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/controller/TestEnvironmentController.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.controller; import cn.edu.tsinghua.iginx.metadata.entity.StorageEngineMeta; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/datasource/DataSourceIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/datasource/DataSourceIT.java index aede81abd9..b2eb7a2bad 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/datasource/DataSourceIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/datasource/DataSourceIT.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.datasource; import static org.junit.Assert.assertNull; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java index 1577c7587b..2d280f2384 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.expansion; import static cn.edu.tsinghua.iginx.integration.controller.Controller.SUPPORT_KEY; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseHistoryDataGenerator.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseHistoryDataGenerator.java index b2660298d5..a5d483dffe 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseHistoryDataGenerator.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseHistoryDataGenerator.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.expansion; import static cn.edu.tsinghua.iginx.integration.expansion.constant.Constant.*; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/constant/Constant.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/constant/Constant.java index 7ef5adbc14..30f9a3c941 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/constant/Constant.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/constant/Constant.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.expansion.constant; import cn.edu.tsinghua.iginx.integration.controller.Controller; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java index 657bf4de45..449a1d2a52 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.expansion.filesystem; import static cn.edu.tsinghua.iginx.thrift.StorageEngineType.filesystem; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemHistoryDataGenerator.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemHistoryDataGenerator.java index 0b3ebfea51..103bf1a69b 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemHistoryDataGenerator.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemHistoryDataGenerator.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.expansion.filesystem; import static cn.edu.tsinghua.iginx.integration.expansion.constant.Constant.*; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/influxdb/InfluxDBCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/influxdb/InfluxDBCapacityExpansionIT.java index 47d638e437..eda0e0b9e1 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/influxdb/InfluxDBCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/influxdb/InfluxDBCapacityExpansionIT.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.expansion.influxdb; import static cn.edu.tsinghua.iginx.thrift.StorageEngineType.influxdb; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/influxdb/InfluxDBHistoryDataGenerator.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/influxdb/InfluxDBHistoryDataGenerator.java index bd246a7c9d..8498008528 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/influxdb/InfluxDBHistoryDataGenerator.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/influxdb/InfluxDBHistoryDataGenerator.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.expansion.influxdb; import cn.edu.tsinghua.iginx.integration.expansion.BaseHistoryDataGenerator; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/iotdb/IoTDB12CapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/iotdb/IoTDB12CapacityExpansionIT.java index 0361e3d49f..aad4f8d6d9 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/iotdb/IoTDB12CapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/iotdb/IoTDB12CapacityExpansionIT.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.expansion.iotdb; import static cn.edu.tsinghua.iginx.thrift.StorageEngineType.iotdb12; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/iotdb/IoTDB12HistoryDataGenerator.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/iotdb/IoTDB12HistoryDataGenerator.java index df9f3cdfc4..33680c0968 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/iotdb/IoTDB12HistoryDataGenerator.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/iotdb/IoTDB12HistoryDataGenerator.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.expansion.iotdb; import cn.edu.tsinghua.iginx.integration.expansion.BaseHistoryDataGenerator; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java index 603db64f97..a7b840345e 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.expansion.mongodb; import static cn.edu.tsinghua.iginx.thrift.StorageEngineType.mongodb; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBHistoryDataGenerator.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBHistoryDataGenerator.java index b2ffb3b2cb..7c764705ad 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBHistoryDataGenerator.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBHistoryDataGenerator.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.expansion.mongodb; import static cn.edu.tsinghua.iginx.integration.expansion.constant.Constant.readOnlyPort; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mysql/MySQLCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mysql/MySQLCapacityExpansionIT.java index f75fbea476..3112e99e9e 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mysql/MySQLCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mysql/MySQLCapacityExpansionIT.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.expansion.mysql; import cn.edu.tsinghua.iginx.integration.controller.Controller; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mysql/MySQLHistoryDataGenerator.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mysql/MySQLHistoryDataGenerator.java index 298b03100f..b7d79f0ba1 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mysql/MySQLHistoryDataGenerator.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mysql/MySQLHistoryDataGenerator.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.expansion.mysql; import cn.edu.tsinghua.iginx.integration.expansion.BaseHistoryDataGenerator; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetCapacityExpansionIT.java index 178847bcd6..60f3aa60ee 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetCapacityExpansionIT.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.expansion.parquet; import static cn.edu.tsinghua.iginx.thrift.StorageEngineType.parquet; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetHistoryDataGenerator.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetHistoryDataGenerator.java index fb8edc8443..30a5d71a38 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetHistoryDataGenerator.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetHistoryDataGenerator.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.expansion.parquet; import static cn.edu.tsinghua.iginx.integration.expansion.BaseCapacityExpansionIT.DBCE_PARQUET_FS_TEST_DIR; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/postgresql/PostgreSQLCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/postgresql/PostgreSQLCapacityExpansionIT.java index 7d5d52dc11..c3e7bf6895 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/postgresql/PostgreSQLCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/postgresql/PostgreSQLCapacityExpansionIT.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.expansion.postgresql; import cn.edu.tsinghua.iginx.integration.controller.Controller; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/postgresql/PostgreSQLHistoryDataGenerator.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/postgresql/PostgreSQLHistoryDataGenerator.java index 2571b08e14..afeb554045 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/postgresql/PostgreSQLHistoryDataGenerator.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/postgresql/PostgreSQLHistoryDataGenerator.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.expansion.postgresql; import cn.edu.tsinghua.iginx.integration.expansion.BaseHistoryDataGenerator; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisCapacityExpansionIT.java index fdfb57e0ad..8a9502c46f 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisCapacityExpansionIT.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.expansion.redis; import static cn.edu.tsinghua.iginx.thrift.StorageEngineType.redis; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisHistoryDataGenerator.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisHistoryDataGenerator.java index 3f01f7c569..5e9cbcb02f 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisHistoryDataGenerator.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisHistoryDataGenerator.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.expansion.redis; import static cn.edu.tsinghua.iginx.integration.expansion.constant.Constant.readOnlyPort; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/utils/SQLTestTools.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/utils/SQLTestTools.java index 6085f6798c..c421de3683 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/utils/SQLTestTools.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/utils/SQLTestTools.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.expansion.utils; import static org.junit.Assert.*; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/rest/RestAnnotationIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/rest/RestAnnotationIT.java index 54552baa2f..d6609829de 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/rest/RestAnnotationIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/rest/RestAnnotationIT.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.func.rest; import static org.junit.Assert.assertEquals; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/rest/RestIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/rest/RestIT.java index 2a465ee114..5ad12b0435 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/rest/RestIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/rest/RestIT.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.func.rest; import static cn.edu.tsinghua.iginx.integration.controller.Controller.clearAllData; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/BaseSessionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/BaseSessionIT.java index 2e28b2bc64..337bf2e181 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/BaseSessionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/BaseSessionIT.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.func.session; import static org.junit.Assert.fail; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/InsertAPIType.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/InsertAPIType.java index a257c77507..207ba90857 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/InsertAPIType.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/InsertAPIType.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.func.session; public enum InsertAPIType { diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/NewSessionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/NewSessionIT.java index a5a2a7b49e..e725b88827 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/NewSessionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/NewSessionIT.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.func.session; import static cn.edu.tsinghua.iginx.engine.shared.Constants.WINDOW_END_COL; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/PySessionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/PySessionIT.java index ca36b5cd24..1dcea36696 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/PySessionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/PySessionIT.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.func.session; import static cn.edu.tsinghua.iginx.integration.controller.Controller.clearAllData; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/SQLCompareIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/SQLCompareIT.java index 32bddea191..98a231f1f8 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/SQLCompareIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/SQLCompareIT.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.func.session; import static org.junit.Assert.assertEquals; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/SessionConcurrencyIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/SessionConcurrencyIT.java index d88f5fad9b..6e66593d39 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/SessionConcurrencyIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/SessionConcurrencyIT.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.func.session; import static org.junit.Assert.*; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/SessionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/SessionIT.java index dc3dc2b0c9..8e8f302ef7 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/SessionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/SessionIT.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.integration.func.session; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/SessionPoolIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/SessionPoolIT.java index 1fec5af133..5c8b777752 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/SessionPoolIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/SessionPoolIT.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.func.session; import cn.edu.tsinghua.iginx.integration.tool.MultiConnection; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/SessionV2IT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/SessionV2IT.java index 1b3dc26691..e206003c78 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/SessionV2IT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/SessionV2IT.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.func.session; import static cn.edu.tsinghua.iginx.engine.shared.Constants.WINDOW_END_COL; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/TestDataSection.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/TestDataSection.java index fac441696e..e7ff77187d 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/TestDataSection.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/TestDataSection.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.func.session; import cn.edu.tsinghua.iginx.thrift.DataType; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/sql/SQLSessionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/sql/SQLSessionIT.java index 7fdc7b9231..efb83e338f 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/sql/SQLSessionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/sql/SQLSessionIT.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.func.sql; import static cn.edu.tsinghua.iginx.integration.controller.Controller.SUPPORT_KEY; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/sql/SQLSessionPoolIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/sql/SQLSessionPoolIT.java index ce3652e2f4..02acf2e09e 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/sql/SQLSessionPoolIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/sql/SQLSessionPoolIT.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.func.sql; import static cn.edu.tsinghua.iginx.integration.controller.Controller.SUPPORT_KEY; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/tag/TagIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/tag/TagIT.java index 971b5bdd29..d58314d442 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/tag/TagIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/tag/TagIT.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.func.tag; import static cn.edu.tsinghua.iginx.constant.GlobalConstant.CLEAR_DUMMY_DATA_CAUTION; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/udf/RemoteUDFIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/udf/RemoteUDFIT.java index 1e4ebd6856..60539fd249 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/udf/RemoteUDFIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/udf/RemoteUDFIT.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.func.udf; import static cn.edu.tsinghua.iginx.integration.controller.Controller.clearAllData; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/udf/TransformIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/udf/TransformIT.java index 58078130ea..0e524e84e8 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/udf/TransformIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/udf/TransformIT.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.integration.func.udf; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/udf/UDFIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/udf/UDFIT.java index 5232b01045..fe3808532e 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/udf/UDFIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/udf/UDFIT.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.integration.func.udf; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/udf/UDFTestTools.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/udf/UDFTestTools.java index 7964b8736c..3b813e3b01 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/udf/UDFTestTools.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/udf/UDFTestTools.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.func.udf; import static org.junit.Assert.assertEquals; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/mds/ETCDSyncProtocolTest.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/mds/ETCDSyncProtocolTest.java index 1f5a961ae1..e799d78a63 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/mds/ETCDSyncProtocolTest.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/mds/ETCDSyncProtocolTest.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.mds; import cn.edu.tsinghua.iginx.metadata.sync.protocol.SyncProtocol; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/mds/IMetaManagerTest.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/mds/IMetaManagerTest.java index bce3b41008..03ba693280 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/mds/IMetaManagerTest.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/mds/IMetaManagerTest.java @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package cn.edu.tsinghua.iginx.integration.mds; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/mds/RandomUtils.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/mds/RandomUtils.java index f10fce8b63..0d10627071 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/mds/RandomUtils.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/mds/RandomUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.mds; import java.util.Random; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/mds/SyncProtocolTest.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/mds/SyncProtocolTest.java index 1dfaca0716..408ce61d45 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/mds/SyncProtocolTest.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/mds/SyncProtocolTest.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.mds; import static org.junit.Assert.*; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/mds/ZooKeeperSyncProtocolTest.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/mds/ZooKeeperSyncProtocolTest.java index 77ea5e612d..14e2f15cf6 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/mds/ZooKeeperSyncProtocolTest.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/mds/ZooKeeperSyncProtocolTest.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.mds; import cn.edu.tsinghua.iginx.metadata.sync.protocol.NetworkException; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/other/FileLoaderTest.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/other/FileLoaderTest.java index e950b8f790..11fa789805 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/other/FileLoaderTest.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/other/FileLoaderTest.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.other; import static org.junit.Assert.fail; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/other/TimePrecisionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/other/TimePrecisionIT.java index 073f3076c9..af3a78e240 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/other/TimePrecisionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/other/TimePrecisionIT.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.other; import static org.junit.Assert.fail; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/other/UDFPathIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/other/UDFPathIT.java index c4b8d54254..6987222deb 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/other/UDFPathIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/other/UDFPathIT.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.other; import cn.edu.tsinghua.iginx.exception.SessionException; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/regression/MixClusterShowColumnsRegressionTest.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/regression/MixClusterShowColumnsRegressionTest.java index a7dd882c26..c22d1ff3b4 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/regression/MixClusterShowColumnsRegressionTest.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/regression/MixClusterShowColumnsRegressionTest.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.regression; import static org.junit.Assert.assertEquals; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/CombinedInsertTests.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/CombinedInsertTests.java index 753dda308e..74e5507e39 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/CombinedInsertTests.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/CombinedInsertTests.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.tool; import cn.edu.tsinghua.iginx.exception.SessionException; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/ConfLoader.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/ConfLoader.java index 618b6a18e4..c0f6fcff94 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/ConfLoader.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/ConfLoader.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.tool; import cn.edu.tsinghua.iginx.integration.expansion.constant.Constant; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/DBConf.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/DBConf.java index 30d7fbacaf..e1cccbaf10 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/DBConf.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/DBConf.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.tool; import java.util.HashMap; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/MultiConnection.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/MultiConnection.java index e0f816e2dd..631f9fd436 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/MultiConnection.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/MultiConnection.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.tool; import static cn.edu.tsinghua.iginx.constant.GlobalConstant.*; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/SQLExecutor.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/SQLExecutor.java index 69eb1fb334..256b438748 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/SQLExecutor.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/SQLExecutor.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.tool; import static cn.edu.tsinghua.iginx.constant.GlobalConstant.CLEAR_DUMMY_DATA_CAUTION; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/TestUtils.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/TestUtils.java index 8cc01bee91..0968c622ae 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/TestUtils.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/TestUtils.java @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package cn.edu.tsinghua.iginx.integration.tool; import java.util.ArrayList; diff --git a/test/src/test/resources/pySessionIT/tests.py b/test/src/test/resources/pySessionIT/tests.py index caca95074b..535ac3e75c 100644 --- a/test/src/test/resources/pySessionIT/tests.py +++ b/test/src/test/resources/pySessionIT/tests.py @@ -1,21 +1,20 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University # -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . # - # 无法单独执行,用来测试PySessionIT import sys, traceback sys.path.append('../session_py/') # 将上一级目录添加到Python模块搜索路径中 diff --git a/test/src/test/resources/transform/transformer_add_one.py b/test/src/test/resources/transform/transformer_add_one.py index 6315786272..4fe45d624a 100644 --- a/test/src/test/resources/transform/transformer_add_one.py +++ b/test/src/test/resources/transform/transformer_add_one.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + import pandas as pd diff --git a/test/src/test/resources/transform/transformer_row_sum.py b/test/src/test/resources/transform/transformer_row_sum.py index cfc503c1cd..b85dd676af 100644 --- a/test/src/test/resources/transform/transformer_row_sum.py +++ b/test/src/test/resources/transform/transformer_row_sum.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + import pandas as pd import numpy as np diff --git a/test/src/test/resources/transform/transformer_sleep.py b/test/src/test/resources/transform/transformer_sleep.py index e8145a01c8..909a7841e6 100644 --- a/test/src/test/resources/transform/transformer_sleep.py +++ b/test/src/test/resources/transform/transformer_sleep.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + import time diff --git a/test/src/test/resources/transform/transformer_sum.py b/test/src/test/resources/transform/transformer_sum.py index 63dea29ddb..e4ef01dd18 100644 --- a/test/src/test/resources/transform/transformer_sum.py +++ b/test/src/test/resources/transform/transformer_sum.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + import pandas as pd diff --git a/test/src/test/resources/udf/mock_udf.py b/test/src/test/resources/udf/mock_udf.py index e6e3ba2c3c..e8917fe921 100644 --- a/test/src/test/resources/udf/mock_udf.py +++ b/test/src/test/resources/udf/mock_udf.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + class MockUDF(): def __init__(self): pass diff --git a/test/src/test/resources/udf/my_module/__init__.py b/test/src/test/resources/udf/my_module/__init__.py index e69de29bb2..02225d5e15 100644 --- a/test/src/test/resources/udf/my_module/__init__.py +++ b/test/src/test/resources/udf/my_module/__init__.py @@ -0,0 +1,18 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + diff --git a/test/src/test/resources/udf/my_module/dateutil_test.py b/test/src/test/resources/udf/my_module/dateutil_test.py index a30ae42433..bef6bd3db0 100644 --- a/test/src/test/resources/udf/my_module/dateutil_test.py +++ b/test/src/test/resources/udf/my_module/dateutil_test.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + from dateutil import parser diff --git a/test/src/test/resources/udf/my_module/idle_classes.py b/test/src/test/resources/udf/my_module/idle_classes.py index 0bba39deb2..cb7c0f2d4a 100644 --- a/test/src/test/resources/udf/my_module/idle_classes.py +++ b/test/src/test/resources/udf/my_module/idle_classes.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + class ClassA: def transform(self, data, args, kvargs): return [["col_outer_a"], ["LONG"], [1]] diff --git a/test/src/test/resources/udf/my_module/my_class_a.py b/test/src/test/resources/udf/my_module/my_class_a.py index 439a6a0225..7f1fbe419d 100644 --- a/test/src/test/resources/udf/my_module/my_class_a.py +++ b/test/src/test/resources/udf/my_module/my_class_a.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + class ClassA: def print_self(self): return "class A" diff --git a/test/src/test/resources/udf/my_module/sub_module/__init__.py b/test/src/test/resources/udf/my_module/sub_module/__init__.py index e69de29bb2..02225d5e15 100644 --- a/test/src/test/resources/udf/my_module/sub_module/__init__.py +++ b/test/src/test/resources/udf/my_module/sub_module/__init__.py @@ -0,0 +1,18 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + diff --git a/test/src/test/resources/udf/my_module/sub_module/sub_class_a.py b/test/src/test/resources/udf/my_module/sub_module/sub_class_a.py index 9ba42710b1..ab71bac6b4 100644 --- a/test/src/test/resources/udf/my_module/sub_module/sub_class_a.py +++ b/test/src/test/resources/udf/my_module/sub_module/sub_class_a.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + class SubClassA: def print_self(self): return "sub class A" diff --git a/thrift/src/main/proto/filesystem.thrift b/thrift/src/main/proto/filesystem.thrift index 51a6a5f180..30955c8c9a 100644 --- a/thrift/src/main/proto/filesystem.thrift +++ b/thrift/src/main/proto/filesystem.thrift @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + include "rpc.thrift" namespace java cn.edu.tsinghua.iginx.filesystem.thrift diff --git a/thrift/src/main/proto/parquet.thrift b/thrift/src/main/proto/parquet.thrift index da88565a8f..086c6c84ee 100644 --- a/thrift/src/main/proto/parquet.thrift +++ b/thrift/src/main/proto/parquet.thrift @@ -1,3 +1,21 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + namespace java cn.edu.tsinghua.iginx.parquet.thrift struct Status { diff --git a/thrift/src/main/proto/rpc.thrift b/thrift/src/main/proto/rpc.thrift index f4bae6553e..7223d28930 100644 --- a/thrift/src/main/proto/rpc.thrift +++ b/thrift/src/main/proto/rpc.thrift @@ -1,20 +1,19 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ namespace java cn.edu.tsinghua.iginx.thrift namespace py iginx.thrift.rpc diff --git a/udf_funcs/python_scripts/class_loader.py b/udf_funcs/python_scripts/class_loader.py index c306484d9c..98c4891589 100644 --- a/udf_funcs/python_scripts/class_loader.py +++ b/udf_funcs/python_scripts/class_loader.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + from transformer import BaseTransformer diff --git a/udf_funcs/python_scripts/constant.py b/udf_funcs/python_scripts/constant.py index a2097214de..504ad3c7cf 100644 --- a/udf_funcs/python_scripts/constant.py +++ b/udf_funcs/python_scripts/constant.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + from enum import IntEnum diff --git a/udf_funcs/python_scripts/py_worker.py b/udf_funcs/python_scripts/py_worker.py index e7caddeba3..0ed6b570db 100644 --- a/udf_funcs/python_scripts/py_worker.py +++ b/udf_funcs/python_scripts/py_worker.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + import os import socket import sys diff --git a/udf_funcs/python_scripts/transformer_apply.py b/udf_funcs/python_scripts/transformer_apply.py index e1d74a7133..1d46645596 100644 --- a/udf_funcs/python_scripts/transformer_apply.py +++ b/udf_funcs/python_scripts/transformer_apply.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + """ Apply a function along an axis of the DataFrame. diff --git a/udf_funcs/python_scripts/transformer_between_time.py b/udf_funcs/python_scripts/transformer_between_time.py index 9545bbb171..7132d0341a 100644 --- a/udf_funcs/python_scripts/transformer_between_time.py +++ b/udf_funcs/python_scripts/transformer_between_time.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + """ Select values between particular times of the day (e.g., 9:00-9:30 AM). """ diff --git a/udf_funcs/python_scripts/transformer_bool.py b/udf_funcs/python_scripts/transformer_bool.py index c14288253c..8937ee46b2 100644 --- a/udf_funcs/python_scripts/transformer_bool.py +++ b/udf_funcs/python_scripts/transformer_bool.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + """ Return the bool of a single element Series or DataFrame. This must be a boolean scalar value, either True or False. diff --git a/udf_funcs/python_scripts/transformer_bottom.py b/udf_funcs/python_scripts/transformer_bottom.py index b1cdb04a24..f059d2dea6 100644 --- a/udf_funcs/python_scripts/transformer_bottom.py +++ b/udf_funcs/python_scripts/transformer_bottom.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + """ The bottom() function sorts a table by columns and keeps only the bottom n records. bottom() is a selector function. bottom() 函数按列对表进行排序并仅保留底部的 n 条记录。 bottom() 是一个选择器函数。 diff --git a/udf_funcs/python_scripts/transformer_distinct.py b/udf_funcs/python_scripts/transformer_distinct.py index ceb33a71cf..668fadae7b 100644 --- a/udf_funcs/python_scripts/transformer_distinct.py +++ b/udf_funcs/python_scripts/transformer_distinct.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + """ Writing a distinct() function for IginX: Count the distinct field values associated with a field key. diff --git a/udf_funcs/python_scripts/transformer_filter.py b/udf_funcs/python_scripts/transformer_filter.py index bf8957ce0f..9dfa7be692 100644 --- a/udf_funcs/python_scripts/transformer_filter.py +++ b/udf_funcs/python_scripts/transformer_filter.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + """ The filter() function is used to subset rows or columns of dataframe according to labels in the specified index. """ diff --git a/udf_funcs/python_scripts/transformer_head.py b/udf_funcs/python_scripts/transformer_head.py index 57d0874cc0..4a12f09b0b 100644 --- a/udf_funcs/python_scripts/transformer_head.py +++ b/udf_funcs/python_scripts/transformer_head.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + """ Return the first n rows. This function returns the first n rows for the object based on position. diff --git a/udf_funcs/python_scripts/transformer_loc.py b/udf_funcs/python_scripts/transformer_loc.py index f96dfa4c89..1fd3c720a8 100644 --- a/udf_funcs/python_scripts/transformer_loc.py +++ b/udf_funcs/python_scripts/transformer_loc.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + """ Access a group of rows and columns by label(s) or a boolean array. """ diff --git a/udf_funcs/python_scripts/transformer_mean.py b/udf_funcs/python_scripts/transformer_mean.py index b639921862..722d289bac 100644 --- a/udf_funcs/python_scripts/transformer_mean.py +++ b/udf_funcs/python_scripts/transformer_mean.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + """ mean() returns the average of non-null values in a specified column from each input table. Mean function returns the average by dividing the sum of the values in the set by their number. diff --git a/udf_funcs/python_scripts/transformer_skew.py b/udf_funcs/python_scripts/transformer_skew.py index e1e7061e8b..d8813767e0 100644 --- a/udf_funcs/python_scripts/transformer_skew.py +++ b/udf_funcs/python_scripts/transformer_skew.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + """ Return unbiased skew over requested axis. Normalized by N-1. diff --git a/udf_funcs/python_scripts/transformer_sortindex.py b/udf_funcs/python_scripts/transformer_sortindex.py index 0579441296..3e50de5c56 100644 --- a/udf_funcs/python_scripts/transformer_sortindex.py +++ b/udf_funcs/python_scripts/transformer_sortindex.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + """ Sorts index in descending order: diff --git a/udf_funcs/python_scripts/transformer_spread.py b/udf_funcs/python_scripts/transformer_spread.py index 57b896e2a0..3361816d2b 100644 --- a/udf_funcs/python_scripts/transformer_spread.py +++ b/udf_funcs/python_scripts/transformer_spread.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + import pandas as pd diff --git a/udf_funcs/python_scripts/udf_avg.py b/udf_funcs/python_scripts/udf_avg.py index 2cb5dc817b..3dda56303f 100644 --- a/udf_funcs/python_scripts/udf_avg.py +++ b/udf_funcs/python_scripts/udf_avg.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + class UDFAvg: def __init__(self): pass diff --git a/udf_funcs/python_scripts/udf_count.py b/udf_funcs/python_scripts/udf_count.py index a6bf93bf75..375843d6f5 100644 --- a/udf_funcs/python_scripts/udf_count.py +++ b/udf_funcs/python_scripts/udf_count.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + class UDFCount: def __init__(self): pass diff --git a/udf_funcs/python_scripts/udf_max.py b/udf_funcs/python_scripts/udf_max.py index 156db6974c..e996e66164 100644 --- a/udf_funcs/python_scripts/udf_max.py +++ b/udf_funcs/python_scripts/udf_max.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + class UDFMax: def __init__(self): pass diff --git a/udf_funcs/python_scripts/udf_max_with_key.py b/udf_funcs/python_scripts/udf_max_with_key.py index c503ae63de..1003915b2e 100644 --- a/udf_funcs/python_scripts/udf_max_with_key.py +++ b/udf_funcs/python_scripts/udf_max_with_key.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + class UDFMaxWithKey: def __init__(self): pass diff --git a/udf_funcs/python_scripts/udf_min.py b/udf_funcs/python_scripts/udf_min.py index 6c896505d8..bd1b2a4977 100644 --- a/udf_funcs/python_scripts/udf_min.py +++ b/udf_funcs/python_scripts/udf_min.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + class UDFMin: def __init__(self): pass diff --git a/udf_funcs/python_scripts/udf_sum.py b/udf_funcs/python_scripts/udf_sum.py index 7b8375cc5b..617e5070dc 100644 --- a/udf_funcs/python_scripts/udf_sum.py +++ b/udf_funcs/python_scripts/udf_sum.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + class UDFSum: def __init__(self): pass diff --git a/udf_funcs/python_scripts/udsf_reverse_rows.py b/udf_funcs/python_scripts/udsf_reverse_rows.py index 8f1dbbe365..7c05e0a738 100644 --- a/udf_funcs/python_scripts/udsf_reverse_rows.py +++ b/udf_funcs/python_scripts/udsf_reverse_rows.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + class UDFReverseRows: def __init__(self): pass diff --git a/udf_funcs/python_scripts/udsf_transpose.py b/udf_funcs/python_scripts/udsf_transpose.py index 7c787249b6..90be6ad228 100644 --- a/udf_funcs/python_scripts/udsf_transpose.py +++ b/udf_funcs/python_scripts/udsf_transpose.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + class UDFTranspose: def __init__(self): pass diff --git a/udf_funcs/python_scripts/udtf_column_expand.py b/udf_funcs/python_scripts/udtf_column_expand.py index 66dd008bc3..29b1a3e4ba 100644 --- a/udf_funcs/python_scripts/udtf_column_expand.py +++ b/udf_funcs/python_scripts/udtf_column_expand.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + class UDFColumnExpand: def __init__(self): pass diff --git a/udf_funcs/python_scripts/udtf_cos.py b/udf_funcs/python_scripts/udtf_cos.py index f3ba7cdbc2..bd4160df9a 100644 --- a/udf_funcs/python_scripts/udtf_cos.py +++ b/udf_funcs/python_scripts/udtf_cos.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + import math diff --git a/udf_funcs/python_scripts/udtf_key_add_one.py b/udf_funcs/python_scripts/udtf_key_add_one.py index b5b9afeaf2..6a39d2b8de 100644 --- a/udf_funcs/python_scripts/udtf_key_add_one.py +++ b/udf_funcs/python_scripts/udtf_key_add_one.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + class UDFKeyAddOne: def __init__(self): pass diff --git a/udf_funcs/python_scripts/udtf_multiply.py b/udf_funcs/python_scripts/udtf_multiply.py index 959a0f7e65..f28fa6a94a 100644 --- a/udf_funcs/python_scripts/udtf_multiply.py +++ b/udf_funcs/python_scripts/udtf_multiply.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + class UDFMultiply: def __init__(self): pass diff --git a/udf_funcs/python_scripts/udtf_pow.py b/udf_funcs/python_scripts/udtf_pow.py index 93e6e04093..7f02151b24 100644 --- a/udf_funcs/python_scripts/udtf_pow.py +++ b/udf_funcs/python_scripts/udtf_pow.py @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + class UDFPow: def __init__(self): self._n = 1 From 96bb3c8d9dd74fcdfc30fd8fc0410bf41889ddae Mon Sep 17 00:00:00 2001 From: An Qi Date: Sat, 29 Jun 2024 13:17:18 +0800 Subject: [PATCH 052/138] fix(assembly): missing optimizer (#362) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复 release 打包时遗漏 optimizer 的问题 添加测试 同时,将release打包时未能删除的遗留UDF声明,进行了删除 --- .github/workflows/assembly-test.yml | 116 ++++++++++++++++++ .github/workflows/full-test-suite.yml | 2 + .github/workflows/standard-test-suite.yml | 2 + .../src/assembly/component/iginx-core.xml | 3 + .../assembly/component/iginx-optimizer.xml | 39 ++++++ assembly/src/assembly/include.xml | 1 + .../resources/fast-deploy/clearAllData.bat | 12 ++ .../resources/fast-deploy/clearAllData.sh | 22 +++- assembly/src/assembly/server.xml | 1 + .../src/assembly/resources/sbin/start_cli.bat | 2 - .../src/assembly/resources/sbin/start_cli.sh | 2 - optimizer/pom.xml | 1 + pom.xml | 11 +- 13 files changed, 201 insertions(+), 13 deletions(-) create mode 100644 .github/workflows/assembly-test.yml create mode 100644 assembly/src/assembly/component/iginx-optimizer.xml diff --git a/.github/workflows/assembly-test.yml b/.github/workflows/assembly-test.yml new file mode 100644 index 0000000000..280d553dbc --- /dev/null +++ b/.github/workflows/assembly-test.yml @@ -0,0 +1,116 @@ +name: "Assembly Package Test" +on: + workflow_call: + inputs: + java-matrix: + description: "The java version to run the test on" + type: string + required: false + default: '["8"]' + python-matrix: + description: "The python version to run the test on" + type: string + required: false + default: '["3.9"]' + os-matrix: + description: "The operating system to run the test on" + type: string + required: false + default: '["ubuntu-latest", "macos-13", "windows-latest"]' + +env: + FUNCTEST: SQLSessionIT#testShowColumns + +jobs: + assembly-include-test: + timeout-minutes: 30 + strategy: + fail-fast: false + matrix: + java: ${{ fromJSON(inputs.java-matrix) }} + python-version: ${{ fromJSON(inputs.python-matrix) }} + os: ${{ fromJSON(inputs.os-matrix) }} + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v2 + - name: Environment dependence + uses: ./.github/actions/dependence + with: + python-version: ${{ matrix.python-version }} + java: ${{ matrix.java }} + + - name: assembly include package + run: mvn clean package -D skipTests -P !format -P release + + - name: Setup Platform Dependence + id: platform + shell: bash + run: | + SUFFIX="sh" + if [ "$RUNNER_OS" == "macOS" ]; then + brew install tree + elif [ "$RUNNER_OS" == "Windows" ]; then + choco install tree + SUFFIX="bat" + fi + echo "suffix=$SUFFIX" >> $GITHUB_OUTPUT + + - name: Save Origin Workspace Tree + run: tree assembly/target/iginx-assembly-${{ env.VERSION }}-include >origin-tree.txt + + - name: Run IGinX include Zookeeper with Pemjax + run: | + cd assembly/target/iginx-assembly-${{ env.VERSION }}-include + ./runIGinXOn1HostWithPemjax.${{ steps.platform.outputs.suffix }} + sleep 10 + + - name: Get Cluster Info + shell: bash + run: | + ./client/target/iginx-client-0.7.0-SNAPSHOT/sbin/start_cli.${{ steps.platform.outputs.suffix }} -e "show cluster info;" > cluster-info.txt + cat cluster-info.txt + LINE_COUNT=$(wc -l < cluster-info.txt) + if [ $LINE_COUNT -ne 19 ]; then + echo "Cluster info is not 19 lines" + exit 1 + fi + + - name: Run Tests + shell: bash + run: mvn test -Dtest=${{ env.FUNCTEST }} -DfailIfNoTests=false -P !format + + - name: Check Whether Logs Contains Error + shell: bash + run: | + cd assembly/target/iginx-assembly-${{ env.VERSION }}-include + if grep "ERROR" sbin/logs/iginx-latest.log; then + echo "Error found in log" + exit 1 + fi + + - name: Show IGinX Log + if: always() + run: cat assembly/target/iginx-assembly-${{ env.VERSION }}-include/sbin/logs/iginx-latest.log + + - name: Clean Up + run: | + cd assembly/target/iginx-assembly-${{ env.VERSION }}-include + ./stopIGinX.${{ steps.platform.outputs.suffix }} + ./clearAllData.${{ steps.platform.outputs.suffix }} + + - name: Save Final Workspace Tree + run: tree assembly/target/iginx-assembly-${{ env.VERSION }}-include >final-tree.txt + + - name: Compare Workspace Tree to Ensure Clean Up + shell: bash + run: | + diff origin-tree.txt final-tree.txt + exit $? + + - name: Show Origin Workspace Tree + if: always() + run: cat origin-tree.txt + + - name: Show Final Workspace Tree + if: always() + run: cat final-tree.txt diff --git a/.github/workflows/full-test-suite.yml b/.github/workflows/full-test-suite.yml index a7e34ee6f8..32e0a65a15 100644 --- a/.github/workflows/full-test-suite.yml +++ b/.github/workflows/full-test-suite.yml @@ -24,3 +24,5 @@ jobs: uses: ./.github/workflows/DB-CE.yml remote-test: uses: ./.github/workflows/remote-test.yml + assemebly-test: + uses: ./.github/workflows/assembly-test.yml diff --git a/.github/workflows/standard-test-suite.yml b/.github/workflows/standard-test-suite.yml index a4f8234894..29f327370c 100644 --- a/.github/workflows/standard-test-suite.yml +++ b/.github/workflows/standard-test-suite.yml @@ -35,3 +35,5 @@ jobs: uses: ./.github/workflows/remote-test.yml with: metadata-matrix: '["zookeeper"]' + assemebly-test: + uses: ./.github/workflows/assembly-test.yml diff --git a/assembly/src/assembly/component/iginx-core.xml b/assembly/src/assembly/component/iginx-core.xml index ae1237caf3..d0d0625082 100644 --- a/assembly/src/assembly/component/iginx-core.xml +++ b/assembly/src/assembly/component/iginx-core.xml @@ -37,6 +37,9 @@ ${project.build.directory}/iginx-core-${project.version}/lib lib + + iginx-optimizer-*.jar + diff --git a/assembly/src/assembly/component/iginx-optimizer.xml b/assembly/src/assembly/component/iginx-optimizer.xml new file mode 100644 index 0000000000..daa6d82358 --- /dev/null +++ b/assembly/src/assembly/component/iginx-optimizer.xml @@ -0,0 +1,39 @@ + + + + + + true + false + + cn.edu.tsinghua:iginx-optimizer + + + false + + + src/main/resources + + iginx-optimizer-*.jar + + lib + + + + + + \ No newline at end of file diff --git a/assembly/src/assembly/include.xml b/assembly/src/assembly/include.xml index bcaf358339..412c2c043e 100644 --- a/assembly/src/assembly/include.xml +++ b/assembly/src/assembly/include.xml @@ -23,6 +23,7 @@ false src/assembly/component/iginx-core.xml + src/assembly/component/iginx-optimizer.xml src/assembly/component/iginx-iotdb12-driver.xml src/assembly/component/iginx-parquet-driver.xml src/assembly/component/include-zookeeper.xml diff --git a/assembly/src/assembly/resources/fast-deploy/clearAllData.bat b/assembly/src/assembly/resources/fast-deploy/clearAllData.bat index ad8f811e83..4112980cda 100644 --- a/assembly/src/assembly/resources/fast-deploy/clearAllData.bat +++ b/assembly/src/assembly/resources/fast-deploy/clearAllData.bat @@ -40,6 +40,18 @@ for /l %%i in (1,1,1) do ( ) ) +set built_in_udf[1]=udf_list +set built_in_udf[2]=python_scripts\class_loader.py +set built_in_udf[3]=python_scripts\constant.py +set built_in_udf[4]=python_scripts\py_worker.py + +move udf_funcs udf_funcs_bak +mkdir udf_funcs\python_scripts +for /l %%i in (1,1,4) do ( + move udf_funcs_bak\!built_in_udf[%%i]! udf_funcs\!built_in_udf[%%i]! +) +rd /s /q udf_funcs_bak + @REM ----------------------------------------------------------------------------- :finally echo Done! diff --git a/assembly/src/assembly/resources/fast-deploy/clearAllData.sh b/assembly/src/assembly/resources/fast-deploy/clearAllData.sh index 4b02f8a2b3..2de988ec8f 100644 --- a/assembly/src/assembly/resources/fast-deploy/clearAllData.sh +++ b/assembly/src/assembly/resources/fast-deploy/clearAllData.sh @@ -18,14 +18,14 @@ # -array=( +REMOVE_DIRS=( include/apache-zookeeper/data include/apache-zookeeper/logs sbin/parquetData sbin/logs ) -for folder in ${array[@]}; do +for folder in ${REMOVE_DIRS[@]}; do if [ -d "$folder" ]; then rm -rf $folder @@ -33,14 +33,14 @@ for folder in ${array[@]}; do done -arrayf=( +REMOVE_FIELS=( iginx.out gc.log sbin/nohup.out include/apache-zookeeper/nohup.out ) -for file in ${arrayf[@]}; do +for file in ${REMOVE_FIELS[@]}; do if [ -f "$file" ]; then rm -f $file @@ -48,5 +48,19 @@ for file in ${arrayf[@]}; do done +BUILT_IN_UDF=( + udf_list + python_scripts/class_loader.py + python_scripts/constant.py + python_scripts/py_worker.py +) + +mv udf_funcs udf_funcs_bak +mkdir -p udf_funcs/python_scripts +for file in ${BUILT_IN_UDF[@]}; do + mv udf_funcs_bak/$file udf_funcs/$file +done +rm -rf udf_funcs_bak + echo Done! diff --git a/assembly/src/assembly/server.xml b/assembly/src/assembly/server.xml index 3eebc37834..399abccad4 100644 --- a/assembly/src/assembly/server.xml +++ b/assembly/src/assembly/server.xml @@ -23,6 +23,7 @@ false src/assembly/component/iginx-core.xml + src/assembly/component/iginx-optimizer.xml src/assembly/component/iginx-filesystem-driver.xml src/assembly/component/iginx-influxdb-driver.xml src/assembly/component/iginx-iotdb12-driver.xml diff --git a/client/src/assembly/resources/sbin/start_cli.bat b/client/src/assembly/resources/sbin/start_cli.bat index 23d9584e67..1abc13645a 100644 --- a/client/src/assembly/resources/sbin/start_cli.bat +++ b/client/src/assembly/resources/sbin/start_cli.bat @@ -58,8 +58,6 @@ echo %PARAMETERS% | findstr /c:"-p ">nul && (set PARAMETERS=%PARAMETERS%) || (se echo %PARAMETERS% | findstr /c:"-h ">nul && (set PARAMETERS=%PARAMETERS%) || (set PARAMETERS=%h_parameter% %PARAMETERS%) echo %PARAMETERS% | findstr /c:"-fs ">nul && (set PARAMETERS=%PARAMETERS%) || (set PARAMETERS=%fs_parameter% %PARAMETERS%) -echo %PARAMETERS% - "%JAVA_HOME%\bin\java" %JAVA_OPTS% -cp %CLASSPATH% %MAIN_CLASS% %PARAMETERS% goto finally diff --git a/client/src/assembly/resources/sbin/start_cli.sh b/client/src/assembly/resources/sbin/start_cli.sh index 3a8a8d37a9..4508777298 100755 --- a/client/src/assembly/resources/sbin/start_cli.sh +++ b/client/src/assembly/resources/sbin/start_cli.sh @@ -89,8 +89,6 @@ case "${PARAMETERS[@]}" in *) PARAMETERS=("-h" "127.0.0.1" "${PARAMETERS[@]}") ;; esac -echo ${PARAMETERS[@]} - exec "$JAVA" -cp "$CLASSPATH" "$MAIN_CLASS" "${PARAMETERS[@]}" exit $? \ No newline at end of file diff --git a/optimizer/pom.xml b/optimizer/pom.xml index b13681b4ab..0095925b03 100644 --- a/optimizer/pom.xml +++ b/optimizer/pom.xml @@ -21,6 +21,7 @@ cn.edu.tsinghua iginx-core + provided diff --git a/pom.xml b/pom.xml index 47e906a459..70ff6663d0 100644 --- a/pom.xml +++ b/pom.xml @@ -10,18 +10,19 @@ IGinX - core - thrift shared + thrift + session + jdbc client antlr - jdbc - session + core + optimizer dataSources example test + assembly - optimizer From 39318c065bb647ca0b620712252b2a4f0cd5529c Mon Sep 17 00:00:00 2001 From: SolomonAnn Date: Sat, 6 Jul 2024 09:44:34 +0800 Subject: [PATCH 053/138] Change timestamps to keys in Session(Pool).java (#369) --- .../edu/tsinghua/iginx/pool/SessionPool.java | 52 ++++--- .../edu/tsinghua/iginx/session/Session.java | 132 ++++++++---------- 2 files changed, 85 insertions(+), 99 deletions(-) diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/pool/SessionPool.java b/session/src/main/java/cn/edu/tsinghua/iginx/pool/SessionPool.java index e292601853..ce2023a4db 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/pool/SessionPool.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/pool/SessionPool.java @@ -493,7 +493,7 @@ public void removeHistoryDataSource(List removedStorag return; } catch (SessionException e) { // TException means the connection is broken, remove it and get a new one. - LOGGER.warn("remove history data source failed", e); + LOGGER.warn("removeHistoryDataSource failed", e); cleanSessionAndMayThrowConnectionException(session, i, e); } catch (RuntimeException e) { putBack(session); @@ -525,7 +525,7 @@ public List showColumns() throws SessionException { return ret; } catch (SessionException e) { // TException means the connection is broken, remove it and get a new one. - LOGGER.warn("insertTablet failed", e); + LOGGER.warn("showColumns failed", e); cleanSessionAndMayThrowConnectionException(session, i, e); } catch (RuntimeException e) { putBack(session); @@ -592,12 +592,12 @@ public void deleteColumns( } public void insertColumnRecords( - List paths, long[] timestamps, Object[] valuesList, List dataTypeList) + List paths, long[] keys, Object[] valuesList, List dataTypeList) throws SessionException { for (int i = 0; i < RETRY; i++) { Session session = getSession(); try { - session.insertColumnRecords(paths, timestamps, valuesList, dataTypeList); + session.insertColumnRecords(paths, keys, valuesList, dataTypeList); putBack(session); return; } catch (SessionException e) { @@ -613,7 +613,7 @@ public void insertColumnRecords( public void insertColumnRecords( List paths, - long[] timestamps, + long[] keys, Object[] valuesList, List dataTypeList, List> tagsList) @@ -621,7 +621,7 @@ public void insertColumnRecords( for (int i = 0; i < RETRY; i++) { Session session = getSession(); try { - session.insertColumnRecords(paths, timestamps, valuesList, dataTypeList, tagsList); + session.insertColumnRecords(paths, keys, valuesList, dataTypeList, tagsList); putBack(session); return; } catch (SessionException e) { @@ -637,7 +637,7 @@ public void insertColumnRecords( public void insertColumnRecords( List paths, - long[] timestamps, + long[] keys, Object[] valuesList, List dataTypeList, List> tagsList, @@ -646,8 +646,7 @@ public void insertColumnRecords( for (int i = 0; i < RETRY; i++) { Session session = getSession(); try { - session.insertColumnRecords( - paths, timestamps, valuesList, dataTypeList, tagsList, precision); + session.insertColumnRecords(paths, keys, valuesList, dataTypeList, tagsList, precision); putBack(session); return; } catch (SessionException e) { @@ -662,12 +661,12 @@ public void insertColumnRecords( } public void insertNonAlignedColumnRecords( - List paths, long[] timestamps, Object[] valuesList, List dataTypeList) + List paths, long[] keys, Object[] valuesList, List dataTypeList) throws SessionException { for (int i = 0; i < RETRY; i++) { Session session = getSession(); try { - session.insertNonAlignedColumnRecords(paths, timestamps, valuesList, dataTypeList); + session.insertNonAlignedColumnRecords(paths, keys, valuesList, dataTypeList); putBack(session); return; } catch (SessionException e) { @@ -683,7 +682,7 @@ public void insertNonAlignedColumnRecords( public void insertNonAlignedColumnRecords( List paths, - long[] timestamps, + long[] keys, Object[] valuesList, List dataTypeList, List> tagsList) @@ -691,8 +690,7 @@ public void insertNonAlignedColumnRecords( for (int i = 0; i < RETRY; i++) { Session session = getSession(); try { - session.insertNonAlignedColumnRecords( - paths, timestamps, valuesList, dataTypeList, tagsList); + session.insertNonAlignedColumnRecords(paths, keys, valuesList, dataTypeList, tagsList); putBack(session); return; } catch (SessionException e) { @@ -708,7 +706,7 @@ public void insertNonAlignedColumnRecords( public void insertNonAlignedColumnRecords( List paths, - long[] timestamps, + long[] keys, Object[] valuesList, List dataTypeList, List> tagsList, @@ -718,7 +716,7 @@ public void insertNonAlignedColumnRecords( Session session = getSession(); try { session.insertNonAlignedColumnRecords( - paths, timestamps, valuesList, dataTypeList, tagsList, precision); + paths, keys, valuesList, dataTypeList, tagsList, precision); putBack(session); return; } catch (SessionException e) { @@ -734,7 +732,7 @@ public void insertNonAlignedColumnRecords( public void insertRowRecords( List paths, - long[] timestamps, + long[] keys, Object[] valuesList, List dataTypeList, List> tagsList) @@ -742,7 +740,7 @@ public void insertRowRecords( for (int i = 0; i < RETRY; i++) { Session session = getSession(); try { - session.insertRowRecords(paths, timestamps, valuesList, dataTypeList, tagsList); + session.insertRowRecords(paths, keys, valuesList, dataTypeList, tagsList); putBack(session); return; } catch (SessionException e) { @@ -758,7 +756,7 @@ public void insertRowRecords( public void insertRowRecords( List paths, - long[] timestamps, + long[] keys, Object[] valuesList, List dataTypeList, List> tagsList, @@ -767,7 +765,7 @@ public void insertRowRecords( for (int i = 0; i < RETRY; i++) { Session session = getSession(); try { - session.insertRowRecords(paths, timestamps, valuesList, dataTypeList, tagsList, precison); + session.insertRowRecords(paths, keys, valuesList, dataTypeList, tagsList, precison); putBack(session); return; } catch (SessionException e) { @@ -782,12 +780,12 @@ public void insertRowRecords( } public void insertNonAlignedRowRecords( - List paths, long[] timestamps, Object[] valuesList, List dataTypeList) + List paths, long[] keys, Object[] valuesList, List dataTypeList) throws SessionException { for (int i = 0; i < RETRY; i++) { Session session = getSession(); try { - session.insertNonAlignedRowRecords(paths, timestamps, valuesList, dataTypeList); + session.insertNonAlignedRowRecords(paths, keys, valuesList, dataTypeList); putBack(session); return; } catch (SessionException e) { @@ -803,7 +801,7 @@ public void insertNonAlignedRowRecords( public void insertNonAlignedRowRecords( List paths, - long[] timestamps, + long[] keys, Object[] valuesList, List dataTypeList, List> tagsList) @@ -811,7 +809,7 @@ public void insertNonAlignedRowRecords( for (int i = 0; i < RETRY; i++) { Session session = getSession(); try { - session.insertNonAlignedRowRecords(paths, timestamps, valuesList, dataTypeList, tagsList); + session.insertNonAlignedRowRecords(paths, keys, valuesList, dataTypeList, tagsList); putBack(session); return; } catch (SessionException e) { @@ -827,7 +825,7 @@ public void insertNonAlignedRowRecords( public void insertNonAlignedRowRecords( List paths, - long[] timestamps, + long[] keys, Object[] valuesList, List dataTypeList, List> tagsList, @@ -837,7 +835,7 @@ public void insertNonAlignedRowRecords( Session session = getSession(); try { session.insertNonAlignedRowRecords( - paths, timestamps, valuesList, dataTypeList, tagsList, precision); + paths, keys, valuesList, dataTypeList, tagsList, precision); putBack(session); return; } catch (SessionException e) { @@ -1011,7 +1009,7 @@ public SessionQueryDataSet downsampleQuery( return downsampleQuery(paths, KEY_MIN_VAL, KEY_MAX_VAL, aggregateType, precision); } - // downsample query with time interval + // downsample query with key interval public SessionQueryDataSet downsampleQuery( List paths, long startKey, long endKey, AggregateType aggregateType, long precision) throws SessionException { diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session/Session.java b/session/src/main/java/cn/edu/tsinghua/iginx/session/Session.java index 100e1341a6..9190d6a0cb 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session/Session.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session/Session.java @@ -308,33 +308,30 @@ public void deleteColumns( } public void insertColumnRecords( - List paths, long[] timestamps, Object[] valuesList, List dataTypeList) + List paths, long[] keys, Object[] valuesList, List dataTypeList) throws SessionException { - insertColumnRecords(paths, timestamps, valuesList, dataTypeList, null, timeUnit); + insertColumnRecords(paths, keys, valuesList, dataTypeList, null, timeUnit); } public void insertColumnRecords( List paths, - long[] timestamps, + long[] keys, Object[] valuesList, List dataTypeList, List> tagsList) throws SessionException { - insertColumnRecords(paths, timestamps, valuesList, dataTypeList, tagsList, timeUnit); + insertColumnRecords(paths, keys, valuesList, dataTypeList, tagsList, timeUnit); } public void insertColumnRecords( List paths, - long[] timestamps, + long[] keys, Object[] valuesList, List dataTypeList, List> tagsList, TimePrecision precision) throws SessionException { - if (paths.isEmpty() - || timestamps.length == 0 - || valuesList.length == 0 - || dataTypeList.isEmpty()) { + if (paths.isEmpty() || keys.length == 0 || valuesList.length == 0 || dataTypeList.isEmpty()) { LOGGER.error("Invalid insert request!"); return; } @@ -347,14 +344,14 @@ public void insertColumnRecords( return; } - long[] sortedTimestamps = Arrays.copyOf(timestamps, timestamps.length); - Integer[] index = new Integer[sortedTimestamps.length]; - for (int i = 0; i < sortedTimestamps.length; i++) { + long[] sortedKeys = Arrays.copyOf(keys, keys.length); + Integer[] index = new Integer[sortedKeys.length]; + for (int i = 0; i < sortedKeys.length; i++) { index[i] = i; } Arrays.sort( - index, Comparator.comparingLong(Arrays.asList(ArrayUtils.toObject(sortedTimestamps))::get)); - Arrays.sort(sortedTimestamps); + index, Comparator.comparingLong(Arrays.asList(ArrayUtils.toObject(sortedKeys))::get)); + Arrays.sort(sortedKeys); for (int i = 0; i < valuesList.length; i++) { Object[] values = new Object[index.length]; for (int j = 0; j < index.length; j++) { @@ -387,13 +384,13 @@ public void insertColumnRecords( List bitmapBufferList = new ArrayList<>(); for (int i = 0; i < sortedValuesList.length; i++) { Object[] values = (Object[]) sortedValuesList[i]; - if (values.length != sortedTimestamps.length) { - LOGGER.error("The sizes of timestamps and the element of valuesList should be equal."); + if (values.length != sortedKeys.length) { + LOGGER.error("The sizes of keys and the element of valuesList should be equal."); return; } valueBufferList.add(ByteUtils.getColumnByteBuffer(values, sortedDataTypeList.get(i))); - Bitmap bitmap = new Bitmap(sortedTimestamps.length); - for (int j = 0; j < sortedTimestamps.length; j++) { + Bitmap bitmap = new Bitmap(sortedKeys.length); + for (int j = 0; j < sortedKeys.length; j++) { if (values[j] != null) { bitmap.mark(j); } @@ -404,7 +401,7 @@ public void insertColumnRecords( InsertColumnRecordsReq req = new InsertColumnRecordsReq(); req.setSessionId(sessionId); req.setPaths(sortedPaths); - req.setKeys(getByteArrayFromLongArray(sortedTimestamps)); + req.setKeys(getByteArrayFromLongArray(sortedKeys)); req.setValuesList(valueBufferList); req.setBitmapList(bitmapBufferList); req.setDataTypeList(sortedDataTypeList); @@ -415,33 +412,30 @@ public void insertColumnRecords( } public void insertNonAlignedColumnRecords( - List paths, long[] timestamps, Object[] valuesList, List dataTypeList) + List paths, long[] keys, Object[] valuesList, List dataTypeList) throws SessionException { - insertNonAlignedColumnRecords(paths, timestamps, valuesList, dataTypeList, null, timeUnit); + insertNonAlignedColumnRecords(paths, keys, valuesList, dataTypeList, null, timeUnit); } public void insertNonAlignedColumnRecords( List paths, - long[] timestamps, + long[] keys, Object[] valuesList, List dataTypeList, List> tagsList) throws SessionException { - insertNonAlignedColumnRecords(paths, timestamps, valuesList, dataTypeList, tagsList, timeUnit); + insertNonAlignedColumnRecords(paths, keys, valuesList, dataTypeList, tagsList, timeUnit); } public void insertNonAlignedColumnRecords( List paths, - long[] timestamps, + long[] keys, Object[] valuesList, List dataTypeList, List> tagsList, TimePrecision precision) throws SessionException { - if (paths.isEmpty() - || timestamps.length == 0 - || valuesList.length == 0 - || dataTypeList.isEmpty()) { + if (paths.isEmpty() || keys.length == 0 || valuesList.length == 0 || dataTypeList.isEmpty()) { LOGGER.error("Invalid insert request!"); return; } @@ -454,14 +448,14 @@ public void insertNonAlignedColumnRecords( return; } - long[] sortedTimestamps = Arrays.copyOf(timestamps, timestamps.length); - Integer[] index = new Integer[sortedTimestamps.length]; - for (int i = 0; i < sortedTimestamps.length; i++) { + long[] sortedKeys = Arrays.copyOf(keys, keys.length); + Integer[] index = new Integer[sortedKeys.length]; + for (int i = 0; i < sortedKeys.length; i++) { index[i] = i; } Arrays.sort( - index, Comparator.comparingLong(Arrays.asList(ArrayUtils.toObject(sortedTimestamps))::get)); - Arrays.sort(sortedTimestamps); + index, Comparator.comparingLong(Arrays.asList(ArrayUtils.toObject(sortedKeys))::get)); + Arrays.sort(sortedKeys); for (int i = 0; i < valuesList.length; i++) { Object[] values = new Object[index.length]; for (int j = 0; j < index.length; j++) { @@ -494,13 +488,13 @@ public void insertNonAlignedColumnRecords( List bitmapBufferList = new ArrayList<>(); for (int i = 0; i < sortedValuesList.length; i++) { Object[] values = (Object[]) sortedValuesList[i]; - if (values.length != sortedTimestamps.length) { - LOGGER.error("The sizes of timestamps and the element of valuesList should be equal."); + if (values.length != sortedKeys.length) { + LOGGER.error("The sizes of keys and the element of valuesList should be equal."); return; } valueBufferList.add(ByteUtils.getColumnByteBuffer(values, sortedDataTypeList.get(i))); - Bitmap bitmap = new Bitmap(sortedTimestamps.length); - for (int j = 0; j < sortedTimestamps.length; j++) { + Bitmap bitmap = new Bitmap(sortedKeys.length); + for (int j = 0; j < sortedKeys.length; j++) { if (values[j] != null) { bitmap.mark(j); } @@ -511,7 +505,7 @@ public void insertNonAlignedColumnRecords( InsertNonAlignedColumnRecordsReq req = new InsertNonAlignedColumnRecordsReq(); req.setSessionId(sessionId); req.setPaths(sortedPaths); - req.setKeys(getByteArrayFromLongArray(sortedTimestamps)); + req.setKeys(getByteArrayFromLongArray(sortedKeys)); req.setValuesList(valueBufferList); req.setBitmapList(bitmapBufferList); req.setDataTypeList(sortedDataTypeList); @@ -523,26 +517,23 @@ public void insertNonAlignedColumnRecords( public void insertRowRecords( List paths, - long[] timestamps, + long[] keys, Object[] valuesList, List dataTypeList, List> tagsList) throws SessionException { - insertRowRecords(paths, timestamps, valuesList, dataTypeList, tagsList, timeUnit); + insertRowRecords(paths, keys, valuesList, dataTypeList, tagsList, timeUnit); } public void insertRowRecords( List paths, - long[] timestamps, + long[] keys, Object[] valuesList, List dataTypeList, List> tagsList, TimePrecision precision) throws SessionException { - if (paths.isEmpty() - || timestamps.length == 0 - || valuesList.length == 0 - || dataTypeList.isEmpty()) { + if (paths.isEmpty() || keys.length == 0 || valuesList.length == 0 || dataTypeList.isEmpty()) { LOGGER.error("Invalid insert request!"); return; } @@ -550,8 +541,8 @@ public void insertRowRecords( LOGGER.error("The sizes of paths and dataTypeList should be equal."); return; } - if (timestamps.length != valuesList.length) { - LOGGER.error("The sizes of timestamps and valuesList should be equal."); + if (keys.length != valuesList.length) { + LOGGER.error("The sizes of keys and valuesList should be equal."); return; } if (tagsList != null && !tagsList.isEmpty() && paths.size() != tagsList.size()) { @@ -559,14 +550,14 @@ public void insertRowRecords( return; } - long[] sortedTimestamps = Arrays.copyOf(timestamps, timestamps.length); - Integer[] index = new Integer[sortedTimestamps.length]; - for (int i = 0; i < sortedTimestamps.length; i++) { + long[] sortedKeys = Arrays.copyOf(keys, keys.length); + Integer[] index = new Integer[sortedKeys.length]; + for (int i = 0; i < sortedKeys.length; i++) { index[i] = i; } Arrays.sort( - index, Comparator.comparingLong(Arrays.asList(ArrayUtils.toObject(sortedTimestamps))::get)); - Arrays.sort(sortedTimestamps); + index, Comparator.comparingLong(Arrays.asList(ArrayUtils.toObject(sortedKeys))::get)); + Arrays.sort(sortedKeys); Object[] sortedValuesList = new Object[valuesList.length]; for (int i = 0; i < valuesList.length; i++) { sortedValuesList[i] = valuesList[index[i]]; @@ -599,7 +590,7 @@ public void insertRowRecords( List valueBufferList = new ArrayList<>(); List bitmapBufferList = new ArrayList<>(); - for (int i = 0; i < sortedTimestamps.length; i++) { + for (int i = 0; i < sortedKeys.length; i++) { Object[] values = (Object[]) sortedValuesList[i]; if (values.length != sortedPaths.size()) { LOGGER.error("The sizes of paths and the element of valuesList should be equal."); @@ -618,7 +609,7 @@ public void insertRowRecords( InsertRowRecordsReq req = new InsertRowRecordsReq(); req.setSessionId(sessionId); req.setPaths(sortedPaths); - req.setKeys(getByteArrayFromLongArray(sortedTimestamps)); + req.setKeys(getByteArrayFromLongArray(sortedKeys)); req.setValuesList(valueBufferList); req.setBitmapList(bitmapBufferList); req.setDataTypeList(sortedDataTypeList); @@ -629,33 +620,30 @@ public void insertRowRecords( } public void insertNonAlignedRowRecords( - List paths, long[] timestamps, Object[] valuesList, List dataTypeList) + List paths, long[] keys, Object[] valuesList, List dataTypeList) throws SessionException { - insertNonAlignedRowRecords(paths, timestamps, valuesList, dataTypeList, null, timeUnit); + insertNonAlignedRowRecords(paths, keys, valuesList, dataTypeList, null, timeUnit); } public void insertNonAlignedRowRecords( List paths, - long[] timestamps, + long[] keys, Object[] valuesList, List dataTypeList, List> tagsList) throws SessionException { - insertNonAlignedRowRecords(paths, timestamps, valuesList, dataTypeList, tagsList, timeUnit); + insertNonAlignedRowRecords(paths, keys, valuesList, dataTypeList, tagsList, timeUnit); } public void insertNonAlignedRowRecords( List paths, - long[] timestamps, + long[] keys, Object[] valuesList, List dataTypeList, List> tagsList, TimePrecision precision) throws SessionException { - if (paths.isEmpty() - || timestamps.length == 0 - || valuesList.length == 0 - || dataTypeList.isEmpty()) { + if (paths.isEmpty() || keys.length == 0 || valuesList.length == 0 || dataTypeList.isEmpty()) { LOGGER.error("Invalid insert request!"); return; } @@ -663,8 +651,8 @@ public void insertNonAlignedRowRecords( LOGGER.error("The sizes of paths and dataTypeList should be equal."); return; } - if (timestamps.length != valuesList.length) { - LOGGER.error("The sizes of timestamps and valuesList should be equal."); + if (keys.length != valuesList.length) { + LOGGER.error("The sizes of keys and valuesList should be equal."); return; } if (tagsList != null && !tagsList.isEmpty() && paths.size() != tagsList.size()) { @@ -672,14 +660,14 @@ public void insertNonAlignedRowRecords( return; } - long[] sortedTimestamps = Arrays.copyOf(timestamps, timestamps.length); - Integer[] index = new Integer[sortedTimestamps.length]; - for (int i = 0; i < sortedTimestamps.length; i++) { + long[] sortedKeys = Arrays.copyOf(keys, keys.length); + Integer[] index = new Integer[sortedKeys.length]; + for (int i = 0; i < sortedKeys.length; i++) { index[i] = i; } Arrays.sort( - index, Comparator.comparingLong(Arrays.asList(ArrayUtils.toObject(sortedTimestamps))::get)); - Arrays.sort(sortedTimestamps); + index, Comparator.comparingLong(Arrays.asList(ArrayUtils.toObject(sortedKeys))::get)); + Arrays.sort(sortedKeys); Object[] sortedValuesList = new Object[valuesList.length]; for (int i = 0; i < valuesList.length; i++) { sortedValuesList[i] = valuesList[index[i]]; @@ -712,7 +700,7 @@ public void insertNonAlignedRowRecords( List valueBufferList = new ArrayList<>(); List bitmapBufferList = new ArrayList<>(); - for (int i = 0; i < sortedTimestamps.length; i++) { + for (int i = 0; i < sortedKeys.length; i++) { Object[] values = (Object[]) sortedValuesList[i]; if (values.length != sortedPaths.size()) { LOGGER.error("The sizes of paths and the element of valuesList should be equal."); @@ -731,7 +719,7 @@ public void insertNonAlignedRowRecords( InsertNonAlignedRowRecordsReq req = new InsertNonAlignedRowRecordsReq(); req.setSessionId(sessionId); req.setPaths(sortedPaths); - req.setKeys(getByteArrayFromLongArray(sortedTimestamps)); + req.setKeys(getByteArrayFromLongArray(sortedKeys)); req.setValuesList(valueBufferList); req.setBitmapList(bitmapBufferList); req.setDataTypeList(sortedDataTypeList); From 703c2b4e4c20017056c3e51a174a800fd53a9453 Mon Sep 17 00:00:00 2001 From: SolomonAnn Date: Sat, 6 Jul 2024 09:46:04 +0800 Subject: [PATCH 054/138] Remove useless lines (#370) Co-authored-by: Yuqing Zhu --- .../cn/edu/tsinghua/iginx/integration/client/ImportFileIT.java | 1 - .../java/cn/edu/tsinghua/iginx/integration/func/tag/TagIT.java | 2 -- 2 files changed, 3 deletions(-) diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/client/ImportFileIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/client/ImportFileIT.java index 5bc50d2ea4..2af25690d4 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/client/ImportFileIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/client/ImportFileIT.java @@ -34,7 +34,6 @@ public class ImportFileIT { @BeforeClass public static void setUp() throws SessionException { MultiConnection session = new MultiConnection(new Session("127.0.0.1", 6888, "root", "root")); - ; executor = new SQLExecutor(session); executor.open(); } diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/tag/TagIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/tag/TagIT.java index d58314d442..87737b1270 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/tag/TagIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/tag/TagIT.java @@ -935,7 +935,6 @@ public void testDeleteTSWithMultiTags() { String showColumnsData = "SELECT v FROM ah.* WITH t1=v1 AND t2=v2;"; expected = "ResultSets:\n" + "+---+\n" + "|key|\n" + "+---+\n" + "+---+\n" + "Empty set.\n"; - ; executeAndCompare(showColumnsData, expected); deleteTimeSeries = "DELETE COLUMNS * WITH t1=v1 AND t2=vv2 OR t1=vv1 AND t2=v2;"; @@ -963,7 +962,6 @@ public void testDeleteTSWithMultiTags() { showColumnsData = "SELECT * FROM * WITH t1=v1 AND t2=vv2 OR t1=vv1 AND t2=v2;"; expected = "ResultSets:\n" + "+---+\n" + "|key|\n" + "+---+\n" + "+---+\n" + "Empty set.\n"; - ; executeAndCompare(showColumnsData, expected); } From 89c038e5cb901c449d6fc20e4a24f2d209f23b81 Mon Sep 17 00:00:00 2001 From: SolomonAnn Date: Sat, 6 Jul 2024 10:18:25 +0800 Subject: [PATCH 055/138] Fix deadlock bug (#371) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 涉及到代码编写习惯,同一个文件中加的代码用的就是这种try-finally块,比如updateFragmentByColumnsInterval函数 在复杂实验中,没有这种try-finally块,会导致问题;修改后,问题可解决 --- .../metadata/cache/DefaultMetaCache.java | 533 ++++++++++-------- 1 file changed, 305 insertions(+), 228 deletions(-) diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/cache/DefaultMetaCache.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/cache/DefaultMetaCache.java index c62a5a35fd..4dd3513e9c 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/cache/DefaultMetaCache.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/cache/DefaultMetaCache.java @@ -215,30 +215,36 @@ private static List searchFragmentList( @Override public void initFragment(Map> fragmentListMap) { storageUnitLock.readLock().lock(); - fragmentListMap - .values() - .forEach( - e -> - e.forEach( - f -> - f.setMasterStorageUnit( - storageUnitMetaMap.get(f.getMasterStorageUnitId())))); - storageUnitLock.readLock().unlock(); + try { + fragmentListMap + .values() + .forEach( + e -> + e.forEach( + f -> + f.setMasterStorageUnit( + storageUnitMetaMap.get(f.getMasterStorageUnitId())))); + } finally { + storageUnitLock.readLock().unlock(); + } fragmentLock.writeLock().lock(); - sortedFragmentMetaLists.addAll( - fragmentListMap.entrySet().stream() - .sorted(Map.Entry.comparingByKey()) - .map(e -> new Pair<>(e.getKey(), e.getValue())) - .collect(Collectors.toList())); - fragmentListMap.forEach(fragmentMetaListMap::put); - if (enableFragmentCacheControl) { - // 统计分片总数 - fragmentCacheSize = sortedFragmentMetaLists.stream().mapToInt(e -> e.v.size()).sum(); - while (fragmentCacheSize > fragmentCacheMaxSize) { - kickOffHistoryFragment(); + try { + sortedFragmentMetaLists.addAll( + fragmentListMap.entrySet().stream() + .sorted(Map.Entry.comparingByKey()) + .map(e -> new Pair<>(e.getKey(), e.getValue())) + .collect(Collectors.toList())); + fragmentListMap.forEach(fragmentMetaListMap::put); + if (enableFragmentCacheControl) { + // 统计分片总数 + fragmentCacheSize = sortedFragmentMetaLists.stream().mapToInt(e -> e.v.size()).sum(); + while (fragmentCacheSize > fragmentCacheMaxSize) { + kickOffHistoryFragment(); + } } + } finally { + fragmentLock.writeLock().unlock(); } - fragmentLock.writeLock().unlock(); } private void kickOffHistoryFragment() { @@ -261,26 +267,28 @@ private void kickOffHistoryFragment() { @Override public void addFragment(FragmentMeta fragmentMeta) { fragmentLock.writeLock().lock(); - // 更新 fragmentMetaListMap - List fragmentMetaList = - fragmentMetaListMap.computeIfAbsent( - fragmentMeta.getColumnsInterval(), v -> new ArrayList<>()); - if (fragmentMetaList.size() == 0) { - // 更新 sortedFragmentMetaLists - updateSortedFragmentsList(fragmentMeta.getColumnsInterval(), fragmentMetaList); - } - fragmentMetaList.add(fragmentMeta); - if (enableFragmentCacheControl) { - if (fragmentMeta.getKeyInterval().getStartKey() < minKey) { - minKey = fragmentMeta.getKeyInterval().getStartKey(); + try { + // 更新 fragmentMetaListMap + List fragmentMetaList = + fragmentMetaListMap.computeIfAbsent( + fragmentMeta.getColumnsInterval(), v -> new ArrayList<>()); + if (fragmentMetaList.size() == 0) { + // 更新 sortedFragmentMetaLists + updateSortedFragmentsList(fragmentMeta.getColumnsInterval(), fragmentMetaList); } - fragmentCacheSize++; - while (fragmentCacheSize > fragmentCacheMaxSize) { - kickOffHistoryFragment(); + fragmentMetaList.add(fragmentMeta); + if (enableFragmentCacheControl) { + if (fragmentMeta.getKeyInterval().getStartKey() < minKey) { + minKey = fragmentMeta.getKeyInterval().getStartKey(); + } + fragmentCacheSize++; + while (fragmentCacheSize > fragmentCacheMaxSize) { + kickOffHistoryFragment(); + } } + } finally { + fragmentLock.writeLock().unlock(); } - - fragmentLock.writeLock().unlock(); } private void updateSortedFragmentsList( @@ -312,11 +320,14 @@ private void updateSortedFragmentsList( @Override public void updateFragment(FragmentMeta fragmentMeta) { fragmentLock.writeLock().lock(); - // 更新 fragmentMetaListMap - List fragmentMetaList = - fragmentMetaListMap.get(fragmentMeta.getColumnsInterval()); - fragmentMetaList.set(fragmentMetaList.size() - 1, fragmentMeta); - fragmentLock.writeLock().unlock(); + try { + // 更新 fragmentMetaListMap + List fragmentMetaList = + fragmentMetaListMap.get(fragmentMeta.getColumnsInterval()); + fragmentMetaList.set(fragmentMetaList.size() - 1, fragmentMeta); + } finally { + fragmentLock.writeLock().unlock(); + } } @Override @@ -371,23 +382,29 @@ public Map> getFragmentMapByColumnsInterval( ColumnsInterval columnsInterval) { Map> resultMap = new HashMap<>(); fragmentLock.readLock().lock(); - searchFragmentSeriesList(sortedFragmentMetaLists, columnsInterval) - .forEach(e -> resultMap.put(e.k, e.v)); - fragmentLock.readLock().unlock(); + try { + searchFragmentSeriesList(sortedFragmentMetaLists, columnsInterval) + .forEach(e -> resultMap.put(e.k, e.v)); + } finally { + fragmentLock.readLock().unlock(); + } return resultMap; } @Override public List getDummyFragmentsByColumnsInterval(ColumnsInterval columnsInterval) { - fragmentLock.readLock().lock(); List results = new ArrayList<>(); - for (FragmentMeta fragmentMeta : dummyFragments) { - if (fragmentMeta.isValid() - && fragmentMeta.getColumnsInterval().isIntersect(columnsInterval)) { - results.add(fragmentMeta); + fragmentLock.readLock().lock(); + try { + for (FragmentMeta fragmentMeta : dummyFragments) { + if (fragmentMeta.isValid() + && fragmentMeta.getColumnsInterval().isIntersect(columnsInterval)) { + results.add(fragmentMeta); + } } + } finally { + fragmentLock.readLock().unlock(); } - fragmentLock.readLock().unlock(); return results; } @@ -395,11 +412,14 @@ public List getDummyFragmentsByColumnsInterval(ColumnsInterval col public Map getLatestFragmentMap() { Map latestFragmentMap = new HashMap<>(); fragmentLock.readLock().lock(); - sortedFragmentMetaLists.stream() - .map(e -> e.v.get(e.v.size() - 1)) - .filter(e -> e.getKeyInterval().getEndKey() == Long.MAX_VALUE) - .forEach(e -> latestFragmentMap.put(e.getColumnsInterval(), e)); - fragmentLock.readLock().unlock(); + try { + sortedFragmentMetaLists.stream() + .map(e -> e.v.get(e.v.size() - 1)) + .filter(e -> e.getKeyInterval().getEndKey() == Long.MAX_VALUE) + .forEach(e -> latestFragmentMap.put(e.getColumnsInterval(), e)); + } finally { + fragmentLock.readLock().unlock(); + } return latestFragmentMap; } @@ -408,11 +428,14 @@ public Map getLatestFragmentMapByColumnsInterval( ColumnsInterval columnsInterval) { Map latestFragmentMap = new HashMap<>(); fragmentLock.readLock().lock(); - searchFragmentSeriesList(sortedFragmentMetaLists, columnsInterval).stream() - .map(e -> e.v.get(e.v.size() - 1)) - .filter(e -> e.getKeyInterval().getEndKey() == Long.MAX_VALUE) - .forEach(e -> latestFragmentMap.put(e.getColumnsInterval(), e)); - fragmentLock.readLock().unlock(); + try { + searchFragmentSeriesList(sortedFragmentMetaLists, columnsInterval).stream() + .map(e -> e.v.get(e.v.size() - 1)) + .filter(e -> e.getKeyInterval().getEndKey() == Long.MAX_VALUE) + .forEach(e -> latestFragmentMap.put(e.getColumnsInterval(), e)); + } finally { + fragmentLock.readLock().unlock(); + } return latestFragmentMap; } @@ -421,31 +444,37 @@ public Map> getFragmentMapByColumnsIntervalA ColumnsInterval columnsInterval, KeyInterval keyInterval) { Map> resultMap = new HashMap<>(); fragmentLock.readLock().lock(); - searchFragmentSeriesList(sortedFragmentMetaLists, columnsInterval) - .forEach( - e -> { - List fragmentMetaList = searchFragmentList(e.v, keyInterval); - if (!fragmentMetaList.isEmpty()) { - resultMap.put(e.k, fragmentMetaList); - } - }); - fragmentLock.readLock().unlock(); + try { + searchFragmentSeriesList(sortedFragmentMetaLists, columnsInterval) + .forEach( + e -> { + List fragmentMetaList = searchFragmentList(e.v, keyInterval); + if (!fragmentMetaList.isEmpty()) { + resultMap.put(e.k, fragmentMetaList); + } + }); + } finally { + fragmentLock.readLock().unlock(); + } return resultMap; } @Override public List getDummyFragmentsByColumnsIntervalAndKeyInterval( ColumnsInterval columnsInterval, KeyInterval keyInterval) { - fragmentLock.readLock().lock(); List results = new ArrayList<>(); - for (FragmentMeta fragmentMeta : dummyFragments) { - if (fragmentMeta.isValid() - && fragmentMeta.getColumnsInterval().isIntersect(columnsInterval) - && fragmentMeta.getKeyInterval().isIntersect(keyInterval)) { - results.add(fragmentMeta); + fragmentLock.readLock().lock(); + try { + for (FragmentMeta fragmentMeta : dummyFragments) { + if (fragmentMeta.isValid() + && fragmentMeta.getColumnsInterval().isIntersect(columnsInterval) + && fragmentMeta.getKeyInterval().isIntersect(keyInterval)) { + results.add(fragmentMeta); + } } + } finally { + fragmentLock.readLock().unlock(); } - fragmentLock.readLock().unlock(); return results; } @@ -453,22 +482,25 @@ public List getDummyFragmentsByColumnsIntervalAndKeyInterval( public List getFragmentListByColumnName(String columnName) { List resultList; fragmentLock.readLock().lock(); - resultList = - searchFragmentSeriesList(sortedFragmentMetaLists, columnName).stream() - .map(e -> e.v) - .flatMap(List::stream) - .sorted( - (o1, o2) -> { - if (o1.getColumnsInterval().getStartColumn() == null - && o2.getColumnsInterval().getStartColumn() == null) return 0; - else if (o1.getColumnsInterval().getStartColumn() == null) return -1; - else if (o2.getColumnsInterval().getStartColumn() == null) return 1; - return o1.getColumnsInterval() - .getStartColumn() - .compareTo(o2.getColumnsInterval().getStartColumn()); - }) - .collect(Collectors.toList()); - fragmentLock.readLock().unlock(); + try { + resultList = + searchFragmentSeriesList(sortedFragmentMetaLists, columnName).stream() + .map(e -> e.v) + .flatMap(List::stream) + .sorted( + (o1, o2) -> { + if (o1.getColumnsInterval().getStartColumn() == null + && o2.getColumnsInterval().getStartColumn() == null) return 0; + else if (o1.getColumnsInterval().getStartColumn() == null) return -1; + else if (o2.getColumnsInterval().getStartColumn() == null) return 1; + return o1.getColumnsInterval() + .getStartColumn() + .compareTo(o2.getColumnsInterval().getStartColumn()); + }) + .collect(Collectors.toList()); + } finally { + fragmentLock.readLock().unlock(); + } return resultList; } @@ -476,14 +508,17 @@ public List getFragmentListByColumnName(String columnName) { public FragmentMeta getLatestFragmentByColumnName(String columnName) { FragmentMeta result; fragmentLock.readLock().lock(); - result = - searchFragmentSeriesList(sortedFragmentMetaLists, columnName).stream() - .map(e -> e.v) - .flatMap(List::stream) - .filter(e -> e.getKeyInterval().getEndKey() == Long.MAX_VALUE) - .findFirst() - .orElse(null); - fragmentLock.readLock().unlock(); + try { + result = + searchFragmentSeriesList(sortedFragmentMetaLists, columnName).stream() + .map(e -> e.v) + .flatMap(List::stream) + .filter(e -> e.getKeyInterval().getEndKey() == Long.MAX_VALUE) + .findFirst() + .orElse(null); + } finally { + fragmentLock.readLock().unlock(); + } return result; } @@ -507,14 +542,17 @@ public List getFragmentListByColumnNameAndKeyInterval( String columnName, KeyInterval keyInterval) { List resultList; fragmentLock.readLock().lock(); - List fragmentMetas = - searchFragmentSeriesList(sortedFragmentMetaLists, columnName).stream() - .map(e -> e.v) - .flatMap(List::stream) - .sorted(Comparator.comparingLong(o -> o.getKeyInterval().getStartKey())) - .collect(Collectors.toList()); - resultList = searchFragmentList(fragmentMetas, keyInterval); - fragmentLock.readLock().unlock(); + try { + List fragmentMetas = + searchFragmentSeriesList(sortedFragmentMetaLists, columnName).stream() + .map(e -> e.v) + .flatMap(List::stream) + .sorted(Comparator.comparingLong(o -> o.getKeyInterval().getStartKey())) + .collect(Collectors.toList()); + resultList = searchFragmentList(fragmentMetas, keyInterval); + } finally { + fragmentLock.readLock().unlock(); + } return resultList; } @@ -522,14 +560,17 @@ public List getFragmentListByColumnNameAndKeyInterval( public List getFragmentListByStorageUnitId(String storageUnitId) { List resultList; fragmentLock.readLock().lock(); - List fragmentMetas = - sortedFragmentMetaLists.stream() - .map(e -> e.v) - .flatMap(List::stream) - .sorted(Comparator.comparingLong(o -> o.getKeyInterval().getStartKey())) - .collect(Collectors.toList()); - resultList = searchFragmentList(fragmentMetas, storageUnitId); - fragmentLock.readLock().unlock(); + try { + List fragmentMetas = + sortedFragmentMetaLists.stream() + .map(e -> e.v) + .flatMap(List::stream) + .sorted(Comparator.comparingLong(o -> o.getKeyInterval().getStartKey())) + .collect(Collectors.toList()); + resultList = searchFragmentList(fragmentMetas, storageUnitId); + } finally { + fragmentLock.readLock().unlock(); + } return resultList; } @@ -546,22 +587,28 @@ public boolean hasStorageUnit() { @Override public void initStorageUnit(Map storageUnits) { storageUnitLock.writeLock().lock(); - for (StorageUnitMeta storageUnit : storageUnits.values()) { - storageUnitMetaMap.put(storageUnit.getId(), storageUnit); - getStorageEngine(storageUnit.getStorageEngineId()).addStorageUnit(storageUnit); + try { + for (StorageUnitMeta storageUnit : storageUnits.values()) { + storageUnitMetaMap.put(storageUnit.getId(), storageUnit); + getStorageEngine(storageUnit.getStorageEngineId()).addStorageUnit(storageUnit); + } + } finally { + storageUnitLock.writeLock().unlock(); } - storageUnitLock.writeLock().unlock(); } @Override public StorageUnitMeta getStorageUnit(String id) { StorageUnitMeta storageUnit; storageUnitLock.readLock().lock(); - storageUnit = storageUnitMetaMap.get(id); - if (storageUnit == null) { - storageUnit = dummyStorageUnitMetaMap.get(id); + try { + storageUnit = storageUnitMetaMap.get(id); + if (storageUnit == null) { + storageUnit = dummyStorageUnitMetaMap.get(id); + } + } finally { + storageUnitLock.readLock().unlock(); } - storageUnitLock.readLock().unlock(); return storageUnit; } @@ -569,18 +616,21 @@ public StorageUnitMeta getStorageUnit(String id) { public Map getStorageUnits(Set ids) { Map resultMap = new HashMap<>(); storageUnitLock.readLock().lock(); - for (String id : ids) { - StorageUnitMeta storageUnit = storageUnitMetaMap.get(id); - if (storageUnit != null) { - resultMap.put(id, storageUnit); - } else { - storageUnit = dummyStorageUnitMetaMap.get(id); + try { + for (String id : ids) { + StorageUnitMeta storageUnit = storageUnitMetaMap.get(id); if (storageUnit != null) { resultMap.put(id, storageUnit); + } else { + storageUnit = dummyStorageUnitMetaMap.get(id); + if (storageUnit != null) { + resultMap.put(id, storageUnit); + } } } + } finally { + storageUnitLock.readLock().unlock(); } - storageUnitLock.readLock().unlock(); return resultMap; } @@ -588,24 +638,33 @@ public Map getStorageUnits(Set ids) { public List getStorageUnits() { List storageUnitMetaList; storageUnitLock.readLock().lock(); - storageUnitMetaList = new ArrayList<>(storageUnitMetaMap.values()); - storageUnitMetaList.addAll(dummyStorageUnitMetaMap.values()); - storageUnitLock.readLock().unlock(); + try { + storageUnitMetaList = new ArrayList<>(storageUnitMetaMap.values()); + storageUnitMetaList.addAll(dummyStorageUnitMetaMap.values()); + } finally { + storageUnitLock.readLock().unlock(); + } return storageUnitMetaList; } @Override public void addStorageUnit(StorageUnitMeta storageUnitMeta) { storageUnitLock.writeLock().lock(); - storageUnitMetaMap.put(storageUnitMeta.getId(), storageUnitMeta); - storageUnitLock.writeLock().unlock(); + try { + storageUnitMetaMap.put(storageUnitMeta.getId(), storageUnitMeta); + } finally { + storageUnitLock.writeLock().unlock(); + } } @Override public void updateStorageUnit(StorageUnitMeta storageUnitMeta) { storageUnitLock.writeLock().lock(); - storageUnitMetaMap.put(storageUnitMeta.getId(), storageUnitMeta); - storageUnitLock.writeLock().unlock(); + try { + storageUnitMetaMap.put(storageUnitMeta.getId(), storageUnitMeta); + } finally { + storageUnitLock.writeLock().unlock(); + } } @Override @@ -627,38 +686,42 @@ public void removeIginx(long id) { public void addStorageEngine(StorageEngineMeta storageEngineMeta) { storageUnitLock.writeLock().lock(); fragmentLock.writeLock().lock(); - if (!storageEngineMetaMap.containsKey(storageEngineMeta.getId())) { - storageEngineMetaMap.put(storageEngineMeta.getId(), storageEngineMeta); - if (storageEngineMeta.isHasData()) { - StorageUnitMeta dummyStorageUnit = storageEngineMeta.getDummyStorageUnit(); - FragmentMeta dummyFragment = storageEngineMeta.getDummyFragment(); - dummyFragment.setMasterStorageUnit(dummyStorageUnit); - dummyStorageUnitMetaMap.put(dummyStorageUnit.getId(), dummyStorageUnit); - dummyFragments.add(dummyFragment); + try { + if (!storageEngineMetaMap.containsKey(storageEngineMeta.getId())) { + storageEngineMetaMap.put(storageEngineMeta.getId(), storageEngineMeta); + if (storageEngineMeta.isHasData()) { + StorageUnitMeta dummyStorageUnit = storageEngineMeta.getDummyStorageUnit(); + FragmentMeta dummyFragment = storageEngineMeta.getDummyFragment(); + dummyFragment.setMasterStorageUnit(dummyStorageUnit); + dummyStorageUnitMetaMap.put(dummyStorageUnit.getId(), dummyStorageUnit); + dummyFragments.add(dummyFragment); + } } + } finally { + fragmentLock.writeLock().unlock(); + storageUnitLock.writeLock().unlock(); } - fragmentLock.writeLock().unlock(); - storageUnitLock.writeLock().unlock(); } @Override public boolean removeDummyStorageEngine(long storageEngineId) { storageUnitLock.writeLock().lock(); fragmentLock.writeLock().lock(); - - if (!storageEngineMetaMap.containsKey(storageEngineId)) { - LOGGER.error("unexpected dummy storage engine {} to be removed", storageEngineId); - return false; + try { + if (!storageEngineMetaMap.containsKey(storageEngineId)) { + LOGGER.error("unexpected dummy storage engine {} to be removed", storageEngineId); + return false; + } + String dummyStorageUnitId = generateDummyStorageUnitId(storageEngineId); + StorageEngineMeta oldStorageEngineMeta = storageEngineMetaMap.get(storageEngineId); + assert oldStorageEngineMeta.isHasData(); + dummyFragments.removeIf(e -> e.getMasterStorageUnitId().equals(dummyStorageUnitId)); + dummyStorageUnitMetaMap.remove(dummyStorageUnitId); + storageEngineMetaMap.remove(storageEngineId); + } finally { + fragmentLock.writeLock().unlock(); + storageUnitLock.writeLock().unlock(); } - String dummyStorageUnitId = generateDummyStorageUnitId(storageEngineId); - StorageEngineMeta oldStorageEngineMeta = storageEngineMetaMap.get(storageEngineId); - assert oldStorageEngineMeta.isHasData(); - dummyFragments.removeIf(e -> e.getMasterStorageUnitId().equals(dummyStorageUnitId)); - dummyStorageUnitMetaMap.remove(dummyStorageUnitId); - storageEngineMetaMap.remove(storageEngineId); - - fragmentLock.writeLock().unlock(); - storageUnitLock.writeLock().unlock(); return true; } @@ -675,11 +738,14 @@ public StorageEngineMeta getStorageEngine(long id) { @Override public List getFragments() { List fragments = new ArrayList<>(); - this.fragmentLock.readLock().lock(); - for (Pair> pair : sortedFragmentMetaLists) { - fragments.addAll(pair.v); + fragmentLock.readLock().lock(); + try { + for (Pair> pair : sortedFragmentMetaLists) { + fragments.addAll(pair.v); + } + } finally { + fragmentLock.readLock().unlock(); } - this.fragmentLock.readLock().unlock(); return fragments; } @@ -760,68 +826,72 @@ public void timeSeriesIsUpdated(int node, int version) { @Override public void saveColumnsData(InsertStatement statement) { insertRecordLock.writeLock().lock(); - long now = System.currentTimeMillis(); - - RawData data = statement.getRawData(); - List paths = data.getPaths(); - if (data.isColumnData()) { - DataView view = new ColumnDataView(data, 0, data.getPaths().size(), 0, data.getKeys().size()); - for (int i = 0; i < view.getPathNum(); i++) { - long minn = Long.MAX_VALUE; - long maxx = Long.MIN_VALUE; - long totalByte = 0L; - int count = 0; - BitmapView bitmapView = view.getBitmapView(i); - for (int j = 0; j < view.getKeySize(); j++) { - if (bitmapView.get(j)) { - minn = Math.min(minn, view.getKey(j)); - maxx = Math.max(maxx, view.getKey(j)); - if (view.getDataType(i) == DataType.BINARY) { - totalByte += ((byte[]) view.getValue(i, j)).length; - } else { - totalByte += transDatatypeToByte(view.getDataType(i)); + try { + long now = System.currentTimeMillis(); + + RawData data = statement.getRawData(); + List paths = data.getPaths(); + if (data.isColumnData()) { + DataView view = + new ColumnDataView(data, 0, data.getPaths().size(), 0, data.getKeys().size()); + for (int i = 0; i < view.getPathNum(); i++) { + long minn = Long.MAX_VALUE; + long maxx = Long.MIN_VALUE; + long totalByte = 0L; + int count = 0; + BitmapView bitmapView = view.getBitmapView(i); + for (int j = 0; j < view.getKeySize(); j++) { + if (bitmapView.get(j)) { + minn = Math.min(minn, view.getKey(j)); + maxx = Math.max(maxx, view.getKey(j)); + if (view.getDataType(i) == DataType.BINARY) { + totalByte += ((byte[]) view.getValue(i, j)).length; + } else { + totalByte += transDatatypeToByte(view.getDataType(i)); + } + count++; } - count++; + } + if (count > 0) { + updateColumnCalDOConcurrentHashMap(paths.get(i), now, minn, maxx, totalByte, count); } } - if (count > 0) { - updateColumnCalDOConcurrentHashMap(paths.get(i), now, minn, maxx, totalByte, count); - } - } - } else { - DataView view = new RowDataView(data, 0, data.getPaths().size(), 0, data.getKeys().size()); - long[] totalByte = new long[view.getPathNum()]; - int[] count = new int[view.getPathNum()]; - long[] minn = new long[view.getPathNum()]; - long[] maxx = new long[view.getPathNum()]; - Arrays.fill(minn, Long.MAX_VALUE); - Arrays.fill(maxx, Long.MIN_VALUE); - - for (int i = 0; i < view.getKeySize(); i++) { - BitmapView bitmapView = view.getBitmapView(i); - int index = 0; - for (int j = 0; j < view.getPathNum(); j++) { - if (bitmapView.get(j)) { - minn[j] = Math.min(minn[j], view.getKey(i)); - maxx[j] = Math.max(maxx[j], view.getKey(i)); - if (view.getDataType(j) == DataType.BINARY) { - totalByte[j] += ((byte[]) view.getValue(i, index)).length; - } else { - totalByte[j] += transDatatypeToByte(view.getDataType(j)); + } else { + DataView view = new RowDataView(data, 0, data.getPaths().size(), 0, data.getKeys().size()); + long[] totalByte = new long[view.getPathNum()]; + int[] count = new int[view.getPathNum()]; + long[] minn = new long[view.getPathNum()]; + long[] maxx = new long[view.getPathNum()]; + Arrays.fill(minn, Long.MAX_VALUE); + Arrays.fill(maxx, Long.MIN_VALUE); + + for (int i = 0; i < view.getKeySize(); i++) { + BitmapView bitmapView = view.getBitmapView(i); + int index = 0; + for (int j = 0; j < view.getPathNum(); j++) { + if (bitmapView.get(j)) { + minn[j] = Math.min(minn[j], view.getKey(i)); + maxx[j] = Math.max(maxx[j], view.getKey(i)); + if (view.getDataType(j) == DataType.BINARY) { + totalByte[j] += ((byte[]) view.getValue(i, index)).length; + } else { + totalByte[j] += transDatatypeToByte(view.getDataType(j)); + } + count[j]++; + index++; } - count[j]++; - index++; } } - } - for (int i = 0; i < count.length; i++) { - if (count[i] > 0) { - updateColumnCalDOConcurrentHashMap( - paths.get(i), now, minn[i], maxx[i], totalByte[i], count[i]); + for (int i = 0; i < count.length; i++) { + if (count[i] > 0) { + updateColumnCalDOConcurrentHashMap( + paths.get(i), now, minn[i], maxx[i], totalByte[i], count[i]); + } } } + } finally { + insertRecordLock.writeLock().unlock(); } - insertRecordLock.writeLock().unlock(); } private void updateColumnCalDOConcurrentHashMap( @@ -852,21 +922,28 @@ private long transDatatypeToByte(DataType dataType) { @Override public List getMaxValueFromColumns() { + List ret; insertRecordLock.readLock().lock(); - List ret = - columnCalDOConcurrentHashMap.values().stream() - .filter(e -> random.nextDouble() < config.getCachedTimeseriesProb()) - .collect(Collectors.toList()); - insertRecordLock.readLock().unlock(); + try { + ret = + columnCalDOConcurrentHashMap.values().stream() + .filter(e -> random.nextDouble() < config.getCachedTimeseriesProb()) + .collect(Collectors.toList()); + } finally { + insertRecordLock.readLock().unlock(); + } return ret; } @Override public double getSumFromColumns() { + double ret; insertRecordLock.readLock().lock(); - double ret = - columnCalDOConcurrentHashMap.values().stream().mapToDouble(ColumnCalDO::getValue).sum(); - insertRecordLock.readLock().unlock(); + try { + ret = columnCalDOConcurrentHashMap.values().stream().mapToDouble(ColumnCalDO::getValue).sum(); + } finally { + insertRecordLock.readLock().unlock(); + } return ret; } From f27747580fe2b882cdda733af6a3a041daca7984 Mon Sep 17 00:00:00 2001 From: An Qi Date: Wed, 10 Jul 2024 19:55:07 +0800 Subject: [PATCH 056/138] build(dependency): add pemjax jar (#375) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将 pemajx 的 jar 包内置在 IGinX 仓库中,编译时触发 mvn install:install-file 将 dataSources 模块改名为 dataSource --- .github/actions/dbRunner/action.yml | 2 +- .github/workflows/unit-test.yml | 2 +- core/pom.xml | 11 ---- .../filesystem/pom.xml | 0 .../iginx/filesystem/FileSystemStorage.java | 0 ...FileSystemTaskExecuteFailureException.java | 0 .../exception/FilesystemException.java | 0 .../iginx/filesystem/exec/Executor.java | 0 .../filesystem/exec/FileSystemManager.java | 0 .../iginx/filesystem/exec/LocalExecutor.java | 0 .../iginx/filesystem/exec/RemoteExecutor.java | 0 .../filesystem/file/DefaultFileOperator.java | 0 .../iginx/filesystem/file/IFileOperator.java | 0 .../filesystem/file/entity/FileMeta.java | 0 .../FileSystemHistoryQueryRowStream.java | 0 .../entity/FileSystemQueryRowStream.java | 0 .../query/entity/FileSystemResultTable.java | 0 .../iginx/filesystem/query/entity/Record.java | 0 .../filesystem/server/FileSystemServer.java | 0 .../filesystem/server/FileSystemWorker.java | 0 .../iginx/filesystem/shared/Constant.java | 0 .../iginx/filesystem/shared/FileType.java | 0 .../iginx/filesystem/tools/FilePathUtils.java | 0 .../filesystem/tools/FilterTransformer.java | 0 .../filesystem/tools/LimitedSizeMap.java | 0 .../iginx/filesystem/tools/MemoryPool.java | 0 {dataSources => dataSource}/influxdb/pom.xml | 0 .../iginx/influxdb/InfluxDBStorage.java | 0 .../influxdb/exception/InfluxDBException.java | 0 .../InfluxDBTaskExecuteFailureException.java | 0 .../entity/InfluxDBHistoryQueryRowStream.java | 0 .../query/entity/InfluxDBQueryRowStream.java | 0 .../influxdb/query/entity/InfluxDBSchema.java | 0 .../influxdb/tools/DataTypeTransformer.java | 0 .../influxdb/tools/FilterTransformer.java | 0 .../influxdb/tools/SchemaTransformer.java | 0 .../iginx/influxdb/tools/TagFilterUtils.java | 0 .../iginx/influxdb/tools/TimeUtils.java | 0 {dataSources => dataSource}/iotdb12/pom.xml | 0 .../tsinghua/iginx/iotdb/IoTDBStorage.java | 0 .../iginx/iotdb/exception/IoTDBException.java | 0 .../IoTDBTaskExecuteFailureException.java | 0 .../query/entity/IoTDBQueryRowStream.java | 0 .../iotdb/tools/DataTypeTransformer.java | 0 .../iginx/iotdb/tools/DataViewWrapper.java | 0 .../iginx/iotdb/tools/FilterTransformer.java | 0 .../iginx/iotdb/tools/TagKVUtils.java | 0 {dataSources => dataSource}/mongodb/pom.xml | 0 .../iginx/mongodb/MongoDBStorage.java | 0 .../iginx/mongodb/dummy/DummyQuery.java | 0 .../iginx/mongodb/dummy/FilterUtils.java | 0 .../iginx/mongodb/dummy/FindRowStream.java | 0 .../iginx/mongodb/dummy/NameUtils.java | 0 .../iginx/mongodb/dummy/PathTree.java | 0 .../iginx/mongodb/dummy/QueryRowStream.java | 0 .../iginx/mongodb/dummy/QueryUtils.java | 0 .../iginx/mongodb/dummy/ResultColumn.java | 0 .../iginx/mongodb/dummy/ResultRow.java | 0 .../iginx/mongodb/dummy/ResultTable.java | 0 .../iginx/mongodb/dummy/SampleQuery.java | 0 .../iginx/mongodb/dummy/SchemaSample.java | 0 .../iginx/mongodb/dummy/TypeUtils.java | 0 .../iginx/mongodb/entity/ColumnQuery.java | 0 .../iginx/mongodb/entity/JoinQuery.java | 0 .../iginx/mongodb/entity/SourceTable.java | 0 .../iginx/mongodb/tools/FilterUtils.java | 0 .../iginx/mongodb/tools/NameUtils.java | 0 .../iginx/mongodb/tools/TypeUtils.java | 0 .../iginx/mongodb/dummy/TypeUtilsTest.java | 0 {dataSources => dataSource}/parquet/pom.xml | 0 .../iginx/parquet/ParquetStorage.java | 0 .../tsinghua/iginx/parquet/db/Database.java | 0 .../iginx/parquet/db/ImmutableDatabase.java | 0 .../iginx/parquet/db/lsm/OneTierDB.java | 0 .../iginx/parquet/db/lsm/api/ReadWriter.java | 0 .../iginx/parquet/db/lsm/api/TableMeta.java | 0 .../parquet/db/lsm/buffer/DataBuffer.java | 0 .../parquet/db/lsm/compact/Compactor.java | 0 .../parquet/db/lsm/table/DeletedTable.java | 0 .../db/lsm/table/DeletedTableMeta.java | 0 .../parquet/db/lsm/table/EmptyTable.java | 0 .../iginx/parquet/db/lsm/table/FileTable.java | 0 .../parquet/db/lsm/table/MemoryTable.java | 0 .../iginx/parquet/db/lsm/table/Table.java | 0 .../parquet/db/lsm/table/TableIndex.java | 0 .../parquet/db/lsm/table/TableStorage.java | 0 .../iginx/parquet/db/util/AreaSet.java | 0 .../parquet/db/util/SequenceGenerator.java | 0 .../db/util/iterator/AreaFilterScanner.java | 0 .../db/util/iterator/BatchPlaneScanner.java | 0 .../util/iterator/ColumnUnionRowScanner.java | 0 .../db/util/iterator/ConcatScanner.java | 0 .../db/util/iterator/EmptyScanner.java | 0 .../db/util/iterator/IteratorScanner.java | 0 .../db/util/iterator/RowUnionScanner.java | 0 .../parquet/db/util/iterator/Scanner.java | 0 .../parquet/db/util/iterator/SizeUtils.java | 0 .../tsinghua/iginx/parquet/exec/Executor.java | 0 .../iginx/parquet/exec/LocalExecutor.java | 0 .../iginx/parquet/exec/RemoteExecutor.java | 0 .../tsinghua/iginx/parquet/io/FileFormat.java | 0 .../tsinghua/iginx/parquet/io/FileIndex.java | 0 .../tsinghua/iginx/parquet/io/FileMeta.java | 0 .../tsinghua/iginx/parquet/io/FileReader.java | 0 .../tsinghua/iginx/parquet/io/FileWriter.java | 0 .../iginx/parquet/io/common/DataChunk.java | 0 .../iginx/parquet/io/common/DataChunks.java | 0 .../iginx/parquet/io/common/EmptyReader.java | 0 .../iginx/parquet/io/parquet/FilterUtils.java | 0 .../parquet/io/parquet/IGroupConverter.java | 0 .../parquet/io/parquet/IParquetReader.java | 0 .../parquet/io/parquet/IParquetWriter.java | 0 .../iginx/parquet/io/parquet/IRecord.java | 0 .../io/parquet/IRecordDematerializer.java | 0 .../io/parquet/IRecordMaterializer.java | 0 .../parquet/io/parquet/ProjectUtils.java | 0 .../iginx/parquet/manager/Manager.java | 0 .../parquet/manager/data/DataManager.java | 0 .../parquet/manager/data/DataViewWrapper.java | 0 .../manager/data/FilterRangeUtils.java | 0 .../parquet/manager/data/LongFormat.java | 0 .../parquet/manager/data/ObjectFormat.java | 0 .../manager/data/ParquetReadWriter.java | 0 .../parquet/manager/data/ProjectUtils.java | 0 .../manager/data/ScannerRowStream.java | 0 .../parquet/manager/data/SerializeUtils.java | 0 .../iginx/parquet/manager/data/SizeUtils.java | 0 .../parquet/manager/data/StringFormat.java | 0 .../manager/data/TombstoneStorage.java | 0 .../iginx/parquet/manager/dummy/Column.java | 0 .../parquet/manager/dummy/DummyManager.java | 0 .../parquet/manager/dummy/EmptyManager.java | 0 .../iginx/parquet/manager/dummy/Field.java | 0 .../iginx/parquet/manager/dummy/Loader.java | 0 .../manager/dummy/NewQueryRowStream.java | 0 .../iginx/parquet/manager/dummy/Storer.java | 0 .../iginx/parquet/manager/dummy/Table.java | 0 .../parquet/manager/utils/RangeUtils.java | 0 .../parquet/manager/utils/TagKVUtils.java | 0 .../parquet/server/FilterTransformer.java | 0 .../iginx/parquet/server/ParquetServer.java | 0 .../iginx/parquet/server/ParquetWorker.java | 0 .../iginx/parquet/util/CachePool.java | 0 .../iginx/parquet/util/Constants.java | 0 .../iginx/parquet/util/ParseUtils.java | 0 .../tsinghua/iginx/parquet/util/Shared.java | 0 .../iginx/parquet/util/StorageProperties.java | 0 .../exception/InvalidFieldNameException.java | 0 .../util/exception/IsClosedException.java | 0 .../util/exception/NotIntegrityException.java | 0 .../util/exception/SchemaException.java | 0 .../util/exception/StorageException.java | 0 .../exception/StorageRuntimeException.java | 0 .../util/exception/TimeoutException.java | 0 .../exception/TypeConflictedException.java | 0 .../exception/UnsupportedFilterException.java | 0 .../db/common/utils/SerializeUtilsTest.java | 0 .../iginx/parquet/io/ParquetFormatIOTest.java | 0 .../manager/data/FilterRangeUtilsTest.java | 0 {dataSources => dataSource}/pom.xml | 0 {dataSources => dataSource}/redis/pom.xml | 0 .../tsinghua/iginx/redis/RedisStorage.java | 0 .../tsinghua/iginx/redis/entity/Column.java | 0 .../redis/entity/RedisQueryRowStream.java | 0 .../tsinghua/iginx/redis/tools/DataCoder.java | 0 .../iginx/redis/tools/DataTransformer.java | 0 .../iginx/redis/tools/DataViewWrapper.java | 0 .../iginx/redis/tools/FilterUtils.java | 0 .../iginx/redis/tools/TagKVUtils.java | 0 .../relational/.gitignore | 0 .../relational/pom.xml | 0 .../iginx/relational/RelationalStorage.java | 0 .../transformer/IDataTypeTransformer.java | 0 .../transformer/JDBCDataTypeTransformer.java | 0 .../PostgreSQLDataTypeTransformer.java | 0 .../exception/RelationalException.java | 0 ...RelationalTaskExecuteFailureException.java | 0 .../meta/AbstractRelationalMeta.java | 0 .../iginx/relational/meta/JDBCMeta.java | 0 .../iginx/relational/meta/PostgreSQLMeta.java | 0 .../query/entity/RelationQueryRowStream.java | 0 .../iginx/relational/tools/ColumnField.java | 0 .../iginx/relational/tools/Constants.java | 0 .../relational/tools/FilterTransformer.java | 0 .../iginx/relational/tools/HashUtils.java | 0 .../relational/tools/RelationSchema.java | 0 .../iginx/relational/tools/TagKVUtils.java | 0 .../resources/mysql-meta-template.properties | 0 .../main/resources/oceanbase-meta.properties | 0 .../src/assembly/driver.xml | 0 dependency/pom.xml | 51 ++++++++++++++++++ .../src/main/resources/pemja-0.5-SNAPSHOT.jar | Bin 0 -> 20105 bytes pom.xml | 4 +- .../mysql/MySQLCapacityExpansionIT.java | 2 +- test/src/test/resources/testConfig.properties | 2 +- 195 files changed, 58 insertions(+), 16 deletions(-) rename {dataSources => dataSource}/filesystem/pom.xml (100%) rename {dataSources => dataSource}/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/FileSystemStorage.java (100%) rename {dataSources => dataSource}/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exception/FileSystemTaskExecuteFailureException.java (100%) rename {dataSources => dataSource}/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exception/FilesystemException.java (100%) rename {dataSources => dataSource}/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/Executor.java (100%) rename {dataSources => dataSource}/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java (100%) rename {dataSources => dataSource}/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java (100%) rename {dataSources => dataSource}/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/RemoteExecutor.java (100%) rename {dataSources => dataSource}/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/file/DefaultFileOperator.java (100%) rename {dataSources => dataSource}/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/file/IFileOperator.java (100%) rename {dataSources => dataSource}/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/file/entity/FileMeta.java (100%) rename {dataSources => dataSource}/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/FileSystemHistoryQueryRowStream.java (100%) rename {dataSources => dataSource}/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/FileSystemQueryRowStream.java (100%) rename {dataSources => dataSource}/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/FileSystemResultTable.java (100%) rename {dataSources => dataSource}/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/Record.java (100%) rename {dataSources => dataSource}/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/server/FileSystemServer.java (100%) rename {dataSources => dataSource}/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/server/FileSystemWorker.java (100%) rename {dataSources => dataSource}/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/shared/Constant.java (100%) rename {dataSources => dataSource}/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/shared/FileType.java (100%) rename {dataSources => dataSource}/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/FilePathUtils.java (100%) rename {dataSources => dataSource}/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/FilterTransformer.java (100%) rename {dataSources => dataSource}/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/LimitedSizeMap.java (100%) rename {dataSources => dataSource}/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/MemoryPool.java (100%) rename {dataSources => dataSource}/influxdb/pom.xml (100%) rename {dataSources => dataSource}/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java (100%) rename {dataSources => dataSource}/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/exception/InfluxDBException.java (100%) rename {dataSources => dataSource}/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/exception/InfluxDBTaskExecuteFailureException.java (100%) rename {dataSources => dataSource}/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/query/entity/InfluxDBHistoryQueryRowStream.java (100%) rename {dataSources => dataSource}/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/query/entity/InfluxDBQueryRowStream.java (100%) rename {dataSources => dataSource}/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/query/entity/InfluxDBSchema.java (100%) rename {dataSources => dataSource}/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/DataTypeTransformer.java (100%) rename {dataSources => dataSource}/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/FilterTransformer.java (100%) rename {dataSources => dataSource}/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/SchemaTransformer.java (100%) rename {dataSources => dataSource}/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/TagFilterUtils.java (100%) rename {dataSources => dataSource}/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/TimeUtils.java (100%) rename {dataSources => dataSource}/iotdb12/pom.xml (100%) rename {dataSources => dataSource}/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java (100%) rename {dataSources => dataSource}/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/exception/IoTDBException.java (100%) rename {dataSources => dataSource}/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/exception/IoTDBTaskExecuteFailureException.java (100%) rename {dataSources => dataSource}/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/query/entity/IoTDBQueryRowStream.java (100%) rename {dataSources => dataSource}/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/DataTypeTransformer.java (100%) rename {dataSources => dataSource}/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/DataViewWrapper.java (100%) rename {dataSources => dataSource}/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/FilterTransformer.java (100%) rename {dataSources => dataSource}/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/TagKVUtils.java (100%) rename {dataSources => dataSource}/mongodb/pom.xml (100%) rename {dataSources => dataSource}/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java (100%) rename {dataSources => dataSource}/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/DummyQuery.java (100%) rename {dataSources => dataSource}/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/FilterUtils.java (100%) rename {dataSources => dataSource}/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/FindRowStream.java (100%) rename {dataSources => dataSource}/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/NameUtils.java (100%) rename {dataSources => dataSource}/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/PathTree.java (100%) rename {dataSources => dataSource}/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/QueryRowStream.java (100%) rename {dataSources => dataSource}/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/QueryUtils.java (100%) rename {dataSources => dataSource}/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/ResultColumn.java (100%) rename {dataSources => dataSource}/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/ResultRow.java (100%) rename {dataSources => dataSource}/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/ResultTable.java (100%) rename {dataSources => dataSource}/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/SampleQuery.java (100%) rename {dataSources => dataSource}/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/SchemaSample.java (100%) rename {dataSources => dataSource}/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/TypeUtils.java (100%) rename {dataSources => dataSource}/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/entity/ColumnQuery.java (100%) rename {dataSources => dataSource}/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/entity/JoinQuery.java (100%) rename {dataSources => dataSource}/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/entity/SourceTable.java (100%) rename {dataSources => dataSource}/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/tools/FilterUtils.java (100%) rename {dataSources => dataSource}/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/tools/NameUtils.java (100%) rename {dataSources => dataSource}/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/tools/TypeUtils.java (100%) rename {dataSources => dataSource}/mongodb/src/test/java/cn/edu/tsinghua/iginx/mongodb/dummy/TypeUtilsTest.java (100%) rename {dataSources => dataSource}/parquet/pom.xml (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/ParquetStorage.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/Database.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/ImmutableDatabase.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/OneTierDB.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/api/ReadWriter.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/api/TableMeta.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/DataBuffer.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/compact/Compactor.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/DeletedTable.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/DeletedTableMeta.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/EmptyTable.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/FileTable.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/MemoryTable.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/Table.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/TableIndex.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/TableStorage.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/AreaSet.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/SequenceGenerator.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/AreaFilterScanner.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/BatchPlaneScanner.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/ColumnUnionRowScanner.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/ConcatScanner.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/EmptyScanner.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/IteratorScanner.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/RowUnionScanner.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/Scanner.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/SizeUtils.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/Executor.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileFormat.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileIndex.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileMeta.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileReader.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileWriter.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/DataChunk.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/DataChunks.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/EmptyReader.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/FilterUtils.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IGroupConverter.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IParquetReader.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IParquetWriter.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IRecord.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IRecordDematerializer.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IRecordMaterializer.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/ProjectUtils.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/Manager.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/DataManager.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/DataViewWrapper.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/FilterRangeUtils.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/LongFormat.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ObjectFormat.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ParquetReadWriter.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ProjectUtils.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ScannerRowStream.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/SerializeUtils.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/SizeUtils.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/StringFormat.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/TombstoneStorage.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Column.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/DummyManager.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/EmptyManager.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Field.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Loader.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/NewQueryRowStream.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Storer.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Table.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/utils/RangeUtils.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/utils/TagKVUtils.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/FilterTransformer.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetServer.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetWorker.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/CachePool.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/Constants.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/ParseUtils.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/Shared.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/StorageProperties.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/InvalidFieldNameException.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/IsClosedException.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/NotIntegrityException.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/SchemaException.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/StorageException.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/StorageRuntimeException.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/TimeoutException.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/TypeConflictedException.java (100%) rename {dataSources => dataSource}/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/UnsupportedFilterException.java (100%) rename {dataSources => dataSource}/parquet/src/test/java/cn/edu/tsinghua/iginx/parquet/db/common/utils/SerializeUtilsTest.java (100%) rename {dataSources => dataSource}/parquet/src/test/java/cn/edu/tsinghua/iginx/parquet/io/ParquetFormatIOTest.java (100%) rename {dataSources => dataSource}/parquet/src/test/java/cn/edu/tsinghua/iginx/parquet/manager/data/FilterRangeUtilsTest.java (100%) rename {dataSources => dataSource}/pom.xml (100%) rename {dataSources => dataSource}/redis/pom.xml (100%) rename {dataSources => dataSource}/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java (100%) rename {dataSources => dataSource}/redis/src/main/java/cn/edu/tsinghua/iginx/redis/entity/Column.java (100%) rename {dataSources => dataSource}/redis/src/main/java/cn/edu/tsinghua/iginx/redis/entity/RedisQueryRowStream.java (100%) rename {dataSources => dataSource}/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/DataCoder.java (100%) rename {dataSources => dataSource}/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/DataTransformer.java (100%) rename {dataSources => dataSource}/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/DataViewWrapper.java (100%) rename {dataSources => dataSource}/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/FilterUtils.java (100%) rename {dataSources => dataSource}/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/TagKVUtils.java (100%) rename {dataSources => dataSource}/relational/.gitignore (100%) rename {dataSources => dataSource}/relational/pom.xml (100%) rename {dataSources => dataSource}/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java (100%) rename {dataSources => dataSource}/relational/src/main/java/cn/edu/tsinghua/iginx/relational/datatype/transformer/IDataTypeTransformer.java (100%) rename {dataSources => dataSource}/relational/src/main/java/cn/edu/tsinghua/iginx/relational/datatype/transformer/JDBCDataTypeTransformer.java (100%) rename {dataSources => dataSource}/relational/src/main/java/cn/edu/tsinghua/iginx/relational/datatype/transformer/PostgreSQLDataTypeTransformer.java (100%) rename {dataSources => dataSource}/relational/src/main/java/cn/edu/tsinghua/iginx/relational/exception/RelationalException.java (100%) rename {dataSources => dataSource}/relational/src/main/java/cn/edu/tsinghua/iginx/relational/exception/RelationalTaskExecuteFailureException.java (100%) rename {dataSources => dataSource}/relational/src/main/java/cn/edu/tsinghua/iginx/relational/meta/AbstractRelationalMeta.java (100%) rename {dataSources => dataSource}/relational/src/main/java/cn/edu/tsinghua/iginx/relational/meta/JDBCMeta.java (100%) rename {dataSources => dataSource}/relational/src/main/java/cn/edu/tsinghua/iginx/relational/meta/PostgreSQLMeta.java (100%) rename {dataSources => dataSource}/relational/src/main/java/cn/edu/tsinghua/iginx/relational/query/entity/RelationQueryRowStream.java (100%) rename {dataSources => dataSource}/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/ColumnField.java (100%) rename {dataSources => dataSource}/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/Constants.java (100%) rename {dataSources => dataSource}/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/FilterTransformer.java (100%) rename {dataSources => dataSource}/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/HashUtils.java (100%) rename {dataSources => dataSource}/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/RelationSchema.java (100%) rename {dataSources => dataSource}/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/TagKVUtils.java (100%) rename {dataSources => dataSource}/relational/src/main/resources/mysql-meta-template.properties (100%) rename {dataSources => dataSource}/relational/src/main/resources/oceanbase-meta.properties (100%) rename {dataSources => dataSource}/src/assembly/driver.xml (100%) create mode 100644 dependency/pom.xml create mode 100644 dependency/src/main/resources/pemja-0.5-SNAPSHOT.jar diff --git a/.github/actions/dbRunner/action.yml b/.github/actions/dbRunner/action.yml index 9f2a4c72d2..2a57acb4c7 100644 --- a/.github/actions/dbRunner/action.yml +++ b/.github/actions/dbRunner/action.yml @@ -185,7 +185,7 @@ runs: working-directory: ${{ github.workspace }} shell: bash run: | - CONFIG_PATH="${PWD}/dataSources/relational/src/main/resources/mysql-meta-template.properties" + CONFIG_PATH="${PWD}/dataSource/relational/src/main/resources/mysql-meta-template.properties" if [ "$RUNNER_OS" == "Windows" ]; then CONFIG_PATH=$(cygpath -m $CONFIG_PATH) fi diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 2c12c12252..550b3e8702 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -38,4 +38,4 @@ jobs: - name: Test with Maven run: | - mvn clean package -pl core -am -P-format -q + mvn clean package -pl dependency -pl core -am -P-format -q diff --git a/core/pom.xml b/core/pom.xml index bc1b4e11fa..850741af55 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -194,17 +194,6 @@ - - - - true - always - - IGinX-Pemja - IGinX Pemja GitHub repository - https://iginx-thu.github.io/pemjax/maven-repo - - diff --git a/dataSources/filesystem/pom.xml b/dataSource/filesystem/pom.xml similarity index 100% rename from dataSources/filesystem/pom.xml rename to dataSource/filesystem/pom.xml diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/FileSystemStorage.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/FileSystemStorage.java similarity index 100% rename from dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/FileSystemStorage.java rename to dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/FileSystemStorage.java diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exception/FileSystemTaskExecuteFailureException.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exception/FileSystemTaskExecuteFailureException.java similarity index 100% rename from dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exception/FileSystemTaskExecuteFailureException.java rename to dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exception/FileSystemTaskExecuteFailureException.java diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exception/FilesystemException.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exception/FilesystemException.java similarity index 100% rename from dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exception/FilesystemException.java rename to dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exception/FilesystemException.java diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/Executor.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/Executor.java similarity index 100% rename from dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/Executor.java rename to dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/Executor.java diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java similarity index 100% rename from dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java rename to dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java similarity index 100% rename from dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java rename to dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/RemoteExecutor.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/RemoteExecutor.java similarity index 100% rename from dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/RemoteExecutor.java rename to dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/RemoteExecutor.java diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/file/DefaultFileOperator.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/file/DefaultFileOperator.java similarity index 100% rename from dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/file/DefaultFileOperator.java rename to dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/file/DefaultFileOperator.java diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/file/IFileOperator.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/file/IFileOperator.java similarity index 100% rename from dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/file/IFileOperator.java rename to dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/file/IFileOperator.java diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/file/entity/FileMeta.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/file/entity/FileMeta.java similarity index 100% rename from dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/file/entity/FileMeta.java rename to dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/file/entity/FileMeta.java diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/FileSystemHistoryQueryRowStream.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/FileSystemHistoryQueryRowStream.java similarity index 100% rename from dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/FileSystemHistoryQueryRowStream.java rename to dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/FileSystemHistoryQueryRowStream.java diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/FileSystemQueryRowStream.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/FileSystemQueryRowStream.java similarity index 100% rename from dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/FileSystemQueryRowStream.java rename to dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/FileSystemQueryRowStream.java diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/FileSystemResultTable.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/FileSystemResultTable.java similarity index 100% rename from dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/FileSystemResultTable.java rename to dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/FileSystemResultTable.java diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/Record.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/Record.java similarity index 100% rename from dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/Record.java rename to dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/query/entity/Record.java diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/server/FileSystemServer.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/server/FileSystemServer.java similarity index 100% rename from dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/server/FileSystemServer.java rename to dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/server/FileSystemServer.java diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/server/FileSystemWorker.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/server/FileSystemWorker.java similarity index 100% rename from dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/server/FileSystemWorker.java rename to dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/server/FileSystemWorker.java diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/shared/Constant.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/shared/Constant.java similarity index 100% rename from dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/shared/Constant.java rename to dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/shared/Constant.java diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/shared/FileType.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/shared/FileType.java similarity index 100% rename from dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/shared/FileType.java rename to dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/shared/FileType.java diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/FilePathUtils.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/FilePathUtils.java similarity index 100% rename from dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/FilePathUtils.java rename to dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/FilePathUtils.java diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/FilterTransformer.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/FilterTransformer.java similarity index 100% rename from dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/FilterTransformer.java rename to dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/FilterTransformer.java diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/LimitedSizeMap.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/LimitedSizeMap.java similarity index 100% rename from dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/LimitedSizeMap.java rename to dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/LimitedSizeMap.java diff --git a/dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/MemoryPool.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/MemoryPool.java similarity index 100% rename from dataSources/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/MemoryPool.java rename to dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/MemoryPool.java diff --git a/dataSources/influxdb/pom.xml b/dataSource/influxdb/pom.xml similarity index 100% rename from dataSources/influxdb/pom.xml rename to dataSource/influxdb/pom.xml diff --git a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java b/dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java similarity index 100% rename from dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java rename to dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java diff --git a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/exception/InfluxDBException.java b/dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/exception/InfluxDBException.java similarity index 100% rename from dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/exception/InfluxDBException.java rename to dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/exception/InfluxDBException.java diff --git a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/exception/InfluxDBTaskExecuteFailureException.java b/dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/exception/InfluxDBTaskExecuteFailureException.java similarity index 100% rename from dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/exception/InfluxDBTaskExecuteFailureException.java rename to dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/exception/InfluxDBTaskExecuteFailureException.java diff --git a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/query/entity/InfluxDBHistoryQueryRowStream.java b/dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/query/entity/InfluxDBHistoryQueryRowStream.java similarity index 100% rename from dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/query/entity/InfluxDBHistoryQueryRowStream.java rename to dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/query/entity/InfluxDBHistoryQueryRowStream.java diff --git a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/query/entity/InfluxDBQueryRowStream.java b/dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/query/entity/InfluxDBQueryRowStream.java similarity index 100% rename from dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/query/entity/InfluxDBQueryRowStream.java rename to dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/query/entity/InfluxDBQueryRowStream.java diff --git a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/query/entity/InfluxDBSchema.java b/dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/query/entity/InfluxDBSchema.java similarity index 100% rename from dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/query/entity/InfluxDBSchema.java rename to dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/query/entity/InfluxDBSchema.java diff --git a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/DataTypeTransformer.java b/dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/DataTypeTransformer.java similarity index 100% rename from dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/DataTypeTransformer.java rename to dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/DataTypeTransformer.java diff --git a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/FilterTransformer.java b/dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/FilterTransformer.java similarity index 100% rename from dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/FilterTransformer.java rename to dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/FilterTransformer.java diff --git a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/SchemaTransformer.java b/dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/SchemaTransformer.java similarity index 100% rename from dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/SchemaTransformer.java rename to dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/SchemaTransformer.java diff --git a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/TagFilterUtils.java b/dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/TagFilterUtils.java similarity index 100% rename from dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/TagFilterUtils.java rename to dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/TagFilterUtils.java diff --git a/dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/TimeUtils.java b/dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/TimeUtils.java similarity index 100% rename from dataSources/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/TimeUtils.java rename to dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/tools/TimeUtils.java diff --git a/dataSources/iotdb12/pom.xml b/dataSource/iotdb12/pom.xml similarity index 100% rename from dataSources/iotdb12/pom.xml rename to dataSource/iotdb12/pom.xml diff --git a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java b/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java similarity index 100% rename from dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java rename to dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java diff --git a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/exception/IoTDBException.java b/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/exception/IoTDBException.java similarity index 100% rename from dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/exception/IoTDBException.java rename to dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/exception/IoTDBException.java diff --git a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/exception/IoTDBTaskExecuteFailureException.java b/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/exception/IoTDBTaskExecuteFailureException.java similarity index 100% rename from dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/exception/IoTDBTaskExecuteFailureException.java rename to dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/exception/IoTDBTaskExecuteFailureException.java diff --git a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/query/entity/IoTDBQueryRowStream.java b/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/query/entity/IoTDBQueryRowStream.java similarity index 100% rename from dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/query/entity/IoTDBQueryRowStream.java rename to dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/query/entity/IoTDBQueryRowStream.java diff --git a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/DataTypeTransformer.java b/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/DataTypeTransformer.java similarity index 100% rename from dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/DataTypeTransformer.java rename to dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/DataTypeTransformer.java diff --git a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/DataViewWrapper.java b/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/DataViewWrapper.java similarity index 100% rename from dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/DataViewWrapper.java rename to dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/DataViewWrapper.java diff --git a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/FilterTransformer.java b/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/FilterTransformer.java similarity index 100% rename from dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/FilterTransformer.java rename to dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/FilterTransformer.java diff --git a/dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/TagKVUtils.java b/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/TagKVUtils.java similarity index 100% rename from dataSources/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/TagKVUtils.java rename to dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/tools/TagKVUtils.java diff --git a/dataSources/mongodb/pom.xml b/dataSource/mongodb/pom.xml similarity index 100% rename from dataSources/mongodb/pom.xml rename to dataSource/mongodb/pom.xml diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java b/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java similarity index 100% rename from dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java rename to dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/DummyQuery.java b/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/DummyQuery.java similarity index 100% rename from dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/DummyQuery.java rename to dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/DummyQuery.java diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/FilterUtils.java b/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/FilterUtils.java similarity index 100% rename from dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/FilterUtils.java rename to dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/FilterUtils.java diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/FindRowStream.java b/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/FindRowStream.java similarity index 100% rename from dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/FindRowStream.java rename to dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/FindRowStream.java diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/NameUtils.java b/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/NameUtils.java similarity index 100% rename from dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/NameUtils.java rename to dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/NameUtils.java diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/PathTree.java b/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/PathTree.java similarity index 100% rename from dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/PathTree.java rename to dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/PathTree.java diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/QueryRowStream.java b/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/QueryRowStream.java similarity index 100% rename from dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/QueryRowStream.java rename to dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/QueryRowStream.java diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/QueryUtils.java b/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/QueryUtils.java similarity index 100% rename from dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/QueryUtils.java rename to dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/QueryUtils.java diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/ResultColumn.java b/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/ResultColumn.java similarity index 100% rename from dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/ResultColumn.java rename to dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/ResultColumn.java diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/ResultRow.java b/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/ResultRow.java similarity index 100% rename from dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/ResultRow.java rename to dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/ResultRow.java diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/ResultTable.java b/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/ResultTable.java similarity index 100% rename from dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/ResultTable.java rename to dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/ResultTable.java diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/SampleQuery.java b/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/SampleQuery.java similarity index 100% rename from dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/SampleQuery.java rename to dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/SampleQuery.java diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/SchemaSample.java b/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/SchemaSample.java similarity index 100% rename from dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/SchemaSample.java rename to dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/SchemaSample.java diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/TypeUtils.java b/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/TypeUtils.java similarity index 100% rename from dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/TypeUtils.java rename to dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/dummy/TypeUtils.java diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/entity/ColumnQuery.java b/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/entity/ColumnQuery.java similarity index 100% rename from dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/entity/ColumnQuery.java rename to dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/entity/ColumnQuery.java diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/entity/JoinQuery.java b/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/entity/JoinQuery.java similarity index 100% rename from dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/entity/JoinQuery.java rename to dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/entity/JoinQuery.java diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/entity/SourceTable.java b/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/entity/SourceTable.java similarity index 100% rename from dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/entity/SourceTable.java rename to dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/entity/SourceTable.java diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/tools/FilterUtils.java b/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/tools/FilterUtils.java similarity index 100% rename from dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/tools/FilterUtils.java rename to dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/tools/FilterUtils.java diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/tools/NameUtils.java b/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/tools/NameUtils.java similarity index 100% rename from dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/tools/NameUtils.java rename to dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/tools/NameUtils.java diff --git a/dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/tools/TypeUtils.java b/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/tools/TypeUtils.java similarity index 100% rename from dataSources/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/tools/TypeUtils.java rename to dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/tools/TypeUtils.java diff --git a/dataSources/mongodb/src/test/java/cn/edu/tsinghua/iginx/mongodb/dummy/TypeUtilsTest.java b/dataSource/mongodb/src/test/java/cn/edu/tsinghua/iginx/mongodb/dummy/TypeUtilsTest.java similarity index 100% rename from dataSources/mongodb/src/test/java/cn/edu/tsinghua/iginx/mongodb/dummy/TypeUtilsTest.java rename to dataSource/mongodb/src/test/java/cn/edu/tsinghua/iginx/mongodb/dummy/TypeUtilsTest.java diff --git a/dataSources/parquet/pom.xml b/dataSource/parquet/pom.xml similarity index 100% rename from dataSources/parquet/pom.xml rename to dataSource/parquet/pom.xml diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/ParquetStorage.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/ParquetStorage.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/ParquetStorage.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/ParquetStorage.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/Database.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/Database.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/Database.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/Database.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/ImmutableDatabase.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/ImmutableDatabase.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/ImmutableDatabase.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/ImmutableDatabase.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/OneTierDB.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/OneTierDB.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/OneTierDB.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/OneTierDB.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/api/ReadWriter.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/api/ReadWriter.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/api/ReadWriter.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/api/ReadWriter.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/api/TableMeta.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/api/TableMeta.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/api/TableMeta.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/api/TableMeta.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/DataBuffer.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/DataBuffer.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/DataBuffer.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/DataBuffer.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/compact/Compactor.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/compact/Compactor.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/compact/Compactor.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/compact/Compactor.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/DeletedTable.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/DeletedTable.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/DeletedTable.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/DeletedTable.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/DeletedTableMeta.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/DeletedTableMeta.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/DeletedTableMeta.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/DeletedTableMeta.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/EmptyTable.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/EmptyTable.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/EmptyTable.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/EmptyTable.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/FileTable.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/FileTable.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/FileTable.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/FileTable.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/MemoryTable.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/MemoryTable.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/MemoryTable.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/MemoryTable.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/Table.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/Table.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/Table.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/Table.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/TableIndex.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/TableIndex.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/TableIndex.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/TableIndex.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/TableStorage.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/TableStorage.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/TableStorage.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/TableStorage.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/AreaSet.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/AreaSet.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/AreaSet.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/AreaSet.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/SequenceGenerator.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/SequenceGenerator.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/SequenceGenerator.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/SequenceGenerator.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/AreaFilterScanner.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/AreaFilterScanner.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/AreaFilterScanner.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/AreaFilterScanner.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/BatchPlaneScanner.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/BatchPlaneScanner.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/BatchPlaneScanner.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/BatchPlaneScanner.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/ColumnUnionRowScanner.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/ColumnUnionRowScanner.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/ColumnUnionRowScanner.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/ColumnUnionRowScanner.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/ConcatScanner.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/ConcatScanner.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/ConcatScanner.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/ConcatScanner.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/EmptyScanner.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/EmptyScanner.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/EmptyScanner.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/EmptyScanner.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/IteratorScanner.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/IteratorScanner.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/IteratorScanner.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/IteratorScanner.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/RowUnionScanner.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/RowUnionScanner.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/RowUnionScanner.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/RowUnionScanner.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/Scanner.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/Scanner.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/Scanner.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/Scanner.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/SizeUtils.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/SizeUtils.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/SizeUtils.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/SizeUtils.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/Executor.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/Executor.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/Executor.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/Executor.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileFormat.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileFormat.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileFormat.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileFormat.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileIndex.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileIndex.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileIndex.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileIndex.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileMeta.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileMeta.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileMeta.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileMeta.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileReader.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileReader.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileReader.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileReader.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileWriter.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileWriter.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileWriter.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileWriter.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/DataChunk.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/DataChunk.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/DataChunk.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/DataChunk.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/DataChunks.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/DataChunks.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/DataChunks.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/DataChunks.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/EmptyReader.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/EmptyReader.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/EmptyReader.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/EmptyReader.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/FilterUtils.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/FilterUtils.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/FilterUtils.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/FilterUtils.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IGroupConverter.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IGroupConverter.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IGroupConverter.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IGroupConverter.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IParquetReader.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IParquetReader.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IParquetReader.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IParquetReader.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IParquetWriter.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IParquetWriter.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IParquetWriter.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IParquetWriter.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IRecord.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IRecord.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IRecord.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IRecord.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IRecordDematerializer.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IRecordDematerializer.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IRecordDematerializer.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IRecordDematerializer.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IRecordMaterializer.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IRecordMaterializer.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IRecordMaterializer.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IRecordMaterializer.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/ProjectUtils.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/ProjectUtils.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/ProjectUtils.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/ProjectUtils.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/Manager.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/Manager.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/Manager.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/Manager.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/DataManager.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/DataManager.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/DataManager.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/DataManager.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/DataViewWrapper.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/DataViewWrapper.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/DataViewWrapper.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/DataViewWrapper.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/FilterRangeUtils.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/FilterRangeUtils.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/FilterRangeUtils.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/FilterRangeUtils.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/LongFormat.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/LongFormat.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/LongFormat.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/LongFormat.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ObjectFormat.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ObjectFormat.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ObjectFormat.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ObjectFormat.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ParquetReadWriter.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ParquetReadWriter.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ParquetReadWriter.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ParquetReadWriter.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ProjectUtils.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ProjectUtils.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ProjectUtils.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ProjectUtils.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ScannerRowStream.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ScannerRowStream.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ScannerRowStream.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ScannerRowStream.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/SerializeUtils.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/SerializeUtils.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/SerializeUtils.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/SerializeUtils.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/SizeUtils.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/SizeUtils.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/SizeUtils.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/SizeUtils.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/StringFormat.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/StringFormat.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/StringFormat.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/StringFormat.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/TombstoneStorage.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/TombstoneStorage.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/TombstoneStorage.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/TombstoneStorage.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Column.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Column.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Column.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Column.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/DummyManager.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/DummyManager.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/DummyManager.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/DummyManager.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/EmptyManager.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/EmptyManager.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/EmptyManager.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/EmptyManager.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Field.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Field.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Field.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Field.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Loader.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Loader.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Loader.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Loader.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/NewQueryRowStream.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/NewQueryRowStream.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/NewQueryRowStream.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/NewQueryRowStream.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Storer.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Storer.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Storer.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Storer.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Table.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Table.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Table.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/Table.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/utils/RangeUtils.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/utils/RangeUtils.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/utils/RangeUtils.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/utils/RangeUtils.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/utils/TagKVUtils.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/utils/TagKVUtils.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/utils/TagKVUtils.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/utils/TagKVUtils.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/FilterTransformer.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/FilterTransformer.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/FilterTransformer.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/FilterTransformer.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetServer.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetServer.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetServer.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetServer.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetWorker.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetWorker.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetWorker.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetWorker.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/CachePool.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/CachePool.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/CachePool.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/CachePool.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/Constants.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/Constants.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/Constants.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/Constants.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/ParseUtils.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/ParseUtils.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/ParseUtils.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/ParseUtils.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/Shared.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/Shared.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/Shared.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/Shared.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/StorageProperties.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/StorageProperties.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/StorageProperties.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/StorageProperties.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/InvalidFieldNameException.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/InvalidFieldNameException.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/InvalidFieldNameException.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/InvalidFieldNameException.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/IsClosedException.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/IsClosedException.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/IsClosedException.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/IsClosedException.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/NotIntegrityException.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/NotIntegrityException.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/NotIntegrityException.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/NotIntegrityException.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/SchemaException.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/SchemaException.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/SchemaException.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/SchemaException.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/StorageException.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/StorageException.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/StorageException.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/StorageException.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/StorageRuntimeException.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/StorageRuntimeException.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/StorageRuntimeException.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/StorageRuntimeException.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/TimeoutException.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/TimeoutException.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/TimeoutException.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/TimeoutException.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/TypeConflictedException.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/TypeConflictedException.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/TypeConflictedException.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/TypeConflictedException.java diff --git a/dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/UnsupportedFilterException.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/UnsupportedFilterException.java similarity index 100% rename from dataSources/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/UnsupportedFilterException.java rename to dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/UnsupportedFilterException.java diff --git a/dataSources/parquet/src/test/java/cn/edu/tsinghua/iginx/parquet/db/common/utils/SerializeUtilsTest.java b/dataSource/parquet/src/test/java/cn/edu/tsinghua/iginx/parquet/db/common/utils/SerializeUtilsTest.java similarity index 100% rename from dataSources/parquet/src/test/java/cn/edu/tsinghua/iginx/parquet/db/common/utils/SerializeUtilsTest.java rename to dataSource/parquet/src/test/java/cn/edu/tsinghua/iginx/parquet/db/common/utils/SerializeUtilsTest.java diff --git a/dataSources/parquet/src/test/java/cn/edu/tsinghua/iginx/parquet/io/ParquetFormatIOTest.java b/dataSource/parquet/src/test/java/cn/edu/tsinghua/iginx/parquet/io/ParquetFormatIOTest.java similarity index 100% rename from dataSources/parquet/src/test/java/cn/edu/tsinghua/iginx/parquet/io/ParquetFormatIOTest.java rename to dataSource/parquet/src/test/java/cn/edu/tsinghua/iginx/parquet/io/ParquetFormatIOTest.java diff --git a/dataSources/parquet/src/test/java/cn/edu/tsinghua/iginx/parquet/manager/data/FilterRangeUtilsTest.java b/dataSource/parquet/src/test/java/cn/edu/tsinghua/iginx/parquet/manager/data/FilterRangeUtilsTest.java similarity index 100% rename from dataSources/parquet/src/test/java/cn/edu/tsinghua/iginx/parquet/manager/data/FilterRangeUtilsTest.java rename to dataSource/parquet/src/test/java/cn/edu/tsinghua/iginx/parquet/manager/data/FilterRangeUtilsTest.java diff --git a/dataSources/pom.xml b/dataSource/pom.xml similarity index 100% rename from dataSources/pom.xml rename to dataSource/pom.xml diff --git a/dataSources/redis/pom.xml b/dataSource/redis/pom.xml similarity index 100% rename from dataSources/redis/pom.xml rename to dataSource/redis/pom.xml diff --git a/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java b/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java similarity index 100% rename from dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java rename to dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java diff --git a/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/entity/Column.java b/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/entity/Column.java similarity index 100% rename from dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/entity/Column.java rename to dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/entity/Column.java diff --git a/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/entity/RedisQueryRowStream.java b/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/entity/RedisQueryRowStream.java similarity index 100% rename from dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/entity/RedisQueryRowStream.java rename to dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/entity/RedisQueryRowStream.java diff --git a/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/DataCoder.java b/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/DataCoder.java similarity index 100% rename from dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/DataCoder.java rename to dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/DataCoder.java diff --git a/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/DataTransformer.java b/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/DataTransformer.java similarity index 100% rename from dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/DataTransformer.java rename to dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/DataTransformer.java diff --git a/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/DataViewWrapper.java b/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/DataViewWrapper.java similarity index 100% rename from dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/DataViewWrapper.java rename to dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/DataViewWrapper.java diff --git a/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/FilterUtils.java b/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/FilterUtils.java similarity index 100% rename from dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/FilterUtils.java rename to dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/FilterUtils.java diff --git a/dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/TagKVUtils.java b/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/TagKVUtils.java similarity index 100% rename from dataSources/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/TagKVUtils.java rename to dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/tools/TagKVUtils.java diff --git a/dataSources/relational/.gitignore b/dataSource/relational/.gitignore similarity index 100% rename from dataSources/relational/.gitignore rename to dataSource/relational/.gitignore diff --git a/dataSources/relational/pom.xml b/dataSource/relational/pom.xml similarity index 100% rename from dataSources/relational/pom.xml rename to dataSource/relational/pom.xml diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java similarity index 100% rename from dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java rename to dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/datatype/transformer/IDataTypeTransformer.java b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/datatype/transformer/IDataTypeTransformer.java similarity index 100% rename from dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/datatype/transformer/IDataTypeTransformer.java rename to dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/datatype/transformer/IDataTypeTransformer.java diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/datatype/transformer/JDBCDataTypeTransformer.java b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/datatype/transformer/JDBCDataTypeTransformer.java similarity index 100% rename from dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/datatype/transformer/JDBCDataTypeTransformer.java rename to dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/datatype/transformer/JDBCDataTypeTransformer.java diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/datatype/transformer/PostgreSQLDataTypeTransformer.java b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/datatype/transformer/PostgreSQLDataTypeTransformer.java similarity index 100% rename from dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/datatype/transformer/PostgreSQLDataTypeTransformer.java rename to dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/datatype/transformer/PostgreSQLDataTypeTransformer.java diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/exception/RelationalException.java b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/exception/RelationalException.java similarity index 100% rename from dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/exception/RelationalException.java rename to dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/exception/RelationalException.java diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/exception/RelationalTaskExecuteFailureException.java b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/exception/RelationalTaskExecuteFailureException.java similarity index 100% rename from dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/exception/RelationalTaskExecuteFailureException.java rename to dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/exception/RelationalTaskExecuteFailureException.java diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/meta/AbstractRelationalMeta.java b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/meta/AbstractRelationalMeta.java similarity index 100% rename from dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/meta/AbstractRelationalMeta.java rename to dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/meta/AbstractRelationalMeta.java diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/meta/JDBCMeta.java b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/meta/JDBCMeta.java similarity index 100% rename from dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/meta/JDBCMeta.java rename to dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/meta/JDBCMeta.java diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/meta/PostgreSQLMeta.java b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/meta/PostgreSQLMeta.java similarity index 100% rename from dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/meta/PostgreSQLMeta.java rename to dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/meta/PostgreSQLMeta.java diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/query/entity/RelationQueryRowStream.java b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/query/entity/RelationQueryRowStream.java similarity index 100% rename from dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/query/entity/RelationQueryRowStream.java rename to dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/query/entity/RelationQueryRowStream.java diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/ColumnField.java b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/ColumnField.java similarity index 100% rename from dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/ColumnField.java rename to dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/ColumnField.java diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/Constants.java b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/Constants.java similarity index 100% rename from dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/Constants.java rename to dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/Constants.java diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/FilterTransformer.java b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/FilterTransformer.java similarity index 100% rename from dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/FilterTransformer.java rename to dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/FilterTransformer.java diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/HashUtils.java b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/HashUtils.java similarity index 100% rename from dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/HashUtils.java rename to dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/HashUtils.java diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/RelationSchema.java b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/RelationSchema.java similarity index 100% rename from dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/RelationSchema.java rename to dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/RelationSchema.java diff --git a/dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/TagKVUtils.java b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/TagKVUtils.java similarity index 100% rename from dataSources/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/TagKVUtils.java rename to dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/tools/TagKVUtils.java diff --git a/dataSources/relational/src/main/resources/mysql-meta-template.properties b/dataSource/relational/src/main/resources/mysql-meta-template.properties similarity index 100% rename from dataSources/relational/src/main/resources/mysql-meta-template.properties rename to dataSource/relational/src/main/resources/mysql-meta-template.properties diff --git a/dataSources/relational/src/main/resources/oceanbase-meta.properties b/dataSource/relational/src/main/resources/oceanbase-meta.properties similarity index 100% rename from dataSources/relational/src/main/resources/oceanbase-meta.properties rename to dataSource/relational/src/main/resources/oceanbase-meta.properties diff --git a/dataSources/src/assembly/driver.xml b/dataSource/src/assembly/driver.xml similarity index 100% rename from dataSources/src/assembly/driver.xml rename to dataSource/src/assembly/driver.xml diff --git a/dependency/pom.xml b/dependency/pom.xml new file mode 100644 index 0000000000..11c8c2706b --- /dev/null +++ b/dependency/pom.xml @@ -0,0 +1,51 @@ + + + 4.0.0 + + cn.edu.tsinghua + iginx + ${revision} + + + iginx-dependency + pom + IGinX Dependency + + + 8 + 8 + UTF-8 + + + + + install-jars + + true + + + + + org.apache.maven.plugins + maven-install-plugin + 3.1.2 + + + install-pemjax + + install-file + + generate-sources + + src/main/resources/pemja-0.5-SNAPSHOT.jar + + + + + + + + + + diff --git a/dependency/src/main/resources/pemja-0.5-SNAPSHOT.jar b/dependency/src/main/resources/pemja-0.5-SNAPSHOT.jar new file mode 100644 index 0000000000000000000000000000000000000000..fa5c6734468bf85c1cfe56fd31d0d77dbb00d5cb GIT binary patch literal 20105 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�yJ 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 s^Fh@Ra_t7HaS>pS8@~ literal 0 HcmV?d00001 diff --git a/pom.xml b/pom.xml index 70ff6663d0..456054ee2c 100644 --- a/pom.xml +++ b/pom.xml @@ -10,6 +10,8 @@ IGinX + + dependency shared thrift session @@ -18,7 +20,7 @@ antlr core optimizer - dataSources + dataSource example test diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mysql/MySQLCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mysql/MySQLCapacityExpansionIT.java index 3112e99e9e..4e04b6f86f 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mysql/MySQLCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mysql/MySQLCapacityExpansionIT.java @@ -35,7 +35,7 @@ public MySQLCapacityExpansionIT() { super( StorageEngineType.relational, "engine:mysql, username:root," - + "meta_properties_path:dataSources/relational/src/main/resources/mysql-meta-template.properties", + + "meta_properties_path:dataSource/relational/src/main/resources/mysql-meta-template.properties", new MySQLHistoryDataGenerator()); ConfLoader conf = new ConfLoader(Controller.CONFIG_FILE); DBConf dbConf = conf.loadDBConf(conf.getStorageType()); diff --git a/test/src/test/resources/testConfig.properties b/test/src/test/resources/testConfig.properties index b6ac7558ae..33719ca3e8 100644 --- a/test/src/test/resources/testConfig.properties +++ b/test/src/test/resources/testConfig.properties @@ -33,7 +33,7 @@ PostgreSQL_mock=127.0.0.1#5432#relational#engine=postgresql#username=postgres#pa MongoDB_mock=127.0.0.1#27017#MongoDB#has_data=false Redis_mock=127.0.0.1#6379#Redis#has_data=false#is_read_only=false#timeout=5000 FileSystem_mock=127.0.0.1#6667#FileSystem#dir=test/iginx_mn#dummy_dir=/path/to/your/data#iginx_port=6888#chunk_size_in_bytes=1048576#memory_pool_size=100#has_data=false#is_read_only=false -MySQL_mock=127.0.0.1#3306#relational#engine=mysql#has_data=false#username=root#meta_properties_path=../dataSources/relational/src/main/resources/mysql-meta-template.properties +MySQL_mock=127.0.0.1#3306#relational#engine=mysql#has_data=false#username=root#meta_properties_path=../dataSource/relational/src/main/resources/mysql-meta-template.properties # class name for each DB IoTDB12_class=cn.edu.tsinghua.iginx.iotdb.IoTDBStorage From bf83675da17b52dcb32c19ceedb01b48f6162c17 Mon Sep 17 00:00:00 2001 From: An Qi Date: Thu, 11 Jul 2024 14:34:56 +0800 Subject: [PATCH 057/138] fix(test): correcting logic bug in `testCancelSession` design (#377) --- .../tsinghua/iginx/integration/func/session/NewSessionIT.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/NewSessionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/NewSessionIT.java index e725b88827..37ad705d16 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/NewSessionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/session/NewSessionIT.java @@ -394,8 +394,8 @@ public void testCancelSession() { List existsSessionIDs = conn.executeSql("show sessionid;").getSessionIDs(); - if (!new HashSet<>(existsSessionIDs).equals(new HashSet<>(sessionIDs))) { - LOGGER.error("server session_id_list does not equal to active_session_id_list."); + if (!existsSessionIDs.containsAll(sessionIDs)) { + LOGGER.error("server session_id_list doesn't contain all session IDs."); fail(); } From 7e47c9b67697cd5e3915d4ebcc9467fe0b94a734 Mon Sep 17 00:00:00 2001 From: An Qi Date: Fri, 12 Jul 2024 09:23:36 +0800 Subject: [PATCH 058/138] fix(redis): clear data timeout (#374) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 更快的 clear data 实现:使用 flushDB 实现 clear data 操作,不逐条删除 将默认超时时间从 5s 改为 10s 重构异常与日志打印 --- conf/config.properties | 2 +- .../tsinghua/iginx/redis/RedisStorage.java | 154 +++++++----------- 2 files changed, 61 insertions(+), 95 deletions(-) diff --git a/conf/config.properties b/conf/config.properties index 892b496f93..fc185977aa 100644 --- a/conf/config.properties +++ b/conf/config.properties @@ -23,7 +23,7 @@ storageEngineList=127.0.0.1#6667#iotdb12#username=root#password=root#sessionPool #storageEngineList=127.0.0.1#6667#parquet#dir=/path/to/your/parquet#dummy_dir=/path/to/your/data#iginx_port=6888#has_data=false#is_read_only=false#thrift_timeout=30000#thrift_pool_max_size=100#thrift_pool_min_evictable_idle_time_millis=600000#write.buffer.size=104857600#write.batch.size=1048576#compact.permits=16#cache.capacity=1073741824#parquet.block.size=134217728#parquet.page.size=8192#parquet.compression=SNAPPY #storageEngineList=127.0.0.1#27017#mongodb#has_data=false#schema.sample.size=1000#dummy.sample.size=0 #storageEngineList=127.0.0.1#6667#filesystem#dir=/path/to/your/filesystem#dummy_dir=/path/to/your/data#iginx_port=6888#chunk_size_in_bytes=1048576#memory_pool_size=100#has_data=false#is_read_only=false#thrift_timeout=5000#thrift_pool_max_size=100#thrift_pool_min_evictable_idle_time_millis=600000 -#storageEngineList=127.0.0.1#6379#redis#has_data=false#is_read_only=false#timeout=5000#data_db=1#dummy_db=0 +#storageEngineList=127.0.0.1#6379#redis#has_data=false#is_read_only=false#timeout=10000#data_db=1#dummy_db=0 # UDF定义文件夹存储路径(相对或绝对),文件夹内的文件需要按以下格式进行编写 # %defaultUDFDir% diff --git a/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java b/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java index b49c280ea9..b0928cd656 100644 --- a/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java +++ b/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java @@ -82,7 +82,7 @@ public class RedisStorage implements IStorage { private static final String DATA_PASSWORD = "dummy_db"; - private static final int DEFAULT_TIMEOUT = 5000; + private static final int DEFAULT_TIMEOUT = 10000; private static final int DEFAULT_DATA_DB = 1; @@ -135,14 +135,8 @@ public boolean isSupportProjectWithSelect() { public TaskExecuteResult executeProjectWithSelect( Project project, Select select, DataArea dataArea) { String storageUnit = dataArea.getStorageUnit(); - List queryPaths; - try { - queryPaths = determinePathList(storageUnit, project.getPatterns(), project.getTagFilter()); - } catch (PhysicalException e) { - LOGGER.error("encounter error when delete path: ", e); - return new TaskExecuteResult( - new PhysicalTaskExecuteFailureException("execute delete path task in redis failure", e)); - } + List queryPaths = + determinePathList(storageUnit, project.getPatterns(), project.getTagFilter()); Filter filter = select.getFilter(); List> keyRanges = FilterUtils.keyRangesFrom(filter); @@ -192,9 +186,6 @@ public TaskExecuteResult executeProjectWithSelect( columns.add(column); } } - } catch (Exception e) { - return new TaskExecuteResult( - new PhysicalTaskExecuteFailureException("execute query path task in redis failure", e)); } return new TaskExecuteResult(new RedisQueryRowStream(columns, filter), null); @@ -249,10 +240,6 @@ public TaskExecuteResult executeProjectDummyWithSelect( LOGGER.warn("unknown key type, type={}", type); } } - } catch (Exception e) { - return new TaskExecuteResult( - new PhysicalTaskExecuteFailureException( - "execute query history task in redis failure", e)); } Filter filter = select.getFilter(); @@ -262,14 +249,8 @@ public TaskExecuteResult executeProjectDummyWithSelect( @Override public TaskExecuteResult executeProject(Project project, DataArea dataArea) { String storageUnit = dataArea.getStorageUnit(); - List queryPaths; - try { - queryPaths = determinePathList(storageUnit, project.getPatterns(), project.getTagFilter()); - } catch (PhysicalException e) { - LOGGER.error("encounter error when delete path: ", e); - return new TaskExecuteResult( - new PhysicalTaskExecuteFailureException("execute delete path task in redis failure", e)); - } + List queryPaths = + determinePathList(storageUnit, project.getPatterns(), project.getTagFilter()); List columns = new ArrayList<>(); try (Jedis jedis = getDataConnection()) { @@ -290,9 +271,6 @@ public TaskExecuteResult executeProject(Project project, DataArea dataArea) { columns.add(column); } } - } catch (Exception e) { - return new TaskExecuteResult( - new PhysicalTaskExecuteFailureException("execute query path task in redis failure", e)); } return new TaskExecuteResult(new RedisQueryRowStream(columns), null); } @@ -345,10 +323,6 @@ public TaskExecuteResult executeProjectDummy(Project project, DataArea dataArea) LOGGER.warn("unknown key type, type={}", type); } } - } catch (Exception e) { - return new TaskExecuteResult( - new PhysicalTaskExecuteFailureException( - "execute query history task in redis failure", e)); } return new TaskExecuteResult(new RedisQueryRowStream(columns), null); } @@ -356,68 +330,71 @@ public TaskExecuteResult executeProjectDummy(Project project, DataArea dataArea) @Override public TaskExecuteResult executeDelete(Delete delete, DataArea dataArea) { String storageUnit = dataArea.getStorageUnit(); - List deletedPaths; - try { - deletedPaths = determinePathList(storageUnit, delete.getPatterns(), delete.getTagFilter()); - } catch (PhysicalException e) { - LOGGER.warn("encounter error when delete path: ", e); - return new TaskExecuteResult( - new PhysicalTaskExecuteFailureException("execute delete path task in redis failure", e)); - } + List deletedKeyRanges = delete.getKeyRanges(); + boolean deleteAllColumn = + delete.getPatterns().stream().anyMatch(STAR::equals) && delete.getTagFilter() == null; + boolean deleteAllRange = delete.getKeyRanges() == null || deletedKeyRanges.isEmpty(); - if (deletedPaths.isEmpty()) { - return new TaskExecuteResult(null, null); - } - - if (delete.getKeyRanges() == null || delete.getKeyRanges().isEmpty()) { - // 没有传任何 time range, 删除全部数据 + if (deleteAllColumn && deleteAllRange) { try (Jedis jedis = getDataConnection()) { - int size = deletedPaths.size(); - String[] deletedPathArray = new String[size * 3]; - for (int i = 0; i < size; i++) { - String path = deletedPaths.get(i); - deletedPathArray[i] = String.format(KEY_FORMAT_HASH_VALUES, storageUnit, path); - deletedPathArray[i + size] = String.format(KEY_FORMAT_ZSET_KEYS, storageUnit, path); - deletedPathArray[i + 2 * size] = String.format(KEY_FORMAT_STRING_PATH, storageUnit, path); - } - jedis.del(deletedPathArray); - jedis.hdel(KEY_DATA_TYPE, deletedPaths.toArray(new String[0])); - } catch (Exception e) { - LOGGER.warn("encounter error when delete path: ", e); - return new TaskExecuteResult( - new PhysicalException("execute delete path in redis failure", e)); + jedis.flushDB(); } } else { - // 删除指定部分数据 - try (Jedis jedis = getDataConnection()) { - for (String path : deletedPaths) { - for (KeyRange keyRange : delete.getKeyRanges()) { - byte[] zSetKey = - DataCoder.encode(String.format(KEY_FORMAT_ZSET_KEYS, storageUnit, path)); - byte[] beginKeyRange = - concat(CLOSED_SIGN, DataCoder.encode(keyRange.getActualBeginKey())); - byte[] endKeyRange = concat(CLOSED_SIGN, DataCoder.encode(keyRange.getActualEndKey())); + List deletedPaths = + determinePathList(storageUnit, delete.getPatterns(), delete.getTagFilter()); + if (!deletedPaths.isEmpty()) { + if (deleteAllRange) { + deleteColumns(deletedPaths, storageUnit); + } else { + deleteColumnsRanges(deletedPaths, deletedKeyRanges, storageUnit); + } + } + } - List keys = jedis.zrangeByLex(zSetKey, beginKeyRange, endKeyRange); - if (!keys.isEmpty()) { - byte[] hashKey = - DataCoder.encode(String.format(KEY_FORMAT_HASH_VALUES, storageUnit, path)); - jedis.hdel(hashKey, keys.toArray(new byte[0][0])); - jedis.zremrangeByLex(zSetKey, beginKeyRange, endKeyRange); - } + return new TaskExecuteResult(null, null); + } + + private void deleteColumnsRanges( + List deletedPaths, List deletedKeyRanges, String storageUnit) { + // 删除指定部分数据 + try (Jedis jedis = getDataConnection()) { + for (String path : deletedPaths) { + for (KeyRange keyRange : deletedKeyRanges) { + byte[] zSetKey = DataCoder.encode(String.format(KEY_FORMAT_ZSET_KEYS, storageUnit, path)); + byte[] beginKeyRange = + concat(CLOSED_SIGN, DataCoder.encode(keyRange.getActualBeginKey())); + byte[] endKeyRange = concat(CLOSED_SIGN, DataCoder.encode(keyRange.getActualEndKey())); + + List keys = jedis.zrangeByLex(zSetKey, beginKeyRange, endKeyRange); + if (!keys.isEmpty()) { + byte[] hashKey = + DataCoder.encode(String.format(KEY_FORMAT_HASH_VALUES, storageUnit, path)); + jedis.hdel(hashKey, keys.toArray(new byte[0][0])); + jedis.zremrangeByLex(zSetKey, beginKeyRange, endKeyRange); } } - } catch (Exception e) { - LOGGER.warn("encounter error when delete path: ", e); - return new TaskExecuteResult( - new PhysicalException("execute delete data in redis failure", e)); } } - return new TaskExecuteResult(null, null); + } + + private void deleteColumns(List deletedPaths, String storageUnit) { + // 没有传任何 time range, 删除全部数据 + try (Jedis jedis = getDataConnection()) { + int size = deletedPaths.size(); + String[] deletedPathArray = new String[size * 3]; + for (int i = 0; i < size; i++) { + String path = deletedPaths.get(i); + deletedPathArray[i] = String.format(KEY_FORMAT_HASH_VALUES, storageUnit, path); + deletedPathArray[i + size] = String.format(KEY_FORMAT_ZSET_KEYS, storageUnit, path); + deletedPathArray[i + 2 * size] = String.format(KEY_FORMAT_STRING_PATH, storageUnit, path); + } + jedis.del(deletedPathArray); + jedis.hdel(KEY_DATA_TYPE, deletedPaths.toArray(new String[0])); + } } private List determinePathList( - String storageUnit, List patterns, TagFilter tagFilter) throws PhysicalException { + String storageUnit, List patterns, TagFilter tagFilter) { boolean hasTagFilter = tagFilter != null; List paths = new ArrayList<>(); try (Jedis jedis = getDataConnection()) { @@ -437,9 +414,6 @@ private List determinePathList( paths.add(path); }); } - } catch (Exception e) { - LOGGER.error("get du time series error, cause by: ", e); - return Collections.emptyList(); } if (!hasTagFilter) { return paths; @@ -477,8 +451,6 @@ public TaskExecuteResult executeInsert(Insert insert, DataArea dataArea) { jedis.hset(KEY_DATA_TYPE, path, type); jedis.set(String.format(KEY_FORMAT_STRING_PATH, storageUnit, path), EMTPY_STRING); - } catch (Exception e) { - return new TaskExecuteResult(new PhysicalException("execute insert in redis error", e)); } } return new TaskExecuteResult(null, null); @@ -548,12 +520,8 @@ public Pair getBoundaryOfStorage(String prefix) if (prefix != null) { columnsInterval = new ColumnsInterval(prefix); } else { - if (!paths.isEmpty()) { - columnsInterval = - new ColumnsInterval(paths.get(0), StringUtils.nextString(paths.get(paths.size() - 1))); - } else { - columnsInterval = new ColumnsInterval(null, null); - } + columnsInterval = + new ColumnsInterval(paths.get(0), StringUtils.nextString(paths.get(paths.size() - 1))); } KeyInterval keyInterval = KeyInterval.getDefaultKeyInterval(); return new Pair<>(columnsInterval, keyInterval); @@ -564,8 +532,6 @@ private List getKeysByPattern(String pattern) { try (Jedis jedis = jedisPool.getResource()) { Set keys = jedis.keys(pattern); paths.addAll(keys); - } catch (Exception e) { - LOGGER.error("get keys error, cause by: ", e); } return paths; } From 5338335196ba002b5e6dc9e9720e0503c56a95bd Mon Sep 17 00:00:00 2001 From: An Qi Date: Fri, 12 Jul 2024 11:35:20 +0800 Subject: [PATCH 059/138] feat(optimizer): coexist with extension (#376) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 移除主仓库中的混淆配置 使用 SPI 机制动态加载规则 更新混淆 jar 包 --- .github/actions/confWriter/action.yml | 5 -- .../src/assembly/component/iginx-core.xml | 3 - .../assembly/component/iginx-optimizer.xml | 39 ------------ assembly/src/assembly/include.xml | 1 - assembly/src/assembly/server.xml | 1 - .../cn/edu/tsinghua/iginx/IginxWorker.java | 13 ++-- ...inx-optimizer-extension-0.7.0-SNAPSHOT.jar | Bin 0 -> 8307 bytes optimizer/pom.xml | 58 ++++++------------ optimizer/proguard.cfg | 16 ----- .../optimizer/rules/ColumnPruningRule.java | 12 +--- .../rules/ConstantPropagationRule.java | 12 +--- .../rules/FilterConstantFoldingRule.java | 14 +---- .../rules/FilterJoinTransposeRule.java | 11 +--- .../FilterPushDownAddSchemaPrefixRule.java | 13 +--- .../rules/FilterPushDownGroupByRule.java | 12 +--- .../FilterPushDownPathUnionJoinRule.java | 13 +--- .../FilterPushDownProjectReorderSortRule.java | 13 +--- .../rules/FilterPushDownRenameRule.java | 11 +--- .../rules/FilterPushDownSelectRule.java | 11 +--- .../rules/FilterPushDownSetOpRule.java | 12 +--- .../rules/FilterPushDownTransformRule.java | 12 +--- .../FilterPushIntoJoinConditionRule.java | 13 +--- .../rules/FilterPushOutJoinConditionRule.java | 13 +--- .../rules/FragmentPruningByFilterRule.java | 12 +--- .../rules/FragmentPruningByPatternRule.java | 12 +--- .../rules/FunctionDistinctEliminateRule.java | 12 +--- .../rules/InExistsDistinctEliminateRule.java | 11 +--- .../optimizer/rules/NotFilterRemoveRule.java | 12 +--- .../RowTransformConstantFoldingRule.java | 12 +--- .../iginx/logical/optimizer/rules/Rule.java | 28 ++++++++- .../optimizer/rules/RuleCollection.java | 56 +++++++++-------- .../iginx-optimizer-0.7.0-SNAPSHOT.jar | Bin 523231 -> 0 bytes 32 files changed, 140 insertions(+), 323 deletions(-) delete mode 100644 assembly/src/assembly/component/iginx-optimizer.xml create mode 100644 dependency/src/main/resources/iginx-optimizer-extension-0.7.0-SNAPSHOT.jar delete mode 100644 optimizer/proguard.cfg delete mode 100644 optimizer/src/main/resources/iginx-optimizer-0.7.0-SNAPSHOT.jar diff --git a/.github/actions/confWriter/action.yml b/.github/actions/confWriter/action.yml index ea38d91995..117ddbaa2e 100644 --- a/.github/actions/confWriter/action.yml +++ b/.github/actions/confWriter/action.yml @@ -200,8 +200,3 @@ runs: echo "$RUNNER_OS is not supported" exit 1 fi - - - name: Copy Optimizer Jar - shell: bash - run: | - cp -f "${GITHUB_WORKSPACE}/optimizer/src/main/resources/iginx-optimizer-${VERSION}.jar" "${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/lib/" diff --git a/assembly/src/assembly/component/iginx-core.xml b/assembly/src/assembly/component/iginx-core.xml index d0d0625082..ae1237caf3 100644 --- a/assembly/src/assembly/component/iginx-core.xml +++ b/assembly/src/assembly/component/iginx-core.xml @@ -37,9 +37,6 @@ ${project.build.directory}/iginx-core-${project.version}/lib lib - - iginx-optimizer-*.jar - diff --git a/assembly/src/assembly/component/iginx-optimizer.xml b/assembly/src/assembly/component/iginx-optimizer.xml deleted file mode 100644 index daa6d82358..0000000000 --- a/assembly/src/assembly/component/iginx-optimizer.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - true - false - - cn.edu.tsinghua:iginx-optimizer - - - false - - - src/main/resources - - iginx-optimizer-*.jar - - lib - - - - - - \ No newline at end of file diff --git a/assembly/src/assembly/include.xml b/assembly/src/assembly/include.xml index 412c2c043e..bcaf358339 100644 --- a/assembly/src/assembly/include.xml +++ b/assembly/src/assembly/include.xml @@ -23,7 +23,6 @@ false src/assembly/component/iginx-core.xml - src/assembly/component/iginx-optimizer.xml src/assembly/component/iginx-iotdb12-driver.xml src/assembly/component/iginx-parquet-driver.xml src/assembly/component/include-zookeeper.xml diff --git a/assembly/src/assembly/server.xml b/assembly/src/assembly/server.xml index 399abccad4..3eebc37834 100644 --- a/assembly/src/assembly/server.xml +++ b/assembly/src/assembly/server.xml @@ -23,7 +23,6 @@ false src/assembly/component/iginx-core.xml - src/assembly/component/iginx-optimizer.xml src/assembly/component/iginx-filesystem-driver.xml src/assembly/component/iginx-influxdb-driver.xml src/assembly/component/iginx-iotdb12-driver.xml diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/IginxWorker.java b/core/src/main/java/cn/edu/tsinghua/iginx/IginxWorker.java index 5d64ce1427..d6a5d8ded6 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/IginxWorker.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/IginxWorker.java @@ -1217,7 +1217,7 @@ public ShowRulesResp showRules(ShowRulesReq req) { try { IRuleCollection ruleCollection = getRuleCollection(); return new ShowRulesResp(RpcUtils.SUCCESS, ruleCollection.getRulesInfo()); - } catch (ClassNotFoundException e) { + } catch (Exception e) { LOGGER.error("show rules failed: ", e); return new ShowRulesResp(RpcUtils.FAILURE, null); } @@ -1229,20 +1229,21 @@ public Status setRules(SetRulesReq req) { try { getRuleCollection().setRules(rulesChange); return RpcUtils.SUCCESS; - } catch (ClassNotFoundException e) { + } catch (Exception e) { LOGGER.error("set rules failed: ", e); return RpcUtils.FAILURE; } } - private IRuleCollection getRuleCollection() throws ClassNotFoundException { + private IRuleCollection getRuleCollection() + throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException { // 获取接口的类加载器 ClassLoader classLoader = IRuleCollection.class.getClassLoader(); // 加载枚举类 - Class enumClass = + Class ruleCollectionClass = classLoader.loadClass("cn.edu.tsinghua.iginx.logical.optimizer.rules.RuleCollection"); - // 获取枚举实例 - Object enumInstance = enumClass.getEnumConstants()[0]; + // get INSTANCE static field + Object enumInstance = ruleCollectionClass.getField("INSTANCE").get(null); // 强制转换为接口类型 return (IRuleCollection) enumInstance; diff --git a/dependency/src/main/resources/iginx-optimizer-extension-0.7.0-SNAPSHOT.jar b/dependency/src/main/resources/iginx-optimizer-extension-0.7.0-SNAPSHOT.jar new file mode 100644 index 0000000000000000000000000000000000000000..61b4e81405129250c42e859752338b62ca9218d1 GIT binary patch literal 8307 zcmb`McTg1Vn)ZjBh8zbG0f8Y7IfF=$oP*>X2Z_UwgTw(ODLE=xa?U|v21F!FkPIU# zAZb9tAgG_ad%p9Y*Q(vBv$frQS9Sl<&vke8RrTC;{S376@JRsx05L!XzHbg75{WkW z{bcmJ=zf>(0}~}dO+7UsT_rtDwFkx~5M8xzx)b9%+JcZ-a&1Arsfp<}BjI_mt)f=xd`Vy zi9Ng|eB^k$To!b(VOcK~QzzWQ?t!GlsDqBht&}WTS9C9)_xOKVOV7W)o}PXL5JHI8N@Kw{407fA-8{g)O9HEMD#-RvmI5wI>Q-3x7 z%3IoGwCNax_4iJSwID@();iufzH^5rYy$foiYB)H+>i+O??WVFz=_56;H z?_|${UE4yomrWC^Sdnzlts=3JPv`lp#y%z`XI6;e$mvXA(--d&;ll`6W)lj3;3-Dl zvSZgr3sFfAAlgT3!RTq21SJ_z~x`sgRH6EDTMOTG5MyJ^b-|n%`{iyO>qpx z0%+>xfKw0gT@qw#SUf?Or0V;Kd#dk##A9daMODm?lG)#H+P{*Iw@r-;QC7=?zrGs+ znzb^9?w`K+uB6IXV{Y8&wYx$o@Wxkq%5dmi7TccR)7xL2GxSn-tqWlC{keocasTcI z%>ByQVJZN?Ukm`y{I~s}{WE*XLDl>I zeEt-YFT-AM9{qq*cKx!uol)$6Jn6Mj*^o(j88&?!G}qHf$DZWpI3kGn zreu(kq~B~Sfq<1ESanMsKhk7t6hG2>%P{(q>m~j@HcZ|iYcwV4P5a3OECZ?w^a_QsK^%+SM4=Oa zijG(jln_(oB<2=kQ}iYcO$mJLjHN|wGX0#wP$C}F*jL`>MuFsXqMJm+W6_1cO(!fp z>KOFAONA>uAN^ZxL^CjtP-tl=6(VOcL<@8~6wa(!1~Qh8;<&bp5+jy@{w($n3h@r4 z$8p3k97GdH7-Ebf4^PnrONJr?{+h;c;AjD9L0?2?ntL!AcwbHuLoi~v4EYJhw}oF^ ze`(9P!kFPQ*a8&6gHQ@{;@8etG1P0OpXq>NpfS^z9sq`hkxhOFmsSN73la)66s9uo z;mvCm$r4*agCQ$N1dyk`rDWW~I?mPhjhPNKQa0VqNL=>NmEFDSW+X#sW0f1f!sMA} z`3`evV+Jd5P8{*-Y=!z~aOyU1HT$d($(wVNb-S| z9Sk#o5k=L~E$c}R;6V1Q5Qc@j^%wyU_oVOH23?Bz#OkXneJ+o?1zFaQ&C1SFM?pTT1hL%wj@KfUT&id zTe!fOYGn(z=3Hd(es)*fOLPtNDoMaQY2-YloSj)V9&wa?IrcM=#p|2TMw=N_^Gkpf zc)KFI_hnUIUnV;7^*tzdI(x*O7;HXPQ9q^Dll=XQ^La<0x>W|+eEzj9Si>!_{L+# z-*weB<^^JXef`+gcj{@sNyaAXqW&_);>y>(t!&kf{K59Q_v|-YPF|nGG@bw$r|8rW z-4JC;046VUz50y=KeZs`=J$ft{9Hnx;0E22!w`(bbAOhqjSI^{%Prw!<~H&kBH5P> z3^@AM-51ildRVD9$k}tz4;<)1=SGX*SJ}Vr(vmS~o0NF6Uq1WDY4$iwy$?6!^Ag$T z-WHvlps$^bb4X>9UkozV@-=iXh#k=JyX!UF&(UPn5DqX6e^6>e468pnq6Pd~RM5Qs zAp^~tVa1EZK+Wi%NM?pGQfpK^E<|jFPa*#JDCUQ=o=Wu3mMhP@`u<5fF;7Seu=zS; zzHqyGl@lqxu?ur|JZO2M#SB$)06ZwWQLmM-mg{3)-bz;GDCFG^EX|#wE;1-gG*Imq z%STG?KrKVo9<4lxgasp>`QzJbN z9dE>{ifkB@xqIan?$BGyNRsEvwR@}5Gv*NGrq#bJx!wuYYJBz}Crm4HC-+G;!EG0e98f`!YCnn+`>MH;8mWjia4V%PFtP!eSRsj-nb0L>a|N%b(> zT3hzVBaxMoj&|DK;y#`#HIaLV_z}DB414^%r1?fED@@r0ZY}Jl+_sgisz_*dHrY-Y zU|AP-+7`Nl+PM``mgX^k;h7F${cJBwb$3Mn8H?R5a;TEHWpdjQaoobTTw+#}+R5Fd zGmS%a+6Pjd@DUU78#OFnDc>(sEGJ*@=t#SJ>`i(7_dQYOz1s5HmaN3Uro9m5c6ZS8 zQ*&*Bf-IEbS9pb{#5TJO!kWslFjJQKJFv?w(xaxl@-3?@;^1>0(&rcoNWB zaCepNqcq9>3hJ4Gb<(1`%DYH>xu99`caa}+jqlzLaxIg3<{c`*(=ax<@~l`xS7My6 zv;n^GG<9Aiyr0|f5gCDrculQYs&7ri*v0Vo;Ciu!;+K_=nk4#POSZM-KyW-f$-6pU zx;a-dq;=$zXVA^hC|kFWCvgW5O!;z1C9R;6(ARo#wEMDs8E_esI9i#WAqKrFO}C?k z?1joh7UWGovPbD?jW%QNDBEhGyCQ^}((X&gNq6}D)pFi=Qn%Ah-%CQ7*^P<9FYkU$ zsxM*@zU?X`P!F(cuHmQ2db_xp+JsfJApUi&oH*I_l#e4sBi5!Tc2;aU{6<)VwLk;n zz*d|by~8wyuU2TD;|X}KOzi_laR$?~ee2;e!t5#GFO5tuNXR-?+^H{AUFpDxa&s-` z_@=w1Z#Y`8;kp{m3Cxr_Zui1C#13dc4sLn|tR-`~i6fa>i2;ERkZ-;94Etly5V1IvkNn4#dB+}ztbs2 zG@0^)O+PyM+J2fhfajyWUxMU}I7q-i&*m~X%mD@U#lIEiaPH8Yb^DSq%wfO>a3nqi z%`=t+bcr||CfruH_m-S18WKK+N91aJm)2UQK$TBw$|yit1t)pWUA% zPH+&Smb#moN7LLp$tT3Nro6K#R@vs|{YWToO)>^2xGt&txrfkYe2>r?QEGxi?W!n# zwo=!E*M95(o^LWq|(G!$v@FKe=06DOwA#jn2odG8lbag60yg9K?S(QvonZqFXB?dMo7D$H2D8 zOp^f+s3y|5JFt1*m8kH&Ud=%~1x)%XD^R$pO~GD7sO_O8bo1zb_Z^Q%d=1ci^-@HT z7BHGi8lPUNtB11Dh-8+sLA6iNTZ!+xz29JX0)3cKY)IKXQ=sWH=7qV~_JvQMDGL&1 z9S!a{d^PCYX;3kEUZY#4u^Ve?)X8CgagL;~eTCD_*oJsEz~OIBzr0FhBklSt$b8^oZpBkiv=v1XdS66!krnaCVweSJV3u*)Y?f>vH!x>cvVfv% z-Ah5u;zLfU$DO)bm|UKiOtODDiFC@GnodyezS=yKWYO!Dr);+Zn}-RO*wU0LC5=-Z zkReLkRH*DRHnLFLkd1xGOJtStURH{!un0ljedm|9?|SC;NFza#6*?bg8){o!XUE?p zolAy76>2%9c3lXTl=5Qe2@8qb`+Il@ zTapXzmkgP<<^JUPoL z{_5fvRJL`XM6nH>8bGb!XZfWT$dG?Lo)ltVnZx&)btnw$`rnaK<_vU4xDg-Kk& z7;fx;#wd)IyvwceQwxos4o#r+1Z&QRrKUKlX{~>8ARjl!3Hr43$y97bwd+dUptHZ9 zh()$1js`=eLlSz878Tk_%z=*tl0UBpQN&X4x!cANH2HR@mU;xdthSW&f0_Y4S9Yse zDebX5lqH({YDg;sd@oWgZukrS5Ko@zO4Xfm5JmmX)3^<7)h{M0n;Swl_L!LA&6%y#s9dov+{{pc%bquKTfqGvp8 zFr4pE@z5JFVWqa!@T@%No|e8;^1@J~OXfF1FWH`Fm%+;lNKsXm=MN^{Zto^Fxhm?H zq=kfiZzEq#U4d?`&RL*oooQMS)xDAHGj^{R;>#2^iI44e-Uc zNzmGr%_-lXA?`gw#!cB(e*?qHjMuY&R662>lW;Ed8&dX=`OJS?c{t@iaapK-;A5SBTJtx_tR&Br8Ai{DUpNb zqm<5X&9gzSg#I3t_+(dPYT*I^RsXB#%<;csk%lZQ!_7DLtgyPxAwfPUe*4=aLP%@=MvDxJ^T#1V5I@D8+Xt*8o9A>m;x5{nyS? zh3mSVijN~UaeNt33`Z8-KIrIp9I{vv;v!dZ(J9da&<==^rg{jZM!Ri|+tK~DJF8-a zLG4inpCwbS7aU!c`e?V)uUK2Eo3m#g)jbkgs2#)W{e=d+}pz4j;xXpGk031P8Dy8b78 z*4q)dcYisY)j&=8W*212Z%)St>7dnZ+~%`-JXFPn1>wq09Xl}{c;pB56qN2Zk|tC9 zU%@YPg5O9apOwUwZDtJ4%)0UlhY!n;zD0#$Vq*4r(i_Rw%dRbNLHV9Tw3*@Go>-c` zH;z=A!e4&UCXeW_Ol74R|1b$LxBnH>-PW` zMX*RjmQTc$?3yV^Xj5@R2EC7$>Np^Owjt;QH_S$H=5g~ zx*1g$mOkYUm#pAUZ1pw5`02di8$9AloJ;@$g5TUqj$x#ZS48N>1!d!EC@uLU>Y4dLI-xt+ovRvw7PPnJV8GagC*L1j3lBw z*%+%JYtJT3^PjreSi9aBINrEE>hsyS^P%a6(4LEs^u&bSmd;OW*otF=;Uq0F=s`dD zV+8d8hh8%F{%``vJsLl~;VzD;WUSusB}XKWGP|Ux34JMXA(Nz-2_qUZFM0qROkT&q z8r+GxLklmI9NyH)050Ma)m!e8#++3cu78#szhdT5)8zU~ul%^5PFv=yLKuh!7 zEjW5C7rSqo2V_7QBFs4Z5#A(C+ax4DC8kJCd0w>c5tfNr#S#fN;0k}DNAjZ72Dzi5 zg~fdmC)Bge|D{-|Fs=<~cb5x&i-`vE(T_wCnS-IV?W`(2N5R_ z1fxC&;4a3GZ)+-4RlFBjH9GISXlF5AHTj{TGh1Wm_^{8DuO@G{GOyJuuVwvcG!$on zHoGINH%o~?SM_N|!A(|$*T|Yfb#I-^VV-r%-cgqUNN3w;a7_bk%R$4F(D~~eh za9A>t|J-VMTI&vhRu9ML*`(zx+ zvR>z09s}RgF2{ZQ`bX>O3hlUb6WO#dcpn6_m+M$jzc%ltQlX z4{)qxjo+iS+)NZB&H{uZgT8qXr86YJ^Su#WEQ1;2f#9$-<$|&-$0~7O@YcC zvMvx{Z2kC%XUf2BN|icOb@Ua$uEJ*jXW7-j{PXVwT$8yi^3+Lo$ce|kM3z5bE@s zPC9u*ezQ!-|7V$y|74kvf3Qr*KUpT^KUpT^KX$n6i6N3GVIaXw-xlApGNmoP6tToS zrNlEyg1xhcMT7ft{Uw}XTtYL!CfusKx?>!;;MQ@!GR-RMOgc-TtiSKL`+@MfY`O|I zyMBS|^;}jje_!}Go`E(FE-B!@r@p_N|Ci&R-|;UD_|Fyoq_%&(9`pP5f5mYBl=u?_ z{w0y|d*=Q3B>o31_^0fjL-k*>1GN9H>_0~AKPCPgjsB9bWcYU_{-;6dPu)Ka`iginx-core provided + + com.google.auto.service + auto-service-annotations + 1.1.1 + - org.apache.maven.plugins - maven-assembly-plugin + maven-compiler-plugin + 3.13.0 + + + + com.google.auto.service + auto-service + 1.1.1 + + + org.apache.maven.plugins @@ -64,9 +78,12 @@ - + + + + @@ -75,39 +92,4 @@ - - - - java8 - - [1.8,1.8.999] - - - - - com.github.wvengen - proguard-maven-plugin - 2.6.0 - - ${project.basedir}/proguard.cfg - - - - - - ${java.home}/lib/rt.jar - - - - - - proguard - - - - - - - - diff --git a/optimizer/proguard.cfg b/optimizer/proguard.cfg deleted file mode 100644 index b19333e1aa..0000000000 --- a/optimizer/proguard.cfg +++ /dev/null @@ -1,16 +0,0 @@ -# 保留指定类及其所有成员 --keep class cn.edu.tsinghua.iginx.logical.optimizer.rbo.RuleBasedOptimizer { - *; -} - --keep class cn.edu.tsinghua.iginx.physical.optimizer.naive.NaivePhysicalOptimizer { - *; -} - --keep enum cn.edu.tsinghua.iginx.logical.optimizer.rules.RuleCollection { - *; -} - --keep class cn.edu.tsinghua.iginx.logical.optimizer.rules.Rule { - *; -} diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/ColumnPruningRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/ColumnPruningRule.java index 4eb237fb74..54ee1dc87c 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/ColumnPruningRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/ColumnPruningRule.java @@ -40,23 +40,17 @@ import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; import cn.edu.tsinghua.iginx.utils.Pair; import cn.edu.tsinghua.iginx.utils.StringUtils; +import com.google.auto.service.AutoService; import java.util.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +@AutoService(Rule.class) public class ColumnPruningRule extends Rule { private static final Logger LOGGER = LoggerFactory.getLogger(ColumnPruningRule.class); - private static final class InstanceHolder { - static final ColumnPruningRule INSTANCE = new ColumnPruningRule(); - } - - public static ColumnPruningRule getInstance() { - return InstanceHolder.INSTANCE; - } - - protected ColumnPruningRule() { + public ColumnPruningRule() { /* * we want to match the topology like: * Any diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/ConstantPropagationRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/ConstantPropagationRule.java index ffda74db40..26a2afb2b9 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/ConstantPropagationRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/ConstantPropagationRule.java @@ -29,25 +29,19 @@ import cn.edu.tsinghua.iginx.engine.shared.operator.filter.*; import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; import cn.edu.tsinghua.iginx.utils.Pair; +import com.google.auto.service.AutoService; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Logger; +@AutoService(Rule.class) public class ConstantPropagationRule extends Rule { private static final Logger LOGGER = Logger.getLogger(ConstantPropagationRule.class.getName()); - private static final class InstanceHolder { - static final ConstantPropagationRule INSTANCE = new ConstantPropagationRule(); - } - - public static ConstantPropagationRule getInstance() { - return InstanceHolder.INSTANCE; - } - - protected ConstantPropagationRule() { + public ConstantPropagationRule() { /* * we want to match the topology like: * SELECT diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterConstantFoldingRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterConstantFoldingRule.java index 075f0c9753..9de5f1f110 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterConstantFoldingRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterConstantFoldingRule.java @@ -25,21 +25,13 @@ import cn.edu.tsinghua.iginx.engine.shared.operator.filter.ExprFilter; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Filter; import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; +import com.google.auto.service.AutoService; import java.util.List; -import java.util.logging.Logger; +@AutoService(Rule.class) public class FilterConstantFoldingRule extends Rule { - private static final Logger LOGGER = Logger.getLogger(FilterConstantFoldingRule.class.getName()); - private static final class InstanceHolder { - static final FilterConstantFoldingRule INSTANCE = new FilterConstantFoldingRule(); - } - - public static FilterConstantFoldingRule getInstance() { - return InstanceHolder.INSTANCE; - } - - protected FilterConstantFoldingRule() { + public FilterConstantFoldingRule() { /* * we want to match the topology like: * SELECT diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterJoinTransposeRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterJoinTransposeRule.java index 107090b3f2..b6fde4e1ee 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterJoinTransposeRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterJoinTransposeRule.java @@ -26,17 +26,10 @@ import cn.edu.tsinghua.iginx.engine.shared.source.Source; import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; +// @AutoService(Rule.class) public class FilterJoinTransposeRule extends Rule { - private static final class InstanceHolder { - static final FilterJoinTransposeRule INSTANCE = new FilterJoinTransposeRule(); - } - - public static FilterJoinTransposeRule getInstance() { - return InstanceHolder.INSTANCE; - } - - protected FilterJoinTransposeRule() { + public FilterJoinTransposeRule() { /* * we want to match the topology like: * Select diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownAddSchemaPrefixRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownAddSchemaPrefixRule.java index 5aeda23cb9..1b772aeb11 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownAddSchemaPrefixRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownAddSchemaPrefixRule.java @@ -24,19 +24,12 @@ import cn.edu.tsinghua.iginx.engine.shared.operator.filter.*; import cn.edu.tsinghua.iginx.engine.shared.source.OperatorSource; import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; +import com.google.auto.service.AutoService; +@AutoService(Rule.class) public class FilterPushDownAddSchemaPrefixRule extends Rule { - private static class InstanceHolder { - private static final FilterPushDownAddSchemaPrefixRule INSTANCE = - new FilterPushDownAddSchemaPrefixRule(); - } - - public static FilterPushDownAddSchemaPrefixRule getInstance() { - return InstanceHolder.INSTANCE; - } - - protected FilterPushDownAddSchemaPrefixRule() { + public FilterPushDownAddSchemaPrefixRule() { /* * we want to match the topology like: * Select diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownGroupByRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownGroupByRule.java index eaf6e90545..f30df3158b 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownGroupByRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownGroupByRule.java @@ -25,24 +25,18 @@ import cn.edu.tsinghua.iginx.engine.shared.operator.type.OperatorType; import cn.edu.tsinghua.iginx.engine.shared.source.OperatorSource; import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; +import com.google.auto.service.AutoService; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; +@AutoService(Rule.class) public class FilterPushDownGroupByRule extends Rule { private static List validOps = Arrays.asList(OperatorType.GroupBy, OperatorType.Distinct); - private static class InstanceHolder { - private static final FilterPushDownGroupByRule INSTANCE = new FilterPushDownGroupByRule(); - } - - public static FilterPushDownGroupByRule getInstance() { - return InstanceHolder.INSTANCE; - } - - protected FilterPushDownGroupByRule() { + public FilterPushDownGroupByRule() { /* * we want to match the topology like: * Select diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownPathUnionJoinRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownPathUnionJoinRule.java index 354f80307b..63b2fe4577 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownPathUnionJoinRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownPathUnionJoinRule.java @@ -29,9 +29,11 @@ import cn.edu.tsinghua.iginx.engine.shared.source.OperatorSource; import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; import cn.edu.tsinghua.iginx.metadata.entity.ColumnsInterval; +import com.google.auto.service.AutoService; import java.util.*; import java.util.stream.Collectors; +@AutoService(Rule.class) public class FilterPushDownPathUnionJoinRule extends Rule { private static final Set validOps = new HashSet<>( @@ -47,16 +49,7 @@ public class FilterPushDownPathUnionJoinRule extends Rule { private static final Map selectMap = new HashMap<>(); - private static class InstanceHolder { - private static final FilterPushDownPathUnionJoinRule instance = - new FilterPushDownPathUnionJoinRule(); - } - - public static FilterPushDownPathUnionJoinRule getInstance() { - return InstanceHolder.instance; - } - - protected FilterPushDownPathUnionJoinRule() { + public FilterPushDownPathUnionJoinRule() { /* * we want to match the topology like: * Select diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownProjectReorderSortRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownProjectReorderSortRule.java index b6fdc7e391..10d8ab473e 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownProjectReorderSortRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownProjectReorderSortRule.java @@ -22,25 +22,18 @@ import cn.edu.tsinghua.iginx.engine.shared.source.OperatorSource; import cn.edu.tsinghua.iginx.engine.shared.source.SourceType; import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; +import com.google.auto.service.AutoService; import java.util.Arrays; import java.util.HashSet; import java.util.Set; +@AutoService(Rule.class) public class FilterPushDownProjectReorderSortRule extends Rule { private static final Set validOps = new HashSet<>(Arrays.asList(Project.class, Reorder.class, Sort.class)); - private static final class InstanceHolder { - static final FilterPushDownProjectReorderSortRule INSTANCE = - new FilterPushDownProjectReorderSortRule(); - } - - public static FilterPushDownProjectReorderSortRule getInstance() { - return InstanceHolder.INSTANCE; - } - - protected FilterPushDownProjectReorderSortRule() { + public FilterPushDownProjectReorderSortRule() { /* * we want to match the topology like: * Select diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownRenameRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownRenameRule.java index e3d94d2211..2d43357910 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownRenameRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownRenameRule.java @@ -25,18 +25,13 @@ import cn.edu.tsinghua.iginx.engine.shared.operator.filter.*; import cn.edu.tsinghua.iginx.engine.shared.source.OperatorSource; import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; +import com.google.auto.service.AutoService; import java.util.Map; +@AutoService(Rule.class) public class FilterPushDownRenameRule extends Rule { - private static class InstanceHolder { - private static final FilterPushDownRenameRule INSTANCE = new FilterPushDownRenameRule(); - } - - public static FilterPushDownRenameRule getInstance() { - return InstanceHolder.INSTANCE; - } - protected FilterPushDownRenameRule() { + public FilterPushDownRenameRule() { /* * we want to match the topology like: * Select diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownSelectRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownSelectRule.java index 241b73a719..8c59575ee2 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownSelectRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownSelectRule.java @@ -21,17 +21,12 @@ import cn.edu.tsinghua.iginx.engine.logical.utils.LogicalFilterUtils; import cn.edu.tsinghua.iginx.engine.shared.operator.Select; import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; +import com.google.auto.service.AutoService; +@AutoService(Rule.class) public class FilterPushDownSelectRule extends Rule { - private static final class InstanceHolder { - static final FilterPushDownSelectRule INSTANCE = new FilterPushDownSelectRule(); - } - - public static FilterPushDownSelectRule getInstance() { - return InstanceHolder.INSTANCE; - } - protected FilterPushDownSelectRule() { + public FilterPushDownSelectRule() { /* * we want to match the topology like: * Select diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownSetOpRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownSetOpRule.java index 05cd0be93c..80f0e62abb 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownSetOpRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownSetOpRule.java @@ -24,9 +24,11 @@ import cn.edu.tsinghua.iginx.engine.shared.source.OperatorSource; import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; import cn.edu.tsinghua.iginx.utils.Pair; +import com.google.auto.service.AutoService; import java.util.*; import java.util.stream.IntStream; +@AutoService(Rule.class) public class FilterPushDownSetOpRule extends Rule { static final Set validSetOps = @@ -35,15 +37,7 @@ public class FilterPushDownSetOpRule extends Rule { // 部分情况下Select只能超集下推,这时候需要记录该Select有没有超集下推过,如果有,下次就不能再下推了 static final Map> selectMap = new HashMap<>(); - private static class InstanceHolder { - private static final FilterPushDownSetOpRule INSTANCE = new FilterPushDownSetOpRule(); - } - - public static FilterPushDownSetOpRule getInstance() { - return InstanceHolder.INSTANCE; - } - - protected FilterPushDownSetOpRule() { + public FilterPushDownSetOpRule() { /* * we want to match the topology like: * Select diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownTransformRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownTransformRule.java index 4d8387ae7e..c761586e44 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownTransformRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownTransformRule.java @@ -26,22 +26,16 @@ import cn.edu.tsinghua.iginx.engine.shared.source.OperatorSource; import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; import cn.edu.tsinghua.iginx.utils.StringUtils; +import com.google.auto.service.AutoService; import java.util.*; +@AutoService(Rule.class) public class FilterPushDownTransformRule extends Rule { static final Set validTransforms = new HashSet<>(Arrays.asList(MappingTransform.class, RowTransform.class, SetTransform.class)); - private static class InstanceHolder { - private static final FilterPushDownTransformRule INSTANCE = new FilterPushDownTransformRule(); - } - - public static FilterPushDownTransformRule getInstance() { - return InstanceHolder.INSTANCE; - } - - protected FilterPushDownTransformRule() { + public FilterPushDownTransformRule() { /* * we want to match the topology like: * Select diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushIntoJoinConditionRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushIntoJoinConditionRule.java index d358597e2e..910d243b21 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushIntoJoinConditionRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushIntoJoinConditionRule.java @@ -22,22 +22,15 @@ import cn.edu.tsinghua.iginx.engine.shared.operator.*; import cn.edu.tsinghua.iginx.engine.shared.operator.type.OperatorType; import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; +import com.google.auto.service.AutoService; import java.util.*; +@AutoService(Rule.class) public class FilterPushIntoJoinConditionRule extends Rule { private static final Set validOps = new HashSet<>(Arrays.asList(OperatorType.InnerJoin, OperatorType.CrossJoin)); - private static class FilterPushIntoJoinConditionRuleInstance { - private static final FilterPushIntoJoinConditionRule INSTANCE = - new FilterPushIntoJoinConditionRule(); - } - - public static FilterPushIntoJoinConditionRule getInstance() { - return FilterPushIntoJoinConditionRuleInstance.INSTANCE; - } - - protected FilterPushIntoJoinConditionRule() { + public FilterPushIntoJoinConditionRule() { /* * we want to match the topology like: * Select diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushOutJoinConditionRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushOutJoinConditionRule.java index 4a93ff3a82..f5b62f79c5 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushOutJoinConditionRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushOutJoinConditionRule.java @@ -30,8 +30,10 @@ import cn.edu.tsinghua.iginx.engine.shared.operator.type.OuterJoinType; import cn.edu.tsinghua.iginx.engine.shared.source.OperatorSource; import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; +import com.google.auto.service.AutoService; import java.util.*; +@AutoService(Rule.class) public class FilterPushOutJoinConditionRule extends Rule { private static final Set validOps = new HashSet<>( @@ -41,16 +43,7 @@ public class FilterPushOutJoinConditionRule extends Rule { OperatorType.MarkJoin, OperatorType.SingleJoin)); - private static class FilterPushOutJoinConditionRuleInstance { - private static final FilterPushOutJoinConditionRule INSTANCE = - new FilterPushOutJoinConditionRule(); - } - - public static FilterPushOutJoinConditionRule getInstance() { - return FilterPushOutJoinConditionRuleInstance.INSTANCE; - } - - protected FilterPushOutJoinConditionRule() { + public FilterPushOutJoinConditionRule() { /* * we want to match the topology like: * Inner/Outer/Mark/Single Join diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FragmentPruningByFilterRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FragmentPruningByFilterRule.java index ab1dc4eb22..b56681fa38 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FragmentPruningByFilterRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FragmentPruningByFilterRule.java @@ -36,6 +36,7 @@ import cn.edu.tsinghua.iginx.metadata.entity.KeyInterval; import cn.edu.tsinghua.iginx.metadata.utils.FragmentUtils; import cn.edu.tsinghua.iginx.utils.Pair; +import com.google.auto.service.AutoService; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -43,19 +44,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +@AutoService(Rule.class) public class FragmentPruningByFilterRule extends Rule { private static final Logger LOGGER = LoggerFactory.getLogger(FragmentPruningByFilterRule.class); - private static final class InstanceHolder { - static final FragmentPruningByFilterRule INSTANCE = new FragmentPruningByFilterRule(); - } - - public static FragmentPruningByFilterRule getInstance() { - return FragmentPruningByFilterRule.InstanceHolder.INSTANCE; - } - - protected FragmentPruningByFilterRule() { + public FragmentPruningByFilterRule() { /* * we want to match the topology like: * Select diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FragmentPruningByPatternRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FragmentPruningByPatternRule.java index 3af23df73a..ed428242ce 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FragmentPruningByPatternRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FragmentPruningByPatternRule.java @@ -25,25 +25,19 @@ import cn.edu.tsinghua.iginx.engine.shared.source.Source; import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; import cn.edu.tsinghua.iginx.metadata.entity.ColumnsInterval; +import com.google.auto.service.AutoService; import java.util.ArrayList; import java.util.List; import java.util.Map; +@AutoService(Rule.class) public class FragmentPruningByPatternRule extends Rule { /* 该规则是根据Project的Pattern来判断是否需要Fragment,与列裁剪规则有关, 列裁剪规则裁剪了Project-Fragment中不需要的列,可能导致该Fragment不再需要 */ - private static final class InstanceHolder { - private static final FragmentPruningByPatternRule instance = new FragmentPruningByPatternRule(); - } - - public static FragmentPruningByPatternRule getInstance() { - return InstanceHolder.instance; - } - - protected FragmentPruningByPatternRule() { + public FragmentPruningByPatternRule() { /* * we want to match the topology like: * Project diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FunctionDistinctEliminateRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FunctionDistinctEliminateRule.java index bfa94abf97..2a58bdd611 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FunctionDistinctEliminateRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FunctionDistinctEliminateRule.java @@ -25,22 +25,16 @@ import cn.edu.tsinghua.iginx.engine.shared.operator.type.OperatorType; import cn.edu.tsinghua.iginx.engine.shared.source.OperatorSource; import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; +import com.google.auto.service.AutoService; import java.util.*; /** 该类实现了GroupBy节点中函数中的Distinct的消除。该规则用于消除函数中的Distinct,比如在min(distinct a)中的distinct是不必要的。 */ +@AutoService(Rule.class) public class FunctionDistinctEliminateRule extends Rule { private static final Set functionSet = new HashSet<>(Arrays.asList(Min.MIN, Max.MAX)); - private static class InstanceHolder { - static final FunctionDistinctEliminateRule INSTANCE = new FunctionDistinctEliminateRule(); - } - - public static FunctionDistinctEliminateRule getInstance() { - return InstanceHolder.INSTANCE; - } - - protected FunctionDistinctEliminateRule() { + public FunctionDistinctEliminateRule() { /* * we want to match the topology like: * GroupBy/DownSample/Row/Mapping/SetTransform diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/InExistsDistinctEliminateRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/InExistsDistinctEliminateRule.java index bd3ee246eb..bf01bb503b 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/InExistsDistinctEliminateRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/InExistsDistinctEliminateRule.java @@ -23,21 +23,16 @@ import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; import cn.edu.tsinghua.iginx.engine.shared.operator.type.OperatorType; import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; +import com.google.auto.service.AutoService; /** * 该类实现了Distinct节点的消除。该规则用于消除IN/EXISTS子查询中的DISTINCT节点, 例如SELECT * FROM t1 WHERE EXISTS (SELECT * DISTINCT * FROM t2 WHERE t1.a = t2.a),这里面的DISTINCT节点其实是不必要的。 */ +@AutoService(Rule.class) public class InExistsDistinctEliminateRule extends Rule { - private static class InstanceHolder { - static final InExistsDistinctEliminateRule INSTANCE = new InExistsDistinctEliminateRule(); - } - - public static InExistsDistinctEliminateRule getInstance() { - return InstanceHolder.INSTANCE; - } - protected InExistsDistinctEliminateRule() { + public InExistsDistinctEliminateRule() { /* * we want to match the topology like: * MarkJoin diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/NotFilterRemoveRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/NotFilterRemoveRule.java index 8cd0454f3e..77033056ea 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/NotFilterRemoveRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/NotFilterRemoveRule.java @@ -22,18 +22,12 @@ import cn.edu.tsinghua.iginx.engine.shared.operator.*; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.*; import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; +import com.google.auto.service.AutoService; +@AutoService(Rule.class) public class NotFilterRemoveRule extends Rule { - private static final class InstanceHolder { - static final NotFilterRemoveRule INSTANCE = new NotFilterRemoveRule(); - } - - public static NotFilterRemoveRule getInstance() { - return NotFilterRemoveRule.InstanceHolder.INSTANCE; - } - - protected NotFilterRemoveRule() { + public NotFilterRemoveRule() { /* * we want to match the topology like: * Select diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/RowTransformConstantFoldingRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/RowTransformConstantFoldingRule.java index d98665c811..5ffca61e34 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/RowTransformConstantFoldingRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/RowTransformConstantFoldingRule.java @@ -25,21 +25,15 @@ import cn.edu.tsinghua.iginx.engine.shared.operator.RowTransform; import cn.edu.tsinghua.iginx.engine.shared.source.OperatorSource; import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; +import com.google.auto.service.AutoService; import java.util.HashMap; import java.util.List; import java.util.Map; +@AutoService(Rule.class) public class RowTransformConstantFoldingRule extends Rule { - private static final class InstanceHolder { - static final RowTransformConstantFoldingRule INSTANCE = new RowTransformConstantFoldingRule(); - } - - public static RowTransformConstantFoldingRule getInstance() { - return RowTransformConstantFoldingRule.InstanceHolder.INSTANCE; - } - - protected RowTransformConstantFoldingRule() { + public RowTransformConstantFoldingRule() { /* * we want to match the topology like: * RowTransform diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/Rule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/Rule.java index 465bf528b9..60537677a3 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/Rule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/Rule.java @@ -25,6 +25,10 @@ public abstract class Rule { + public static final long DEFAULT_PRIORITY = 0; + + public static final RuleStrategy DEFAULT_STRATEGY = RuleStrategy.FIXED_POINT; + private final String ruleName; /** operand describes the local topology we want to match in this rule */ @@ -32,15 +36,24 @@ public abstract class Rule { private final RuleStrategy strategy; + private final long priority; + protected Rule(String ruleName, Operand operand) { - this.ruleName = ruleName; - this.operand = operand; - this.strategy = RuleStrategy.FIXED_POINT; + this(ruleName, operand, DEFAULT_PRIORITY, DEFAULT_STRATEGY); + } + + protected Rule(String ruleName, Operand operand, long priority) { + this(ruleName, operand, priority, DEFAULT_STRATEGY); } protected Rule(String ruleName, Operand operand, RuleStrategy strategy) { + this(ruleName, operand, DEFAULT_PRIORITY, strategy); + } + + protected Rule(String ruleName, Operand operand, long priority, RuleStrategy strategy) { this.ruleName = ruleName; this.operand = operand; + this.priority = priority; this.strategy = strategy; } @@ -56,6 +69,10 @@ public RuleStrategy getStrategy() { return strategy; } + public long getPriority() { + return priority; + } + /** * Returns whether this rule could possibly match the given operands. * @@ -78,4 +95,9 @@ public static Operand any() { public static Operand operand(Class clazz, Operand... children) { return new Operand(clazz, Arrays.asList(children)); } + + @Override + public String toString() { + return ruleName; + } } diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/RuleCollection.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/RuleCollection.java index c2cb7b56b9..4db5894c94 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/RuleCollection.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/RuleCollection.java @@ -22,46 +22,41 @@ import cn.edu.tsinghua.iginx.conf.ConfigDescriptor; import cn.edu.tsinghua.iginx.engine.logical.optimizer.IRuleCollection; import java.util.*; +import javax.annotation.Nonnull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public enum RuleCollection implements IRuleCollection { - INSTANCE; +public class RuleCollection implements IRuleCollection, Iterable { private static final Logger LOGGER = LoggerFactory.getLogger(RuleCollection.class); + public static final RuleCollection INSTANCE = new RuleCollection(); + private final Map rules = new HashMap<>(); private final Map bannedRules = new HashMap<>(); - private ConfigDescriptor configDescriptor = ConfigDescriptor.getInstance(); - - private RuleCollection() { - // add rules here - // 在这里添加规则 - addRule(NotFilterRemoveRule.getInstance()); - addRule(FragmentPruningByFilterRule.getInstance()); - addRule(ColumnPruningRule.getInstance()); - addRule(FragmentPruningByPatternRule.getInstance()); - addRule(ConstantPropagationRule.getInstance()); - addRule(FilterConstantFoldingRule.getInstance()); - addRule(RowTransformConstantFoldingRule.getInstance()); - addRule(FunctionDistinctEliminateRule.getInstance()); - addRule(InExistsDistinctEliminateRule.getInstance()); - addRule(FilterPushDownAddSchemaPrefixRule.getInstance()); - addRule(FilterPushDownGroupByRule.getInstance()); - addRule(FilterPushDownPathUnionJoinRule.getInstance()); - addRule(FilterPushDownProjectReorderSortRule.getInstance()); - addRule(FilterPushDownRenameRule.getInstance()); - addRule(FilterPushDownSelectRule.getInstance()); - addRule(FilterPushDownSetOpRule.getInstance()); - addRule(FilterPushDownTransformRule.getInstance()); - addRule(FilterPushIntoJoinConditionRule.getInstance()); - addRule(FilterPushOutJoinConditionRule.getInstance()); + private final ConfigDescriptor configDescriptor = ConfigDescriptor.getInstance(); + protected RuleCollection() { + addRulesBySPI(); setRulesByConfig(); } + private void addRulesBySPI() { + if (LOGGER.isDebugEnabled()) { + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + LOGGER.debug("ClassLoader: {}", cl); + String path = System.getProperty("java.class.path"); + LOGGER.debug("ClassPath: {}", path); + } + + for (Rule rule : ServiceLoader.load(Rule.class)) { + LOGGER.debug("Add rule by SPI: {}", rule); + addRule(rule); + } + } + /** 根据配置文件设置rules,未在配置文件中出现的规则默认为off */ private void setRulesByConfig() { Config config = configDescriptor.getConfig(); @@ -164,10 +159,17 @@ public Map getRulesInfo() { return rulesInfo; } + @Override + @Nonnull public Iterator iterator() { // ensure that this round of optimization will not be affected by rule set modifications // 确保这一轮优化不会受到规则集修改的影响 - return new RuleIterator(new ArrayList<>(rules.values()), new HashSet<>(bannedRules.values())); + List rules = new ArrayList<>(this.rules.values()); + Set bannedRules = new HashSet<>(this.bannedRules.values()); + + // sort rules by priority and rule name + rules.sort(Comparator.comparingLong(Rule::getPriority).thenComparing(Rule::getRuleName)); + return new RuleIterator(rules, bannedRules); } static class RuleIterator implements Iterator { diff --git a/optimizer/src/main/resources/iginx-optimizer-0.7.0-SNAPSHOT.jar b/optimizer/src/main/resources/iginx-optimizer-0.7.0-SNAPSHOT.jar deleted file mode 100644 index 57311a0eaf9fbda0068efcf6da8896b39a2dd647..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 523231 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

C8n1?f z$n^(!MHzWZnX4&|{2XnCRwu&A0;X9Nw8Z$iV(hoW!!4GtCDuEYsZY%jQVm`pQwL=c-y=@*YH(hWVT;A(GG@)OX`O}l z0B&dq-5R>bWgo`dhhs+=OAd>$>%OadNn0pylE0X-I7b$BXLNdyt&2N)+j5?ubUG}1 z(78h*rrVlz9bLeXg1vuCYwie-?Y3aoqkRbBF!-j8dHPvaQo-H54!ZLtxi&4gi$8H! zSI`q zN|f4{)KA-M1834WwxW03f3I)){uAf_7(C$r)X9qfRo@AHO8qJ*k~bnHj5TUo8PAY) zc(IohRK@z}o)k>^My=&_Q8vDN})y)SGHuJVbK`gKN?JZ9 zMJR_^wQ^HIgihjFk6Vus5cJ7MM^Xvopvpz{Qm-p{7Kd4sYDLw!^2Tpl@zJ|5FL9JG z^&4(QsgT2lfvK9cqpdx9=ijzK!_7*0zivl$=AB|c{E3Zb_9lh~{rEdnc!B0MgP&BW z@wv?L@2Sw{FEP|I^h5uo!U(5T_fC;W9ooPUFj_>0rd2RTO}%ohWDI;8#AnVeg=EI; zt&H5~rtLrUx5$8jaBtMmnIdE_q4;+)rl!0#hd;2R!vZR(7VoboD?6YD zgRQcM?hL0ir)?z%Epd{B@_a%os*5ht(z?=;5k=kAu%COm@&AscX`1S+nlq}>TpbWr=ga+B-4+5gOHF#0X$z&(eurw2Ney}61eYh zYctxS?WuZHZc9SG1GWZNaJcVc!Qv*U((dYE@wF9GSj@$C#nI_A*!Ilk!y@7po-?>q z2RH`2eQE6d(r7ptaCwZ{=XcZ8J-ayNy*Xg$%Wpeqbj@nCTAfh7k^uajL-y|F+1|3s z-Og5Oe#?+tYZzQd9muJ+S`7pv=*)2L{;?c6W>PIt_voQUYvo~;GG{qQ)P~Rs*OC6( zJpSV#ZKAt@^G6q*L%XzLf(M(-d2n0@Dd9?1a`wrUEHWd|JEBj~3-i`#!M$SQ3ahhh zp7iJ0NAk{<>Lg!q)bnrm82^oe7Z=*Ymh|nkW!!Y=zQHXW53E+YnUbgFxnB$D@z0j@ z^5#0v3o|5xKNHB3bD9iC+zv4Y-p6EStzMH%a2(1^hM&O31bHtyDcL$iutWC5u(3}? zL|tEu;#QpQEGXj zjLS*Qf?V;WKmAdij*D?{Zq!BH( zl(n!2IY+iWrSuK>Hk608P1AIH%R*&Nq=Z0l-1P68mH;+Vhl9P3|e-BITw*vb2=Aq3sthiSga`Axxilzu;uJ=

o&t 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 z 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μ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%0A6?as8GuBv}o=eX_D)+#ZIBs7iIy9{G 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 + com.google.flatbuffers + flatbuffers-java + + + org.apache.arrow + arrow-format + org.apache.arrow arrow-vector - 7.0.0 + + + org.apache.arrow + arrow-memory-core org.apache.arrow arrow-memory-netty - 7.0.0 runtime + + org.apache.arrow + arrow-memory-netty-buffer-patch + runtime + + + org.apache.arrow + arrow-algorithm + cn.edu.tsinghua.iginx pemja diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/StatementExecutor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/StatementExecutor.java index 46b77b84d6..a0f4c7ec55 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/StatementExecutor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/StatementExecutor.java @@ -722,8 +722,7 @@ private void processInsertFromSelect(RequestContext ctx) private void processCountPoints(RequestContext ctx) throws StatementExecutionException, PhysicalException { SelectStatement statement = - new UnarySelectStatement( - Collections.singletonList("*"), 0, Long.MAX_VALUE, AggregateType.COUNT); + new UnarySelectStatement(Collections.singletonList("*"), AggregateType.COUNT); ctx.setStatement(statement); process(ctx); diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/utils/OperatorUtils.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/utils/OperatorUtils.java index c6ef09c468..efe872e189 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/utils/OperatorUtils.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/utils/OperatorUtils.java @@ -65,7 +65,7 @@ public static Operator joinOperatorsByTime(List operators) { return joinOperators(operators, KEY); } - public static Operator joinOperators(List operators, String joinBy) { + public static Operator joinOperators(List operators, String joinBy) { if (operators == null || operators.isEmpty()) return null; if (operators.size() == 1) return operators.get(0); Operator join = operators.get(0); diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/IStorage.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/IStorage.java index 0a1068f50a..28c5fffaf1 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/IStorage.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/IStorage.java @@ -21,10 +21,7 @@ import cn.edu.tsinghua.iginx.engine.physical.storage.domain.Column; import cn.edu.tsinghua.iginx.engine.physical.storage.domain.DataArea; import cn.edu.tsinghua.iginx.engine.physical.task.TaskExecuteResult; -import cn.edu.tsinghua.iginx.engine.shared.operator.Delete; -import cn.edu.tsinghua.iginx.engine.shared.operator.Insert; -import cn.edu.tsinghua.iginx.engine.shared.operator.Project; -import cn.edu.tsinghua.iginx.engine.shared.operator.Select; +import cn.edu.tsinghua.iginx.engine.shared.operator.*; import cn.edu.tsinghua.iginx.metadata.entity.ColumnsInterval; import cn.edu.tsinghua.iginx.metadata.entity.KeyInterval; import cn.edu.tsinghua.iginx.utils.Pair; @@ -47,6 +44,15 @@ public interface IStorage { TaskExecuteResult executeProjectDummyWithSelect( Project project, Select select, DataArea dataArea); + default boolean isSupportProjectWithSetTransform(SetTransform setTransform, DataArea dataArea) { + return false; + } + + default TaskExecuteResult executeProjectWithSetTransform( + Project project, SetTransform setTransform, DataArea dataArea) { + throw new UnsupportedOperationException(); + } + /** 对非叠加分片删除数据 */ TaskExecuteResult executeDelete(Delete delete, DataArea dataArea); diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/domain/ColumnKey.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/domain/ColumnKey.java index 3b7f50d382..68a4338a59 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/domain/ColumnKey.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/domain/ColumnKey.java @@ -18,12 +18,18 @@ package cn.edu.tsinghua.iginx.engine.physical.storage.domain; +import cn.edu.tsinghua.iginx.engine.shared.Constants; import java.util.*; public class ColumnKey { + public static final ColumnKey KEY = new ColumnKey(Constants.KEY, Collections.emptyMap()); private final String path; private final SortedMap tags; + public ColumnKey(String path) { + this(path, Collections.emptyMap()); + } + public ColumnKey(String path, Map tagList) { this.path = Objects.requireNonNull(path); this.tags = Collections.unmodifiableSortedMap(new TreeMap<>(tagList)); diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java index 05fbe2cb51..599cc05033 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java @@ -24,6 +24,8 @@ import cn.edu.tsinghua.iginx.engine.physical.exception.TooManyPhysicalTasksException; import cn.edu.tsinghua.iginx.engine.physical.exception.UnexpectedOperatorException; import cn.edu.tsinghua.iginx.engine.physical.memory.MemoryPhysicalTaskDispatcher; +import cn.edu.tsinghua.iginx.engine.physical.memory.execute.OperatorMemoryExecutor; +import cn.edu.tsinghua.iginx.engine.physical.memory.execute.OperatorMemoryExecutorFactory; import cn.edu.tsinghua.iginx.engine.physical.optimizer.ReplicaDispatcher; import cn.edu.tsinghua.iginx.engine.physical.storage.IStorage; import cn.edu.tsinghua.iginx.engine.physical.storage.StorageManager; @@ -35,12 +37,8 @@ import cn.edu.tsinghua.iginx.engine.physical.task.MemoryPhysicalTask; import cn.edu.tsinghua.iginx.engine.physical.task.StoragePhysicalTask; import cn.edu.tsinghua.iginx.engine.physical.task.TaskExecuteResult; -import cn.edu.tsinghua.iginx.engine.shared.operator.Delete; -import cn.edu.tsinghua.iginx.engine.shared.operator.Insert; -import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; -import cn.edu.tsinghua.iginx.engine.shared.operator.Project; -import cn.edu.tsinghua.iginx.engine.shared.operator.Select; -import cn.edu.tsinghua.iginx.engine.shared.operator.ShowColumns; +import cn.edu.tsinghua.iginx.engine.shared.data.read.RowStream; +import cn.edu.tsinghua.iginx.engine.shared.operator.*; import cn.edu.tsinghua.iginx.engine.shared.operator.tag.TagFilter; import cn.edu.tsinghua.iginx.engine.shared.operator.type.OperatorType; import cn.edu.tsinghua.iginx.metadata.DefaultMetaManager; @@ -158,11 +156,21 @@ private StoragePhysicalTaskExecutor() { pair.k.isSupportProjectWithSelect() && operators.size() == 2 && operators.get(1).getType() == OperatorType.Select; + boolean needSetTransformPushDown = + operators.size() == 2 + && operators.get(1).getType() + == OperatorType.SetTransform; + boolean canSetTransformPushDown = + needSetTransformPushDown + && pair.k.isSupportProjectWithSetTransform( + (SetTransform) operators.get(1), dataArea); if (isDummyStorageUnit) { if (needSelectPushDown) { result = pair.k.executeProjectDummyWithSelect( (Project) op, (Select) operators.get(1), dataArea); + } else if (needSetTransformPushDown) { + throw new IllegalStateException(); } else { result = pair.k.executeProjectDummy((Project) op, dataArea); } @@ -171,6 +179,36 @@ private StoragePhysicalTaskExecutor() { result = pair.k.executeProjectWithSelect( (Project) op, (Select) operators.get(1), dataArea); + } else if (needSetTransformPushDown) { + if (canSetTransformPushDown) { + result = + pair.k.executeProjectWithSetTransform( + (Project) op, + (SetTransform) operators.get(1), + dataArea); + } else { + TaskExecuteResult tempResult = + pair.k.executeProject((Project) op, dataArea); + if (tempResult.getException() != null) { + result = tempResult; + } else { + // set transform push down is not supported, execute set + // transform in memory + OperatorMemoryExecutor executor = + OperatorMemoryExecutorFactory.getInstance() + .getMemoryExecutor(); + try { + RowStream rowStream = + executor.executeUnaryOperator( + (SetTransform) operators.get(1), + tempResult.getRowStream(), + task.getContext()); + result = new TaskExecuteResult(rowStream); + } catch (PhysicalException e) { + result = new TaskExecuteResult(e); + } + } + } } else { result = pair.k.executeProject((Project) op, dataArea); } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/policy/naive/NaivePolicy.java b/core/src/main/java/cn/edu/tsinghua/iginx/policy/naive/NaivePolicy.java index f8aea68416..3372fa62bc 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/policy/naive/NaivePolicy.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/policy/naive/NaivePolicy.java @@ -176,7 +176,7 @@ public Pair, List> generateInitialFragmentsA private Pair>, List> generateInitialFragmentsAndStorageUnitsByClients( List paths, KeyInterval keyInterval) { - Map> fragmentMap = new HashMap<>(); + Map> fragmentMap = new TreeMap<>(); List storageUnitList = new ArrayList<>(); List storageEngineList = iMetaManager.getWritableStorageEngineList(); @@ -184,13 +184,13 @@ public Pair, List> generateInitialFragmentsA String[] clients = ConfigDescriptor.getInstance().getConfig().getClients().split(","); int instancesNumPerClient = - ConfigDescriptor.getInstance().getConfig().getInstancesNumPerClient() - 1; - int replicaNum = + ConfigDescriptor.getInstance().getConfig().getInstancesNumPerClient(); + int totalReplicaNum = Math.min(1 + ConfigDescriptor.getInstance().getConfig().getReplicaNum(), storageEngineNum); String[] prefixes = new String[clients.length * instancesNumPerClient]; for (int i = 0; i < clients.length; i++) { for (int j = 0; j < instancesNumPerClient; j++) { - prefixes[i * instancesNumPerClient + j] = clients[i] + (j + 2); + prefixes[i * instancesNumPerClient + j] = clients[i] + (j + 1); } } Arrays.sort(prefixes); @@ -198,23 +198,55 @@ public Pair, List> generateInitialFragmentsA List fragmentMetaList; String masterId; StorageUnitMeta storageUnit; - for (int i = 0; i < clients.length * instancesNumPerClient - 1; i++) { + + // (null, prefixes[1]) + // 包括prefixes[0] + fragmentMetaList = new ArrayList<>(); + masterId = RandomStringUtils.randomAlphanumeric(16); + storageUnit = new StorageUnitMeta(masterId, storageEngineList.get(0).getId(), masterId, true); + for (int i = 1; i < totalReplicaNum; i++) { + storageUnit.addReplica( + new StorageUnitMeta( + RandomStringUtils.randomAlphanumeric(16), + storageEngineList.get(i).getId(), + masterId, + false)); + } + storageUnitList.add(storageUnit); + fragmentMetaList.add(new FragmentMeta(null, prefixes[1], 0, Long.MAX_VALUE, masterId)); + fragmentMap.put(new ColumnsInterval(null, prefixes[1]), fragmentMetaList); + + for (int i = 1; i < clients.length * instancesNumPerClient - 1; i++) { + int masterIndex = i / instancesNumPerClient; fragmentMetaList = new ArrayList<>(); masterId = RandomStringUtils.randomAlphanumeric(16); + // TODO 全链路同机 storageUnit = - new StorageUnitMeta( - masterId, storageEngineList.get(i % storageEngineNum).getId(), masterId, true); + new StorageUnitMeta(masterId, storageEngineList.get(masterIndex).getId(), masterId, true); + // TODO Round Robin + // storageUnit = + // new StorageUnitMeta( + // masterId, storageEngineList.get(i % storageEngineNum).getId(), masterId, + // true); // storageUnit = new StorageUnitMeta(masterId, getStorageEngineList().get(i * // 2 % getStorageEngineList().size()).getId(), masterId, true); - for (int j = i + 1; j < i + replicaNum; j++) { + for (int j = 1; j < totalReplicaNum; j++) { + int replicaIndex = (masterIndex + j) % storageEngineNum; + // TODO 全链路同机 storageUnit.addReplica( new StorageUnitMeta( RandomStringUtils.randomAlphanumeric(16), - storageEngineList.get(j % storageEngineNum).getId(), + storageEngineList.get(replicaIndex).getId(), masterId, false)); - // storageUnit.addReplica(new - // StorageUnitMeta(RandomStringUtils.randomAlphanumeric(16), + // TODO Round Robin + // storageUnit.addReplica( + // new StorageUnitMeta( + // RandomStringUtils.randomAlphanumeric(16), + // storageEngineList.get(j % storageEngineNum).getId(), + // masterId, + // false)); + // storageUnit.addReplica(new StorageUnitMeta(RandomStringUtils.randomAlphanumeric(16), // getStorageEngineList().get((i * 2 + 1) % getStorageEngineList().size()).getId(), // masterId, false)); } @@ -224,31 +256,17 @@ public Pair, List> generateInitialFragmentsA fragmentMap.put(new ColumnsInterval(prefixes[i], prefixes[i + 1]), fragmentMetaList); } - fragmentMetaList = new ArrayList<>(); - masterId = RandomStringUtils.randomAlphanumeric(16); - storageUnit = new StorageUnitMeta(masterId, storageEngineList.get(0).getId(), masterId, true); - for (int i = 1; i < replicaNum; i++) { - storageUnit.addReplica( - new StorageUnitMeta( - RandomStringUtils.randomAlphanumeric(16), - storageEngineList.get(i).getId(), - masterId, - false)); - } - storageUnitList.add(storageUnit); - fragmentMetaList.add(new FragmentMeta(null, prefixes[0], 0, Long.MAX_VALUE, masterId)); - fragmentMap.put(new ColumnsInterval(null, prefixes[0]), fragmentMetaList); - + // [prefixes[clients.length * instancesNumPerClient - 1], null) fragmentMetaList = new ArrayList<>(); masterId = RandomStringUtils.randomAlphanumeric(16); storageUnit = new StorageUnitMeta( masterId, storageEngineList.get(storageEngineNum - 1).getId(), masterId, true); - for (int i = 1; i < replicaNum; i++) { + for (int i = 1; i < totalReplicaNum; i++) { storageUnit.addReplica( new StorageUnitMeta( RandomStringUtils.randomAlphanumeric(16), - storageEngineList.get(storageEngineNum - 1 - i).getId(), + storageEngineList.get((storageEngineNum - 1 + i) % storageEngineNum).getId(), masterId, false)); } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/UnarySelectStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/UnarySelectStatement.java index c78b28063d..32dedde8c1 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/UnarySelectStatement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/UnarySelectStatement.java @@ -81,8 +81,7 @@ public UnarySelectStatement(List paths, long startKey, long endKey) { } // aggregate query - public UnarySelectStatement( - List paths, long startKey, long endKey, AggregateType aggregateType) { + public UnarySelectStatement(List paths, AggregateType aggregateType) { this(false); if (aggregateType == AggregateType.LAST || aggregateType == AggregateType.FIRST) { @@ -100,7 +99,11 @@ public UnarySelectStatement( }); setHasFunc(true); + } + public UnarySelectStatement( + List paths, long startKey, long endKey, AggregateType aggregateType) { + this(paths, aggregateType); this.setFromSession(startKey, endKey); } diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/ParquetStorage.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/ParquetStorage.java index f8783f700e..e03d3790e6 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/ParquetStorage.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/ParquetStorage.java @@ -26,15 +26,18 @@ import cn.edu.tsinghua.iginx.engine.physical.storage.domain.Column; import cn.edu.tsinghua.iginx.engine.physical.storage.domain.DataArea; import cn.edu.tsinghua.iginx.engine.physical.task.TaskExecuteResult; -import cn.edu.tsinghua.iginx.engine.shared.operator.Delete; -import cn.edu.tsinghua.iginx.engine.shared.operator.Insert; -import cn.edu.tsinghua.iginx.engine.shared.operator.Project; -import cn.edu.tsinghua.iginx.engine.shared.operator.Select; +import cn.edu.tsinghua.iginx.engine.shared.function.Function; +import cn.edu.tsinghua.iginx.engine.shared.function.FunctionCall; +import cn.edu.tsinghua.iginx.engine.shared.function.FunctionParams; +import cn.edu.tsinghua.iginx.engine.shared.function.FunctionType; +import cn.edu.tsinghua.iginx.engine.shared.operator.*; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.AndFilter; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Filter; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.KeyFilter; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Op; -import cn.edu.tsinghua.iginx.metadata.entity.*; +import cn.edu.tsinghua.iginx.metadata.entity.ColumnsInterval; +import cn.edu.tsinghua.iginx.metadata.entity.KeyInterval; +import cn.edu.tsinghua.iginx.metadata.entity.StorageEngineMeta; import cn.edu.tsinghua.iginx.parquet.exec.Executor; import cn.edu.tsinghua.iginx.parquet.exec.LocalExecutor; import cn.edu.tsinghua.iginx.parquet.exec.RemoteExecutor; @@ -113,7 +116,12 @@ public TaskExecuteResult executeProject(Project project, DataArea dataArea) { new KeyFilter(Op.GE, keyInterval.getStartKey()), new KeyFilter(Op.L, keyInterval.getEndKey()))); return executor.executeProjectTask( - project.getPatterns(), project.getTagFilter(), filter, dataArea.getStorageUnit(), false); + project.getPatterns(), + project.getTagFilter(), + filter, + null, + dataArea.getStorageUnit(), + false); } @Override @@ -125,7 +133,12 @@ public TaskExecuteResult executeProjectDummy(Project project, DataArea dataArea) new KeyFilter(Op.GE, keyInterval.getStartKey()), new KeyFilter(Op.L, keyInterval.getEndKey()))); return executor.executeProjectTask( - project.getPatterns(), project.getTagFilter(), filter, dataArea.getStorageUnit(), true); + project.getPatterns(), + project.getTagFilter(), + filter, + null, + dataArea.getStorageUnit(), + true); } @Override @@ -144,7 +157,12 @@ public TaskExecuteResult executeProjectWithSelect( new KeyFilter(Op.L, keyInterval.getEndKey()), select.getFilter())); return executor.executeProjectTask( - project.getPatterns(), project.getTagFilter(), filter, dataArea.getStorageUnit(), false); + project.getPatterns(), + project.getTagFilter(), + filter, + null, + dataArea.getStorageUnit(), + false); } @Override @@ -158,7 +176,57 @@ public TaskExecuteResult executeProjectDummyWithSelect( new KeyFilter(Op.L, keyInterval.getEndKey()), select.getFilter())); return executor.executeProjectTask( - project.getPatterns(), project.getTagFilter(), filter, dataArea.getStorageUnit(), true); + project.getPatterns(), + project.getTagFilter(), + filter, + null, + dataArea.getStorageUnit(), + true); + } + + @Override + public boolean isSupportProjectWithSetTransform(SetTransform setTransform, DataArea dataArea) { + // just push down in full column fragment + KeyInterval keyInterval = dataArea.getKeyInterval(); + if (keyInterval.getStartKey() > 0 || keyInterval.getEndKey() < Long.MAX_VALUE) { + return false; + } + + // just push down count(*) for now + List functionCalls = setTransform.getFunctionCallList(); + if (functionCalls.size() != 1) { + return false; + } + FunctionCall functionCall = functionCalls.get(0); + Function function = functionCall.getFunction(); + FunctionParams params = functionCall.getParams(); + if (function.getFunctionType() != FunctionType.System) { + return false; + } + if (!function.getIdentifier().equals("count")) { + return false; + } + if (params.getPaths().size() != 1) { + return false; + } + String path = params.getPaths().get(0); + return path.equals("*") || path.equals("*.*"); + } + + @Override + public TaskExecuteResult executeProjectWithSetTransform( + Project project, SetTransform setTransform, DataArea dataArea) { + if (!isSupportProjectWithSetTransform(setTransform, dataArea)) { + throw new IllegalArgumentException("unsupported set transform"); + } + + return executor.executeProjectTask( + project.getPatterns(), + project.getTagFilter(), + null, + setTransform.getFunctionCallList(), + dataArea.getStorageUnit(), + false); } @Override diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/Database.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/Database.java index ea8b3f1072..9881bb8476 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/Database.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/Database.java @@ -18,18 +18,34 @@ package cn.edu.tsinghua.iginx.parquet.db; +import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Filter; import cn.edu.tsinghua.iginx.parquet.db.util.AreaSet; import cn.edu.tsinghua.iginx.parquet.db.util.iterator.Scanner; import cn.edu.tsinghua.iginx.parquet.util.exception.StorageException; +import cn.edu.tsinghua.iginx.thrift.DataType; +import com.google.common.collect.RangeSet; +import java.io.IOException; import java.util.Map; +import java.util.Set; +import org.apache.arrow.vector.types.pojo.Field; -public interface Database, F, T, V> extends ImmutableDatabase { +public interface Database extends AutoCloseable { - void upsertRows(Scanner> scanner, Map schema) throws StorageException; + Scanner> query( + Set fields, RangeSet ranges, Filter filter) throws StorageException, IOException; - void upsertColumns(Scanner> scanner, Map schema) throws StorageException; + Map count(Set strings) + throws InterruptedException, IOException, StorageException; - void delete(AreaSet areas) throws StorageException; + Set schema() throws StorageException; + + void upsertRows(Scanner> scanner, Map schema) + throws StorageException, InterruptedException; + + void upsertColumns(Scanner> scanner, Map schema) + throws StorageException, InterruptedException; + + void delete(AreaSet areas) throws StorageException; void clear() throws StorageException; } diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/ImmutableDatabase.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/ImmutableDatabase.java deleted file mode 100644 index e32b9108ce..0000000000 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/ImmutableDatabase.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * IGinX - the polystore system with high performance - * Copyright (C) Tsinghua University - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package cn.edu.tsinghua.iginx.parquet.db; - -import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Filter; -import cn.edu.tsinghua.iginx.parquet.db.util.iterator.Scanner; -import cn.edu.tsinghua.iginx.parquet.util.exception.StorageException; -import com.google.common.collect.Range; -import com.google.common.collect.RangeSet; -import java.util.Map; -import java.util.Optional; -import java.util.Set; - -public interface ImmutableDatabase, F, T, V> extends AutoCloseable { - Scanner> query(Set fields, RangeSet ranges, Filter filter) - throws StorageException; - - Optional> range() throws StorageException; - - Map schema() throws StorageException; -} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/OneTierDB.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/OneTierDB.java index f93fa6d7d8..76001ecbee 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/OneTierDB.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/OneTierDB.java @@ -22,350 +22,207 @@ import cn.edu.tsinghua.iginx.parquet.db.Database; import cn.edu.tsinghua.iginx.parquet.db.lsm.api.ReadWriter; import cn.edu.tsinghua.iginx.parquet.db.lsm.buffer.DataBuffer; -import cn.edu.tsinghua.iginx.parquet.db.lsm.table.MemoryTable; -import cn.edu.tsinghua.iginx.parquet.db.lsm.table.Table; -import cn.edu.tsinghua.iginx.parquet.db.lsm.table.TableIndex; +import cn.edu.tsinghua.iginx.parquet.db.lsm.buffer.MemTableQueue; +import cn.edu.tsinghua.iginx.parquet.db.lsm.buffer.chunk.Chunk; +import cn.edu.tsinghua.iginx.parquet.db.lsm.compact.Flusher; import cn.edu.tsinghua.iginx.parquet.db.lsm.table.TableStorage; import cn.edu.tsinghua.iginx.parquet.db.util.AreaSet; +import cn.edu.tsinghua.iginx.parquet.db.util.WriteBatches; import cn.edu.tsinghua.iginx.parquet.db.util.iterator.BatchPlaneScanner; import cn.edu.tsinghua.iginx.parquet.db.util.iterator.Scanner; +import cn.edu.tsinghua.iginx.parquet.manager.utils.TagKVUtils; +import cn.edu.tsinghua.iginx.parquet.util.NoexceptAutoCloseable; +import cn.edu.tsinghua.iginx.parquet.util.NoexceptAutoCloseables; import cn.edu.tsinghua.iginx.parquet.util.Shared; -import cn.edu.tsinghua.iginx.parquet.util.exception.NotIntegrityException; +import cn.edu.tsinghua.iginx.parquet.util.arrow.ArrowFields; import cn.edu.tsinghua.iginx.parquet.util.exception.StorageException; import cn.edu.tsinghua.iginx.parquet.util.exception.StorageRuntimeException; +import cn.edu.tsinghua.iginx.parquet.util.exception.TypeConflictedException; +import cn.edu.tsinghua.iginx.thrift.DataType; import com.google.common.collect.Range; import com.google.common.collect.RangeSet; -import com.google.common.collect.TreeRangeSet; -import com.google.common.util.concurrent.ThreadFactoryBuilder; import java.io.IOException; -import java.util.*; -import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.atomic.LongAdder; -import java.util.concurrent.locks.Lock; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.stream.Collectors; +import javax.annotation.WillClose; +import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.util.AutoCloseables; +import org.apache.arrow.vector.types.pojo.Field; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class OneTierDB, F, T, V> implements Database { +public class OneTierDB implements Database { private static final Logger LOGGER = LoggerFactory.getLogger(OneTierDB.class); - private final Shared shared; - private final TableStorage tableStorage; - private final TableIndex tableIndex; - - private DataBuffer writeBuffer = new DataBuffer<>(); - private String previousTableName = null; - private final AtomicLong bufferDirtiedTime = new AtomicLong(Long.MAX_VALUE); - private final LongAdder bufferInsertedSize = new LongAdder(); - private final Lock checkLock = new ReentrantLock(true); - private final ReadWriteLock deleteLock = new ReentrantReadWriteLock(true); - private final ReadWriteLock commitLock = new ReentrantReadWriteLock(true); - private final ReadWriteLock storageLock = new ReentrantReadWriteLock(true); - private final ScheduledExecutorService scheduler; + private final ReadWriteLock lock = new ReentrantReadWriteLock(true); private final String name; - private final long timeout; + private final Shared shared; + private final BufferAllocator allocator; + private final TableStorage tableStorage; + private final MemTableQueue memTableQueue; + private final Flusher flusher; - public OneTierDB(String name, Shared shared, ReadWriter readerWriter) - throws IOException { + public OneTierDB(String name, Shared shared, ReadWriter readerWriter) throws IOException { this.name = name; this.shared = shared; - this.tableStorage = new TableStorage<>(shared, readerWriter); - this.tableIndex = new TableIndex<>(tableStorage); - - ThreadFactory threadFactory = - new ThreadFactoryBuilder().setNameFormat("OneTierDB-" + name + "-%d").build(); - this.timeout = shared.getStorageProperties().getWriteBufferTimeout().toMillis(); - this.scheduler = Executors.newSingleThreadScheduledExecutor(threadFactory); - if (timeout > 0) { - LOGGER.info("db {} start to check buffer timeout check every {}ms", name, timeout); - this.scheduler.scheduleWithFixedDelay( - this::checkBufferTimeout, timeout, timeout, TimeUnit.MILLISECONDS); - } else { - LOGGER.info("db {} buffer timeout check is immediately after writing", name); - } + this.allocator = shared.getAllocator().newChildAllocator(name, 0, Long.MAX_VALUE); + this.tableStorage = new TableStorage(shared, readerWriter); + this.memTableQueue = new MemTableQueue(shared, allocator); + this.flusher = new Flusher(name, shared, allocator, memTableQueue, tableStorage); } @Override - public Scanner> query(Set fields, RangeSet ranges, Filter filter) - throws StorageException { - DataBuffer readBuffer = new DataBuffer<>(); - - commitLock.readLock().lock(); - deleteLock.readLock().lock(); - storageLock.readLock().lock(); + public Scanner> query( + Set fields, RangeSet ranges, Filter filter) + throws IOException, StorageException { + Set innerFields = + fields.stream() + .map(field -> TagKVUtils.toFullName(ArrowFields.toColumnKey(field))) + .collect(Collectors.toSet()); + + lock.readLock().lock(); try { - AreaSet areas = new AreaSet<>(); - areas.add(fields, ranges); - Set tables = tableIndex.find(areas); - List sortedTableNames = new ArrayList<>(tables); - sortedTableNames.sort(Comparator.naturalOrder()); - for (String tableName : sortedTableNames) { - Table table = tableStorage.get(tableName); - try (Scanner> scanner = table.scan(fields, ranges)) { + List>> inMemories = + memTableQueue.scan(new ArrayList<>(fields), ranges, allocator); + try (AutoCloseable c = AutoCloseables.all(inMemories)) { + DataBuffer readBuffer = + tableStorage.query(innerFields, ranges, filter); + for (Scanner> scanner : inMemories) { readBuffer.putRows(scanner); } + return readBuffer.scanRows(innerFields, Range.all()); + } catch (Exception e) { + throw new IllegalStateException(e); } - - for (Range range : ranges.asRanges()) { - readBuffer.putRows(writeBuffer.scanRows(fields, range)); - } - } catch (IOException | StorageException e) { - throw new RuntimeException(e); } finally { - storageLock.readLock().unlock(); - deleteLock.readLock().unlock(); - commitLock.readLock().unlock(); + lock.readLock().unlock(); } - - return readBuffer.scanRows(fields, Range.all()); } @Override - public Optional> range() throws StorageException { - commitLock.readLock().lock(); - deleteLock.readLock().lock(); - storageLock.readLock().lock(); + public Map count(Set fields) + throws InterruptedException, IOException, StorageException { + lock.readLock().lock(); try { - TreeRangeSet rangeSet = TreeRangeSet.create(); - for (Range range : tableIndex.ranges().values()) { - rangeSet.add(range); - } - for (Range range : writeBuffer.ranges().values()) { - rangeSet.add(range); - } - if (rangeSet.isEmpty()) { - return Optional.empty(); - } else { - return Optional.of(rangeSet.span()); - } + // to simplify the implementation, we flush the memTableQueue before counting + memTableQueue.compact(); + memTableQueue.flush(); + Set innerFields = + fields.stream() + .map(field -> TagKVUtils.toFullName(ArrowFields.toColumnKey(field))) + .collect(Collectors.toSet()); + return tableStorage.count(innerFields); } finally { - storageLock.readLock().unlock(); - deleteLock.readLock().unlock(); - commitLock.readLock().unlock(); + lock.readLock().unlock(); } } @Override - public Map schema() throws StorageException { - return tableIndex.getType(); + public Set schema() throws StorageException { + lock.readLock().lock(); + try { + Map types = tableStorage.schema(); + return ArrowFields.of(types); + } finally { + lock.readLock().unlock(); + } } @Override - public void upsertRows(Scanner> scanner, Map schema) - throws StorageException { - try (Scanner>> batchScanner = + public void upsertRows( + Scanner> scanner, Map schema) + throws StorageException, InterruptedException { + try (Scanner>> batchScanner = new BatchPlaneScanner<>(scanner, shared.getStorageProperties().getWriteBatchSize())) { while (batchScanner.iterate()) { - beforeWriting(); - try { - tableIndex.declareFields(schema); - try (Scanner> batch = batchScanner.value()) { - writeBuffer.putRows(batch); - bufferInsertedSize.add(batchScanner.key()); - } - } finally { - afterWriting(); + try (Scanner> batch = batchScanner.value()) { + putAll(WriteBatches.recordOfRows(batch, schema, allocator), schema); } } } - updateDirty(); - if (timeout <= 0) { - checkBufferTimeout(); - } } @Override - public void upsertColumns(Scanner> scanner, Map schema) - throws StorageException { - try (Scanner>> batchScanner = + public void upsertColumns( + Scanner> scanner, Map schema) + throws StorageException, InterruptedException { + try (Scanner>> batchScanner = new BatchPlaneScanner<>(scanner, shared.getStorageProperties().getWriteBatchSize())) { while (batchScanner.iterate()) { - beforeWriting(); - try { - tableIndex.declareFields(schema); - try (Scanner> batch = batchScanner.value()) { - writeBuffer.putColumns(batch); - bufferInsertedSize.add(batchScanner.key()); - } - } finally { - afterWriting(); + try (Scanner> batch = batchScanner.value()) { + putAll(WriteBatches.recordOfColumns(batch, schema, allocator), schema); } } } - updateDirty(); - if (timeout <= 0) { - checkBufferTimeout(); - } - } - - private void updateDirty() { - long currentTime = System.currentTimeMillis(); - bufferDirtiedTime.updateAndGet(oldTime -> Math.min(oldTime, currentTime)); - } - - private void beforeWriting() { - checkBufferSize(); - commitLock.readLock().lock(); - deleteLock.readLock().lock(); - storageLock.readLock().lock(); } - private void afterWriting() { - storageLock.readLock().unlock(); - deleteLock.readLock().unlock(); - commitLock.readLock().unlock(); - } - - private void checkBufferSize() { - checkLock.lock(); - try { - if (bufferInsertedSize.sum() < shared.getStorageProperties().getWriteBufferSize()) { - return; + private void putAll(@WillClose Iterable chunks, Map schema) + throws TypeConflictedException, InterruptedException { + lock.readLock().lock(); + try (NoexceptAutoCloseable guarder = NoexceptAutoCloseables.all(chunks)) { + tableStorage.declareFields(schema); + memTableQueue.store(chunks); + if (shared.getStorageProperties().getWriteBufferTimeout().toMillis() <= 0) { + memTableQueue.flush(); } - if (LOGGER.isDebugEnabled()) { - LOGGER.debug( - "flushing is triggered when write buffer size {} reaching {}", - bufferInsertedSize.sum(), - shared.getStorageProperties().getWriteBufferSize()); - } - commitMemoryTable(false, new CountDownLatch(1)); } finally { - checkLock.unlock(); - } - } - - private void checkBufferTimeout() { - CountDownLatch latch = new CountDownLatch(1); - checkLock.lock(); - try { - long interval = System.currentTimeMillis() - bufferDirtiedTime.get(); - if (interval < timeout) { - return; - } - - LOGGER.debug( - "flushing is triggered when write buffer dirtied time {}ms reaching {}ms", - interval, - timeout); - boolean temp = bufferInsertedSize.sum() < shared.getStorageProperties().getWriteBufferSize(); - commitMemoryTable(temp, latch); - } finally { - checkLock.unlock(); - } - LOGGER.debug("waiting for flushing table"); - try { - latch.await(); - } catch (InterruptedException e) { - throw new StorageRuntimeException(e); - } - LOGGER.debug("table is flushed"); - } - - private synchronized void commitMemoryTable(boolean temp, CountDownLatch latch) { - commitLock.writeLock().lock(); - deleteLock.readLock().lock(); - try { - Map types = - tableIndex.getType( - writeBuffer.fields(), - f -> { - throw new NotIntegrityException("field " + f + " is not found in schema"); - }); - - MemoryTable table = new MemoryTable<>(writeBuffer, types); - - String toDelete = previousTableName; - String committedTableName = - tableStorage.flush( - table, - () -> { - if (toDelete != null) { - LOGGER.debug("delete table {}", toDelete); - storageLock.writeLock().lock(); - try { - tableIndex.removeTable(toDelete); - tableStorage.remove(toDelete); - } catch (Throwable e) { - LOGGER.error("failed to delete table {}", toDelete, e); - } finally { - storageLock.writeLock().unlock(); - } - } - latch.countDown(); - }); - - LOGGER.debug( - "submit table {} to flush, with temp={}, latch={}", committedTableName, temp, latch); - tableIndex.addTable(committedTableName, table.getMeta()); - this.bufferDirtiedTime.set(Long.MAX_VALUE); - previousTableName = committedTableName; - if (!temp) { - LOGGER.info("reset write buffer"); - this.writeBuffer = new DataBuffer<>(); - bufferInsertedSize.reset(); - previousTableName = null; - } - } catch (InterruptedException e) { - throw new StorageRuntimeException(e); - } finally { - deleteLock.readLock().unlock(); - commitLock.writeLock().unlock(); + lock.readLock().unlock(); } } @Override - public void delete(AreaSet areas) throws StorageException { - commitLock.readLock().lock(); - deleteLock.writeLock().lock(); - storageLock.readLock().lock(); + public void delete(AreaSet range) throws StorageException { + AreaSet innerAreas = ArrowFields.toInnerAreas(range); + lock.writeLock().lock(); try { - LOGGER.info("start to delete {} in {}", areas, name); - writeBuffer.remove(areas); - Set tables = tableIndex.find(areas); - tableStorage.delete(tables, areas); - tableIndex.delete(areas); + LOGGER.debug("start to delete {} in {}", range, name); + memTableQueue.delete(range); + tableStorage.delete(innerAreas); } catch (IOException e) { throw new StorageRuntimeException(e); } finally { - storageLock.readLock().unlock(); - deleteLock.writeLock().unlock(); - commitLock.readLock().unlock(); + lock.writeLock().unlock(); } } @Override public void clear() throws StorageException { - commitLock.readLock().lock(); - deleteLock.writeLock().lock(); + lock.writeLock().lock(); try { LOGGER.debug("start to clear {}", name); - previousTableName = null; + flusher.stop(); + memTableQueue.clear(); tableStorage.clear(); - tableIndex.clear(); - writeBuffer.clear(); - bufferDirtiedTime.set(Long.MAX_VALUE); - bufferInsertedSize.reset(); - } catch (InterruptedException e) { - throw new StorageRuntimeException(e); + if (allocator.getAllocatedMemory() > 0) { + throw new IllegalStateException("allocator is not empty: " + allocator.toVerboseString()); + } + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("cleared {}, allocator: {}", name, allocator); + } + flusher.start(); } finally { - deleteLock.writeLock().unlock(); - commitLock.readLock().unlock(); + lock.writeLock().unlock(); } } @Override public void close() throws Exception { - scheduler.shutdown(); - if (shared.getStorageProperties().toFlushOnClose()) { - LOGGER.info("flushing is triggered when closing"); - CountDownLatch latch = new CountDownLatch(1); - commitMemoryTable(false, latch); - latch.await(); + lock.writeLock().lock(); + try { + if (shared.getStorageProperties().toFlushOnClose()) { + memTableQueue.flush(); + } + flusher.close(); + memTableQueue.close(); + tableStorage.close(); + allocator.close(); + } finally { + lock.writeLock().unlock(); } - tableStorage.close(); - tableIndex.close(); } } diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/api/ReadWriter.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/api/ReadWriter.java index 8e251d7c6a..7f6488432d 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/api/ReadWriter.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/api/ReadWriter.java @@ -25,17 +25,19 @@ import java.io.IOException; import java.util.Set; -public interface ReadWriter, F, T, V> { +public interface ReadWriter { - void flush(String name, TableMeta meta, Scanner> scanner) + String getName(); + + void flush(String name, TableMeta meta, Scanner> scanner) throws IOException; - TableMeta readMeta(String name) throws IOException; + TableMeta readMeta(String name) throws IOException; - Scanner> scanData( - String name, Set fields, RangeSet ranges, Filter predicate) throws IOException; + Scanner> scanData( + String name, Set fields, RangeSet ranges, Filter predicate) throws IOException; - void delete(String name, AreaSet areas) throws IOException; + void delete(String name, AreaSet areas) throws IOException; void delete(String name); diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/api/TableMeta.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/api/TableMeta.java index 65665fce2b..85a6d21764 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/api/TableMeta.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/api/TableMeta.java @@ -18,16 +18,29 @@ package cn.edu.tsinghua.iginx.parquet.db.lsm.api; +import cn.edu.tsinghua.iginx.thrift.DataType; import com.google.common.collect.Range; import java.util.Map; +import javax.annotation.Nullable; -public interface TableMeta, F, T, V> { - Map getSchema(); +public interface TableMeta { + Map getSchema(); - /** - * Get the range of the table. 若某个字段没有数据,则返回的range为null - * - * @return the range of the table, the key is the field name, the value is the range of the field - */ - Map> getRanges(); + Range getRange(String field); + + default Range getRange(Iterable fields) { + Range range = null; + for (String field : fields) { + Range fieldRange = getRange(field); + if (range == null) { + range = getRange(field); + } else { + range = range.span(fieldRange); + } + } + return range; + } + + @Nullable + Long getValueCount(String field); } diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/ActiveMemTable.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/ActiveMemTable.java new file mode 100644 index 0000000000..e9a7fdbe6c --- /dev/null +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/ActiveMemTable.java @@ -0,0 +1,230 @@ +package cn.edu.tsinghua.iginx.parquet.db.lsm.buffer; + +import cn.edu.tsinghua.iginx.parquet.db.lsm.buffer.chunk.Chunk; +import cn.edu.tsinghua.iginx.parquet.db.lsm.table.MemoryTable; +import cn.edu.tsinghua.iginx.parquet.db.util.AreaSet; +import cn.edu.tsinghua.iginx.parquet.db.util.iterator.Scanner; +import cn.edu.tsinghua.iginx.parquet.util.Awaitable; +import cn.edu.tsinghua.iginx.parquet.util.NoexceptAutoCloseable; +import cn.edu.tsinghua.iginx.parquet.util.Shared; +import cn.edu.tsinghua.iginx.parquet.util.arrow.ArrowFields; +import com.google.common.collect.RangeSet; +import java.io.IOException; +import java.util.*; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.function.Consumer; +import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.util.Preconditions; +import org.apache.arrow.vector.types.pojo.Field; + +public class ActiveMemTable { + + private final ReentrantReadWriteLock switchTableLock = new ReentrantReadWriteLock(true); + private final ReentrantLock createLock = new ReentrantLock(true); + private final ReentrantReadWriteLock flushLock = new ReentrantReadWriteLock(true); + + private final Shared shared; + private final BufferAllocator allocator; + + private long activeId = 0; + private BufferAllocator activeAllocator = null; + private MemTable activeTable = null; + private final NavigableMap awaiting = new TreeMap<>(); + + ActiveMemTable(Shared shared, BufferAllocator allocator) { + this.shared = Preconditions.checkNotNull(shared); + this.allocator = Preconditions.checkNotNull(allocator); + } + + public boolean isOverloaded() { + switchTableLock.readLock().lock(); + try { + return activeAllocator != null + && activeAllocator.getAllocatedMemory() + >= shared.getStorageProperties().getWriteBufferSize(); + } finally { + switchTableLock.readLock().unlock(); + } + } + + public void store(Iterable data) { + switchTableLock.readLock().lock(); + try { + createMemtableIfNotExist(); + activeTable.store(data); + } finally { + switchTableLock.readLock().unlock(); + } + } + + private void createMemtableIfNotExist() { + createLock.lock(); + try { + if (activeTable == null) { + assert activeAllocator == null; + String name = + String.join( + "-", allocator.getName(), MemTable.class.getSimpleName(), String.valueOf(activeId)); + activeAllocator = allocator.newChildAllocator(name, 0, Long.MAX_VALUE); + activeTable = + new MemTable( + shared.getStorageProperties().getWriteBufferChunkFactory(), + activeAllocator, + shared.getStorageProperties().getWriteBufferChunkValuesMax(), + shared.getStorageProperties().getWriteBufferChunkValuesMin()); + } + } finally { + createLock.unlock(); + } + } + + public Awaitable flush() { + flushLock.writeLock().lock(); + try { + switchTableLock.readLock().lock(); + try { + if (activeTable == null) { + return () -> {}; + } + } finally { + switchTableLock.readLock().unlock(); + } + CountDownLatch latch = new CountDownLatch(1); + awaiting.put(activeId++, latch); + return latch::await; + } finally { + flushLock.writeLock().unlock(); + } + } + + public Map archive() throws InterruptedException { + shared.getMemTablePermits().acquire(); + flushLock.writeLock().lock(); + switchTableLock.writeLock().lock(); + try { + if (activeTable == null) { + shared.getMemTablePermits().release(); + return Collections.emptyMap(); + } + Map result = new HashMap<>(); + List onClose = new ArrayList<>(); + awaiting.values().forEach(latch -> onClose.add(latch::countDown)); + onClose.add(activeAllocator::close); + onClose.add(() -> shared.getMemTablePermits().release()); + result.put(activeId++, new ArchivedMemTable(activeTable, onClose)); + awaiting.clear(); + activeTable = null; + activeAllocator = null; + return result; + } finally { + switchTableLock.writeLock().unlock(); + flushLock.writeLock().unlock(); + } + } + + public MemoryTable snapshot(long id, BufferAllocator allocator) { + flushLock.readLock().lock(); + try { + if (awaiting.containsKey(id)) { + switchTableLock.readLock().lock(); + try { + return activeTable.snapshot(allocator); + } finally { + switchTableLock.readLock().unlock(); + } + } else { + return MemoryTable.empty(); + } + } finally { + flushLock.readLock().unlock(); + } + } + + public Long newestKey(long idAtLeast) { + flushLock.readLock().lock(); + try { + if (!awaiting.isEmpty()) { + long id = awaiting.lastKey(); + if (id >= idAtLeast) { + return id; + } + } + return null; + } finally { + flushLock.readLock().unlock(); + } + } + + public boolean eliminate(long id) throws InterruptedException { + CountDownLatch latch = null; + flushLock.writeLock().lock(); + try { + if (awaiting.containsKey(id)) { + latch = new CountDownLatch(1); + } + SortedMap older = awaiting.headMap(id, true); + older.values().forEach(CountDownLatch::countDown); + older.clear(); + if (latch != null) { + awaiting.put(id, latch); + } + } finally { + flushLock.writeLock().unlock(); + } + if (latch != null) { + latch.await(); + } + return latch != null; + } + + public void delete(AreaSet areas) { + switchTableLock.readLock().lock(); + try { + if (activeTable != null) { + activeTable.delete(areas); + } + } finally { + switchTableLock.readLock().unlock(); + } + } + + public void reset() { + flushLock.writeLock().lock(); + switchTableLock.writeLock().lock(); + try { + if (activeTable != null) { + activeTable.close(); + activeAllocator.close(); + } + activeId = 0; + activeTable = null; + activeAllocator = null; + awaiting.values().forEach(CountDownLatch::countDown); + awaiting.clear(); + } finally { + switchTableLock.writeLock().unlock(); + flushLock.writeLock().unlock(); + } + } + + public void scan( + List fields, + RangeSet ranges, + BufferAllocator allocator, + Consumer>> consumer) + throws IOException { + switchTableLock.readLock().lock(); + try { + if (activeTable != null) { + Set innerFields = ArrowFields.toInnerFields(fields); + try (MemoryTable table = activeTable.snapshot(fields, ranges, allocator)) { + consumer.accept(table.scan(innerFields, ranges)); + } + } + } finally { + switchTableLock.readLock().unlock(); + } + } +} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/ArchivedMemTable.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/ArchivedMemTable.java new file mode 100644 index 0000000000..ebcb05518e --- /dev/null +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/ArchivedMemTable.java @@ -0,0 +1,64 @@ +package cn.edu.tsinghua.iginx.parquet.db.lsm.buffer; + +import cn.edu.tsinghua.iginx.parquet.db.lsm.table.MemoryTable; +import cn.edu.tsinghua.iginx.parquet.db.util.AreaSet; +import cn.edu.tsinghua.iginx.parquet.util.NoexceptAutoCloseable; +import com.google.common.collect.RangeSet; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import javax.annotation.WillCloseWhenClosed; +import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.util.Preconditions; +import org.apache.arrow.vector.types.pojo.Field; + +public class ArchivedMemTable implements NoexceptAutoCloseable { + private final MemTable memTable; + private final Collection onClose; + private final AreaSet deleted = new AreaSet<>(); + private final CountDownLatch latch = new CountDownLatch(1); + private boolean snapshot = false; + + public ArchivedMemTable( + @WillCloseWhenClosed MemTable memTable, + @WillCloseWhenClosed Collection onClose) { + this.memTable = Preconditions.checkNotNull(memTable); + this.onClose = new ArrayList<>(onClose); + } + + public synchronized MemoryTable snapshot(BufferAllocator allocator) { + snapshot = true; + memTable.compact(); + return memTable.snapshot(allocator); + } + + public synchronized MemoryTable snapshot( + List fields, RangeSet ranges, BufferAllocator allocator) { + snapshot = true; + memTable.compact(); + return memTable.snapshot(fields, ranges, allocator); + } + + public synchronized AreaSet getDeleted() { + return AreaSet.create(deleted); + } + + public synchronized void delete(AreaSet ranges) { + memTable.delete(ranges); + if (snapshot) { + deleted.addAll(ranges); + } + } + + public void waitUntilClosed() throws InterruptedException { + latch.await(); + } + + @Override + public void close() { + latch.countDown(); + memTable.close(); + onClose.forEach(NoexceptAutoCloseable::close); + } +} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/DataBuffer.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/DataBuffer.java index e0d70a2bf3..1c0830a9ba 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/DataBuffer.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/DataBuffer.java @@ -165,4 +165,9 @@ public String toString() { public void close() throws StorageException { data.clear(); } + + public int count(F field) { + NavigableMap column = data.get(field); + return column == null ? 0 : column.size(); + } } diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/MemColumn.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/MemColumn.java new file mode 100644 index 0000000000..130839a5cb --- /dev/null +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/MemColumn.java @@ -0,0 +1,354 @@ +package cn.edu.tsinghua.iginx.parquet.db.lsm.buffer; + +import cn.edu.tsinghua.iginx.parquet.db.lsm.buffer.chunk.Chunk; +import cn.edu.tsinghua.iginx.parquet.db.lsm.buffer.chunk.IndexedChunk; +import cn.edu.tsinghua.iginx.parquet.util.iterator.DedupIterator; +import cn.edu.tsinghua.iginx.parquet.util.iterator.StableMergeIterator; +import com.google.common.collect.*; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.annotation.WillCloseWhenClosed; +import javax.annotation.concurrent.ThreadSafe; +import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.util.Preconditions; + +@ThreadSafe +public class MemColumn implements AutoCloseable { + + private final int maxChunkValueCount; + private final int minChunkValueCount; + private final List compactedChunkSnapshots = new ArrayList<>(); + private final ChunkHolder active; + + public MemColumn( + IndexedChunk.Factory factory, + BufferAllocator allocator, + int maxChunkValueCount, + int minChunkValueCount) { + Preconditions.checkNotNull(allocator); + Preconditions.checkNotNull(factory); + Preconditions.checkArgument(maxChunkValueCount > 0); + Preconditions.checkArgument(minChunkValueCount > 0); + + this.active = new ChunkHolder(factory, allocator); + this.maxChunkValueCount = maxChunkValueCount; + this.minChunkValueCount = minChunkValueCount; + } + + // TODO: make use of ValueFilter + public synchronized Snapshot snapshot(RangeSet ranges, BufferAllocator allocator) { + active.refresh(compactedChunkSnapshots); + return createSnapshot(ranges, compactedChunkSnapshots, allocator); + } + + public synchronized Snapshot snapshot(BufferAllocator allocator) { + return snapshot(ImmutableRangeSet.of(Range.all()), allocator); + } + + private static Snapshot createSnapshot( + RangeSet ranges, + List snapshotHolders, + @Nullable BufferAllocator allocator) { + List snapshots = new ArrayList<>(); + for (ChunkSnapshotHolder snapshot : snapshotHolders) { + ChunkSnapshotHolder filtered; + if (allocator != null) { + filtered = snapshot.slice(allocator); + } else { + filtered = snapshot.slice(); + } + filtered.delete(ranges.complement()); + if (filtered.isEmpty()) { + filtered.close(); + } else { + snapshots.add(filtered); + } + } + return new Snapshot(snapshots); + } + + public synchronized void store(Chunk.Snapshot snapshot) { + int length = snapshot.getValueCount(); + if (length < minChunkValueCount) { + copyStore(snapshot, 0, length); + } else { + splitStore(snapshot, 0, length); + } + } + + public synchronized void splitStore(Chunk.Snapshot snapshot, int offset, int length) { + int activeValueCount = active.getValueCount(); + int padding = minChunkValueCount - active.getValueCount(); + if (activeValueCount > 0) { + if (padding > 0) { + if (padding >= length) { + active.store(snapshot, offset, length); + return; + } + active.store(snapshot, offset, padding); + offset += padding; + length -= padding; + } + compact(); + } + + if (length >= minChunkValueCount) { + compactedChunkSnapshots.add(active.sorted(snapshot, offset, length)); + } else { + active.store(snapshot, offset, length); + } + } + + public synchronized void copyStore(Chunk.Snapshot snapshot, int offset, int length) { + for (int written = offset; written != length; ) { + int free = maxChunkValueCount - active.getValueCount(); + if (free == 0) { + compact(); + } + int toWrite = Math.min(free, length - written); + active.store(snapshot, written, toWrite); + written += toWrite; + } + } + + public synchronized void delete(RangeSet ranges) { + active.delete(ranges); + for (ChunkSnapshotHolder snapshot : compactedChunkSnapshots) { + snapshot.delete(ranges); + } + } + + @Override + public synchronized void close() { + compactedChunkSnapshots.forEach(ChunkSnapshotHolder::close); + compactedChunkSnapshots.clear(); + active.close(); + } + + public synchronized void compact() { + active.refresh(compactedChunkSnapshots); + active.reset(); + } + + public static class Snapshot implements AutoCloseable, Iterable> { + + private final List snapshots; + + Snapshot(@WillCloseWhenClosed List snapshots) { + this.snapshots = Preconditions.checkNotNull(snapshots); + } + + public Snapshot slice(RangeSet ranges, BufferAllocator allocator) { + return createSnapshot(ranges, snapshots, allocator); + } + + public Snapshot slice(RangeSet ranges) { + return createSnapshot(ranges, snapshots, null); + } + + @Override + public void close() { + snapshots.forEach(ChunkSnapshotHolder::close); + snapshots.clear(); + } + + @Override + @Nonnull + public Iterator> iterator() { + Iterator> mergedIterator = + new StableMergeIterator<>(getIterators(), Map.Entry.comparingByKey()); + return new DedupIterator<>(mergedIterator, Map.Entry::getKey); + } + + private List>> getIterators() { + // TODO: 对 Iterator 进行 concat 减少 StableMergeIterator 内 queue 中的项数 + // 目前使用贪心算法,可能不是最优解 + List> rangeGroups = new ArrayList<>(); + RangeMap currentRanges = TreeRangeMap.create(); + for (int i = 0; i < snapshots.size(); i++) { + ChunkSnapshotHolder snapshot = snapshots.get(i); + Range keyRange = snapshot.getKeyRange(); + if (currentRanges.subRangeMap(keyRange).asMapOfRanges().isEmpty()) { + currentRanges.put(keyRange, i); + } else { + rangeGroups.add(currentRanges); + currentRanges = TreeRangeMap.create(); + currentRanges.put(keyRange, i); + } + } + rangeGroups.add(currentRanges); + List>> iterators = new ArrayList<>(); + for (RangeMap rangeMap : rangeGroups) { + List>> groupIterators = new ArrayList<>(); + for (int i : rangeMap.asMapOfRanges().values()) { + groupIterators.add(snapshots.get(i).iterator()); + } + iterators.add(Iterators.concat(groupIterators.iterator())); + } + return iterators; + } + + public RangeSet getRanges() { + RangeSet range = TreeRangeSet.create(); + snapshots.forEach(snapshot -> range.add(snapshot.getKeyRange())); + return range; + } + } + + private static class ChunkSnapshotHolder + implements AutoCloseable, Iterable> { + + private final Chunk.Snapshot snapshot; + private RangeSet mask; + + public ChunkSnapshotHolder(@WillCloseWhenClosed Chunk.Snapshot snapshot) { + this(snapshot, null); + } + + private ChunkSnapshotHolder(@WillCloseWhenClosed Chunk.Snapshot snapshot, RangeSet mask) { + Preconditions.checkArgument(snapshot.getValueCount() > 0); + this.snapshot = snapshot; + if (mask != null) { + this.mask = TreeRangeSet.create(mask); + } else { + this.mask = null; + } + } + + public boolean isEmpty() { + return mask != null && mask.isEmpty(); + } + + public void delete(RangeSet ranges) { + if (mask == null) { + Range fullRange = getKeyRange(snapshot); + if (!ranges.intersects(fullRange)) { + return; + } + mask = TreeRangeSet.create(); + mask.add(fullRange); + } + mask.removeAll(ranges); + } + + public Range getKeyRange() { + if (mask == null) { + return getKeyRange(snapshot); + } + if (mask.isEmpty()) { + return Range.closedOpen(0L, 0L); + } + return mask.span(); + } + + private static Range getKeyRange(Chunk.Snapshot snapshot) { + return Range.closed(snapshot.getKey(0), snapshot.getKey(snapshot.getValueCount() - 1)); + } + + @Override + public void close() { + snapshot.close(); + } + + public ChunkSnapshotHolder slice(BufferAllocator allocator) { + return new ChunkSnapshotHolder(snapshot.slice(allocator), mask); + } + + public ChunkSnapshotHolder slice() { + return new ChunkSnapshotHolder(snapshot.slice(), mask); + } + + @Override + @Nonnull + public Iterator> iterator() { + Iterator> iterator = snapshot.iterator(); + if (mask == null) { + return iterator; + } + return Iterators.filter(iterator, entry -> mask.contains(entry.getKey())); + } + } + + private static class ChunkHolder implements AutoCloseable { + private final IndexedChunk.Factory factory; + private final BufferAllocator allocator; + private IndexedChunk activeChunk = null; + private boolean isDirty = false; + private boolean hasOld = false; + + ChunkHolder(IndexedChunk.Factory factory, BufferAllocator allocator) { + this.factory = factory; + this.allocator = allocator; + } + + public int getValueCount() { + return activeChunk == null ? 0 : activeChunk.getValueCount(); + } + + public ChunkSnapshotHolder sorted(Chunk.Snapshot snapshot, int offset, int length) { + Chunk.Snapshot sorted = factory.sorted(snapshot.slice(offset, length, allocator), allocator); + return new ChunkSnapshotHolder(sorted); + } + + public void store(Chunk.Snapshot data) { + if (data.getValueCount() == 0) { + return; + } + if (activeChunk == null) { + activeChunk = factory.wrap(data, allocator); + } + activeChunk.store(data); + isDirty = true; + } + + public void store(Chunk.Snapshot snapshot, int offset, int length) { + try (Chunk.Snapshot slice = snapshot.slice(offset, length, allocator)) { + store(slice); + } + } + + public void delete(RangeSet ranges) { + if (activeChunk != null) { + activeChunk.delete(ranges); + } + } + + public void refresh(List compactedChunkSnapshots) { + if (!isDirty) { + return; + } + isDirty = false; + + if (hasOld) { + int offset = compactedChunkSnapshots.size() - 1; + compactedChunkSnapshots.remove(offset).close(); + } + + Chunk.Snapshot snapshot = activeChunk.snapshot(allocator); + if (snapshot.getValueCount() > 0) { + compactedChunkSnapshots.add(new ChunkSnapshotHolder(snapshot)); + hasOld = true; + } else { + snapshot.close(); + reset(); + } + } + + public void reset() { + if (activeChunk != null) { + activeChunk.close(); + activeChunk = null; + } + isDirty = false; + hasOld = false; + } + + public void close() { + reset(); + } + } +} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/MemTable.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/MemTable.java new file mode 100644 index 0000000000..203d4a3b41 --- /dev/null +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/MemTable.java @@ -0,0 +1,157 @@ +package cn.edu.tsinghua.iginx.parquet.db.lsm.buffer; + +import cn.edu.tsinghua.iginx.parquet.db.lsm.buffer.chunk.Chunk; +import cn.edu.tsinghua.iginx.parquet.db.lsm.buffer.chunk.IndexedChunk; +import cn.edu.tsinghua.iginx.parquet.db.lsm.table.MemoryTable; +import cn.edu.tsinghua.iginx.parquet.db.util.AreaSet; +import cn.edu.tsinghua.iginx.parquet.util.arrow.ArrowFields; +import com.google.common.collect.RangeSet; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import javax.annotation.concurrent.ThreadSafe; +import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.vector.types.pojo.Field; + +@ThreadSafe +public class MemTable implements AutoCloseable { + + private final ConcurrentHashMap columns = new ConcurrentHashMap<>(); + private final IndexedChunk.Factory factory; + private final BufferAllocator allocator; + private final int maxChunkValueCount; + private final int minChunkValueCount; + + private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + private volatile boolean closed = false; + + public MemTable( + IndexedChunk.Factory factory, + BufferAllocator allocator, + int maxChunkValueCount, + int minChunkValueCount) { + this.factory = factory; + this.allocator = allocator; + this.maxChunkValueCount = maxChunkValueCount; + this.minChunkValueCount = minChunkValueCount; + } + + public void reset() { + lock.writeLock().lock(); + try { + columns.values().forEach(MemColumn::close); + columns.clear(); + } finally { + lock.writeLock().unlock(); + } + } + + @Override + public void close() { + closed = true; + reset(); + } + + public Set getFields() { + return Collections.unmodifiableSet(columns.keySet()); + } + + public MemoryTable snapshot( + List fields, RangeSet ranges, BufferAllocator allocator) { + LinkedHashMap columns = new LinkedHashMap<>(); + lock.readLock().lock(); + try { + for (Field field : fields) { + if (columns.containsKey(field)) { + throw new IllegalArgumentException("Duplicate field: " + field); + } + MemColumn column = this.columns.get(field); + if (column != null) { + columns.put(field, column.snapshot(ranges, allocator)); + } + } + } finally { + lock.readLock().unlock(); + } + return new MemoryTable(columns); + } + + public MemoryTable snapshot(BufferAllocator allocator) { + LinkedHashMap columns = new LinkedHashMap<>(); + lock.readLock().lock(); + try { + for (Map.Entry entry : this.columns.entrySet()) { + columns.put(entry.getKey(), entry.getValue().snapshot(allocator)); + } + } finally { + lock.readLock().unlock(); + } + return new MemoryTable(columns); + } + + public void store(Iterable data) { + lock.readLock().lock(); + try { + data.forEach(this::store); + } finally { + lock.readLock().unlock(); + } + } + + public void store(Chunk.Snapshot data) { + lock.readLock().lock(); + try { + if (closed) { + throw new IllegalStateException("MemTable is closed"); + } + Field field = ArrowFields.nullable(data.getField()); + MemColumn column = + columns.computeIfAbsent( + field, + key -> new MemColumn(factory, allocator, maxChunkValueCount, minChunkValueCount)); + column.store(data); + } finally { + lock.readLock().unlock(); + } + } + + public void compact() { + lock.readLock().lock(); + try { + columns.values().forEach(MemColumn::compact); + } finally { + lock.readLock().unlock(); + } + } + + public void delete(AreaSet areas) { + lock.writeLock().lock(); + try { + for (Field field : areas.getFields()) { + MemColumn column = columns.remove(field); + if (column != null) { + column.close(); + } + } + lock.readLock().lock(); + } finally { + lock.writeLock().unlock(); + } + try { + RangeSet keys = areas.getKeys(); + if (!keys.isEmpty()) { + columns.values().forEach(column -> column.delete(keys)); + } + for (Map.Entry> entry : areas.getSegments().entrySet()) { + Field field = entry.getKey(); + RangeSet ranges = entry.getValue(); + MemColumn column = columns.get(field); + if (column != null) { + column.delete(ranges); + } + } + } finally { + lock.readLock().unlock(); + } + } +} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/MemTableQueue.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/MemTableQueue.java new file mode 100644 index 0000000000..a67ad42760 --- /dev/null +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/MemTableQueue.java @@ -0,0 +1,230 @@ +package cn.edu.tsinghua.iginx.parquet.db.lsm.buffer; + +import cn.edu.tsinghua.iginx.parquet.db.lsm.buffer.chunk.Chunk; +import cn.edu.tsinghua.iginx.parquet.db.lsm.table.MemoryTable; +import cn.edu.tsinghua.iginx.parquet.db.util.AreaSet; +import cn.edu.tsinghua.iginx.parquet.db.util.iterator.AreaFilterScanner; +import cn.edu.tsinghua.iginx.parquet.db.util.iterator.Scanner; +import cn.edu.tsinghua.iginx.parquet.util.Awaitable; +import cn.edu.tsinghua.iginx.parquet.util.NoexceptAutoCloseable; +import cn.edu.tsinghua.iginx.parquet.util.Shared; +import cn.edu.tsinghua.iginx.parquet.util.arrow.ArrowFields; +import com.google.common.collect.RangeSet; +import java.io.IOException; +import java.util.*; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.function.Consumer; +import javax.annotation.Nonnegative; +import javax.annotation.concurrent.ThreadSafe; +import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.util.AutoCloseables; +import org.apache.arrow.vector.types.pojo.Field; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@ThreadSafe +public class MemTableQueue implements NoexceptAutoCloseable { + private final Logger LOGGER = LoggerFactory.getLogger(MemTableQueue.class); + + private final ReentrantLock checkSizeLock = new ReentrantLock(true); + private final ReentrantReadWriteLock queueLock = new ReentrantReadWriteLock(true); + private final ReentrantLock pollLock = new ReentrantLock(true); + private final Condition pollLockCond = pollLock.newCondition(); + + private final NavigableMap archives = new TreeMap<>(); + private final BufferAllocator allocator; + private final ActiveMemTable active; + + public MemTableQueue(Shared shared, BufferAllocator allocator) { + String allocatorName = + String.join("-", allocator.getName(), MemTableQueue.class.getSimpleName()); + this.allocator = allocator.newChildAllocator(allocatorName, 0, Long.MAX_VALUE); + this.active = new ActiveMemTable(shared, this.allocator); + } + + public void store(Iterable data) throws InterruptedException { + checkSizeLock.lock(); + try { + if (active.isOverloaded()) { + compact(); + } + } finally { + checkSizeLock.unlock(); + } + active.store(data); + } + + public void compact() throws InterruptedException { + checkSizeLock.lock(); + try { + Map temp = active.archive(); + queueLock.writeLock().lock(); + try { + archives.putAll(temp); + temp.clear(); + } finally { + queueLock.writeLock().unlock(); + temp.values().forEach(ArchivedMemTable::close); + } + } finally { + checkSizeLock.unlock(); + } + signalAll(); + } + + public void flush() throws InterruptedException { + Awaitable flush; + List waiters = new ArrayList<>(); + queueLock.readLock().lock(); + try { + flush = active.flush(); + for (ArchivedMemTable archivedMemTable : archives.values()) { + waiters.add(archivedMemTable::waitUntilClosed); + } + } finally { + queueLock.readLock().unlock(); + } + signalAll(); + flush.await(); + for (Awaitable waiter : waiters) { + waiter.await(); + } + } + + public void delete(AreaSet areas) { + queueLock.readLock().lock(); + try { + active.delete(areas); + archives.values().forEach(archived -> archived.delete(areas)); + } finally { + queueLock.readLock().unlock(); + } + } + + private void await() throws InterruptedException { + pollLock.lock(); + try { + pollLockCond.await(); + } finally { + pollLock.unlock(); + } + } + + private void signalAll() { + pollLock.lock(); + try { + pollLockCond.signalAll(); + } finally { + pollLock.unlock(); + } + } + + /** + * take next table id, if no table id available, block until new table id available + * + * @param idAtLeast the non-negative table id at least + * @return the next non-negative table id + */ + @Nonnegative + public long awaitNext(@Nonnegative long idAtLeast) throws InterruptedException { + while (true) { + queueLock.readLock().lock(); + try { + Long nextId = archives.ceilingKey(idAtLeast); + if (nextId != null) { + return nextId; + } + Long activeNextId = active.newestKey(idAtLeast); + if (activeNextId != null) { + return activeNextId; + } + } finally { + queueLock.readLock().unlock(); + } + await(); + } + } + + public void eliminate(long id, Consumer> commiter) + throws InterruptedException { + active.eliminate(id); + + queueLock.writeLock().lock(); + try { + if (archives.containsKey(id)) { + try (ArchivedMemTable memTable = archives.remove(id)) { + commiter.accept(memTable.getDeleted()); + } + return; + } + } finally { + queueLock.writeLock().unlock(); + } + + commiter.accept(AreaSet.all()); + } + + public MemoryTable snapshot(long id, BufferAllocator allocator) { + queueLock.readLock().lock(); + try { + ArchivedMemTable archived = archives.get(id); + if (archived != null) { + return archived.snapshot(allocator); + } + return active.snapshot(id, allocator); + } finally { + queueLock.readLock().unlock(); + } + } + + public List>> scan( + List fields, RangeSet ranges, BufferAllocator allocator) throws IOException { + Set innerFields = ArrowFields.toInnerFields(fields); + List>> scanners = new ArrayList<>(); + queueLock.readLock().lock(); + try { + for (ArchivedMemTable archivedMemTable : archives.values()) { + try (MemoryTable table = archivedMemTable.snapshot(fields, ranges, allocator)) { + Scanner> scanner = table.scan(innerFields, ranges); + AreaSet deleted = archivedMemTable.getDeleted(); + if (deleted.isEmpty()) { + scanners.add(scanner); + } else { + AreaSet innerDelete = ArrowFields.toInnerAreas(deleted); + scanners.add(new AreaFilterScanner<>(scanner, innerDelete)); + } + } + } + active.scan(fields, ranges, allocator, scanners::add); + } catch (Exception e) { + try { + AutoCloseables.close(scanners); + } catch (Exception ex) { + e.addSuppressed(ex); + } + throw e; + } finally { + queueLock.readLock().unlock(); + } + return scanners; + } + + public void clear() { + queueLock.writeLock().lock(); + try { + active.reset(); + archives.values().forEach(ArchivedMemTable::close); + archives.clear(); + } finally { + queueLock.writeLock().unlock(); + } + } + + @Override + public void close() { + clear(); + allocator.close(); + } +} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/chunk/Chunk.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/chunk/Chunk.java new file mode 100644 index 0000000000..4735415084 --- /dev/null +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/chunk/Chunk.java @@ -0,0 +1,167 @@ +package cn.edu.tsinghua.iginx.parquet.db.lsm.buffer.chunk; + +import cn.edu.tsinghua.iginx.parquet.util.NoexceptAutoCloseable; +import cn.edu.tsinghua.iginx.parquet.util.arrow.ArrowVectors; +import java.util.AbstractMap; +import java.util.Iterator; +import java.util.Map; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.annotation.WillCloseWhenClosed; +import javax.annotation.concurrent.GuardedBy; +import javax.annotation.concurrent.Immutable; +import javax.annotation.concurrent.ThreadSafe; +import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.util.Preconditions; +import org.apache.arrow.vector.BigIntVector; +import org.apache.arrow.vector.ValueVector; +import org.apache.arrow.vector.ZeroVector; +import org.apache.arrow.vector.types.pojo.Field; + +@ThreadSafe +public class Chunk implements AutoCloseable { + + @GuardedBy("this") + protected final ValueVector keys; + + @GuardedBy("this") + protected final ValueVector values; + + protected Chunk(@WillCloseWhenClosed ValueVector keys, @WillCloseWhenClosed ValueVector values) { + Preconditions.checkNotNull(keys); + Preconditions.checkNotNull(values); + Preconditions.checkArgument(keys.getValueCount() == values.getValueCount()); + + this.keys = keys; + this.values = values; + } + + public static Chunk like(Snapshot snapshot, BufferAllocator allocator) { + return new Chunk( + ArrowVectors.like(snapshot.keys, allocator), ArrowVectors.like(snapshot.values, allocator)); + } + + public synchronized Snapshot snapshot(BufferAllocator allocator) { + return new Snapshot(ArrowVectors.slice(keys, allocator), ArrowVectors.slice(values, allocator)); + } + + public synchronized int store(Snapshot data) { + int offset = keys.getValueCount(); + ArrowVectors.append(keys, data.keys); + ArrowVectors.append(values, data.values); + return offset; + } + + public synchronized int getValueCount() { + return keys.getValueCount(); + } + + @Override + public synchronized void close() { + keys.close(); + values.close(); + } + + @Immutable + public static class Snapshot implements NoexceptAutoCloseable, Iterable> { + + protected final ValueVector keys; + protected final ValueVector values; + + public Snapshot( + @WillCloseWhenClosed ValueVector keys, @WillCloseWhenClosed ValueVector values) { + Preconditions.checkNotNull(keys); + Preconditions.checkNotNull(values); + Preconditions.checkArgument(keys.getValueCount() == values.getValueCount()); + Preconditions.checkArgument(!keys.getField().isNullable()); + Preconditions.checkArgument(!values.getField().isNullable()); + + this.keys = keys; + this.values = values; + } + + public static Snapshot empty(Field key, Field value) { + Preconditions.checkNotNull(key); + Preconditions.checkNotNull(value); + return new Snapshot(new ZeroVector(key), new ZeroVector(value)); + } + + public Field getField() { + return values.getField(); + } + + public int getValueCount() { + return keys.getValueCount(); + } + + public Snapshot slice() { + return doSlice(0, keys.getValueCount(), null); + } + + public Snapshot slice(int start, int length) { + return doSlice(start, length, null); + } + + public Snapshot slice(BufferAllocator allocator) { + return doSlice(0, keys.getValueCount(), allocator); + } + + public Snapshot slice(int start, int length, BufferAllocator allocator) { + return doSlice(start, length, allocator); + } + + private Snapshot doSlice(int start, int length, @Nullable BufferAllocator allocator) { + if (allocator == null) { + return new Snapshot( + ArrowVectors.slice(keys, start, length), ArrowVectors.slice(values, start, length)); + } + return new Snapshot( + ArrowVectors.slice(keys, start, length, allocator), + ArrowVectors.slice(values, start, length, allocator)); + } + + @Override + public void close() { + keys.close(); + values.close(); + } + + public long getKey(int index) { + return doGetKey(index); + } + + private long doGetKey(int index) { + return keys.getDataBuffer().getLong((long) index * BigIntVector.TYPE_WIDTH); + } + + public Map.Entry get(int index) { + long key = doGetKey(index); + Object value = values.getObject(index); + return new AbstractMap.SimpleImmutableEntry<>(key, value); + } + + @Override + @Nonnull + public Iterator> iterator() { + return new ChunkSnapshotReader(); + } + + public class ChunkSnapshotReader implements Iterator> { + private int position = 0; + private final int valueCount = getValueCount(); + + @Override + public boolean hasNext() { + return position < valueCount; + } + + @Override + public Map.Entry next() { + if (!hasNext()) { + throw new IndexOutOfBoundsException(); + } + return get(position++); + } + } + } +} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/chunk/IndexedChunk.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/chunk/IndexedChunk.java new file mode 100644 index 0000000000..ea2dc8ed12 --- /dev/null +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/chunk/IndexedChunk.java @@ -0,0 +1,139 @@ +package cn.edu.tsinghua.iginx.parquet.db.lsm.buffer.chunk; + +import cn.edu.tsinghua.iginx.parquet.util.arrow.ArrowVectors; +import com.google.common.collect.RangeSet; +import java.util.Map; +import javax.annotation.Nullable; +import javax.annotation.WillClose; +import javax.annotation.WillCloseWhenClosed; +import javax.annotation.concurrent.Immutable; +import javax.annotation.concurrent.ThreadSafe; +import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.util.Preconditions; +import org.apache.arrow.vector.IntVector; +import org.apache.arrow.vector.types.Types; + +@ThreadSafe +public abstract class IndexedChunk extends Chunk { + + protected final BufferAllocator allocator; + + protected IndexedChunk(@WillCloseWhenClosed Chunk chunk, BufferAllocator allocator) { + super(chunk.keys, chunk.values); + this.allocator = allocator; + } + + @Override + public synchronized Snapshot snapshot(BufferAllocator allocator) { + Snapshot snapshot = super.snapshot(allocator); + if (ArrowVectors.isSorted(snapshot.keys)) { + return snapshot; + } + IntVector indexes = indexOf(snapshot, allocator); + return new IndexedSnapshot(snapshot, indexes); + } + + @Override + public synchronized int store(Snapshot data) { + int offset = super.store(data); + updateIndex(data, offset); + return offset; + } + + public synchronized void delete(RangeSet rangeSet) { + Preconditions.checkNotNull(rangeSet); + deleteIndex(rangeSet); + } + + @Override + public synchronized void close() { + super.close(); + } + + protected abstract IntVector indexOf(Snapshot snapshot, BufferAllocator allocator); + + protected abstract void updateIndex(Snapshot data, int offset); + + protected abstract void deleteIndex(RangeSet rangeSet); + + public interface Factory { + IndexedChunk wrap(@WillCloseWhenClosed Chunk chunk, BufferAllocator allocator); + + default IndexedChunk wrap(Snapshot snapshot, BufferAllocator allocator) { + return wrap(Chunk.like(snapshot, allocator), allocator); + } + + default Snapshot sorted(@WillClose Snapshot snapshot, BufferAllocator allocator) { + try (IndexedChunk chunk = wrap(new Chunk(snapshot.keys, snapshot.values), allocator)) { + return chunk.snapshot(allocator); + } + } + } + + @Immutable + protected static class IndexedSnapshot extends Snapshot { + + protected final IntVector indexes; + + public IndexedSnapshot( + @WillCloseWhenClosed Snapshot snapshot, @WillCloseWhenClosed IntVector indexes) { + super(snapshot.keys, snapshot.values); + this.indexes = indexes; + Preconditions.checkArgument(snapshot.keys.getMinorType() == Types.MinorType.BIGINT); + Preconditions.checkArgument(!indexes.getField().isNullable()); + } + + @Override + public void close() { + super.close(); + indexes.close(); + } + + @Override + public int getValueCount() { + return indexes.getValueCount(); + } + + @Override + public IndexedSnapshot slice() { + return doSlice(0, indexes.getValueCount(), null); + } + + @Override + public IndexedSnapshot slice(int start, int length) { + return doSlice(start, length, null); + } + + @Override + public IndexedSnapshot slice(BufferAllocator allocator) { + return doSlice(0, indexes.getValueCount(), allocator); + } + + @Override + public IndexedSnapshot slice(int start, int length, BufferAllocator allocator) { + return doSlice(start, length, allocator); + } + + private IndexedSnapshot doSlice(int start, int length, @Nullable BufferAllocator allocator) { + if (allocator == null) { + return new IndexedSnapshot(super.slice(), ArrowVectors.slice(indexes, start, length)); + } + return new IndexedSnapshot( + super.slice(allocator), ArrowVectors.slice(indexes, start, length, allocator)); + } + + public int getIndex(int index) { + return indexes.getDataBuffer().getInt((long) index * IntVector.TYPE_WIDTH); + } + + @Override + public long getKey(int index) { + return super.getKey(getIndex(index)); + } + + @Override + public Map.Entry get(int index) { + return super.get(getIndex(index)); + } + } +} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/chunk/IndexedChunkType.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/chunk/IndexedChunkType.java new file mode 100644 index 0000000000..ba9c5e5d3e --- /dev/null +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/chunk/IndexedChunkType.java @@ -0,0 +1,16 @@ +package cn.edu.tsinghua.iginx.parquet.db.lsm.buffer.chunk; + +public enum IndexedChunkType { + SKIP_LIST(SkipListChunk::new), + NONE(NoIndexChunk::new); + + private final IndexedChunk.Factory factory; + + IndexedChunkType(IndexedChunk.Factory factory) { + this.factory = factory; + } + + public IndexedChunk.Factory factory() { + return factory; + } +} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/chunk/NoIndexChunk.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/chunk/NoIndexChunk.java new file mode 100644 index 0000000000..4861afde7a --- /dev/null +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/chunk/NoIndexChunk.java @@ -0,0 +1,55 @@ +package cn.edu.tsinghua.iginx.parquet.db.lsm.buffer.chunk; + +import cn.edu.tsinghua.iginx.parquet.util.arrow.ArrowVectors; +import com.google.common.collect.RangeSet; +import com.google.common.collect.TreeRangeSet; +import java.util.Map; +import java.util.TreeMap; +import javax.annotation.WillCloseWhenClosed; +import javax.annotation.concurrent.ThreadSafe; +import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.vector.IntVector; + +@ThreadSafe +public class NoIndexChunk extends IndexedChunk { + + private final TreeMap> tombstone = new TreeMap<>(); + + private int valueCount = 0; + + public NoIndexChunk(@WillCloseWhenClosed Chunk chunk, BufferAllocator allocator) { + super(chunk, allocator); + tombstone.put(0, TreeRangeSet.create()); + } + + @Override + protected IntVector indexOf(Snapshot snapshot, BufferAllocator allocator) { + IntVector indexes = ArrowVectors.stableSortIndexes(snapshot.keys, allocator); + ArrowVectors.dedupSortedIndexes(snapshot.keys, indexes); + if (!tombstone.isEmpty()) { + ArrowVectors.filter(indexes, i -> !isDeleted(snapshot, i)); + } + return indexes; + } + + private boolean isDeleted(Snapshot snapshot, int index) { + Map.Entry> entry = tombstone.higherEntry(index); + if (entry == null) { + return false; + } + RangeSet deleted = entry.getValue(); + long key = snapshot.getKey(index); + return deleted.contains(key); + } + + @Override + protected void updateIndex(Snapshot data, int offset) { + valueCount = offset + data.getValueCount(); + } + + @Override + protected void deleteIndex(RangeSet rangeSet) { + tombstone.computeIfAbsent(valueCount, k -> TreeRangeSet.create()).addAll(rangeSet); + tombstone.values().forEach(r -> r.removeAll(rangeSet)); + } +} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/chunk/SkipListChunk.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/chunk/SkipListChunk.java new file mode 100644 index 0000000000..517032f745 --- /dev/null +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/chunk/SkipListChunk.java @@ -0,0 +1,72 @@ +package cn.edu.tsinghua.iginx.parquet.db.lsm.buffer.chunk; + +import cn.edu.tsinghua.iginx.parquet.util.arrow.ArrowVectors; +import com.google.common.collect.BoundType; +import com.google.common.collect.Range; +import com.google.common.collect.RangeSet; +import java.util.NavigableMap; +import java.util.concurrent.ConcurrentSkipListMap; +import javax.annotation.WillCloseWhenClosed; +import javax.annotation.concurrent.ThreadSafe; +import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.vector.IntVector; + +@ThreadSafe +public class SkipListChunk extends IndexedChunk { + + protected final ConcurrentSkipListMap index = new ConcurrentSkipListMap<>(); + + public SkipListChunk(@WillCloseWhenClosed Chunk chunk, BufferAllocator allocator) { + super(chunk, allocator); + try (Snapshot snapshot = chunk.snapshot(allocator)) { + updateIndex(snapshot, 0); + } + } + + @Override + protected IntVector indexOf(Snapshot snapshot, BufferAllocator allocator) { + IntVector indexes = ArrowVectors.nonnullIntVector("indexes", allocator); + ArrowVectors.collect(indexes, index.values()); + return indexes; + } + + @Override + protected void updateIndex(Snapshot snapshot, int offset) { + for (int i = 0; i < snapshot.getValueCount(); i++) { + index.put(snapshot.getKey(i), i + offset); + } + } + + @Override + protected void deleteIndex(RangeSet rangeSet) { + rangeSet + .asRanges() + .forEach( + range -> { + subMapRefOf(index, range).clear(); + }); + } + + private static , V> NavigableMap subMapRefOf( + NavigableMap column, Range range) { + if (range.encloses(Range.all())) { + return column; + } else if (!range.hasLowerBound()) { + return column.headMap(range.upperEndpoint(), range.upperBoundType() == BoundType.CLOSED); + } else if (!range.hasUpperBound()) { + return column.tailMap(range.lowerEndpoint(), range.lowerBoundType() == BoundType.CLOSED); + } else { + return column.subMap( + range.lowerEndpoint(), + range.lowerBoundType() == BoundType.CLOSED, + range.upperEndpoint(), + range.upperBoundType() == BoundType.CLOSED); + } + } + + @Override + public void close() { + super.close(); + index.clear(); + } +} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/compact/Compactor.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/compact/Compactor.java deleted file mode 100644 index 2515d35dcc..0000000000 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/compact/Compactor.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * IGinX - the polystore system with high performance - * Copyright (C) Tsinghua University - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package cn.edu.tsinghua.iginx.parquet.db.lsm.compact; - -public class Compactor {} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/compact/Flusher.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/compact/Flusher.java new file mode 100644 index 0000000000..482ca7390d --- /dev/null +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/compact/Flusher.java @@ -0,0 +1,184 @@ +package cn.edu.tsinghua.iginx.parquet.db.lsm.compact; + +import cn.edu.tsinghua.iginx.parquet.db.lsm.buffer.MemTableQueue; +import cn.edu.tsinghua.iginx.parquet.db.lsm.table.MemoryTable; +import cn.edu.tsinghua.iginx.parquet.db.lsm.table.TableStorage; +import cn.edu.tsinghua.iginx.parquet.util.NoexceptAutoCloseable; +import cn.edu.tsinghua.iginx.parquet.util.Shared; +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.*; +import javax.annotation.Nonnegative; +import javax.annotation.concurrent.NotThreadSafe; +import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.util.Preconditions; +import org.apache.arrow.vector.types.pojo.Field; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@NotThreadSafe +public class Flusher implements NoexceptAutoCloseable { + + private static final Logger LOGGER = LoggerFactory.getLogger(Flusher.class); + + private final String name; + private final Shared shared; + private final BufferAllocator allocator; + private final MemTableQueue memTableQueue; + private final TableStorage tableStorage; + + private ScheduledExecutorService scheduler; + private ExecutorService dispatcher; + private ExecutorService leader; + private ExecutorService worker; + private boolean running = false; + + public Flusher( + String name, + Shared shared, + BufferAllocator allocator, + MemTableQueue memTableQueue, + TableStorage tableStorage) { + this.name = name; + this.shared = shared; + this.allocator = + allocator.newChildAllocator(allocator.getName() + "-flusher", 0, Long.MAX_VALUE); + this.memTableQueue = memTableQueue; + this.tableStorage = tableStorage; + start(); + } + + @Override + public void close() { + stop(); + allocator.close(); + } + + public void start() { + Preconditions.checkState(!running, "flusher is already running"); + + ThreadFactory expireFactory = + new ThreadFactoryBuilder().setNameFormat("flusher-" + name + "-scheduler-%d").build(); + this.scheduler = Executors.newSingleThreadScheduledExecutor(expireFactory); + long timeout = shared.getStorageProperties().getWriteBufferTimeout().toMillis(); + if (timeout > 0) { + LOGGER.info("flusher {} start to force flush every {} ms", name, timeout); + this.scheduler.scheduleWithFixedDelay( + handleInterruption(memTableQueue::flush), timeout, timeout, TimeUnit.MILLISECONDS); + } + + ThreadFactory workerFactory = + new ThreadFactoryBuilder().setNameFormat("flusher-" + name + "-worker-%d").build(); + this.worker = Executors.newCachedThreadPool(workerFactory); + + ThreadFactory leaderFactory = + new ThreadFactoryBuilder().setNameFormat("flusher-" + name + "-leader-%d").build(); + this.leader = Executors.newCachedThreadPool(leaderFactory); + + ThreadFactory dispatcherFactory = + new ThreadFactoryBuilder().setNameFormat("flusher-" + name + "-dispatcher-%d").build(); + this.dispatcher = Executors.newSingleThreadExecutor(dispatcherFactory); + dispatcher.submit(handleInterruption((this::dispatch))); + + running = true; + } + + public void stop() { + Preconditions.checkState(running, "flusher is not running"); + + scheduler.shutdownNow(); + dispatcher.shutdownNow(); + worker.shutdownNow(); + leader.shutdownNow(); + + try { + boolean schedulerTerminated = scheduler.awaitTermination(1, TimeUnit.MINUTES); + boolean dispatcherTerminated = dispatcher.awaitTermination(1, TimeUnit.MINUTES); + boolean workerTerminated = worker.awaitTermination(1, TimeUnit.MINUTES); + boolean leaderTerminated = leader.awaitTermination(1, TimeUnit.MINUTES); + if (!schedulerTerminated || !dispatcherTerminated || !workerTerminated || !leaderTerminated) { + throw new IllegalStateException("flusher is not terminated"); + } + running = false; + } catch (InterruptedException e) { + LOGGER.debug("flusher is interrupted:", e); + } + } + + interface InterruptibleRunnable { + void run() throws InterruptedException, ExecutionException; + } + + private Runnable handleInterruption(InterruptibleRunnable runnable) { + return () -> { + try { + runnable.run(); + } catch (InterruptedException e) { + LOGGER.debug("interrupted", e); + } catch (Exception e) { + LOGGER.error("unexpected error", e); + } + }; + } + + private void dispatch() throws InterruptedException { + long memtableIdAtLeast = 0; + while (!Thread.currentThread().isInterrupted()) { + long memtableId = memTableQueue.awaitNext(memtableIdAtLeast); + LOGGER.debug("memtable {} is ready to flush", memtableId); + CountDownLatch pullNext = new CountDownLatch(1); + leader.submit(handleInterruption(() -> submitAndWaitFlush(memtableId, pullNext))); + pullNext.await(); + memtableIdAtLeast = memtableId + 1; + } + throw new InterruptedException(); + } + + private void submitAndWaitFlush(@Nonnegative long memtableId, CountDownLatch onSubmit) + throws InterruptedException, ExecutionException { + List tableNames = new ArrayList<>(); + + LOGGER.debug("start to flush memtable {}", memtableId); + + try (MemoryTable snapshot = memTableQueue.snapshot(memtableId, allocator)) { + List>> futureFlushed = new ArrayList<>(); + + Field[] fields = snapshot.getFields().toArray(new Field[0]); + for (int columnNumber = 0; columnNumber < fields.length; columnNumber++) { + Field field = fields[columnNumber]; + String suffix = String.valueOf(columnNumber); + + shared.getFlusherPermits().acquire(); + Future> future = + worker.submit( + () -> { + try { + return tableStorage.flush(memtableId, suffix, snapshot.subTable(field)); + } finally { + shared.getFlusherPermits().release(); + } + }); + futureFlushed.add(future); + } + + onSubmit.countDown(); + + for (Future> future : futureFlushed) { + tableNames.addAll(future.get()); + } + } + + LOGGER.debug("memtable {} is flushed to tables {}", memtableId, tableNames); + + memTableQueue.eliminate( + memtableId, + tombstone -> { + for (String tableName : tableNames) { + tableStorage.commit(tableName, tombstone); + } + }); + + LOGGER.debug("memtable {} is eliminated", memtableId); + } +} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/DeletedTable.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/DeletedTable.java index aa509cd156..d2bcee8d6b 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/DeletedTable.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/DeletedTable.java @@ -26,34 +26,28 @@ import com.google.common.collect.RangeSet; import java.io.IOException; import java.util.Set; -import javax.annotation.Nonnull; import javax.annotation.Nullable; -public class DeletedTable, F, T, V> implements Table { +public class DeletedTable implements Table { - private final Table table; + private final Table table; - private final AreaSet deletedAreaSet; + private final AreaSet deleted; - private final TableMeta meta; - - public DeletedTable(Table table, AreaSet deleted) throws IOException { + public DeletedTable(Table table, AreaSet deleted) { this.table = table; - this.deletedAreaSet = deleted; - this.meta = new DeletedTableMeta<>(table.getMeta(), deleted); + this.deleted = deleted; } - @Nonnull @Override - public TableMeta getMeta() throws IOException { - return meta; + public TableMeta getMeta() throws IOException { + return new DeletedTableMeta(table.getMeta(), deleted); } - @Nonnull @Override - public Scanner> scan( - @Nonnull Set fields, @Nonnull RangeSet range, @Nullable Filter predicate) + public Scanner> scan( + Set fields, RangeSet range, @Nullable Filter superSetPredicate) throws IOException { - return new AreaFilterScanner<>(table.scan(fields, range, predicate), deletedAreaSet); + return new AreaFilterScanner<>(table.scan(fields, range, superSetPredicate), deleted); } } diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/DeletedTableMeta.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/DeletedTableMeta.java index 8c3faa27f7..f47dfc8fa5 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/DeletedTableMeta.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/DeletedTableMeta.java @@ -20,54 +20,85 @@ import cn.edu.tsinghua.iginx.parquet.db.lsm.api.TableMeta; import cn.edu.tsinghua.iginx.parquet.db.util.AreaSet; +import cn.edu.tsinghua.iginx.thrift.DataType; import com.google.common.collect.Range; import com.google.common.collect.RangeSet; import com.google.common.collect.TreeRangeSet; import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.NoSuchElementException; +import javax.annotation.Nullable; -public class DeletedTableMeta, F, T, V> implements TableMeta { - private final Map schema; - private final Map> ranges; +public class DeletedTableMeta implements TableMeta { + private final Map schema; + private final Map> ranges; + private final Map counts; - public DeletedTableMeta(TableMeta tableMeta, AreaSet tombstone) { + public DeletedTableMeta(TableMeta tableMeta, AreaSet tombstone) { this.schema = new HashMap<>(tableMeta.getSchema()); schema.keySet().removeAll(tombstone.getFields()); - this.ranges = new HashMap<>(); - Map> rangeSetMap = new HashMap<>(); - for (Map.Entry> entry : tableMeta.getRanges().entrySet()) { - F field = entry.getKey(); - Range range = entry.getValue(); + this.counts = new HashMap<>(); + + Map> rangeSetMap = new HashMap<>(); + for (Map.Entry entry : schema.entrySet()) { + String field = entry.getKey(); + Range range = tableMeta.getRange(field); rangeSetMap.put(field, TreeRangeSet.create(Collections.singleton(range))); + Long count = tableMeta.getValueCount(field); + if (count != null) { + counts.put(field, count); + } } - rangeSetMap.keySet().removeAll(tombstone.getFields()); - rangeSetMap.values().forEach(rangeSet -> rangeSet.removeAll(tombstone.getKeys())); - for (Map.Entry> entry : tombstone.getSegments().entrySet()) { - F field = entry.getKey(); - RangeSet rangeSetDeleted = entry.getValue(); - RangeSet rangeSet = rangeSetMap.get(field); + + RangeSet deletedKeys = tombstone.getKeys(); + if (!deletedKeys.isEmpty()) { + counts.clear(); + rangeSetMap.values().forEach(rangeSet -> rangeSet.removeAll(deletedKeys)); + } + + for (Map.Entry> entry : tombstone.getSegments().entrySet()) { + String field = entry.getKey(); + RangeSet rangeSetDeleted = entry.getValue(); + RangeSet rangeSet = rangeSetMap.get(field); if (rangeSet != null) { rangeSet.removeAll(rangeSetDeleted); } + counts.remove(field); } - for (Map.Entry> entry : rangeSetMap.entrySet()) { - F field = entry.getKey(); - RangeSet rangeSet = entry.getValue(); + + this.ranges = new HashMap<>(); + for (Map.Entry> entry : rangeSetMap.entrySet()) { + String field = entry.getKey(); + RangeSet rangeSet = entry.getValue(); if (!rangeSet.isEmpty()) { ranges.put(field, rangeSet.span()); + } else { + ranges.put(field, Range.closedOpen(0L, 0L)); } } } @Override - public Map getSchema() { + public Map getSchema() { return schema; } @Override - public Map> getRanges() { - return ranges; + public Range getRange(String field) { + if (!schema.containsKey(field)) { + throw new NoSuchElementException(); + } + return ranges.get(field); + } + + @Override + @Nullable + public Long getValueCount(String field) { + if (!schema.containsKey(field)) { + throw new NoSuchElementException(); + } + return counts.get(field); } } diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/EmptyTable.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/EmptyTable.java deleted file mode 100644 index 3b1b29bd50..0000000000 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/EmptyTable.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * IGinX - the polystore system with high performance - * Copyright (C) Tsinghua University - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package cn.edu.tsinghua.iginx.parquet.db.lsm.table; - -import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Filter; -import cn.edu.tsinghua.iginx.parquet.db.util.iterator.EmptyScanner; -import cn.edu.tsinghua.iginx.parquet.db.util.iterator.Scanner; -import com.google.common.collect.RangeSet; -import java.io.IOException; -import java.util.HashMap; -import java.util.Set; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public class EmptyTable, F, T, V> implements Table { - private static final EmptyTable EMPTY = new EmptyTable<>(); - - @SuppressWarnings("unchecked") - public static , F, T, V> EmptyTable getInstance() { - return (EmptyTable) EMPTY; - } - - @Nonnull - @Override - public MemoryTable.MemoryTableMeta getMeta() { - return new MemoryTable.MemoryTableMeta<>(new HashMap<>(), new HashMap<>()); - } - - @Nonnull - @Override - public Scanner> scan( - @Nonnull Set fields, @Nonnull RangeSet ranges, @Nullable Filter predicate) - throws IOException { - return EmptyScanner.getInstance(); - } -} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/FileTable.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/FileTable.java index 3b6bdac830..43478aca33 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/FileTable.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/FileTable.java @@ -26,35 +26,32 @@ import java.io.IOException; import java.util.Set; import java.util.StringJoiner; -import javax.annotation.Nonnull; import javax.annotation.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class FileTable, F, T, V> implements Table { +public class FileTable implements Table { private static final Logger LOGGER = LoggerFactory.getLogger(FileTable.class); private final String tableName; - private final ReadWriter readWriter; + private final ReadWriter readWriter; - public FileTable(String tableName, ReadWriter readWriter) { + public FileTable(String tableName, ReadWriter readWriter) { this.tableName = tableName; this.readWriter = readWriter; } @Override - @Nonnull - public TableMeta getMeta() throws IOException { + public TableMeta getMeta() throws IOException { return readWriter.readMeta(tableName); } @Override - @Nonnull - public Scanner> scan( - @Nonnull Set fields, @Nonnull RangeSet ranges, @Nullable Filter predicate) + public Scanner> scan( + Set fields, RangeSet ranges, @Nullable Filter superSetPredicate) throws IOException { - LOGGER.debug("read {} where {} & {} from {}", fields, ranges, predicate, tableName); - return readWriter.scanData(tableName, fields, ranges, predicate); + LOGGER.debug("read {} where {} & {} from {}", fields, ranges, superSetPredicate, tableName); + return readWriter.scanData(tableName, fields, ranges, superSetPredicate); } @Override diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/MemoryTable.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/MemoryTable.java index 39d22d9661..779e4cab06 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/MemoryTable.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/MemoryTable.java @@ -20,74 +20,167 @@ import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Filter; import cn.edu.tsinghua.iginx.parquet.db.lsm.api.TableMeta; -import cn.edu.tsinghua.iginx.parquet.db.lsm.buffer.DataBuffer; -import cn.edu.tsinghua.iginx.parquet.db.util.iterator.ConcatScanner; +import cn.edu.tsinghua.iginx.parquet.db.lsm.buffer.MemColumn; +import cn.edu.tsinghua.iginx.parquet.db.util.iterator.*; import cn.edu.tsinghua.iginx.parquet.db.util.iterator.Scanner; +import cn.edu.tsinghua.iginx.parquet.manager.utils.TagKVUtils; +import cn.edu.tsinghua.iginx.parquet.util.NoexceptAutoCloseable; +import cn.edu.tsinghua.iginx.parquet.util.SingleCache; +import cn.edu.tsinghua.iginx.parquet.util.arrow.ArrowFields; +import cn.edu.tsinghua.iginx.thrift.DataType; import com.google.common.collect.Range; import com.google.common.collect.RangeSet; -import java.io.IOException; import java.util.*; -import javax.annotation.Nonnull; +import java.util.stream.Collectors; import javax.annotation.Nullable; +import javax.annotation.WillCloseWhenClosed; +import org.apache.arrow.vector.types.pojo.Field; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class MemoryTable, F, T, V> implements Table { +public class MemoryTable implements Table, NoexceptAutoCloseable { private static final Logger LOGGER = LoggerFactory.getLogger(MemoryTable.class); - private final DataBuffer buffer; - private final TableMeta meta; + private final LinkedHashMap columns; + private final Map fieldMap = new HashMap<>(); + private final SingleCache meta = + new SingleCache<>(() -> new MemoryTableMeta(getSchema(), getRanges(), getCounts())); - public MemoryTable(DataBuffer buffer, Map types) { - this.buffer = Objects.requireNonNull(buffer); - Objects.requireNonNull(types); - this.meta = new MemoryTableMeta<>(types, buffer.ranges()); + public MemoryTable(@WillCloseWhenClosed LinkedHashMap columns) { + this.columns = new LinkedHashMap<>(columns); + for (Field field : columns.keySet()) { + fieldMap.put(getFieldString(field), field); + } + } + + public static MemoryTable empty() { + return new MemoryTable(new LinkedHashMap<>()); + } + + public Set getFields() { + return columns.keySet(); + } + + public boolean isEmpty() { + return columns.isEmpty(); + } + + private Map getSchema() { + return (Map) ArrowFields.toIginxSchema(columns.keySet()); + } + + private Map> getRanges() { + return columns.keySet().stream() + .collect(Collectors.toMap(this::getFieldString, this::getRange)); + } + + private Map getCounts() { + // TODO: give statistics + return Collections.emptyMap(); + } + + private String getFieldString(Field field) { + return TagKVUtils.toFullName(ArrowFields.toColumnKey(field)); + } + + private Range getRange(Field field) { + MemColumn.Snapshot snapshot = columns.get(field); + RangeSet ranges = snapshot.getRanges(); + if (ranges.isEmpty()) { + return Range.closed(0L, 0L); + } + return ranges.span(); } @Override public String toString() { return new StringJoiner(", ", MemoryTable.class.getSimpleName() + "[", "]") - .add("buffer=" + buffer) .add("meta=" + meta) .toString(); } - @Nonnull @Override - public TableMeta getMeta() { - return meta; + public TableMeta getMeta() { + return meta.get(); } - @Nonnull @Override - public Scanner> scan( - @Nonnull Set fields, @Nonnull RangeSet ranges, @Nullable Filter predicate) - throws IOException { + public Scanner> scan( + Set fields, RangeSet ranges, @Nullable Filter superSetPredicate) { if (LOGGER.isDebugEnabled()) { - LOGGER.debug("read {} where {} from {},{}", fields, ranges, buffer.fields(), buffer.ranges()); + LOGGER.debug("read {} where {} from {}", fields, ranges, meta); + } + Map> columns = new HashMap<>(); + for (String field : fields) { + if (!fieldMap.containsKey(field)) { + continue; + } + Field arrowField = fieldMap.get(field); + MemColumn.Snapshot snapshot = this.columns.get(arrowField); + columns.put(field, scan(snapshot, ranges)); } - List>> scanners = new ArrayList<>(); - for (Range range : ranges.asRanges()) { - scanners.add(buffer.scanRows(fields, range)); + return new ColumnUnionRowScanner<>(columns); + } + + private Scanner scan(MemColumn.Snapshot snapshot, RangeSet ranges) { + if (ranges.isEmpty()) { + return new EmptyScanner<>(); } - return new ConcatScanner<>(scanners.iterator()); + MemColumn.Snapshot sliced = snapshot.slice(ranges); + return new ListenCloseScanner<>(new IteratorScanner<>(sliced.iterator()), sliced::close); + } + + @Override + public void close() { + columns.values().forEach(MemColumn.Snapshot::close); + columns.clear(); + } + + public MemoryTable subTable(Field field) { + LinkedHashMap subColumns = new LinkedHashMap<>(); + subColumns.put(field, columns.get(field)); + return new MemoryTable(subColumns) { + @Override + public void close() { + // do nothing + } + }; } - public static class MemoryTableMeta, F, T, V> - implements TableMeta { - private final Map schema; - private final Map> ranges; + public static class MemoryTableMeta implements TableMeta { + + private final Map schema; + private final Map> ranges; + private final Map counts; - public MemoryTableMeta(Map schema, Map> ranges) { - this.schema = schema; - this.ranges = ranges; + MemoryTableMeta( + Map schema, Map> ranges, Map counts) { + this.schema = Collections.unmodifiableMap(schema); + this.ranges = Collections.unmodifiableMap(ranges); + this.counts = Collections.unmodifiableMap(counts); } - public Map getSchema() { + public Map getSchema() { return schema; } - public Map> getRanges() { + @Override + public Range getRange(String field) { + if (!schema.containsKey(field)) { + throw new NoSuchElementException(); + } + return Objects.requireNonNull(ranges.get(field)); + } + + @Override + public Long getValueCount(String field) { + if (!schema.containsKey(field)) { + throw new NoSuchElementException(); + } + return counts.get(field); + } + + public Map> getRanges() { return ranges; } diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/Table.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/Table.java index e00584d5b7..7cfa02713b 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/Table.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/Table.java @@ -20,25 +20,36 @@ import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Filter; import cn.edu.tsinghua.iginx.parquet.db.lsm.api.TableMeta; +import cn.edu.tsinghua.iginx.parquet.db.util.iterator.LazyRowScanner; import cn.edu.tsinghua.iginx.parquet.db.util.iterator.Scanner; +import cn.edu.tsinghua.iginx.parquet.util.exception.StorageException; import com.google.common.collect.RangeSet; import java.io.IOException; import java.util.Set; -import javax.annotation.Nonnull; import javax.annotation.Nullable; -public interface Table, F, T, V> { - @Nonnull - TableMeta getMeta() throws IOException; +public interface Table { - @Nonnull - Scanner> scan( - @Nonnull Set fields, @Nonnull RangeSet range, @Nullable Filter predicate) + TableMeta getMeta() throws IOException; + + Scanner> scan( + Set fields, RangeSet range, @Nullable Filter superSetPredicate) throws IOException; - @Nonnull - default Scanner> scan(@Nonnull Set fields, @Nonnull RangeSet ranges) + default Scanner> scan(Set fields, RangeSet ranges) throws IOException { return scan(fields, ranges, null); } + + default Scanner> lazyScan( + Set fields, RangeSet ranges) { + return new LazyRowScanner<>( + () -> { + try { + return scan(fields, ranges); + } catch (IOException e) { + throw new StorageException(e); + } + }); + } } diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/TableIndex.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/TableIndex.java index 73c5d8d727..41a1ec3d98 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/TableIndex.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/TableIndex.java @@ -23,6 +23,7 @@ import cn.edu.tsinghua.iginx.parquet.util.exception.NotIntegrityException; import cn.edu.tsinghua.iginx.parquet.util.exception.StorageRuntimeException; import cn.edu.tsinghua.iginx.parquet.util.exception.TypeConflictedException; +import cn.edu.tsinghua.iginx.thrift.DataType; import com.google.common.collect.ImmutableRangeSet; import com.google.common.collect.Range; import com.google.common.collect.RangeSet; @@ -35,16 +36,17 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class TableIndex, F, T, V> implements AutoCloseable { +public class TableIndex { + private static final Logger LOGGER = LoggerFactory.getLogger(TableIndex.class); private final ReadWriteLock lock = new ReentrantReadWriteLock(true); - private final Map> indexes = new HashMap<>(); + private final Map indexes = new HashMap<>(); - public TableIndex(TableStorage tableStorage) { + public TableIndex(TableStorage tableStorage) { try { for (String tableName : tableStorage.tableNames()) { - TableMeta meta = tableStorage.get(tableName).getMeta(); + TableMeta meta = tableStorage.getMeta(tableName); declareFields(meta.getSchema()); addTable(tableName, meta); } @@ -53,27 +55,27 @@ public TableIndex(TableStorage tableStorage) { } } - public Set find(AreaSet areas) { + public Set find(AreaSet areas) { Set result = new HashSet<>(); lock.readLock().lock(); try { - RangeSet rangeSet = areas.getKeys(); + RangeSet rangeSet = areas.getKeys(); if (!rangeSet.isEmpty()) { - for (FieldIndex fieldIndex : indexes.values()) { + for (FieldIndex fieldIndex : indexes.values()) { Set tables = fieldIndex.find(rangeSet); result.addAll(tables); } } - for (F field : areas.getFields()) { - FieldIndex fieldIndex = indexes.get(field); + for (String field : areas.getFields()) { + FieldIndex fieldIndex = indexes.get(field); if (fieldIndex == null) { continue; } Set tables = fieldIndex.find(); result.addAll(tables); } - for (Map.Entry> entry : areas.getSegments().entrySet()) { - FieldIndex fieldIndex = indexes.get(entry.getKey()); + for (Map.Entry> entry : areas.getSegments().entrySet()) { + FieldIndex fieldIndex = indexes.get(entry.getKey()); if (fieldIndex == null) { continue; } @@ -86,12 +88,12 @@ public Set find(AreaSet areas) { return result; } - public Map> ranges() { - Map> result = new HashMap<>(); + public Map> ranges() { + Map> result = new HashMap<>(); lock.readLock().lock(); try { - for (Map.Entry> entry : indexes.entrySet()) { - RangeSet rangeSet = entry.getValue().ranges(); + for (Map.Entry entry : indexes.entrySet()) { + RangeSet rangeSet = entry.getValue().ranges(); if (!rangeSet.isEmpty()) { result.put(entry.getKey(), rangeSet.span()); } @@ -102,19 +104,19 @@ public Map> ranges() { return result; } - public void declareFields(Map schema) throws TypeConflictedException { + public void declareFields(Map schema) throws TypeConflictedException { boolean hasNewField = checkOldFields(schema); if (hasNewField) { declareNewFields(schema); } } - private boolean checkOldFields(Map schema) throws TypeConflictedException { + private boolean checkOldFields(Map schema) throws TypeConflictedException { boolean hasNewField = false; lock.readLock().lock(); try { - for (Map.Entry entry : schema.entrySet()) { - FieldIndex fieldIndex = indexes.get(entry.getKey()); + for (Map.Entry entry : schema.entrySet()) { + FieldIndex fieldIndex = indexes.get(entry.getKey()); if (fieldIndex == null) { hasNewField = true; } else if (!fieldIndex.getType().equals(entry.getValue())) { @@ -130,12 +132,12 @@ private boolean checkOldFields(Map schema) throws TypeConflictedException return hasNewField; } - private void declareNewFields(Map schema) throws TypeConflictedException { - Map newSchema = new HashMap<>(); + private void declareNewFields(Map schema) throws TypeConflictedException { + Map newSchema = new HashMap<>(); lock.writeLock().lock(); try { - for (Map.Entry entry : schema.entrySet()) { - FieldIndex fieldIndex = indexes.get(entry.getKey()); + for (Map.Entry entry : schema.entrySet()) { + FieldIndex fieldIndex = indexes.get(entry.getKey()); if (fieldIndex == null) { newSchema.put(entry.getKey(), entry.getValue()); } else if (!fieldIndex.getType().equals(entry.getValue())) { @@ -146,20 +148,20 @@ private void declareNewFields(Map schema) throws TypeConflictedException { } } LOGGER.debug("declare new fields: {}", newSchema); - for (Map.Entry entry : newSchema.entrySet()) { - indexes.put(entry.getKey(), new FieldIndex<>(entry.getValue())); + for (Map.Entry entry : newSchema.entrySet()) { + indexes.put(entry.getKey(), new FieldIndex(entry.getValue())); } } finally { lock.writeLock().unlock(); } } - public Map getType(Set fields, Consumer processMissingField) { - Map result = new HashMap<>(); + public Map getType(Set fields, Consumer processMissingField) { + Map result = new HashMap<>(); lock.readLock().lock(); try { - for (F field : fields) { - FieldIndex fieldIndex = indexes.get(field); + for (String field : fields) { + FieldIndex fieldIndex = indexes.get(field); if (fieldIndex == null) { processMissingField.accept(field); } else { @@ -172,11 +174,11 @@ public Map getType(Set fields, Consumer processMissingField) { return result; } - public Map getType() { - Map result = new HashMap<>(); + public Map getType() { + Map result = new HashMap<>(); lock.readLock().lock(); try { - for (Map.Entry> entry : indexes.entrySet()) { + for (Map.Entry entry : indexes.entrySet()) { result.put(entry.getKey(), entry.getValue().getType()); } } finally { @@ -185,18 +187,17 @@ public Map getType() { return result; } - public void addTable(String name, TableMeta meta) { + public void addTable(String name, TableMeta meta) { lock.readLock().lock(); try { - Map types = meta.getSchema(); - for (Map.Entry> entry : meta.getRanges().entrySet()) { - F field = entry.getKey(); - FieldIndex fieldIndex = indexes.get(field); + Map types = meta.getSchema(); + for (String field : types.keySet()) { + FieldIndex fieldIndex = indexes.get(field); if (fieldIndex == null) { throw new NotIntegrityException("field " + field + " is not found in schema"); } - T oldType = fieldIndex.getType(); - T newType = types.get(field); + DataType oldType = fieldIndex.getType(); + DataType newType = types.get(field); if (!oldType.equals(newType)) { throw new NotIntegrityException( "field " @@ -206,8 +207,8 @@ public void addTable(String name, TableMeta meta) { + ", new type: " + newType); } - Range range = entry.getValue(); - fieldIndex.addTable(name, range); + Range range = meta.getRange(field); + fieldIndex.addTable(name, Objects.requireNonNull(range)); } } finally { lock.readLock().unlock(); @@ -217,7 +218,7 @@ public void addTable(String name, TableMeta meta) { public void removeTable(String name) { lock.readLock().lock(); try { - for (FieldIndex fieldIndex : indexes.values()) { + for (FieldIndex fieldIndex : indexes.values()) { fieldIndex.removeTable(name); } } finally { @@ -225,15 +226,15 @@ public void removeTable(String name) { } } - public void delete(AreaSet areas) { + public void delete(AreaSet areas) { lock.writeLock().lock(); try { indexes.keySet().removeAll(areas.getFields()); - for (FieldIndex fieldIndex : indexes.values()) { + for (FieldIndex fieldIndex : indexes.values()) { fieldIndex.delete(areas.getKeys()); } - for (Map.Entry> entry : areas.getSegments().entrySet()) { - FieldIndex fieldIndex = indexes.get(entry.getKey()); + for (Map.Entry> entry : areas.getSegments().entrySet()) { + FieldIndex fieldIndex = indexes.get(entry.getKey()); if (fieldIndex != null) { fieldIndex.delete(entry.getValue()); } @@ -252,25 +253,20 @@ public void clear() { } } - @Override - public void close() { - // do nothing - } - - public static class FieldIndex, F, T, V> { + public static class FieldIndex { private final ReadWriteLock lock = new ReentrantReadWriteLock(true); - private final T type; - private final Map> tableRange = new HashMap<>(); + private final DataType type; + private final Map> tableRange = new HashMap<>(); - public FieldIndex(T type) { + public FieldIndex(DataType type) { this.type = type; } - public T getType() { + public DataType getType() { return type; } - public void addTable(String name, Range range) { + public void addTable(String name, Range range) { lock.writeLock().lock(); try { if (this.tableRange.containsKey(name)) { @@ -291,11 +287,11 @@ public void removeTable(String name) { } } - public Set find(RangeSet ranges) { + public Set find(RangeSet ranges) { Set result = new HashSet<>(); lock.readLock().lock(); try { - for (Map.Entry> entry : tableRange.entrySet()) { + for (Map.Entry> entry : tableRange.entrySet()) { if (ranges.intersects(entry.getValue())) { result.add(entry.getKey()); } @@ -317,14 +313,14 @@ public Set find() { return result; } - public void delete(RangeSet ranges) { + public void delete(RangeSet ranges) { lock.writeLock().lock(); try { - RangeSet validRanges = ranges.complement(); - Iterator>> iterator = tableRange.entrySet().iterator(); - Map> overlap = new HashMap<>(); + RangeSet validRanges = ranges.complement(); + Iterator>> iterator = tableRange.entrySet().iterator(); + Map> overlap = new HashMap<>(); while (iterator.hasNext()) { - Map.Entry> entry = iterator.next(); + Map.Entry> entry = iterator.next(); if (!ranges.intersects(entry.getValue())) { continue; } @@ -340,11 +336,11 @@ public void delete(RangeSet ranges) { } } - public RangeSet ranges() { - TreeRangeSet rangeSet = TreeRangeSet.create(); + public RangeSet ranges() { + TreeRangeSet rangeSet = TreeRangeSet.create(); lock.readLock().lock(); try { - for (Range range : tableRange.values()) { + for (Range range : tableRange.values()) { rangeSet.add(range); } } finally { diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/TableStorage.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/TableStorage.java index 4c93860bf6..c9369b1aae 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/TableStorage.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/table/TableStorage.java @@ -18,195 +18,294 @@ package cn.edu.tsinghua.iginx.parquet.db.lsm.table; +import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Filter; import cn.edu.tsinghua.iginx.parquet.db.lsm.api.ReadWriter; import cn.edu.tsinghua.iginx.parquet.db.lsm.api.TableMeta; +import cn.edu.tsinghua.iginx.parquet.db.lsm.buffer.DataBuffer; import cn.edu.tsinghua.iginx.parquet.db.util.AreaSet; -import cn.edu.tsinghua.iginx.parquet.db.util.SequenceGenerator; +import cn.edu.tsinghua.iginx.parquet.db.util.iterator.ConcatScanner; +import cn.edu.tsinghua.iginx.parquet.db.util.iterator.EmtpyHeadRowScanner; +import cn.edu.tsinghua.iginx.parquet.db.util.iterator.RowUnionScanner; import cn.edu.tsinghua.iginx.parquet.db.util.iterator.Scanner; import cn.edu.tsinghua.iginx.parquet.util.Shared; +import cn.edu.tsinghua.iginx.parquet.util.arrow.ArrowFields; import cn.edu.tsinghua.iginx.parquet.util.exception.StorageException; -import cn.edu.tsinghua.iginx.parquet.util.exception.StorageRuntimeException; -import com.google.common.collect.ImmutableRangeSet; -import com.google.common.collect.Range; +import cn.edu.tsinghua.iginx.parquet.util.exception.TypeConflictedException; +import cn.edu.tsinghua.iginx.thrift.DataType; +import com.google.common.collect.*; import java.io.IOException; -import java.util.Comparator; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Semaphore; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.stream.StreamSupport; +import org.apache.arrow.vector.types.pojo.Field; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -// TODO: merge TableStorage, TableIndex and TombstoneStorage to control concurrent access to the -// storage -public class TableStorage, F, T, V> implements AutoCloseable { +public class TableStorage implements AutoCloseable { private static final Logger LOGGER = LoggerFactory.getLogger(TableStorage.class); - private final ReadWriteLock lock = new ReentrantReadWriteLock(true); - private final SequenceGenerator seqGen = new SequenceGenerator(); - private final ExecutorService flusher = Executors.newCachedThreadPool(); + private final TableIndex tableIndex; + private final ReadWriter readWriter; + private long sqnBase; - private final Map> memTables = new HashMap<>(); - private final Map> memTombstones = new HashMap<>(); - private final Shared shared; - private final ReadWriter readWriter; - - private final int localFlusherPermitsTotal; - private final Semaphore localFlusherPermits; - - public TableStorage(Shared shared, ReadWriter readWriter) throws IOException { - this.shared = shared; + public TableStorage(Shared shared, ReadWriter readWriter) throws IOException { this.readWriter = readWriter; - this.localFlusherPermitsTotal = shared.getFlusherPermits().availablePermits(); - this.localFlusherPermits = new Semaphore(localFlusherPermitsTotal, true); - reload(); - } - private void reload() throws IOException { Iterable tableNames = readWriter.tableNames(); String last = StreamSupport.stream(tableNames.spliterator(), false) .max(Comparator.naturalOrder()) - .orElse("0"); - seqGen.reset(getSeq(last)); + .orElse("0-0"); + this.sqnBase = getSeq(last) + 1; + this.tableIndex = new TableIndex(this); } static long getSeq(String tableName) { - return Long.parseLong(tableName, 10); + Pattern pattern = Pattern.compile("^(\\d+)-.*$"); + Matcher matcher = pattern.matcher(tableName); + if (matcher.find()) { + return Long.parseLong(matcher.group(1)); + } else { + throw new IllegalArgumentException("invalid table name: " + tableName); + } } - static String getTableName(long seq) { - return String.format("%019d", seq); + public String getTableName(long sqn, String suffix) { + return String.format("%019d-%s", sqnBase + sqn, suffix); } - public String flush(MemoryTable table, Runnable afterFlush) + public List flush(long sqn, String suffix, MemoryTable table) throws InterruptedException { - shared.getFlusherPermits().acquire(); - localFlusherPermits.acquire(); - lock.writeLock().lock(); - try { - String tableName = getTableName(seqGen.next()); - LOGGER.debug("waiting for flusher permit to flush {}", tableName); - memTables.put(tableName, table); - flusher.submit( - () -> { - LOGGER.debug("task to flush {} started", tableName); - try { - TableMeta meta = table.getMeta(); - try (Scanner> scanner = - table.scan(meta.getSchema().keySet(), ImmutableRangeSet.of(Range.all()))) { - readWriter.flush(tableName, meta, scanner); - } - - commitMemoryTable(tableName); - - LOGGER.debug("{} flushed", tableName); - - afterFlush.run(); - } catch (Throwable e) { - LOGGER.error("failed to flush {}", tableName, e); - } finally { - localFlusherPermits.release(); - shared.getFlusherPermits().release(); - LOGGER.trace("unlock clean lock and released flusher permit"); - } - LOGGER.debug("task to flush {} end", tableName); - }); - return tableName; - } finally { - lock.writeLock().unlock(); - } - } - - private void commitMemoryTable(String name) throws IOException { - lock.writeLock().lock(); - try { - if (memTables.remove(name) != null) { - AreaSet tombstone = memTombstones.remove(name); - if (tombstone != null) { - readWriter.delete(name, tombstone); - } - } else { - readWriter.delete(name); - } - } finally { - lock.writeLock().unlock(); + if (table.isEmpty()) { + return Collections.emptyList(); + } + String name = getTableName(sqn, suffix); + TableMeta meta = table.getMeta(); + try (Scanner> scanner = + table.scan(meta.getSchema().keySet(), ImmutableRangeSet.of(Range.all()))) { + readWriter.flush(name, meta, scanner); + } catch (IOException | StorageException e) { + LOGGER.error("flush table {} failed", name, e); } + return Collections.singletonList(name); } - public void remove(String name) { - lock.writeLock().lock(); + public void commit(String table, AreaSet tombstone) { + AreaSet innerTombstone = ArrowFields.toInnerAreas(tombstone); try { - if (memTables.remove(name) != null) { - memTombstones.remove(name); - } else { - readWriter.delete(name); + if (innerTombstone.isAll()) { + readWriter.delete(table); + return; } - } finally { - lock.writeLock().unlock(); + if (!innerTombstone.isEmpty()) { + readWriter.delete(table, innerTombstone); + } + TableMeta meta = readWriter.readMeta(table); + tableIndex.addTable(table, meta); + } catch (IOException e) { + LOGGER.error("commit table {} failed", table, e); } } - public void clear() throws StorageException, InterruptedException { - localFlusherPermits.acquire(localFlusherPermitsTotal); - lock.writeLock().lock(); + public void clear() { + sqnBase = 0; + tableIndex.clear(); try { - memTables.clear(); - memTombstones.clear(); readWriter.clear(); - seqGen.reset(); } catch (IOException e) { - throw new StorageRuntimeException(e); - } finally { - localFlusherPermits.release(localFlusherPermitsTotal); - lock.writeLock().unlock(); + LOGGER.error("clear failed", e); } } - public Table get(String tableName) throws IOException { - lock.readLock().lock(); - try { - MemoryTable table = memTables.get(tableName); - if (table != null) { - AreaSet tombstone = memTombstones.get(tableName); - if (tombstone == null) { - return table; + public TableMeta getMeta(String tableName) throws IOException { + return new FileTable(tableName, readWriter).getMeta(); + } + + public void delete(AreaSet areas) throws IOException { + Set tables = tableIndex.find(areas); + tableIndex.delete(areas); + for (String tableName : tables) { + readWriter.delete(tableName, areas); + } + } + + public Iterable tableNames() throws IOException { + return readWriter.tableNames(); + } + + @Override + public void close() {} + + public Map schema() { + return tableIndex.getType(); + } + + public void declareFields(Map schema) throws TypeConflictedException { + tableIndex.declareFields(schema); + } + + public DataBuffer query( + Set fields, RangeSet ranges, Filter filter) + throws StorageException, IOException { + + AreaSet areas = new AreaSet<>(); + areas.add(fields, ranges); + DataBuffer buffer = new DataBuffer<>(); + + Set tables = tableIndex.find(areas); + List sortedTableNames = new ArrayList<>(tables); + sortedTableNames.sort(Comparator.naturalOrder()); + + for (String tableName : sortedTableNames) { + try (Scanner> scanner = scan(tableName, fields, ranges)) { + buffer.putRows(scanner); + } + } + + return buffer; + } + + private Scanner> scan( + String tableName, Set fields, RangeSet ranges) throws IOException { + return new FileTable(tableName, readWriter).scan(fields, ranges); + } + + public Map count(Set innerFields) throws StorageException, IOException { + Map counts = new HashMap<>(); + + for (String field : innerFields) { + long count = count(field); + counts.put(field, count); + } + + return counts; + } + + public long count(String field) throws StorageException, IOException { + RangeMap> regionTableLists = getTablesGroupByRegion(field); + + long totalCount = 0; + for (List tables : regionTableLists.asMapOfRanges().values()) { + if (tables.isEmpty()) { + continue; + } else if (tables.size() == 1) { + TableMeta meta = readWriter.readMeta(tables.get(0)); + Long regionCount = meta.getValueCount(field); + if (regionCount != null) { + totalCount += regionCount; + continue; } - return new DeletedTable<>(table, tombstone); } - return new FileTable<>(tableName, readWriter); - } finally { - lock.readLock().unlock(); + totalCount += getOverlapCount(field, tables); } + return totalCount; } - public void delete(Set tables, AreaSet areas) throws IOException { - lock.writeLock().lock(); - try { - for (String tableName : tables) { - MemoryTable table = memTables.get(tableName); - if (table != null) { - memTombstones.computeIfAbsent(tableName, k -> new AreaSet<>()).addAll(areas); - } else { - readWriter.delete(tableName, areas); + private static Range normalize(Range range) { + if (range.isEmpty()) { + return range; + } + long lower = range.lowerEndpoint(); + long upper = range.upperEndpoint(); + if (range.lowerBoundType() == BoundType.OPEN) { + lower++; + } + if (range.upperBoundType() == BoundType.OPEN) { + upper--; + } + return Range.closed(lower, upper); + } + + private RangeMap> getTablesGroupByRegion(String field) throws IOException { + AreaSet areas = new AreaSet<>(); + areas.add(Collections.singleton(field), ImmutableRangeSet.of(Range.all())); + Set tables = tableIndex.find(areas); + List sortedTableNames = new ArrayList<>(tables); + sortedTableNames.sort(Comparator.naturalOrder()); + + HashMap> tableRanges = new HashMap<>(); + for (String tableName : sortedTableNames) { + TableMeta meta = readWriter.readMeta(tableName); + Range range = meta.getRange(field); + tableRanges.put(tableName, range); + } + + RangeSet regions = TreeRangeSet.create(tableRanges.values()); + RangeMap> regionTableLists = TreeRangeMap.create(); + for (Range region : regions.asRanges()) { + regionTableLists.put(region, new ArrayList<>()); + } + + for (String tableName : sortedTableNames) { + Range range = normalize(tableRanges.get(tableName)); + List regionTableList = regionTableLists.get(range.lowerEndpoint()); + assert regionTableList != null; + regionTableList.add(tableName); + } + + return regionTableLists; + } + + private long getOverlapCount(String field, List sortedTableNames) + throws IOException, StorageException { + Set fields = Collections.singleton(field); + + long count = 0; + try (Scanner> scanner = scan(sortedTableNames, fields)) { + while (scanner.iterate()) { + Scanner row = scanner.value(); + while (row.iterate()) { + assert row.value() != null; + count++; } } - } finally { - lock.writeLock().unlock(); } + return count; } - public Iterable tableNames() throws IOException { - return readWriter.tableNames(); + private Scanner> scan(List tableNames, Set fields) + throws IOException, StorageException { + List tables = new ArrayList<>(); + for (String tableName : tableNames) { + tables.add(new FileTable(tableName, readWriter)); + } + List>> overlaps = getOverlapScannerList(fields, tables); + + Collections.reverse(overlaps); + return new RowUnionScanner<>(overlaps); } - @Override - public void close() { - flusher.shutdown(); + private static List>> getOverlapScannerList( + Set fields, List tables) throws IOException { + RangeSet ranges = ImmutableRangeSet.of(Range.all()); + List>> overlaps = new ArrayList<>(); + + RangeSet tableRanges = TreeRangeSet.create(); + List>> noOverlaps = new ArrayList<>(); + for (FileTable table : tables) { + TableMeta meta = table.getMeta(); + Range range = normalize(meta.getRange(fields)); + if (range.isEmpty()) { + continue; + } + if (tableRanges.intersects(range)) { + overlaps.add(new ConcatScanner<>(noOverlaps.iterator())); + noOverlaps = new ArrayList<>(); + tableRanges = TreeRangeSet.create(); + } + long head = range.lowerEndpoint(); + Scanner> lazy = table.lazyScan(fields, ranges); + Scanner> emptyHead = new EmtpyHeadRowScanner<>(head); + Scanner> concat = + new ConcatScanner<>(Iterators.forArray(emptyHead, lazy)); + noOverlaps.add(concat); + tableRanges.add(range); + } + if (!noOverlaps.isEmpty()) { + overlaps.add(new ConcatScanner<>(noOverlaps.iterator())); + } + + return overlaps; } } diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/AreaSet.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/AreaSet.java index 5d4c87bd35..ccdbde91c5 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/AreaSet.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/AreaSet.java @@ -18,6 +18,7 @@ package cn.edu.tsinghua.iginx.parquet.db.util; +import com.google.common.collect.Range; import com.google.common.collect.RangeSet; import com.google.common.collect.TreeRangeSet; import java.util.*; @@ -33,6 +34,20 @@ public AreaSet() { this(new HashMap<>(), new HashSet<>(), TreeRangeSet.create()); } + public static , F> AreaSet create(AreaSet areas) { + Map> deletedRanges = new HashMap<>(); + for (Map.Entry> entry : areas.deletedRanges.entrySet()) { + deletedRanges.put(entry.getKey(), TreeRangeSet.create(entry.getValue())); + } + return new AreaSet<>( + deletedRanges, new HashSet<>(areas.deletedColumns), TreeRangeSet.create(areas.deletedRows)); + } + + public static , F> AreaSet all() { + return new AreaSet( + new HashMap<>(), new HashSet<>(), TreeRangeSet.create(Collections.singleton(Range.all()))); + } + private AreaSet( Map> deletedRanges, Set deletedColumns, RangeSet deletedRows) { this.deletedRanges = deletedRanges; @@ -103,6 +118,10 @@ public boolean isEmpty() { return deletedRanges.isEmpty() && deletedColumns.isEmpty() && deletedRows.isEmpty(); } + public boolean isAll() { + return deletedRows.encloses(Range.all()); + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/WriteBatches.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/WriteBatches.java new file mode 100644 index 0000000000..ea2b8907c4 --- /dev/null +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/WriteBatches.java @@ -0,0 +1,121 @@ +package cn.edu.tsinghua.iginx.parquet.db.util; + +import cn.edu.tsinghua.iginx.engine.physical.storage.domain.ColumnKey; +import cn.edu.tsinghua.iginx.parquet.db.lsm.buffer.chunk.Chunk; +import cn.edu.tsinghua.iginx.parquet.db.util.iterator.Scanner; +import cn.edu.tsinghua.iginx.parquet.manager.utils.TagKVUtils; +import cn.edu.tsinghua.iginx.parquet.util.arrow.ArrowFields; +import cn.edu.tsinghua.iginx.parquet.util.arrow.ArrowTypes; +import cn.edu.tsinghua.iginx.parquet.util.arrow.ArrowVectors; +import cn.edu.tsinghua.iginx.parquet.util.exception.StorageException; +import cn.edu.tsinghua.iginx.thrift.DataType; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Consumer; +import java.util.stream.Collectors; +import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.vector.BigIntVector; +import org.apache.arrow.vector.ValueVector; +import org.apache.arrow.vector.complex.writer.FieldWriter; +import org.apache.arrow.vector.types.Types; + +public class WriteBatches { + + private static class ChunkSnapshotBuilder { + private final BigIntVector keyVector; + private final ValueVector valueVector; + private final FieldWriter valueWriter; + private final Consumer valueAppender; + private int count = 0; + + public ChunkSnapshotBuilder(ColumnKey columnKey, DataType type, BufferAllocator allocator) { + this.keyVector = ArrowVectors.key(allocator); + Types.MinorType minorType = ArrowTypes.minorTypeOf(type); + this.valueVector = + minorType.getNewVector(ArrowFields.of(false, columnKey, type), allocator, null); + this.valueWriter = minorType.getNewFieldWriter(valueVector); + switch (type) { + case BOOLEAN: + valueAppender = value -> valueWriter.writeBit(((Boolean) value) ? 1 : 0); + break; + case INTEGER: + valueAppender = value -> valueWriter.writeInt((Integer) value); + break; + case LONG: + valueAppender = value -> valueWriter.writeBigInt((Long) value); + break; + case FLOAT: + valueAppender = value -> valueWriter.writeFloat4((Float) value); + break; + case DOUBLE: + valueAppender = value -> valueWriter.writeFloat8((Double) value); + break; + case BINARY: + valueAppender = value -> valueWriter.writeVarBinary((byte[]) value); + break; + default: + throw new UnsupportedOperationException("Unsupported data type: " + type); + } + } + + public void append(long key, Object value) { + keyVector.setSafe(count, key); + valueWriter.setPosition(count); + valueAppender.accept(value); + count++; + } + + public Chunk.Snapshot build() { + keyVector.setValueCount(count); + valueVector.setValueCount(count); + return new Chunk.Snapshot(keyVector, valueVector); + } + } + + private static Map builders( + Map schema, BufferAllocator allocator) { + Map headers = new HashMap<>(); + for (Map.Entry entry : schema.entrySet()) { + String name = (String) entry.getKey(); + DataType type = (DataType) entry.getValue(); + ColumnKey columnKey = TagKVUtils.splitFullName(name); + ChunkSnapshotBuilder builder = new ChunkSnapshotBuilder(columnKey, type, allocator); + headers.put(name, builder); + } + return headers; + } + + public static , T> Iterable recordOfRows( + Scanner> rows, Map schema, BufferAllocator allocator) + throws StorageException { + Map builders = builders(schema, allocator); + while (rows.iterate()) { + long key = (Long) rows.key(); + Scanner row = rows.value(); + while (row.iterate()) { + String name = (String) row.key(); + Object value = row.value(); + ChunkSnapshotBuilder builder = builders.get(name); + builder.append(key, value); + } + } + return builders.values().stream().map(ChunkSnapshotBuilder::build).collect(Collectors.toList()); + } + + public static , T> Iterable recordOfColumns( + Scanner> batch, Map schema, BufferAllocator allocator) + throws StorageException { + Map builders = builders(schema, allocator); + while (batch.iterate()) { + String name = (String) batch.key(); + Scanner column = batch.value(); + ChunkSnapshotBuilder builder = builders.get(name); + while (column.iterate()) { + long key = (Long) column.key(); + Object value = column.value(); + builder.append(key, value); + } + } + return builders.values().stream().map(ChunkSnapshotBuilder::build).collect(Collectors.toList()); + } +} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/AreaFilterScanner.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/AreaFilterScanner.java index 9204a5b27a..9301ac34d0 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/AreaFilterScanner.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/AreaFilterScanner.java @@ -21,7 +21,6 @@ import cn.edu.tsinghua.iginx.parquet.db.util.AreaSet; import cn.edu.tsinghua.iginx.parquet.util.exception.StorageException; import com.google.common.collect.RangeSet; -import javax.annotation.Nonnull; public class AreaFilterScanner, F, V> implements Scanner> { @@ -37,13 +36,11 @@ public AreaFilterScanner(Scanner> scanner, AreaSet exclus private K currentKey = null; private Scanner currentValue = null; - @Nonnull @Override public K key() { return currentKey; } - @Nonnull @Override public Scanner value() { return currentValue; @@ -70,10 +67,7 @@ public void close() throws StorageException { } private boolean excludeKey(K key) { - if (areas.getKeys().contains(key)) { - return true; - } - return false; + return areas.getKeys().contains(key); } private class RowFilterScanner implements Scanner { @@ -90,13 +84,11 @@ private RowFilterScanner(Scanner scanner, AreaSet exclusive) { private F currentField = null; private V currentValue = null; - @Nonnull @Override public F key() { return currentField; } - @Nonnull @Override public V value() { return currentValue; diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/BatchPlaneScanner.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/BatchPlaneScanner.java index a8fbb4e20b..2b9f5e7f98 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/BatchPlaneScanner.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/BatchPlaneScanner.java @@ -20,7 +20,6 @@ import cn.edu.tsinghua.iginx.parquet.util.exception.StorageException; import java.util.NoSuchElementException; -import javax.annotation.Nonnull; public class BatchPlaneScanner implements Scanner>> { @@ -40,13 +39,11 @@ public BatchPlaneScanner(Scanner> scannerHelper, long maxBatchS this.maxBatchSize = maxBatchSize; } - @Nonnull @Override public Long key() { return currentBatchSize; } - @Nonnull @Override public Scanner> value() throws NoSuchElementException { return planeScannerHelper; @@ -65,13 +62,11 @@ private class PlaneScannerHelper implements Scanner> { private final Scanner lineScannerHelper = new LineScannerHelper(); - @Nonnull @Override public K key() { return planeScanner.key(); } - @Nonnull @Override public Scanner value() throws NoSuchElementException { return lineScannerHelper; @@ -100,13 +95,11 @@ public void close() {} private class LineScannerHelper implements Scanner { - @Nonnull @Override public F key() throws NoSuchElementException { return planeScanner.value().key(); } - @Nonnull @Override public V value() throws NoSuchElementException { return planeScanner.value().value(); diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/ColumnUnionRowScanner.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/ColumnUnionRowScanner.java index b0227c2e35..5199ed2880 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/ColumnUnionRowScanner.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/ColumnUnionRowScanner.java @@ -23,7 +23,7 @@ import java.util.Map; import java.util.NoSuchElementException; import java.util.PriorityQueue; -import javax.annotation.Nonnull; +import org.apache.arrow.util.AutoCloseables; public class ColumnUnionRowScanner, F, V> implements Scanner> { @@ -32,8 +32,6 @@ public class ColumnUnionRowScanner, F, V> private final Map> scanners; - private K currentKey = null; - private Scanner currentScanner = null; public ColumnUnionRowScanner(Map> scanners) { @@ -49,7 +47,6 @@ private void init() throws StorageException { } } - @Nonnull @Override public K key() throws NoSuchElementException { if (currentScanner == null) { @@ -59,7 +56,6 @@ public K key() throws NoSuchElementException { return queue.peek().getValue().key(); } - @Nonnull @Override public Scanner value() throws NoSuchElementException { if (currentScanner == null) { @@ -87,9 +83,12 @@ public boolean iterate() throws StorageException { @Override public void close() throws StorageException { - Map.Entry> entry; - while ((entry = queue.poll()) != null) { - entry.getValue().close(); + try { + AutoCloseables.close(scanners.values()); + } catch (RuntimeException | StorageException e) { + throw e; + } catch (Exception e) { + throw new StorageException(e); } } @@ -97,7 +96,6 @@ private class QueueScanner implements Scanner { private K currentKey = null; - @Nonnull @Override public F key() throws NoSuchElementException { if (queue.peek() == null) { @@ -106,7 +104,6 @@ public F key() throws NoSuchElementException { return queue.peek().getKey(); } - @Nonnull @Override public V value() throws NoSuchElementException { if (queue.peek() == null) { diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/ConcatScanner.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/ConcatScanner.java index b0f9538811..55cbb45511 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/ConcatScanner.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/ConcatScanner.java @@ -21,7 +21,6 @@ import cn.edu.tsinghua.iginx.parquet.util.exception.StorageException; import java.util.Iterator; import java.util.NoSuchElementException; -import javax.annotation.Nonnull; public class ConcatScanner, V> implements Scanner { @@ -33,7 +32,6 @@ public ConcatScanner(Iterator> iterator) { this.scannerIterator = iterator; } - @Nonnull @Override public K key() throws NoSuchElementException { if (currentScanner == null) { @@ -42,7 +40,6 @@ public K key() throws NoSuchElementException { return currentScanner.key(); } - @Nonnull @Override public V value() throws NoSuchElementException { if (currentScanner == null) { @@ -53,16 +50,23 @@ public V value() throws NoSuchElementException { @Override public boolean iterate() throws StorageException { - if (currentScanner != null && currentScanner.iterate()) { - return true; + if (currentScanner != null) { + if (currentScanner.iterate()) { + return true; + } else { + currentScanner.close(); + currentScanner = null; + } } while (scannerIterator.hasNext()) { currentScanner = scannerIterator.next(); if (currentScanner.iterate()) { return true; + } else { + currentScanner.close(); + currentScanner = null; } } - currentScanner = null; return false; } diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/DelegateScanner.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/DelegateScanner.java new file mode 100644 index 0000000000..fd7bbcb674 --- /dev/null +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/DelegateScanner.java @@ -0,0 +1,31 @@ +package cn.edu.tsinghua.iginx.parquet.db.util.iterator; + +import cn.edu.tsinghua.iginx.parquet.util.exception.StorageException; + +public class DelegateScanner implements Scanner { + private final Scanner scanner; + + public DelegateScanner(Scanner scanner) { + this.scanner = scanner; + } + + @Override + public K key() { + return scanner.key(); + } + + @Override + public V value() { + return scanner.value(); + } + + @Override + public boolean iterate() throws StorageException { + return scanner.iterate(); + } + + @Override + public void close() throws StorageException { + scanner.close(); + } +} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/EmptyScanner.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/EmptyScanner.java index 145e1a42e0..4a7553fdff 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/EmptyScanner.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/EmptyScanner.java @@ -20,7 +20,6 @@ import cn.edu.tsinghua.iginx.parquet.util.exception.StorageException; import java.util.NoSuchElementException; -import javax.annotation.Nonnull; public class EmptyScanner implements Scanner { @@ -31,13 +30,11 @@ public static Scanner getInstance() { return (Scanner) EMPTY; } - @Nonnull @Override public K key() { throw new NoSuchElementException(); } - @Nonnull @Override public V value() { throw new NoSuchElementException(); diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/EmtpyHeadRowScanner.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/EmtpyHeadRowScanner.java new file mode 100644 index 0000000000..6d63fbc48e --- /dev/null +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/EmtpyHeadRowScanner.java @@ -0,0 +1,34 @@ +package cn.edu.tsinghua.iginx.parquet.db.util.iterator; + +import cn.edu.tsinghua.iginx.parquet.util.exception.StorageException; + +public class EmtpyHeadRowScanner, F, V> + implements Scanner> { + + private final K key; + private boolean hasNext = true; + + public EmtpyHeadRowScanner(K key) { + this.key = key; + } + + @Override + public K key() { + return key; + } + + @Override + public Scanner value() { + return EmptyScanner.getInstance(); + } + + @Override + public boolean iterate() throws StorageException { + boolean lastHasNext = hasNext; + hasNext = false; + return lastHasNext; + } + + @Override + public void close() throws StorageException {} +} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/IteratorScanner.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/IteratorScanner.java index b55908e6d6..9f8398a3a8 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/IteratorScanner.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/IteratorScanner.java @@ -21,7 +21,6 @@ import java.util.Iterator; import java.util.Map; import java.util.NoSuchElementException; -import javax.annotation.Nonnull; public class IteratorScanner implements Scanner { @@ -35,7 +34,6 @@ public IteratorScanner(Iterator> iterator) { this.iterator = iterator; } - @Nonnull @Override public K key() throws NoSuchElementException { if (key == null) { @@ -44,7 +42,6 @@ public K key() throws NoSuchElementException { return key; } - @Nonnull @Override public V value() throws NoSuchElementException { if (value == null) { diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/LazyRowScanner.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/LazyRowScanner.java new file mode 100644 index 0000000000..8dea969f0a --- /dev/null +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/LazyRowScanner.java @@ -0,0 +1,39 @@ +package cn.edu.tsinghua.iginx.parquet.db.util.iterator; + +import cn.edu.tsinghua.iginx.parquet.util.exception.StorageException; + +public class LazyRowScanner, F, V> implements Scanner> { + + private final RowScannerFactory factory; + + public LazyRowScanner(RowScannerFactory factory) { + this.factory = factory; + } + + private Scanner> scanner; + + @Override + public K key() { + return scanner.key(); + } + + @Override + public Scanner value() { + return scanner.value(); + } + + @Override + public boolean iterate() throws StorageException { + if (scanner == null) { + scanner = factory.create(); + } + return scanner.iterate(); + } + + @Override + public void close() throws StorageException { + if (scanner != null) { + scanner.close(); + } + } +} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/ListenCloseScanner.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/ListenCloseScanner.java new file mode 100644 index 0000000000..8564cc8961 --- /dev/null +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/ListenCloseScanner.java @@ -0,0 +1,19 @@ +package cn.edu.tsinghua.iginx.parquet.db.util.iterator; + +import cn.edu.tsinghua.iginx.parquet.util.exception.StorageException; + +public class ListenCloseScanner extends DelegateScanner { + + private final Runnable callback; + + public ListenCloseScanner(Scanner scanner, Runnable callback) { + super(scanner); + this.callback = callback; + } + + @Override + public void close() throws StorageException { + super.close(); + callback.run(); + } +} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/RowConcatScanner.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/RowConcatScanner.java new file mode 100644 index 0000000000..687a3dcc48 --- /dev/null +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/RowConcatScanner.java @@ -0,0 +1,3 @@ +package cn.edu.tsinghua.iginx.parquet.db.util.iterator; + +public class RowConcatScanner {} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/RowScannerFactory.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/RowScannerFactory.java new file mode 100644 index 0000000000..5450ed86fd --- /dev/null +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/RowScannerFactory.java @@ -0,0 +1,7 @@ +package cn.edu.tsinghua.iginx.parquet.db.util.iterator; + +import cn.edu.tsinghua.iginx.parquet.util.exception.StorageException; + +public interface RowScannerFactory, F, V> { + Scanner> create() throws StorageException; +} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/RowUnionScanner.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/RowUnionScanner.java index 8d4d15c8eb..b1afb04990 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/RowUnionScanner.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/RowUnionScanner.java @@ -20,7 +20,6 @@ import cn.edu.tsinghua.iginx.parquet.util.exception.StorageException; import java.util.*; -import javax.annotation.Nonnull; public class RowUnionScanner, F, V> implements Scanner> { @@ -31,20 +30,33 @@ public RowUnionScanner(Iterable>> scanners) throws Stor Comparator.comparing(e -> e.getKey().key()); this.queue = new PriorityQueue<>(comparing.thenComparing(Map.Entry::getValue)); + StorageException exception = null; long i = 0; for (Scanner> scanner : scanners) { if (scanner.iterate()) { queue.add(new AbstractMap.SimpleImmutableEntry<>(scanner, i)); i++; + } else { + try { + scanner.close(); + } catch (StorageException e) { + if (exception == null) { + exception = e; + } else { + exception.addSuppressed(e); + } + } } } + if (exception != null) { + throw exception; + } } private Scanner currentRow = null; private K currentKey = null; - @Nonnull @Override public K key() throws NoSuchElementException { if (currentKey == null) { @@ -53,7 +65,6 @@ public K key() throws NoSuchElementException { return currentKey; } - @Nonnull @Override public Scanner value() throws NoSuchElementException { if (currentRow == null) { @@ -91,7 +102,6 @@ public boolean iterate() throws StorageException { private V value; - @Nonnull @Override public F key() throws NoSuchElementException { if (key == null) { @@ -100,7 +110,6 @@ public F key() throws NoSuchElementException { return key; } - @Nonnull @Override public V value() throws NoSuchElementException { if (value == null) { @@ -130,8 +139,20 @@ public void close() throws StorageException {} @Override public void close() throws StorageException { + StorageException exception = null; for (Map.Entry>, Long> entry : queue) { - entry.getKey().close(); + try { + entry.getKey().close(); + } catch (StorageException e) { + if (exception == null) { + exception = e; + } else { + exception.addSuppressed(e); + } + } + } + if (exception != null) { + throw exception; } } } diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/Scanner.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/Scanner.java index 2644383429..5971ee6292 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/Scanner.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/Scanner.java @@ -19,13 +19,11 @@ package cn.edu.tsinghua.iginx.parquet.db.util.iterator; import cn.edu.tsinghua.iginx.parquet.util.exception.StorageException; -import javax.annotation.Nonnull; public interface Scanner extends AutoCloseable { - @Nonnull + K key(); - @Nonnull V value(); boolean iterate() throws StorageException; diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/SizeUtils.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/SizeUtils.java index 4bfb3cf177..cae52979dc 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/SizeUtils.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/SizeUtils.java @@ -21,7 +21,6 @@ import java.util.HashMap; import java.util.Map; import java.util.function.Function; -import javax.annotation.Nonnull; public class SizeUtils { private SizeUtils() {} @@ -37,7 +36,7 @@ private SizeUtils() {} sizeMap.put(byte[].class, (obj) -> (long) ((byte[]) obj).length); } - public static long sizeOf(@Nonnull Object obj) { + public static long sizeOf(Object obj) { Function sizeGetter = sizeMap.get(obj.getClass()); if (sizeGetter == null) { throw new UnsupportedOperationException(obj.getClass() + " is not supported"); diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/Executor.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/Executor.java index 9b1b8e1dde..3f89345452 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/Executor.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/Executor.java @@ -23,19 +23,22 @@ import cn.edu.tsinghua.iginx.engine.physical.task.TaskExecuteResult; import cn.edu.tsinghua.iginx.engine.shared.KeyRange; import cn.edu.tsinghua.iginx.engine.shared.data.write.DataView; +import cn.edu.tsinghua.iginx.engine.shared.function.FunctionCall; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Filter; import cn.edu.tsinghua.iginx.engine.shared.operator.tag.TagFilter; import cn.edu.tsinghua.iginx.metadata.entity.ColumnsInterval; import cn.edu.tsinghua.iginx.metadata.entity.KeyInterval; import cn.edu.tsinghua.iginx.utils.Pair; import java.util.List; +import javax.annotation.Nullable; public interface Executor { TaskExecuteResult executeProjectTask( List paths, - TagFilter tagFilter, - Filter filter, + @Nullable TagFilter tagFilter, + @Nullable Filter filter, + @Nullable List calls, String storageUnit, boolean isDummyStorageUnit); diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java index 04f4e53223..2f33b5f0bd 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java @@ -28,6 +28,7 @@ import cn.edu.tsinghua.iginx.engine.shared.data.read.FilterRowStreamWrapper; import cn.edu.tsinghua.iginx.engine.shared.data.read.RowStream; import cn.edu.tsinghua.iginx.engine.shared.data.write.DataView; +import cn.edu.tsinghua.iginx.engine.shared.function.FunctionCall; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Filter; import cn.edu.tsinghua.iginx.engine.shared.operator.tag.TagFilter; import cn.edu.tsinghua.iginx.metadata.entity.ColumnsInterval; @@ -41,6 +42,7 @@ import cn.edu.tsinghua.iginx.parquet.util.exception.IsClosedException; import cn.edu.tsinghua.iginx.utils.Pair; import cn.edu.tsinghua.iginx.utils.StringUtils; +import com.google.common.base.Preconditions; import com.google.common.collect.Iterables; import java.io.File; import java.io.IOException; @@ -54,6 +56,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; +import javax.annotation.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; @@ -242,6 +245,24 @@ private Manager getOrCreateManager(String storageUnit) throws PhysicalException @Override public TaskExecuteResult executeProjectTask( + List paths, + @Nullable TagFilter tagFilter, + @Nullable Filter filter, + @Nullable List calls, + String storageUnit, + boolean isDummyStorageUnit) { + if (calls != null) { + Preconditions.checkArgument(!calls.isEmpty(), "calls should not be empty"); + Preconditions.checkArgument(filter == null, "filter should be null"); + Preconditions.checkArgument(!isDummyStorageUnit, "dummy storage unit not allowed"); + return executeAggregationTask(paths, tagFilter, calls, storageUnit); + } else { + Preconditions.checkNotNull(filter, "filter should not be null"); + return executeProjectTask(paths, tagFilter, filter, storageUnit, isDummyStorageUnit); + } + } + + private TaskExecuteResult executeProjectTask( List paths, TagFilter tagFilter, Filter filter, @@ -263,6 +284,17 @@ public TaskExecuteResult executeProjectTask( } } + private TaskExecuteResult executeAggregationTask( + List patterns, TagFilter tagFilter, List calls, String storageUnit) { + try { + Manager manager = getOrCreateManager(storageUnit); + RowStream rowStream = ((DataManager) manager).aggregation(patterns, tagFilter, calls); + return new TaskExecuteResult(rowStream); + } catch (PhysicalException e) { + return new TaskExecuteResult(e); + } + } + @Override public TaskExecuteResult executeInsertTask(DataView dataView, String storageUnit) { try { @@ -290,7 +322,8 @@ public TaskExecuteResult executeDeleteTask( public List getColumnsOfStorageUnit(String storageUnit) throws PhysicalException { if (storageUnit.equals("*")) { List columns = new ArrayList<>(); - for (Manager manager : getAllManagers()) { + for (Manager manager : + Iterables.concat(managers.values(), Collections.singleton(dummyManager))) { columns.addAll(manager.getColumns()); } return columns; @@ -302,20 +335,8 @@ public List getColumnsOfStorageUnit(String storageUnit) throws PhysicalE @Override public Pair getBoundaryOfStorage(String dataPrefix) throws PhysicalException { - List paths = new ArrayList<>(); - long start = Long.MAX_VALUE, end = Long.MIN_VALUE; - for (Manager manager : getAllManagers()) { - for (Column column : manager.getColumns()) { - paths.add(column.getPath()); - } - KeyInterval interval = manager.getKeyInterval(); - if (interval.getStartKey() < start) { - start = interval.getStartKey(); - } - if (interval.getEndKey() > end) { - end = interval.getEndKey(); - } - } + List paths = + dummyManager.getColumns().stream().map(Column::getPath).collect(Collectors.toList()); if (dataPrefix != null) { paths = paths.stream().filter(path -> path.startsWith(dataPrefix)).collect(Collectors.toList()); @@ -324,17 +345,9 @@ public Pair getBoundaryOfStorage(String dataPrefix if (paths.isEmpty()) { throw new PhysicalTaskExecuteFailureException("no data"); } - if (start == Long.MAX_VALUE || end == Long.MIN_VALUE) { - throw new PhysicalTaskExecuteFailureException("time range error"); - } ColumnsInterval columnsInterval = new ColumnsInterval(paths.get(0), StringUtils.nextString(paths.get(paths.size() - 1))); - KeyInterval keyInterval = new KeyInterval(start, end); - return new Pair<>(columnsInterval, keyInterval); - } - - private Iterable getAllManagers() { - return Iterables.concat(managers.values(), Collections.singleton(dummyManager)); + return new Pair<>(columnsInterval, KeyInterval.getDefaultKeyInterval()); } @Override diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java index 4abbe370c8..e3e6e20cde 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java @@ -30,6 +30,10 @@ import cn.edu.tsinghua.iginx.engine.shared.data.write.BitmapView; import cn.edu.tsinghua.iginx.engine.shared.data.write.DataView; import cn.edu.tsinghua.iginx.engine.shared.data.write.RawDataType; +import cn.edu.tsinghua.iginx.engine.shared.function.Function; +import cn.edu.tsinghua.iginx.engine.shared.function.FunctionCall; +import cn.edu.tsinghua.iginx.engine.shared.function.FunctionParams; +import cn.edu.tsinghua.iginx.engine.shared.function.system.Count; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Filter; import cn.edu.tsinghua.iginx.engine.shared.operator.tag.AndTagFilter; import cn.edu.tsinghua.iginx.engine.shared.operator.tag.BasePreciseTagFilter; @@ -53,6 +57,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; +import javax.annotation.Nullable; import org.apache.thrift.TException; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.transport.TTransport; @@ -76,8 +82,9 @@ public RemoteExecutor(String ip, int port, Map extraParams) @Override public TaskExecuteResult executeProjectTask( List paths, - TagFilter tagFilter, - Filter filter, + @Nullable TagFilter tagFilter, + @Nullable Filter filter, + @Nullable List calls, String storageUnit, boolean isDummyStorageUnit) { ProjectReq req = new ProjectReq(storageUnit, isDummyStorageUnit, paths); @@ -87,6 +94,11 @@ public TaskExecuteResult executeProjectTask( if (filter != null) { req.setFilter(FilterTransformer.toRawFilter(filter)); } + if (calls != null) { + List rawFunctionCalls = + calls.stream().map(RemoteExecutor::constructRawFunctionCall).collect(Collectors.toList()); + req.setAggregations(rawFunctionCalls); + } try { TTransport transport = thriftConnPool.borrowTransport(); @@ -336,6 +348,24 @@ private RawTagFilter constructRawTagFilter(TagFilter tagFilter) { } } + private static RawFunctionCall constructRawFunctionCall(FunctionCall functionCall) { + RawFunction rawFunction = constructRawFunction(functionCall.getFunction()); + RawFunctionParams rawFunctionParam = constructRawFunctionParam(functionCall.getParams()); + return new RawFunctionCall(rawFunction, rawFunctionParam); + } + + private static RawFunction constructRawFunction(Function function) { + if (function instanceof Count) { + return new RawFunction(Count.COUNT); + } + throw new IllegalArgumentException("unsupported function type"); + } + + private static RawFunctionParams constructRawFunctionParam(FunctionParams params) { + List patterns = params.getPaths(); + return new RawFunctionParams(patterns); + } + @Override public List getColumnsOfStorageUnit(String storageUnit) throws PhysicalException { try { diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileFormat.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileFormat.java deleted file mode 100644 index cd18e98120..0000000000 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileFormat.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * IGinX - the polystore system with high performance - * Copyright (C) Tsinghua University - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package cn.edu.tsinghua.iginx.parquet.io; - -import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Filter; -import java.io.IOException; -import java.nio.file.Path; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public interface FileFormat { - - boolean readIsSeekable(); - - boolean writeIsSeekable(); - - /** - * load meta data from file - * - * @param path file path - * @return meta data - * @throws IOException if an I/O error occurs - */ - @Nonnull - FileMeta getMeta(@Nonnull Path path) throws IOException; - - /** - * load data index from file - * - * @param path file path - * @return data index - * @throws IOException if an I/O error occurs - */ - @Nullable - FileIndex getIndex(@Nonnull Path path, @Nonnull FileMeta meta) throws IOException; - - /** - * get reader of specified file - * - * @param path file path - * @param meta meta data loaded from file - * @param index data index loaded from file - * @param filter filter to apply - * @return file reader - * @throws IOException if an I/O error occurs - */ - @Nonnull - FileReader getReader( - @Nonnull Path path, @Nonnull FileMeta meta, @Nonnull FileIndex index, @Nonnull Filter filter) - throws IOException; - - /** - * get writer of specified file - * - * @param path file path - * @param meta meta data to write - * @return file writer - * @throws IOException if an I/O error occurs - */ - @Nonnull - FileWriter getWriter(@Nonnull Path path, @Nonnull FileMeta meta) throws IOException; -} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileIndex.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileIndex.java deleted file mode 100644 index b131949830..0000000000 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileIndex.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * IGinX - the polystore system with high performance - * Copyright (C) Tsinghua University - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package cn.edu.tsinghua.iginx.parquet.io; - -import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Filter; -import cn.edu.tsinghua.iginx.parquet.db.util.iterator.Scanner; -import java.io.IOException; -import javax.annotation.Nonnull; - -public interface FileIndex { - - /** - * estimate size of data index - * - * @return size of data index in bytes - */ - long size(); - - /** - * detect row ranges - * - * @param filter filter - * @return row ranges. key is start row offset, value is row number. - * @throws IOException if an I/O error occurs - */ - @Nonnull - Scanner detect(@Nonnull Filter filter) throws IOException; -} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileMeta.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileMeta.java deleted file mode 100644 index 10fd4ef2d7..0000000000 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileMeta.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * IGinX - the polystore system with high performance - * Copyright (C) Tsinghua University - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package cn.edu.tsinghua.iginx.parquet.io; - -import cn.edu.tsinghua.iginx.thrift.DataType; -import java.util.Map; -import java.util.Set; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public interface FileMeta { - - /** - * get all fields' name in file - * - * @return all names of fields in file. null if not existed - */ - @Nullable - Set fields(); - - /** - * get type of specified field - * - * @param field field type - * @return type of specified field. null if not existed - */ - @Nullable - DataType getType(@Nonnull String field); - - /** - * get extra information of file - * - * @return extra information of file. null if not existed - */ - @Nullable - Map extra(); -} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileReader.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileReader.java deleted file mode 100644 index fe7fd214e5..0000000000 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileReader.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * IGinX - the polystore system with high performance - * Copyright (C) Tsinghua University - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package cn.edu.tsinghua.iginx.parquet.io; - -import cn.edu.tsinghua.iginx.parquet.io.common.DataChunk; -import java.io.Closeable; -import java.io.IOException; -import java.util.Map; -import java.util.Set; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public interface FileReader extends Closeable { - - /** - * set start row offset to read - * - * @param start start row offset to read - */ - void seek(long start) throws IOException; - - /** - * load data chunks in current row offset - * - * @param fields fields to load. empty if all fields - * @param limit max number of the row to load - * @return data chunks of each field, null if reader has no more data - */ - @Nullable - Map load(@Nonnull Set fields, long limit) throws IOException; -} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileWriter.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileWriter.java deleted file mode 100644 index 141a7001b4..0000000000 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/FileWriter.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * IGinX - the polystore system with high performance - * Copyright (C) Tsinghua University - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package cn.edu.tsinghua.iginx.parquet.io; - -import cn.edu.tsinghua.iginx.parquet.io.common.DataChunk; -import java.io.Closeable; -import java.io.IOException; -import java.util.Map; - -public interface FileWriter extends Closeable { - - /** - * start row offset to read - * - * @param start start row offset to read - */ - void seek(long start) throws IOException; - - /** - * dump data chunks into current row offset - * - * @param data data chunks to dump. key is field name, value is data chunk. row number of each - * data chunk must be same. - */ - void dump(Map data, long limit) throws IOException; -} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/DataChunk.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/DataChunk.java deleted file mode 100644 index 5802384ad4..0000000000 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/DataChunk.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * IGinX - the polystore system with high performance - * Copyright (C) Tsinghua University - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package cn.edu.tsinghua.iginx.parquet.io.common; - -import cn.edu.tsinghua.iginx.parquet.db.util.iterator.Scanner; -import javax.annotation.Nonnull; - -public interface DataChunk extends AutoCloseable { - - /** - * get the size of this data chunk - * - * @return size of this data chunk in bytes - */ - long bytes(); - - /** - * get the scanner of this data chunk - * - * @param start begin row offset - * @return scanner of this data chunk - */ - @Nonnull - Scanner scan(long start); -} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/DataChunks.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/DataChunks.java deleted file mode 100644 index 313559d275..0000000000 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/DataChunks.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * IGinX - the polystore system with high performance - * Copyright (C) Tsinghua University - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package cn.edu.tsinghua.iginx.parquet.io.common; - -import cn.edu.tsinghua.iginx.parquet.db.util.iterator.EmptyScanner; -import cn.edu.tsinghua.iginx.parquet.db.util.iterator.Scanner; -import javax.annotation.Nonnull; - -public class DataChunks { - private DataChunks() {} - - private static class EmptyDataChunk implements DataChunk { - - @Override - public long bytes() { - return 0; - } - - @Nonnull - @Override - public Scanner scan(long position) { - return EmptyScanner.getInstance(); - } - - @Override - public void close() throws Exception {} - } - - private static final DataChunk EMPTY = new EmptyDataChunk(); - - public static DataChunk empty() { - return EMPTY; - } -} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/EmptyReader.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/EmptyReader.java deleted file mode 100644 index c9e6b69eb4..0000000000 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/common/EmptyReader.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * IGinX - the polystore system with high performance - * Copyright (C) Tsinghua University - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package cn.edu.tsinghua.iginx.parquet.io.common; - -import cn.edu.tsinghua.iginx.parquet.io.FileReader; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import javax.annotation.Nonnull; - -public class EmptyReader implements FileReader { - private EmptyReader() {} - - public static EmptyReader getInstance() { - return EmptyReader.INSTANCE; - } - - private static final EmptyReader INSTANCE = new EmptyReader(); - - @Nonnull - @Override - public Map load(@Nonnull Set fields, long limit) throws IOException { - Map result = new HashMap<>(); - for (String field : fields) { - result.put(field, DataChunks.empty()); - } - return result; - } - - @Override - public void seek(long start) throws IOException { - throw new IOException("EmptyReader is not seekable"); - } - - @Override - public void close() throws IOException {} -} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/FilterUtils.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/FilterUtils.java index 10a5676860..2365c5fb24 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/FilterUtils.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/FilterUtils.java @@ -25,15 +25,13 @@ import cn.edu.tsinghua.iginx.parquet.util.Constants; import cn.edu.tsinghua.iginx.utils.Pair; import java.util.Objects; -import javax.annotation.Nonnull; import shaded.iginx.org.apache.parquet.filter2.predicate.FilterApi; import shaded.iginx.org.apache.parquet.filter2.predicate.FilterPredicate; import shaded.iginx.org.apache.parquet.filter2.predicate.Operators; class FilterUtils { - @Nonnull - public static Pair toFilterPredicate(@Nonnull Filter filter) { + public static Pair toFilterPredicate(Filter filter) { switch (filter.getType()) { case Key: return toFilterPredicate((KeyFilter) filter); diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IParquetReader.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IParquetReader.java index aef812f893..011ddab7c4 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IParquetReader.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IParquetReader.java @@ -25,9 +25,7 @@ import com.google.common.collect.Range; import java.io.IOException; import java.nio.file.Path; -import java.util.Objects; -import java.util.Set; -import javax.annotation.Nonnull; +import java.util.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import shaded.iginx.org.apache.parquet.ParquetReadOptions; @@ -39,6 +37,7 @@ import shaded.iginx.org.apache.parquet.hadoop.ParquetRecordReader; import shaded.iginx.org.apache.parquet.hadoop.metadata.BlockMetaData; import shaded.iginx.org.apache.parquet.hadoop.metadata.ColumnChunkMetaData; +import shaded.iginx.org.apache.parquet.hadoop.metadata.ColumnPath; import shaded.iginx.org.apache.parquet.hadoop.metadata.ParquetMetadata; import shaded.iginx.org.apache.parquet.io.InputFile; import shaded.iginx.org.apache.parquet.io.LocalInputFile; @@ -67,6 +66,29 @@ public static Builder builder(Path path) { return new Builder(new LocalInputFile(path)); } + public static Map getCountsOf(ParquetMetadata meta) { + Map counts = new HashMap<>(); + for (BlockMetaData block : meta.getBlocks()) { + List columns = block.getColumns(); + for (ColumnChunkMetaData column : columns) { + ColumnPath path = column.getPath(); + long count = column.getValueCount(); + long nulls = column.getStatistics().getNumNulls(); + long nonNulls = count - nulls; + counts.compute(path, (k, v) -> v == null ? nonNulls : v + nonNulls); + } + } + return counts; + } + + public static Map encodeCounts(Map counts) { + Map result = new HashMap<>(); + for (Map.Entry entry : counts.entrySet()) { + result.put(entry.getKey(), entry.getValue().toString()); + } + return result; + } + public MessageType getSchema() { return schema; } @@ -91,24 +113,32 @@ public void close() throws Exception { } public long getRowCount() { + return getRowCountOf(metadata); + } + + public static long getRowCountOf(ParquetMetadata metadata) { return metadata.getBlocks().stream().mapToLong(BlockMetaData::getRowCount).sum(); } public Range getRange() { + return getRangeOf(metadata); + } + + public static Range getRangeOf(ParquetMetadata metadata) { MessageType schema = metadata.getFileMetaData().getSchema(); if (schema.containsPath(new String[] {Constants.KEY_FIELD_NAME})) { Type type = schema.getType(Constants.KEY_FIELD_NAME); if (type.isPrimitive()) { PrimitiveType primitiveType = type.asPrimitiveType(); if (primitiveType.getPrimitiveTypeName() == PrimitiveType.PrimitiveTypeName.INT64) { - return getKeyRange(); + return getKeyRangeOf(metadata); } } } - return Range.closedOpen(0L, getRowCount()); + return Range.closedOpen(0L, getRowCountOf(metadata)); } - private Range getKeyRange() { + private static Range getKeyRangeOf(ParquetMetadata metadata) { long min = Long.MAX_VALUE; long max = Long.MIN_VALUE; @@ -181,7 +211,6 @@ public IParquetReader build(ParquetMetadata footer) throws IOException { return build(footer, optionsBuilder.build()); } - @Nonnull private IParquetReader build(ParquetMetadata footer, ParquetReadOptions options) throws IOException { MessageType schema = footer.getFileMetaData().getSchema(); diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IParquetWriter.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IParquetWriter.java index f99b9dd424..5304828a34 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IParquetWriter.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/IParquetWriter.java @@ -25,8 +25,10 @@ import java.nio.file.Path; import shaded.iginx.org.apache.parquet.ParquetWriteOptions; import shaded.iginx.org.apache.parquet.bytes.HeapByteBufferAllocator; +import shaded.iginx.org.apache.parquet.hadoop.CodecFactory; import shaded.iginx.org.apache.parquet.hadoop.ParquetFileWriter; import shaded.iginx.org.apache.parquet.hadoop.ParquetRecordWriter; +import shaded.iginx.org.apache.parquet.hadoop.metadata.CompressionCodecName; import shaded.iginx.org.apache.parquet.hadoop.metadata.ParquetMetadata; import shaded.iginx.org.apache.parquet.io.LocalOutputFile; import shaded.iginx.org.apache.parquet.io.OutputFile; @@ -45,7 +47,12 @@ public class IParquetWriter implements AutoCloseable { } public static Builder builder(Path path, MessageType schema) { - return new Builder(new LocalOutputFile(path, new HeapByteBufferAllocator(), 8 * 1024), schema); + return builder(path, schema, 8 * 1024); + } + + public static Builder builder(Path path, MessageType schema, int maxBufferSize) { + return new Builder( + new LocalOutputFile(path, new HeapByteBufferAllocator(), maxBufferSize), schema); } public void write(IRecord record) throws IOException { @@ -93,6 +100,12 @@ public Builder withPageSize(int pageSize) { optionsBuilder.asParquetPropertiesBuilder().withPageSize(pageSize); return this; } + + public Builder withCompressionCodec(String codec) { + CompressionCodecName codecName = CompressionCodecName.valueOf(codec); + optionsBuilder.withCompressor(new CodecFactory().getCompressor(codecName)); + return this; + } } public static IRecord getRecord(MessageType schema, Long key, Scanner value) @@ -102,6 +115,7 @@ public static IRecord getRecord(MessageType schema, Long key, Scanner next() { } }; } + + public void sort() { + values.sort(Comparator.comparingInt(Map.Entry::getKey)); + } } diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/ProjectUtils.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/ProjectUtils.java index 7a54d3b0f0..bc5a9d533d 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/ProjectUtils.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/io/parquet/ProjectUtils.java @@ -22,7 +22,6 @@ import java.util.HashSet; import java.util.Objects; import java.util.Set; -import javax.annotation.Nonnull; import javax.annotation.Nullable; import shaded.iginx.org.apache.parquet.schema.MessageType; import shaded.iginx.org.apache.parquet.schema.Type; @@ -31,8 +30,7 @@ public class ProjectUtils { private ProjectUtils() {} - @Nonnull - static MessageType projectMessageType(@Nonnull MessageType schema, @Nullable Set fields) { + static MessageType projectMessageType(MessageType schema, @Nullable Set fields) { Set schemaFields = new HashSet<>(Objects.requireNonNull(fields)); schemaFields.add(Constants.KEY_FIELD_NAME); diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/Manager.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/Manager.java index 94aec17ac1..57cd1c4f36 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/Manager.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/Manager.java @@ -25,7 +25,6 @@ import cn.edu.tsinghua.iginx.engine.shared.data.write.DataView; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Filter; import cn.edu.tsinghua.iginx.engine.shared.operator.tag.TagFilter; -import cn.edu.tsinghua.iginx.metadata.entity.KeyInterval; import java.util.List; public interface Manager extends AutoCloseable { @@ -36,9 +35,7 @@ RowStream project(List paths, TagFilter tagFilter, Filter filter) void insert(DataView dataView) throws PhysicalException; void delete(List paths, List keyRanges, TagFilter tagFilter) - throws PhysicalException;; + throws PhysicalException; List getColumns() throws PhysicalException; - - KeyInterval getKeyInterval() throws PhysicalException; } diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/AggregatedRowStream.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/AggregatedRowStream.java new file mode 100644 index 0000000000..888d09f218 --- /dev/null +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/AggregatedRowStream.java @@ -0,0 +1,64 @@ +package cn.edu.tsinghua.iginx.parquet.manager.data; + +import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; +import cn.edu.tsinghua.iginx.engine.shared.data.read.Field; +import cn.edu.tsinghua.iginx.engine.shared.data.read.Header; +import cn.edu.tsinghua.iginx.engine.shared.data.read.Row; +import cn.edu.tsinghua.iginx.engine.shared.data.read.RowStream; +import cn.edu.tsinghua.iginx.thrift.DataType; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class AggregatedRowStream implements RowStream { + + private final Row row; + private boolean hasNext = true; + + public AggregatedRowStream(Map values, String functionName) { + List fieldList = new ArrayList<>(values.size()); + List valuesList = new ArrayList<>(values.size()); + for (Map.Entry entry : values.entrySet()) { + Object value = entry.getValue(); + valuesList.add(value); + + Map.Entry> pathWithTags = + DataViewWrapper.parseFieldName(entry.getKey()); + String path = pathWithTags.getKey(); + Map tags = pathWithTags.getValue(); + String pathWithFunctionName = functionName + "(" + path + ")"; + + DataType dataType = typeFromValue(value); + Field field = new Field(pathWithFunctionName, dataType, tags); + fieldList.add(field); + } + row = new Row(new Header(fieldList), valuesList.toArray()); + } + + private static DataType typeFromValue(Object value) { + if (value instanceof Long) { + return DataType.LONG; + } else { + throw new UnsupportedOperationException("Unsupported type: " + value.getClass().getName()); + } + } + + @Override + public Header getHeader() throws PhysicalException { + return row.getHeader(); + } + + @Override + public void close() throws PhysicalException {} + + @Override + public boolean hasNext() throws PhysicalException { + return hasNext; + } + + @Override + public Row next() throws PhysicalException { + hasNext = false; + return row; + } +} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/DataManager.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/DataManager.java index e0a326f1e4..caeb5987d8 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/DataManager.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/DataManager.java @@ -23,54 +23,74 @@ import cn.edu.tsinghua.iginx.engine.shared.KeyRange; import cn.edu.tsinghua.iginx.engine.shared.data.read.RowStream; import cn.edu.tsinghua.iginx.engine.shared.data.write.DataView; +import cn.edu.tsinghua.iginx.engine.shared.function.FunctionCall; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Filter; import cn.edu.tsinghua.iginx.engine.shared.operator.tag.TagFilter; -import cn.edu.tsinghua.iginx.metadata.entity.KeyInterval; import cn.edu.tsinghua.iginx.parquet.db.Database; import cn.edu.tsinghua.iginx.parquet.db.lsm.OneTierDB; import cn.edu.tsinghua.iginx.parquet.db.lsm.api.ReadWriter; import cn.edu.tsinghua.iginx.parquet.db.util.AreaSet; import cn.edu.tsinghua.iginx.parquet.db.util.iterator.Scanner; import cn.edu.tsinghua.iginx.parquet.manager.Manager; -import cn.edu.tsinghua.iginx.parquet.manager.utils.RangeUtils; import cn.edu.tsinghua.iginx.parquet.util.Constants; import cn.edu.tsinghua.iginx.parquet.util.Shared; +import cn.edu.tsinghua.iginx.parquet.util.arrow.ArrowFields; import cn.edu.tsinghua.iginx.parquet.util.exception.StorageException; import cn.edu.tsinghua.iginx.thrift.DataType; -import com.google.common.collect.Range; import com.google.common.collect.RangeSet; import java.io.IOException; import java.nio.file.Path; import java.util.*; +import org.apache.arrow.vector.types.pojo.Field; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class DataManager implements Manager { private static final Logger LOGGER = LoggerFactory.getLogger(DataManager.class); - private final Database db; + private final Database db; private final Shared shared; public DataManager(Shared shared, Path dir) throws IOException { this.shared = shared; Path dataDir = dir.resolve(Constants.DIR_NAME_TABLE); - ReadWriter readWriter = new ParquetReadWriter(shared, dataDir); - this.db = new OneTierDB<>(dir.toString(), shared, readWriter); + ReadWriter readWriter = new ParquetReadWriter(shared, dataDir); + this.db = new OneTierDB(dir.toString(), shared, readWriter); } @Override public RowStream project(List paths, TagFilter tagFilter, Filter filter) throws PhysicalException { - Map schemaMatchTags = ProjectUtils.project(db.schema(), tagFilter); + Map schema = ArrowFields.toIginxSchema(db.schema()); + Map schemaMatchTags = ProjectUtils.project(schema, tagFilter); Map projectedSchema = ProjectUtils.project(schemaMatchTags, paths); Filter projectedFilter = ProjectUtils.project(filter, schemaMatchTags); RangeSet rangeSet = FilterRangeUtils.rangeSetOf(projectedFilter); - Scanner> scanner = - db.query(projectedSchema.keySet(), rangeSet, projectedFilter); - return new ScannerRowStream(projectedSchema, scanner); + try { + Scanner> scanner = + db.query(ArrowFields.of(projectedSchema), rangeSet, projectedFilter); + return new ScannerRowStream(projectedSchema, scanner); + } catch (IOException e) { + throw new StorageException(e); + } + } + + public RowStream aggregation(List patterns, TagFilter tagFilter, List calls) + throws PhysicalException { + Map schema = ArrowFields.toIginxSchema(db.schema()); + Map schemaMatchTags = ProjectUtils.project(schema, tagFilter); + Map projectedSchema = ProjectUtils.project(schemaMatchTags, patterns); + + try { + // TODO: just support count now + Map counts = db.count(ArrowFields.of(projectedSchema)); + return new AggregatedRowStream(counts, "count"); + } catch (InterruptedException | IOException e) { + throw new StorageException(e); + } } @Override @@ -86,8 +106,8 @@ public void insert(DataView data) throws PhysicalException { db.upsertColumns(scanner, wrappedData.getSchema()); } } - } catch (Exception e) { - throw new RuntimeException("failed to close scanner of DataView", e); + } catch (InterruptedException e) { + throw new StorageException(e); } } @@ -106,6 +126,7 @@ public void delete(List paths, List keyRanges, TagFilter tagFi } AreaSet areas = new AreaSet<>(); + Map schema = Collections.emptyMap(); if (paths.stream().anyMatch("*"::equals) && tagFilter == null) { if (rangeSet.isEmpty()) { db.clear(); @@ -113,7 +134,8 @@ public void delete(List paths, List keyRanges, TagFilter tagFi areas.add(rangeSet); } } else { - Map schemaMatchedTags = ProjectUtils.project(db.schema(), tagFilter); + schema = ArrowFields.toIginxSchema(db.schema()); + Map schemaMatchedTags = ProjectUtils.project(schema, tagFilter); Set fields = ProjectUtils.project(schemaMatchedTags, paths).keySet(); if (rangeSet.isEmpty()) { areas.add(fields); @@ -123,14 +145,16 @@ public void delete(List paths, List keyRanges, TagFilter tagFi } if (!areas.isEmpty()) { - db.delete(areas); + AreaSet arrowAreas = ArrowFields.of(areas, schema); + db.delete(arrowAreas); } } @Override public List getColumns() throws StorageException { List columns = new ArrayList<>(); - for (Map.Entry entry : db.schema().entrySet()) { + Map schema = ArrowFields.toIginxSchema(db.schema()); + for (Map.Entry entry : schema.entrySet()) { Map.Entry> pathWithTags = DataViewWrapper.parseFieldName(entry.getKey()); columns.add(new Column(pathWithTags.getKey(), entry.getValue(), pathWithTags.getValue())); @@ -138,12 +162,6 @@ public List getColumns() throws StorageException { return columns; } - @Override - public KeyInterval getKeyInterval() throws PhysicalException { - Optional> optionalRange = db.range(); - return optionalRange.map(RangeUtils::toKeyInterval).orElseGet(() -> new KeyInterval(0, 0)); - } - @Override public void close() throws Exception { db.close(); diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/DataViewWrapper.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/DataViewWrapper.java index 24bb6c1f2a..c36a4fe8b2 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/DataViewWrapper.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/DataViewWrapper.java @@ -26,7 +26,6 @@ import cn.edu.tsinghua.iginx.parquet.util.exception.StorageException; import cn.edu.tsinghua.iginx.thrift.DataType; import java.util.*; -import javax.annotation.Nonnull; class DataViewWrapper { private final DataView dataView; @@ -85,7 +84,6 @@ public DataViewRowsScanner() { } } - @Nonnull @Override public Long key() throws NoSuchElementException { if (key == null) { @@ -94,7 +92,6 @@ public Long key() throws NoSuchElementException { return key; } - @Nonnull @Override public Scanner value() throws NoSuchElementException { if (rowScanner == null) { @@ -136,7 +133,6 @@ public RowScanner(int keyIndex) { this.keyIndex = keyIndex; } - @Nonnull @Override public String key() throws NoSuchElementException { if (fieldName == null) { @@ -145,7 +141,6 @@ public String key() throws NoSuchElementException { return fieldName; } - @Nonnull @Override public Object value() throws NoSuchElementException { if (fieldName == null) { @@ -190,7 +185,6 @@ public DataViewColumnsScanner() { } } - @Nonnull @Override public String key() throws NoSuchElementException { if (fieldName == null) { @@ -199,7 +193,6 @@ public String key() throws NoSuchElementException { return fieldName; } - @Nonnull @Override public Scanner value() throws NoSuchElementException { if (columnScanner == null) { @@ -242,7 +235,6 @@ public ColumnScanner(int fieldIndex) { this.bitmapView = dataView.getBitmapView(fieldIndex); } - @Nonnull @Override public Long key() throws NoSuchElementException { if (key == null) { @@ -251,7 +243,6 @@ public Long key() throws NoSuchElementException { return key; } - @Nonnull @Override public Object value() throws NoSuchElementException { if (key == null) { diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ParquetReadWriter.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ParquetReadWriter.java index f6fea28117..864aa356d5 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ParquetReadWriter.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/ParquetReadWriter.java @@ -42,15 +42,15 @@ import java.io.IOException; import java.nio.file.*; import java.util.*; -import javax.annotation.Nonnull; -import org.ehcache.sizeof.SizeOf; +import javax.annotation.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import shaded.iginx.org.apache.parquet.hadoop.metadata.ColumnPath; import shaded.iginx.org.apache.parquet.hadoop.metadata.ParquetMetadata; import shaded.iginx.org.apache.parquet.schema.MessageType; import shaded.iginx.org.apache.parquet.schema.Type; -public class ParquetReadWriter implements ReadWriter { +public class ParquetReadWriter implements ReadWriter { private static final Logger LOGGER = LoggerFactory.getLogger(ParquetReadWriter.class); @@ -81,11 +81,14 @@ private void cleanTempFiles() { } } + @Override + public String getName() { + return dir.toString(); + } + @Override public void flush( - String tableName, - TableMeta meta, - Scanner> scanner) + String tableName, TableMeta meta, Scanner> scanner) throws IOException { Path path = getPath(tableName); Path tempPath = dir.resolve(tableName + Constants.SUFFIX_FILE_TEMP); @@ -94,9 +97,11 @@ public void flush( LOGGER.debug("flushing into {}", tempPath); MessageType parquetSchema = getMessageType(meta.getSchema()); - IParquetWriter.Builder builder = IParquetWriter.builder(tempPath, parquetSchema); + int maxBufferSize = shared.getStorageProperties().getParquetOutputBufferMaxSize(); + IParquetWriter.Builder builder = IParquetWriter.builder(tempPath, parquetSchema, maxBufferSize); builder.withRowGroupSize(shared.getStorageProperties().getParquetRowGroupSize()); builder.withPageSize((int) shared.getStorageProperties().getParquetPageSize()); + builder.withCompressionCodec(shared.getStorageProperties().getParquetCompression()); try (IParquetWriter writer = builder.build()) { while (scanner.iterate()) { @@ -104,8 +109,7 @@ public void flush( writer.write(record); } ParquetMetadata parquetMeta = writer.flush(); - ParquetTableMeta tableMeta = - new ParquetTableMeta(meta.getSchema(), meta.getRanges(), parquetMeta); + ParquetTableMeta tableMeta = ParquetTableMeta.of(parquetMeta); setParquetTableMeta(path.toString(), tableMeta); } catch (Exception e) { throw new IOException("failed to write " + path, e); @@ -118,7 +122,6 @@ public void flush( Files.move(tempPath, path, StandardCopyOption.REPLACE_EXISTING); } - @Nonnull private static MessageType getMessageType(Map schema) { List fields = new ArrayList<>(); fields.add( @@ -133,7 +136,7 @@ private static MessageType getMessageType(Map schema) { } @Override - public TableMeta readMeta(String tableName) { + public TableMeta readMeta(String tableName) { Path path = getPath(tableName); ParquetTableMeta tableMeta = getParquetTableMeta(path.toString()); AreaSet tombstone = tombstoneStorage.get(tableName); @@ -147,7 +150,6 @@ private void setParquetTableMeta(String fileName, ParquetTableMeta tableMeta) { shared.getCachePool().asMap().put(fileName, tableMeta); } - @Nonnull private ParquetTableMeta getParquetTableMeta(String fileName) { CachePool.Cacheable cacheable = shared.getCachePool().asMap().computeIfAbsent(fileName, this::doReadMeta); @@ -157,32 +159,12 @@ private ParquetTableMeta getParquetTableMeta(String fileName) { return (ParquetTableMeta) cacheable; } - @Nonnull private ParquetTableMeta doReadMeta(String fileName) { Path path = Paths.get(fileName); try (IParquetReader reader = IParquetReader.builder(path).build()) { - Map schemaDst = new HashMap<>(); - MessageType parquetSchema = reader.getSchema(); - for (int i = 0; i < parquetSchema.getFieldCount(); i++) { - Type type = parquetSchema.getType(i); - if (type.getName().equals(Constants.KEY_FIELD_NAME)) { - continue; - } - DataType iginxType = IParquetReader.toIginxType(type.asPrimitiveType()); - schemaDst.put(type.getName(), iginxType); - } - - Range ranges = reader.getRange(); - - Map> rangeMap = new HashMap<>(); - for (String field : schemaDst.keySet()) { - rangeMap.put(field, ranges); - } - ParquetMetadata meta = reader.getMeta(); - - return new ParquetTableMeta(schemaDst, rangeMap, meta); + return ParquetTableMeta.of(meta); } catch (Exception e) { throw new StorageRuntimeException(e); } @@ -272,14 +254,18 @@ public void clear() throws IOException { shared.getCachePool().asMap().remove(fileName); } } + try (DirectoryStream stream = + Files.newDirectoryStream(dir, "*" + Constants.SUFFIX_FILE_TEMP)) { + for (Path path : stream) { + Files.deleteIfExists(path); + } + } tombstoneStorage.clear(); Files.deleteIfExists(dir); } catch (NoSuchFileException e) { LOGGER.trace("Not a directory to clear: {}", dir); } catch (DirectoryNotEmptyException e) { LOGGER.warn("directory not empty to clear: {}", dir); - } catch (IOException e) { - throw new StorageRuntimeException(e); } } @@ -292,7 +278,6 @@ public ParquetScanner(IParquetReader reader) { this.reader = reader; } - @Nonnull @Override public Long key() throws NoSuchElementException { if (key == null) { @@ -301,7 +286,6 @@ public Long key() throws NoSuchElementException { return key; } - @Nonnull @Override public Scanner value() throws NoSuchElementException { if (rowScanner == null) { @@ -348,22 +332,53 @@ public void close() throws StorageException { } } - private static class ParquetTableMeta - implements TableMeta, CachePool.Cacheable { + private static class ParquetTableMeta implements TableMeta, CachePool.Cacheable { private final Map schemaDst; private final Map> rangeMap; + private final Map countMap; private final ParquetMetadata meta; - private final int weight; - public ParquetTableMeta( - Map schemaDst, Map> rangeMap, ParquetMetadata meta) { + public static ParquetTableMeta of(ParquetMetadata meta) { + Map schemaDst = new HashMap<>(); + Map> rangeMap = new HashMap<>(); + Map countMap = new HashMap<>(); + MessageType parquetSchema = meta.getFileMetaData().getSchema(); + + Range ranges = IParquetReader.getRangeOf(meta); + + for (int i = 0; i < parquetSchema.getFieldCount(); i++) { + Type type = parquetSchema.getType(i); + if (type.getName().equals(Constants.KEY_FIELD_NAME)) { + continue; + } + DataType iginxType = IParquetReader.toIginxType(type.asPrimitiveType()); + schemaDst.put(type.getName(), iginxType); + rangeMap.put(type.getName(), ranges); + } + + Map columnPathMap = IParquetReader.getCountsOf(meta); + columnPathMap.forEach( + (columnPath, count) -> { + String[] columnPathArray = columnPath.toArray(); + if (columnPathArray.length != 1) { + throw new IllegalStateException("invalid column path: " + columnPath); + } + String name = columnPath.toArray()[0]; + countMap.put(name, count); + }); + + return new ParquetTableMeta(schemaDst, rangeMap, countMap, meta); + } + + ParquetTableMeta( + Map schemaDst, + Map> rangeMap, + Map countMap, + ParquetMetadata meta) { this.schemaDst = schemaDst; this.rangeMap = rangeMap; + this.countMap = countMap; this.meta = meta; - int schemaWeight = schemaDst.toString().length(); - int rangeWeight = rangeMap.toString().length(); - int metaWeight = (int) SizeOf.newInstance().deepSizeOf(meta); - this.weight = schemaWeight + rangeWeight + metaWeight; } @Override @@ -372,17 +387,24 @@ public Map getSchema() { } @Override - public Map> getRanges() { - return rangeMap; + public Range getRange(String field) { + if (!schemaDst.containsKey(field)) { + throw new NoSuchElementException(); + } + return rangeMap.get(field); } - public ParquetMetadata getMeta() { - return meta; + @Nullable + @Override + public Long getValueCount(String field) { + if (!schemaDst.containsKey(field)) { + throw new NoSuchElementException(); + } + return countMap.get(field); } - @Override - public int getWeight() { - return weight; + public ParquetMetadata getMeta() { + return meta; } } } diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/TombstoneStorage.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/TombstoneStorage.java index 7bb6cee8c4..f0ad22fb29 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/TombstoneStorage.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/TombstoneStorage.java @@ -189,11 +189,8 @@ public static class CachedTombstone, String> private final AreaSet areas; - private final int weight; - public CachedTombstone(AreaSet areas, int size) { this.areas = areas; - this.weight = size + 32; } public CachedTombstone(int length) { @@ -203,10 +200,5 @@ public CachedTombstone(int length) { public AreaSet getTombstone() { return areas == null ? new AreaSet<>() : areas; } - - @Override - public int getWeight() { - return weight; - } } } diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/DummyManager.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/DummyManager.java index df6f748ed0..cf6000084e 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/DummyManager.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/DummyManager.java @@ -28,7 +28,6 @@ import cn.edu.tsinghua.iginx.engine.shared.data.write.DataView; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Filter; import cn.edu.tsinghua.iginx.engine.shared.operator.tag.TagFilter; -import cn.edu.tsinghua.iginx.metadata.entity.KeyInterval; import cn.edu.tsinghua.iginx.parquet.manager.Manager; import cn.edu.tsinghua.iginx.parquet.manager.utils.TagKVUtils; import cn.edu.tsinghua.iginx.utils.StringUtils; @@ -156,11 +155,6 @@ public List getColumns() throws PhysicalException { return columns; } - @Override - public KeyInterval getKeyInterval() { - return KeyInterval.getDefaultKeyInterval(); - } - @Override public void close() throws IOException { LOGGER.info("{} closed", this); diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/EmptyManager.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/EmptyManager.java index 288119484e..14d87a05c3 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/EmptyManager.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/EmptyManager.java @@ -28,7 +28,6 @@ import cn.edu.tsinghua.iginx.engine.shared.data.write.DataView; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Filter; import cn.edu.tsinghua.iginx.engine.shared.operator.tag.TagFilter; -import cn.edu.tsinghua.iginx.metadata.entity.KeyInterval; import cn.edu.tsinghua.iginx.parquet.manager.Manager; import java.util.Collections; import java.util.List; @@ -77,11 +76,6 @@ public List getColumns() throws PhysicalException { return Collections.emptyList(); } - @Override - public KeyInterval getKeyInterval() throws PhysicalException { - return new KeyInterval(0, 0); - } - @Override public void close() throws Exception {} } diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/utils/TagKVUtils.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/utils/TagKVUtils.java index 280ca35540..3f62124651 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/utils/TagKVUtils.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/utils/TagKVUtils.java @@ -25,6 +25,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Objects; public class TagKVUtils { private static final ColumnKeyTranslator COLUMN_KEY_TRANSLATOR = @@ -43,6 +44,11 @@ public static String toFullName(String name, Map tags) { tags = Collections.emptyMap(); } ColumnKey columnKey = new ColumnKey(name, tags); + return toFullName(columnKey); + } + + public static String toFullName(ColumnKey columnKey) { + Objects.requireNonNull(columnKey); return COLUMN_KEY_TRANSLATOR.translate(columnKey); } diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetServer.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetServer.java index 8030a4a2eb..0b2f2c6c06 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetServer.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetServer.java @@ -22,6 +22,11 @@ import cn.edu.tsinghua.iginx.conf.ConfigDescriptor; import cn.edu.tsinghua.iginx.parquet.exec.Executor; import cn.edu.tsinghua.iginx.parquet.thrift.ParquetService; +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; import org.apache.thrift.TProcessor; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.server.TServer; @@ -73,11 +78,18 @@ public void run() { } return; } + ExecutorService executorService = + new ThreadPoolExecutor( + config.getMinThriftWorkerThreadNum(), + config.getMaxThriftWrokerThreadNum(), + 60L, + TimeUnit.SECONDS, + new SynchronousQueue<>(), + new ThreadFactoryBuilder().setNameFormat("parquet-server-" + port + "-%d").build()); TThreadPoolServer.Args args = new TThreadPoolServer.Args(serverTransport) .processor(processor) - .minWorkerThreads(config.getMinThriftWorkerThreadNum()) - .maxWorkerThreads(config.getMaxThriftWrokerThreadNum()) + .executorService(executorService) .protocolFactory(new TBinaryProtocol.Factory()); server = new TThreadPoolServer(args); LOGGER.info("Parquet service starts successfully!"); diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetWorker.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetWorker.java index 14cf525e34..a1ae383f96 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetWorker.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetWorker.java @@ -24,18 +24,12 @@ import cn.edu.tsinghua.iginx.engine.shared.KeyRange; import cn.edu.tsinghua.iginx.engine.shared.data.read.Row; import cn.edu.tsinghua.iginx.engine.shared.data.read.RowStream; -import cn.edu.tsinghua.iginx.engine.shared.data.write.ColumnDataView; -import cn.edu.tsinghua.iginx.engine.shared.data.write.DataView; -import cn.edu.tsinghua.iginx.engine.shared.data.write.RawData; -import cn.edu.tsinghua.iginx.engine.shared.data.write.RawDataType; -import cn.edu.tsinghua.iginx.engine.shared.data.write.RowDataView; -import cn.edu.tsinghua.iginx.engine.shared.operator.tag.AndTagFilter; -import cn.edu.tsinghua.iginx.engine.shared.operator.tag.BasePreciseTagFilter; -import cn.edu.tsinghua.iginx.engine.shared.operator.tag.BaseTagFilter; -import cn.edu.tsinghua.iginx.engine.shared.operator.tag.OrTagFilter; -import cn.edu.tsinghua.iginx.engine.shared.operator.tag.PreciseTagFilter; -import cn.edu.tsinghua.iginx.engine.shared.operator.tag.TagFilter; -import cn.edu.tsinghua.iginx.engine.shared.operator.tag.WithoutTagFilter; +import cn.edu.tsinghua.iginx.engine.shared.data.write.*; +import cn.edu.tsinghua.iginx.engine.shared.function.Function; +import cn.edu.tsinghua.iginx.engine.shared.function.FunctionCall; +import cn.edu.tsinghua.iginx.engine.shared.function.FunctionParams; +import cn.edu.tsinghua.iginx.engine.shared.function.system.Count; +import cn.edu.tsinghua.iginx.engine.shared.operator.tag.*; import cn.edu.tsinghua.iginx.metadata.entity.ColumnsInterval; import cn.edu.tsinghua.iginx.metadata.entity.KeyInterval; import cn.edu.tsinghua.iginx.parquet.exec.Executor; @@ -46,11 +40,7 @@ import cn.edu.tsinghua.iginx.utils.DataTypeUtils; import cn.edu.tsinghua.iginx.utils.Pair; import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; import org.apache.thrift.TException; import org.slf4j.Logger; @@ -82,11 +72,20 @@ public ParquetWorker(Executor executor) { public ProjectResp executeProject(ProjectReq req) throws TException { TagFilter tagFilter = resolveRawTagFilter(req.getTagFilter()); + List calls = null; + if (req.getAggregations() != null) { + calls = + req.getAggregations().stream() + .map(this::resolveRawFunctionCall) + .collect(Collectors.toList()); + } + TaskExecuteResult result = executor.executeProjectTask( req.getPaths(), tagFilter, FilterTransformer.toFilter(req.getFilter()), + calls, req.getStorageUnit(), req.isDummyStorageUnit); @@ -284,6 +283,23 @@ private TagFilter resolveRawTagFilter(RawTagFilter rawTagFilter) { } } + private FunctionCall resolveRawFunctionCall(RawFunctionCall rawFunctionCall) { + Function function = resolveRawFunction(rawFunctionCall.getFunc()); + FunctionParams params = resolveRawFunctionParams(rawFunctionCall.getParams()); + return new FunctionCall(function, params); + } + + private Function resolveRawFunction(RawFunction rawFunction) { + if (rawFunction.getId().equals(Count.COUNT)) { + return Count.getInstance(); + } + throw new UnsupportedOperationException("unsupported function: " + rawFunction); + } + + private FunctionParams resolveRawFunctionParams(RawFunctionParams rawFunctionParams) { + return new FunctionParams(rawFunctionParams.getPatterns()); + } + @Override public GetColumnsOfStorageUnitResp getColumnsOfStorageUnit(String storageUnit) throws TException { List ret = new ArrayList<>(); diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/Awaitable.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/Awaitable.java new file mode 100644 index 0000000000..89c90f3d6a --- /dev/null +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/Awaitable.java @@ -0,0 +1,5 @@ +package cn.edu.tsinghua.iginx.parquet.util; + +public interface Awaitable { + void await() throws InterruptedException; +} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/CachePool.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/CachePool.java index 5a37ca181c..7c17a66173 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/CachePool.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/CachePool.java @@ -23,6 +23,7 @@ import com.github.benmanes.caffeine.cache.Scheduler; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.Executors; +import org.ehcache.sizeof.SizeOf; public class CachePool { @@ -46,6 +47,8 @@ public ConcurrentMap asMap() { } public interface Cacheable { - int getWeight(); + default int getWeight() { + return Math.toIntExact(SizeOf.newInstance().deepSizeOf(this)); + } } } diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/CloseableHolders.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/CloseableHolders.java new file mode 100644 index 0000000000..5d770b3764 --- /dev/null +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/CloseableHolders.java @@ -0,0 +1,41 @@ +package cn.edu.tsinghua.iginx.parquet.util; + +import java.util.NoSuchElementException; +import org.apache.arrow.util.Preconditions; + +public class CloseableHolders { + + public static class NoexceptAutoCloseableHolder + implements NoexceptAutoCloseable { + private T closeable; + + NoexceptAutoCloseableHolder(T closeable) { + this.closeable = Preconditions.checkNotNull(closeable); + } + + public T transfer() { + if (closeable == null) { + throw new NoSuchElementException("Already transferred"); + } + T ret = closeable; + closeable = null; + return ret; + } + + public T peek() { + return closeable; + } + + @Override + public void close() { + if (closeable != null) { + closeable.close(); + closeable = null; + } + } + } + + public static NoexceptAutoCloseableHolder hold(T closeable) { + return new NoexceptAutoCloseableHolder<>(closeable); + } +} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/Constants.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/Constants.java index 9f0f13c55d..706ca47a01 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/Constants.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/Constants.java @@ -40,7 +40,7 @@ public final class Constants { public static final long SIZE_INSERT_BATCH = 4096; - public static final String KEY_FIELD_NAME = "*"; + public static final String KEY_FIELD_NAME = cn.edu.tsinghua.iginx.engine.shared.Constants.KEY; public static final String RECORD_FIELD_NAME = "iginx"; public static final String DIR_DB_LSM = "lsm"; @@ -53,4 +53,5 @@ public final class Constants { public static final String DIR_NAME_TOMBSTONE = "tombstones"; public static final String DIR_NAME_TABLE = "tables"; public static final String LOCK_FILE_NAME = "LOCK"; + public static final String INDICES_VECTOR_NAME = "indices"; } diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/NoexceptAutoCloseable.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/NoexceptAutoCloseable.java new file mode 100644 index 0000000000..ae5a93e64d --- /dev/null +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/NoexceptAutoCloseable.java @@ -0,0 +1,6 @@ +package cn.edu.tsinghua.iginx.parquet.util; + +public interface NoexceptAutoCloseable extends AutoCloseable { + @Override + void close(); +} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/NoexceptAutoCloseables.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/NoexceptAutoCloseables.java new file mode 100644 index 0000000000..498384604f --- /dev/null +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/NoexceptAutoCloseables.java @@ -0,0 +1,20 @@ +package cn.edu.tsinghua.iginx.parquet.util; + +import org.apache.arrow.util.AutoCloseables; + +public class NoexceptAutoCloseables { + + public static void close(Iterable closeables) { + try { + AutoCloseables.close(closeables); + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + + public static NoexceptAutoCloseable all(Iterable closeables) { + return () -> close(closeables); + } +} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/Shared.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/Shared.java index c2b27b5516..203d817a9f 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/Shared.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/Shared.java @@ -19,25 +19,39 @@ package cn.edu.tsinghua.iginx.parquet.util; import java.util.concurrent.Semaphore; +import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.memory.RootAllocator; public class Shared { private final StorageProperties storageProperties; private final Semaphore flusherPermits; + private final Semaphore memTablePermits; + private final CachePool cachePool; + private final BufferAllocator allocator; + public Shared( - StorageProperties storageProperties, Semaphore flusherPermits, CachePool cachePool) { + StorageProperties storageProperties, + Semaphore flusherPermits, + Semaphore memTablePermits, + CachePool cachePool, + BufferAllocator allocator) { this.storageProperties = storageProperties; this.flusherPermits = flusherPermits; + this.memTablePermits = memTablePermits; this.cachePool = cachePool; + this.allocator = allocator; } public static Shared of(StorageProperties storageProperties) { Semaphore flusherPermits = new Semaphore(storageProperties.getCompactPermits(), true); + Semaphore memTablePermits = new Semaphore(storageProperties.getWriteBufferPermits(), true); CachePool cachePool = new CachePool(storageProperties); - return new Shared(storageProperties, flusherPermits, cachePool); + BufferAllocator allocator = new RootAllocator(); + return new Shared(storageProperties, flusherPermits, memTablePermits, cachePool, allocator); } public StorageProperties getStorageProperties() { @@ -48,7 +62,15 @@ public Semaphore getFlusherPermits() { return flusherPermits; } + public Semaphore getMemTablePermits() { + return memTablePermits; + } + public CachePool getCachePool() { return cachePool; } + + public BufferAllocator getAllocator() { + return allocator; + } } diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/SingleCache.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/SingleCache.java new file mode 100644 index 0000000000..412d96859f --- /dev/null +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/SingleCache.java @@ -0,0 +1,27 @@ +package cn.edu.tsinghua.iginx.parquet.util; + +import java.util.function.Consumer; +import java.util.function.Supplier; + +public class SingleCache { + private T obj; + private final Supplier supplier; + + public SingleCache(Supplier supplier) { + this.supplier = supplier; + } + + public T get() { + if (obj == null) { + obj = supplier.get(); + } + return obj; + } + + public void invalidate(Consumer consumer) { + if (obj != null) { + consumer.accept(obj); + obj = null; + } + } +} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/StorageProperties.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/StorageProperties.java index c1f57be2a7..b44308783b 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/StorageProperties.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/StorageProperties.java @@ -18,44 +18,43 @@ package cn.edu.tsinghua.iginx.parquet.util; +import cn.edu.tsinghua.iginx.parquet.db.lsm.buffer.chunk.IndexedChunk; +import cn.edu.tsinghua.iginx.parquet.db.lsm.buffer.chunk.IndexedChunkType; import java.time.Duration; import java.util.Map; import java.util.Optional; import java.util.StringJoiner; +import org.apache.arrow.vector.BaseValueVector; /** The properties of storage engine */ public class StorageProperties { private final boolean flushOnClose; private final long writeBufferSize; + private final int writeBufferChunkValuesMax; + private final int writeBufferChunkValuesMin; + private final IndexedChunkType writeBufferChunkType; private final Duration writeBufferTimeout; private final long writeBatchSize; private final int compactPermits; + private final int writeBufferPermits; private final long cacheCapacity; private final Duration cacheTimeout; private final boolean cacheSoftValues; private final long parquetRowGroupSize; private final long parquetPageSize; + private final int parquetOutputBufferMaxSize; private final String parquetCompression; private final int zstdLevel; private final int zstdWorkers; private final int parquetLz4BufferSize; - /** - * Construct a StorageProperties - * - * @param flushOnClose whether to flush on close - * @param writeBufferSize the size of write buffer, bytes - * @param writeBatchSize the size of write batch, bytes - * @param compactPermits the number of flusher permits - * @param cacheCapacity the capacity of cache, bytes - * @param cacheTimeout the expiry timeout of cache - * @param cacheSoftValues whether to enable soft values of cache - * @param parquetRowGroupSize the size of parquet row group, bytes - * @param parquetPageSize the size of parquet page, bytes - */ private StorageProperties( boolean flushOnClose, long writeBufferSize, + int writeBufferPermits, + int writeBufferChunkValuesMax, + int writeBufferChunkValuesMin, + IndexedChunkType writeBufferChunkType, Duration writeBufferTimeout, long writeBatchSize, int compactPermits, @@ -64,20 +63,26 @@ private StorageProperties( boolean cacheSoftValues, long parquetRowGroupSize, long parquetPageSize, + int parquetOutputBufferMaxSize, String parquetCompression, int zstdLevel, int zstdWorkers, int parquetLz4BufferSize) { this.flushOnClose = flushOnClose; this.writeBufferSize = writeBufferSize; + this.writeBufferChunkValuesMax = writeBufferChunkValuesMax; + this.writeBufferChunkValuesMin = writeBufferChunkValuesMin; + this.writeBufferChunkType = writeBufferChunkType; this.writeBufferTimeout = writeBufferTimeout; this.writeBatchSize = writeBatchSize; this.compactPermits = compactPermits; + this.writeBufferPermits = writeBufferPermits; this.cacheCapacity = cacheCapacity; this.cacheTimeout = cacheTimeout; this.cacheSoftValues = cacheSoftValues; this.parquetRowGroupSize = parquetRowGroupSize; this.parquetPageSize = parquetPageSize; + this.parquetOutputBufferMaxSize = parquetOutputBufferMaxSize; this.parquetCompression = parquetCompression; this.zstdLevel = zstdLevel; this.zstdWorkers = zstdWorkers; @@ -102,6 +107,43 @@ public long getWriteBufferSize() { return writeBufferSize; } + /** + * Get the shared permits of write buffer, which is used to control the total number of write + * buffer + * + * @return the number of write buffer permits + */ + public int getWriteBufferPermits() { + return writeBufferPermits; + } + + /** + * Get the max number of write buffer chunk values + * + * @return the max number of write buffer chunk values + */ + public int getWriteBufferChunkValuesMax() { + return writeBufferChunkValuesMax; + } + + /** + * Get the min number of write buffer chunk values + * + * @return the min number of write buffer chunk values + */ + public int getWriteBufferChunkValuesMin() { + return writeBufferChunkValuesMin; + } + + /** + * Get the write buffer chunk factory + * + * @return the write buffer chunk factory + */ + public IndexedChunk.Factory getWriteBufferChunkFactory() { + return writeBufferChunkType.factory(); + } + /** * Get the timeout of write buffer to flush * @@ -121,8 +163,7 @@ public long getWriteBatchSize() { } /** - * Get the shared permits allocator of flusher, which is used to control the total number of - * flusher + * Get the shared permits of flusher, which is used to control the total number of flusher * * @return the shared permits allocator of flusher */ @@ -175,6 +216,10 @@ public long getParquetPageSize() { return parquetPageSize; } + public int getParquetOutputBufferMaxSize() { + return parquetOutputBufferMaxSize; + } + /** * Get the parquet compression codec name * @@ -223,7 +268,12 @@ public static Builder builder() { @Override public String toString() { return new StringJoiner(", ", StorageProperties.class.getSimpleName() + "[", "]") + .add("flushOnClose=" + flushOnClose) .add("writeBufferSize=" + writeBufferSize) + .add("writeBufferPermits=" + writeBufferPermits) + .add("writeBufferChunkValuesMax=" + writeBufferChunkValuesMax) + .add("writeBufferChunkValuesMin=" + writeBufferChunkValuesMin) + .add("writeBufferChunkType=" + writeBufferChunkType) .add("writeBufferTimeout=" + writeBufferTimeout) .add("writeBatchSize=" + writeBatchSize) .add("compactPermits=" + compactPermits) @@ -232,6 +282,7 @@ public String toString() { .add("cacheSoftValues=" + cacheSoftValues) .add("parquetRowGroupSize=" + parquetRowGroupSize) .add("parquetPageSize=" + parquetPageSize) + .add("parquetOutputBufferMaxSize=" + parquetOutputBufferMaxSize) .add("parquetCompression='" + parquetCompression + "'") .add("zstdLevel=" + zstdLevel) .add("zstdWorkers=" + zstdWorkers) @@ -243,6 +294,10 @@ public String toString() { public static class Builder { public static final String FLUSH_ON_CLOSE = "close.flush"; public static final String WRITE_BUFFER_SIZE = "write.buffer.size"; + public static final String WRITE_BUFFER_PERMITS = "write.buffer.permits"; + public static final String WRITE_BUFFER_CHUNK_VALUES_MAX = "write.buffer.chunk.values.max"; + public static final String WRITE_BUFFER_CHUNK_VALUES_MIN = "write.buffer.chunk.values.min"; + public static final String WRITE_BUFFER_CHUNK_INDEX = "write.buffer.chunk.index"; public static final String WRITE_BUFFER_TIMEOUT = "write.buffer.timeout"; public static final String WRITE_BATCH_SIZE = "write.batch.size"; public static final String COMPACT_PERMITS = "compact.permits"; @@ -251,6 +306,7 @@ public static class Builder { public static final String CACHE_VALUE_SOFT = "cache.value.soft"; public static final String PARQUET_BLOCK_SIZE = "parquet.block.size"; public static final String PARQUET_PAGE_SIZE = "parquet.page.size"; + public static final String PARQUET_OUTPUT_BUFFER_SIZE = "parquet.output.buffer.size"; public static final String PARQUET_COMPRESSOR = "parquet.compression"; public static final String ZSTD_LEVEL = "zstd.level"; public static final String ZSTD_WORKERS = "zstd.workers"; @@ -258,6 +314,10 @@ public static class Builder { private boolean flushOnClose = true; private long writeBufferSize = 100 * 1024 * 1024; // BYTE + private int writeBufferPermits = 2; + private int writeBufferChunkValuesMax = BaseValueVector.INITIAL_VALUE_ALLOCATION; + private int writeBufferChunkValuesMin = BaseValueVector.INITIAL_VALUE_ALLOCATION; + private IndexedChunkType writeBufferChunkIndex = IndexedChunkType.NONE; private Duration writeBufferTimeout = Duration.ofSeconds(0); private long writeBatchSize = 1024 * 1024; // BYTE private long cacheCapacity = 16 * 1024 * 1024; // BYTE @@ -266,6 +326,7 @@ public static class Builder { private int compactPermits = 2; private long parquetRowGroupSize = 128 * 1024 * 1024; // BYTE private long parquetPageSize = 8 * 1024; // BYTE + private int parquetOutputBufferMaxSize = 256 * 1024; // BYTE private String parquetCompression = "UNCOMPRESSED"; private int zstdLevel = 3; private int zstdWorkers = 0; @@ -296,6 +357,54 @@ public Builder setWriteBufferSize(long writeBufferSize) { return this; } + /** + * Set the shared permits of write buffer, which is used to control the total number of write + * buffer + * + * @param writeBufferPermits the number of write buffer permits + * @return this builder + */ + public Builder setWriteBufferPermits(int writeBufferPermits) { + ParseUtils.checkPositive(writeBufferPermits); + this.writeBufferPermits = writeBufferPermits; + return this; + } + + /** + * Set the max number of write buffer chunk values + * + * @param writeBufferChunkValuesMax the max number of write buffer chunk values + * @return this builder + */ + public Builder setWriteBufferChunkValuesMax(int writeBufferChunkValuesMax) { + ParseUtils.checkPositive(writeBufferChunkValuesMax); + this.writeBufferChunkValuesMax = writeBufferChunkValuesMax; + return this; + } + + /** + * Set the min number of write buffer chunk values + * + * @param writeBufferChunkValuesMin the max number of write buffer chunk values + * @return this builder + */ + public Builder setWriteBufferChunkValuesMin(int writeBufferChunkValuesMin) { + ParseUtils.checkPositive(writeBufferChunkValuesMin); + this.writeBufferChunkValuesMin = writeBufferChunkValuesMin; + return this; + } + + /** + * Set the write buffer chunk index + * + * @param writeBufferChunkIndexName the write buffer chunk index name + * @return this builder + */ + public Builder setWriteBufferChunkIndex(String writeBufferChunkIndexName) { + this.writeBufferChunkIndex = IndexedChunkType.valueOf(writeBufferChunkIndexName); + return this; + } + /** * Set the timeout of write buffer to flush * @@ -361,7 +470,7 @@ public Builder setCacheSoftValues(boolean cacheSoftValues) { * @return this builder */ public Builder setCompactorPermits(int compactorPermits) { - ParseUtils.checkPositive(compactorPermits); + // ParseUtils.checkPositive(compactorPermits); this.compactPermits = compactorPermits; return this; } @@ -390,6 +499,18 @@ public Builder setParquetPageSize(long parquetPageSize) { return this; } + /** + * Set the size of parquet output buffer in bytes + * + * @param parquetOutputBufferMaxSize the size of parquet output buffer, bytes + * @return this builder + */ + public Builder setParquetOutputBufferMaxSize(int parquetOutputBufferMaxSize) { + ParseUtils.checkPositive(parquetOutputBufferMaxSize); + this.parquetOutputBufferMaxSize = parquetOutputBufferMaxSize; + return this; + } + /** * Set the parquet compression codec name * @@ -443,29 +564,19 @@ public Builder setParquetLz4BufferSize(int bufferSize) { * Parse properties to set the properties of StorageProperties * * @param properties the properties to be parsed - *

Supported keys: - *

    - *
  • close.flush: whether to flush on close - *
  • write.buffer.size: the size of write buffer, bytes - *
  • write.buffer.timeout: the timeout of write buffer to flush, iso-8601 - *
  • write.batch.size: the size of write batch, bytes - *
  • compact.permits: the number of flusher permits - *
  • cache.capacity: the capacity of cache, bytes - *
  • cache.timeout: the expiry timeout of cache, iso8601 duration - *
  • cache.value.soft: whether to enable soft values of cache - *
  • parquet.block.size: the size of parquet row group, bytes - *
  • parquet.page.size: the size of parquet page, bytes - *
  • parquet.compression: the parquet compression codec name - *
  • parquet.lz4.buffer.size: the parquet lz4 buffer size, bytes - *
  • zstd.level: the zstd level - *
  • zstd.workers: the zstd workers number - *
- * * @return this builder */ public Builder parse(Map properties) { ParseUtils.getOptionalBoolean(properties, FLUSH_ON_CLOSE).ifPresent(this::setFlushOnClose); ParseUtils.getOptionalLong(properties, WRITE_BUFFER_SIZE).ifPresent(this::setWriteBufferSize); + ParseUtils.getOptionalInteger(properties, WRITE_BUFFER_PERMITS) + .ifPresent(this::setWriteBufferPermits); + ParseUtils.getOptionalInteger(properties, WRITE_BUFFER_CHUNK_VALUES_MAX) + .ifPresent(this::setWriteBufferChunkValuesMax); + ParseUtils.getOptionalInteger(properties, WRITE_BUFFER_CHUNK_VALUES_MIN) + .ifPresent(this::setWriteBufferChunkValuesMin); + ParseUtils.getOptionalString(properties, WRITE_BUFFER_CHUNK_INDEX) + .ifPresent(this::setWriteBufferChunkIndex); ParseUtils.getOptionalDuration(properties, WRITE_BUFFER_TIMEOUT) .ifPresent(this::setWriteBufferTimeout); ParseUtils.getOptionalLong(properties, WRITE_BATCH_SIZE).ifPresent(this::setWriteBatchSize); @@ -478,6 +589,8 @@ public Builder parse(Map properties) { ParseUtils.getOptionalLong(properties, PARQUET_BLOCK_SIZE) .ifPresent(this::setParquetRowGroupSize); ParseUtils.getOptionalLong(properties, PARQUET_PAGE_SIZE).ifPresent(this::setParquetPageSize); + ParseUtils.getOptionalInteger(properties, PARQUET_OUTPUT_BUFFER_SIZE) + .ifPresent(this::setParquetOutputBufferMaxSize); ParseUtils.getOptionalString(properties, PARQUET_COMPRESSOR) .ifPresent(this::setParquetCompression); ParseUtils.getOptionalInteger(properties, ZSTD_LEVEL).ifPresent(this::setZstdLevel); @@ -496,6 +609,10 @@ public StorageProperties build() { return new StorageProperties( flushOnClose, writeBufferSize, + writeBufferPermits, + writeBufferChunkValuesMax, + writeBufferChunkValuesMin, + writeBufferChunkIndex, writeBufferTimeout, writeBatchSize, compactPermits, @@ -504,6 +621,7 @@ public StorageProperties build() { cacheSoftValues, parquetRowGroupSize, parquetPageSize, + parquetOutputBufferMaxSize, parquetCompression, zstdLevel, zstdWorkers, diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/arrow/ArrowFieldTypes.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/arrow/ArrowFieldTypes.java new file mode 100644 index 0000000000..9798707d59 --- /dev/null +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/arrow/ArrowFieldTypes.java @@ -0,0 +1,29 @@ +package cn.edu.tsinghua.iginx.parquet.util.arrow; + +import cn.edu.tsinghua.iginx.thrift.DataType; +import java.util.Map; +import javax.annotation.Nullable; +import org.apache.arrow.util.Preconditions; +import org.apache.arrow.vector.types.pojo.DictionaryEncoding; +import org.apache.arrow.vector.types.pojo.FieldType; + +public class ArrowFieldTypes { + + public static FieldType of( + boolean nullable, + DataType dataType, + @Nullable DictionaryEncoding dictionary, + @Nullable Map metadata) { + Preconditions.checkNotNull(dataType, "dataType"); + + return new FieldType(nullable, ArrowTypes.of(dataType), dictionary, metadata); + } + + public static FieldType nonnull(DataType dataType, @Nullable Map metadata) { + return of(false, dataType, null, null); + } + + public static FieldType nonnull(DataType dataType) { + return nonnull(dataType, null); + } +} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/arrow/ArrowFields.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/arrow/ArrowFields.java new file mode 100644 index 0000000000..9710f3dfde --- /dev/null +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/arrow/ArrowFields.java @@ -0,0 +1,118 @@ +package cn.edu.tsinghua.iginx.parquet.util.arrow; + +import cn.edu.tsinghua.iginx.engine.physical.storage.domain.ColumnKey; +import cn.edu.tsinghua.iginx.parquet.db.util.AreaSet; +import cn.edu.tsinghua.iginx.parquet.manager.utils.TagKVUtils; +import cn.edu.tsinghua.iginx.parquet.util.Constants; +import cn.edu.tsinghua.iginx.thrift.DataType; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import javax.annotation.Nullable; +import org.apache.arrow.util.Preconditions; +import org.apache.arrow.vector.types.pojo.DictionaryEncoding; +import org.apache.arrow.vector.types.pojo.Field; +import org.apache.arrow.vector.types.pojo.FieldType; + +public class ArrowFields { + + public static Field of( + boolean nullable, + ColumnKey columnKey, + DataType type, + @Nullable DictionaryEncoding dictionaryEncoding, + @Nullable List children) { + Preconditions.checkNotNull(columnKey, "columnKey"); + Preconditions.checkNotNull(type, "type"); + + Map tags = columnKey.getTags(); + Map metadata = tags.isEmpty() ? null : tags; + FieldType fieldType = ArrowFieldTypes.of(nullable, type, dictionaryEncoding, metadata); + return new Field(columnKey.getPath(), fieldType, children); + } + + public static Field of(boolean nullable, ColumnKey columnKey, DataType type) { + return of(nullable, columnKey, type, null, null); + } + + public static Field of(ColumnKey columnKey, DataType type) { + return of(true, columnKey, type); + } + + public static ColumnKey toColumnKey(Field field) { + Preconditions.checkNotNull(field, "field"); + Preconditions.checkArgument(!field.getType().isComplex()); + + return new ColumnKey(field.getName(), field.getMetadata()); + } + + public static Field KEY = of(false, new ColumnKey(Constants.KEY_FIELD_NAME), DataType.LONG); + + public static Set of(Map schema) { + return schema.entrySet().stream() + .map(entry -> of(TagKVUtils.splitFullName(entry.getKey()), entry.getValue())) + .collect(Collectors.toSet()); + } + + public static Map toIginxSchema(Set fields) { + return fields.stream() + .collect( + Collectors.toMap( + field -> TagKVUtils.toFullName(toColumnKey(field)), + field -> ArrowTypes.toIginxType(field.getType()))); + } + + public static AreaSet toInnerAreas(AreaSet areas) { + AreaSet innerAreas = new AreaSet<>(); + innerAreas.add(areas.getKeys()); + Set innerFields = + areas.getFields().stream().map(ArrowFields::toFullName).collect(Collectors.toSet()); + innerAreas.add(innerFields); + areas + .getSegments() + .forEach( + (field, rangeSet) -> { + String innerField = toFullName(field); + innerAreas.add(Collections.singleton(innerField), rangeSet); + }); + return innerAreas; + } + + public static String toFullName(Field field) { + return TagKVUtils.toFullName(toColumnKey(field)); + } + + public static AreaSet of(AreaSet areas, Map schema) { + AreaSet arrowAreas = new AreaSet<>(); + arrowAreas.add(areas.getKeys()); + Set fields = + areas.getFields().stream() + .map(name -> of(TagKVUtils.splitFullName(name), schema.get(name))) + .collect(Collectors.toSet()); + arrowAreas.add(fields); + areas + .getSegments() + .forEach( + (name, rangeSet) -> { + Field arrowField = of(TagKVUtils.splitFullName(name), schema.get(name)); + arrowAreas.add(Collections.singleton(arrowField), rangeSet); + }); + return arrowAreas; + } + + public static Field notNull(Field field) { + return of(false, toColumnKey(field), ArrowTypes.toIginxType(field.getType())); + } + + public static Field nullable(Field field) { + return of(true, toColumnKey(field), ArrowTypes.toIginxType(field.getType())); + } + + public static Set toInnerFields(List fields) { + return fields.stream() + .map(field -> TagKVUtils.toFullName(ArrowFields.toColumnKey(field))) + .collect(Collectors.toSet()); + } +} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/arrow/ArrowTypes.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/arrow/ArrowTypes.java new file mode 100644 index 0000000000..2716427c17 --- /dev/null +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/arrow/ArrowTypes.java @@ -0,0 +1,72 @@ +package cn.edu.tsinghua.iginx.parquet.util.arrow; + +import cn.edu.tsinghua.iginx.thrift.DataType; +import java.util.Objects; +import org.apache.arrow.vector.types.Types; +import org.apache.arrow.vector.types.pojo.ArrowType; + +public class ArrowTypes { + public static ArrowType of(DataType dataType) { + return minorTypeOf(dataType).getType(); + } + + public static DataType toIginxType(ArrowType arrowType) { + Objects.requireNonNull(arrowType, "arrowType"); + switch (arrowType.getTypeID()) { + case Bool: + return DataType.BOOLEAN; + case Int: + return toIginxType((ArrowType.Int) arrowType); + case FloatingPoint: + return toIginxType((ArrowType.FloatingPoint) arrowType); + case Binary: + return DataType.BINARY; + default: + throw new IllegalArgumentException("Unsupported arrow type: " + arrowType); + } + } + + public static DataType toIginxType(ArrowType.Int arrowType) { + Objects.requireNonNull(arrowType, "arrowType"); + switch (arrowType.getBitWidth()) { + case 32: + return DataType.INTEGER; + case 64: + return DataType.LONG; + default: + throw new IllegalArgumentException("Unsupported arrow type: " + arrowType); + } + } + + public static DataType toIginxType(ArrowType.FloatingPoint arrowType) { + Objects.requireNonNull(arrowType, "arrowType"); + switch (arrowType.getPrecision()) { + case SINGLE: + return DataType.FLOAT; + case DOUBLE: + return DataType.DOUBLE; + default: + throw new IllegalArgumentException("Unsupported arrow type: " + arrowType); + } + } + + public static Types.MinorType minorTypeOf(DataType dataType) { + Objects.requireNonNull(dataType, "dataType"); + switch (dataType) { + case BOOLEAN: + return Types.MinorType.BIT; // 1-bit + case INTEGER: + return Types.MinorType.INT; // 32-bit + case LONG: + return Types.MinorType.BIGINT; // 64-bit + case FLOAT: + return Types.MinorType.FLOAT4; // 32-bit + case DOUBLE: + return Types.MinorType.FLOAT8; // 64-bit + case BINARY: + return Types.MinorType.VARBINARY; // variable length + default: + throw new IllegalArgumentException("Unsupported data type: " + dataType); + } + } +} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/arrow/ArrowVectors.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/arrow/ArrowVectors.java new file mode 100644 index 0000000000..183c54e73c --- /dev/null +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/arrow/ArrowVectors.java @@ -0,0 +1,190 @@ +package cn.edu.tsinghua.iginx.parquet.util.arrow; + +import cn.edu.tsinghua.iginx.engine.physical.storage.domain.ColumnKey; +import cn.edu.tsinghua.iginx.thrift.DataType; +import java.util.function.IntPredicate; +import org.apache.arrow.algorithm.sort.DefaultVectorComparators; +import org.apache.arrow.algorithm.sort.IndexSorter; +import org.apache.arrow.algorithm.sort.StableVectorComparator; +import org.apache.arrow.algorithm.sort.VectorValueComparator; +import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.util.Preconditions; +import org.apache.arrow.vector.*; +import org.apache.arrow.vector.types.Types; +import org.apache.arrow.vector.types.pojo.Field; +import org.apache.arrow.vector.types.pojo.FieldType; +import org.apache.arrow.vector.util.TransferPair; +import org.apache.arrow.vector.util.VectorBatchAppender; + +public class ArrowVectors { + + public static ValueVector of( + boolean nullable, ColumnKey columnKey, DataType type, BufferAllocator allocator) { + Preconditions.checkNotNull(columnKey, "columnKey"); + Preconditions.checkNotNull(type, "type"); + Preconditions.checkNotNull(allocator, "allocator"); + + Field field = ArrowFields.of(nullable, columnKey, type); + + switch (type) { + case BOOLEAN: + return new BitVector(field, allocator); + case INTEGER: + return new IntVector(field, allocator); + case LONG: + return new BigIntVector(field, allocator); + case FLOAT: + return new Float4Vector(field, allocator); + case DOUBLE: + return new Float8Vector(field, allocator); + case BINARY: + return new VarBinaryVector(field, allocator); + default: + throw new IllegalArgumentException("Unsupported data type: " + type); + } + } + + public static ValueVector nullable( + ColumnKey columnKey, DataType type, BufferAllocator allocator) { + return of(true, columnKey, type, allocator); + } + + public static ValueVector nonnull(ColumnKey columnKey, DataType type, BufferAllocator allocator) { + return of(false, columnKey, type, allocator); + } + + public static BigIntVector key(BufferAllocator allocator) { + return (BigIntVector) nonnull(ColumnKey.KEY, DataType.LONG, allocator); + } + + public static V slice(V vector) { + return slice(vector, 0, vector.getValueCount()); + } + + public static V slice(V vector, BufferAllocator allocator) { + return slice(vector, 0, vector.getValueCount(), allocator); + } + + public static V slice(V vector, int start, int valueCount) { + return slice(vector, start, valueCount, vector.getAllocator()); + } + + @SuppressWarnings("unchecked") + public static V slice( + V vector, int start, int length, BufferAllocator allocator) { + if (length == 0) { + // splitAndTransfer 不能处理 length == 0 的情况 + return like(vector, allocator); + } + TransferPair transferPair = vector.getTransferPair(allocator); + transferPair.splitAndTransfer(start, length); + // TODO: splitAndTransferValidityBuffer() 不能正确地对 ValidityBuffer 进行跨 allocator 的 transfer + // 所以这里只好先 splitAndTransfer 然后再 transfer,个人猜测这是一个需要汇报给 Arrow 的 bug + try (V slice = (V) transferPair.getTo()) { + return transfer(slice, allocator); + } + } + + @SuppressWarnings("unchecked") + public static V transfer(V vector, BufferAllocator allocator) { + TransferPair transferPair = vector.getTransferPair(allocator); + transferPair.transfer(); + return (V) transferPair.getTo(); + } + + @SuppressWarnings("unchecked") + public static V like(V vector, BufferAllocator allocator) { + return (V) vector.getTransferPair(allocator).getTo(); + } + + public static boolean isSorted(ValueVector vector) { + VectorValueComparator comparator = + DefaultVectorComparators.createDefaultComparator(vector); + comparator.attachVector(vector); + for (int i = 1; i < vector.getValueCount(); i++) { + if (comparator.compare(i - 1, i) >= 0) { + return false; + } + } + return true; + } + + public static IntVector range(int start, int end, BufferAllocator allocator) { + IntVector indexes = nonnullIntVector("", allocator); + indexes.allocateNew(end - start); + indexes.setValueCount(end - start); + for (int i = start; i < end; i++) { + indexes.set(i - start, i); + } + return indexes; + } + + public static IntVector stableSortIndexes(ValueVector vector, BufferAllocator allocator) { + VectorValueComparator defaultComparator = + DefaultVectorComparators.createDefaultComparator(vector); + VectorValueComparator stableComparator = + new StableVectorComparator<>(defaultComparator); + + IntVector indexes = nonnullIntVector("", allocator); + indexes.setValueCount(vector.getValueCount()); + + new IndexSorter<>().sort(vector, indexes, stableComparator); + + return indexes; + } + + public static IntVector nonnullIntVector(String name, BufferAllocator allocator) { + return new IntVector(name, FieldType.notNullable(Types.MinorType.INT.getType()), allocator); + } + + public static void dedupSortedIndexes(ValueVector vector, IntVector indexes) { + VectorValueComparator defaultComparator = + DefaultVectorComparators.createDefaultComparator(vector); + defaultComparator.attachVector(vector); + + int count = indexes.getValueCount(); + int unique = 0; + for (int i = 1; i < count; i++) { + if (defaultComparator.compare(indexes.get(i - 1), indexes.get(i)) != 0) { + if (unique != i - 1) { + indexes.set(unique, indexes.get(i - 1)); + } + unique++; + } + } + if (count > 0) { + indexes.set(unique, indexes.get(count - 1)); + unique++; + } + indexes.setValueCount(unique); + } + + public static void append(ValueVector to, ValueVector from) { + if (to.getValueCount() == 0) { + to.allocateNew(); + } + VectorBatchAppender.batchAppend(to, from); + } + + public static void collect(IntVector indexes, Iterable values) { + int offset = indexes.getValueCount(); + for (Integer value : values) { + if (value == null) indexes.setNull(offset); + else indexes.setSafe(offset, value); + offset++; + } + indexes.setValueCount(offset); + } + + public static void filter(IntVector indexes, IntPredicate predicate) { + int count = indexes.getValueCount(); + int offset = 0; + for (int i = 0; i < count; i++) { + if (predicate.test(indexes.get(i))) { + indexes.set(offset, indexes.get(i)); + offset++; + } + } + indexes.setValueCount(offset); + } +} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/StorageClosedException.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/StorageClosedException.java new file mode 100644 index 0000000000..e7bf7f2c84 --- /dev/null +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/StorageClosedException.java @@ -0,0 +1,7 @@ +package cn.edu.tsinghua.iginx.parquet.util.exception; + +public class StorageClosedException extends StorageException { + public StorageClosedException(String message) { + super(message); + } +} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/iterator/DedupIterator.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/iterator/DedupIterator.java new file mode 100644 index 0000000000..64cb48d744 --- /dev/null +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/iterator/DedupIterator.java @@ -0,0 +1,40 @@ +package cn.edu.tsinghua.iginx.parquet.util.iterator; + +import com.google.common.collect.Iterators; +import com.google.common.collect.PeekingIterator; +import com.google.common.collect.UnmodifiableIterator; +import java.util.Iterator; +import java.util.function.Function; + +public class DedupIterator extends UnmodifiableIterator { + + private final PeekingIterator iterator; + private final Function keyExtractor; + + public DedupIterator(Iterator iterator, Function keyExtractor) { + this.iterator = Iterators.peekingIterator(iterator); + this.keyExtractor = keyExtractor; + } + + @Override + public boolean hasNext() { + return iterator.hasNext(); + } + + @Override + public T next() { + T next = iterator.next(); + Object key = keyExtractor.apply(next); + while (iterator.hasNext()) { + T peek = iterator.peek(); + Object peekKey = keyExtractor.apply(peek); + if (!key.equals(peekKey)) { + break; + } + next = peek; + key = peekKey; + iterator.next(); + } + return next; + } +} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/iterator/StableMergeIterator.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/iterator/StableMergeIterator.java new file mode 100644 index 0000000000..a78ed8b3a5 --- /dev/null +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/iterator/StableMergeIterator.java @@ -0,0 +1,75 @@ +package cn.edu.tsinghua.iginx.parquet.util.iterator; + +import com.google.common.collect.Iterators; +import com.google.common.collect.PeekingIterator; +import com.google.common.collect.UnmodifiableIterator; +import java.util.Comparator; +import java.util.Iterator; +import java.util.PriorityQueue; + +public class StableMergeIterator extends UnmodifiableIterator { + private final Comparator> comparator; + private final PriorityQueue> queue; + private Entry activeEntry; + + public StableMergeIterator( + Iterable> iterators, Comparator itemComparator) { + + Comparator> heapComparator = Comparator.comparing(Entry::peek, itemComparator); + this.comparator = heapComparator.thenComparing(Entry::order); + this.queue = new PriorityQueue<>(comparator); + + int order = 0; + for (Iterator iterator : iterators) { + if (iterator.hasNext()) { + this.queue.add(new Entry<>(Iterators.peekingIterator(iterator), order)); + order++; + } + } + if (!this.queue.isEmpty()) { + this.activeEntry = this.queue.remove(); + } + } + + public boolean hasNext() { + return activeEntry != null; + } + + public T next() { + T next = activeEntry.peekingIterator.next(); + refreshActiveEntry(); + return next; + } + + private void refreshActiveEntry() { + if (!activeEntry.peekingIterator.hasNext()) { + activeEntry = this.queue.poll(); + return; + } + if (!queue.isEmpty()) { + Entry nextEntry = queue.peek(); + if (comparator.compare(activeEntry, nextEntry) > 0) { + queue.add(activeEntry); + activeEntry = queue.poll(); + } + } + } + + private static class Entry { + final PeekingIterator peekingIterator; + final int order; + + static T peek(Entry entry) { + return entry.peekingIterator.peek(); + } + + static int order(Entry entry) { + return entry.order; + } + + private Entry(PeekingIterator peekingIterator, int order) { + this.peekingIterator = peekingIterator; + this.order = order; + } + } +} diff --git a/dependency/pom.xml b/dependency/pom.xml index 11c8c2706b..81106b6d75 100644 --- a/dependency/pom.xml +++ b/dependency/pom.xml @@ -26,6 +26,109 @@ + + com.googlecode.maven-download-plugin + download-maven-plugin + 1.9.0 + + + get-arrow-java-root + + wget + + generate-sources + + https://github.com/IGinX-THU/IGinX-resources/raw/main/arrow-snapshot/arrow-java-root-17.0.0-20240709.071332-1.pom + target/remote-jars + arrow-java-root-17.0.0-SNAPSHOT.pom + + + + get-arrow-memory + + wget + + generate-sources + + https://github.com/IGinX-THU/IGinX-resources/raw/main/arrow-snapshot/arrow-memory-17.0.0-20240709.071332-1.pom + target/remote-jars + arrow-memory-17.0.0-SNAPSHOT.pom + + + + get-arrow-memory-core-snapshot + + wget + + generate-sources + + https://github.com/IGinX-THU/IGinX-resources/raw/main/arrow-snapshot/arrow-memory-core-17.0.0-20240709.071332-1.jar + target/remote-jars + arrow-memory-core-17.0.0-SNAPSHOT.jar + + + + get-arrow-memory-netty-snapshot + + wget + + generate-sources + + https://github.com/IGinX-THU/IGinX-resources/raw/main/arrow-snapshot/arrow-memory-netty-17.0.0-20240709.071332-1.jar + target/remote-jars + arrow-memory-netty-17.0.0-SNAPSHOT.jar + + + + get-arrow-memory-netty-buffer-patch + + wget + + generate-sources + + https://github.com/IGinX-THU/IGinX-resources/raw/main/arrow-snapshot/arrow-memory-netty-buffer-patch-17.0.0-20240709.071332-1.jar + target/remote-jars + arrow-memory-netty-buffer-patch-17.0.0-SNAPSHOT.jar + + + + get-arrow-format-snapshot + + wget + + generate-sources + + https://github.com/IGinX-THU/IGinX-resources/raw/main/arrow-snapshot/arrow-format-17.0.0-20240709.071332-1.jar + target/remote-jars + arrow-format-17.0.0-SNAPSHOT.jar + + + + get-arrow-vector-snapshot + + wget + + generate-sources + + https://github.com/IGinX-THU/IGinX-resources/raw/main/arrow-snapshot/arrow-vector-17.0.0-20240709.071332-1.jar + target/remote-jars + arrow-vector-17.0.0-SNAPSHOT.jar + + + + get-arrow-algorithm-snapshot + + wget + + generate-sources + + https://github.com/IGinX-THU/IGinX-resources/raw/main/arrow-snapshot/arrow-algorithm-17.0.0-20240709.071332-1.jar + target/remote-jars + arrow-algorithm-17.0.0-SNAPSHOT.jar + + + + org.apache.maven.plugins maven-install-plugin @@ -41,6 +144,88 @@ src/main/resources/pemja-0.5-SNAPSHOT.jar + + install-arrow-java-root + + install-file + + generate-sources + + target/remote-jars/arrow-java-root-17.0.0-SNAPSHOT.pom + target/remote-jars/arrow-java-root-17.0.0-SNAPSHOT.pom + + + + install-arrow-memory + + install-file + + generate-sources + + target/remote-jars/arrow-memory-17.0.0-SNAPSHOT.pom + target/remote-jars/arrow-memory-17.0.0-SNAPSHOT.pom + + + + install-arrow-memory-core-snapshot + + install-file + + generate-sources + + target/remote-jars/arrow-memory-core-17.0.0-SNAPSHOT.jar + + + + install-arrow-memory-netty-snapshot + + install-file + + generate-sources + + target/remote-jars/arrow-memory-netty-17.0.0-SNAPSHOT.jar + + + + install-arrow-memory-netty-buffer-patch + + install-file + + generate-sources + + target/remote-jars/arrow-memory-netty-buffer-patch-17.0.0-SNAPSHOT.jar + + + + install-arrow-format-snapshot + + install-file + + generate-sources + + target/remote-jars/arrow-format-17.0.0-SNAPSHOT.jar + + + + install-arrow-vector-snapshot + + install-file + + generate-sources + + target/remote-jars/arrow-vector-17.0.0-SNAPSHOT.jar + + + + install-arrow-algorithm-snapshot + + install-file + + generate-sources + + target/remote-jars/arrow-algorithm-17.0.0-SNAPSHOT.jar + + diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/SetTransformPushDownPathUnionJoinRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/SetTransformPushDownPathUnionJoinRule.java new file mode 100644 index 0000000000..3189b5f6b5 --- /dev/null +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/SetTransformPushDownPathUnionJoinRule.java @@ -0,0 +1,141 @@ +package cn.edu.tsinghua.iginx.logical.optimizer.rules; + +import cn.edu.tsinghua.iginx.engine.logical.utils.OperatorUtils; +import cn.edu.tsinghua.iginx.engine.shared.Constants; +import cn.edu.tsinghua.iginx.engine.shared.operator.*; +import cn.edu.tsinghua.iginx.engine.shared.operator.visitor.DeepFirstQueueVisitor; +import cn.edu.tsinghua.iginx.engine.shared.source.FragmentSource; +import cn.edu.tsinghua.iginx.engine.shared.source.OperatorSource; +import cn.edu.tsinghua.iginx.engine.shared.source.Source; +import cn.edu.tsinghua.iginx.engine.shared.source.SourceType; +import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; +import cn.edu.tsinghua.iginx.metadata.entity.ColumnsInterval; +import cn.edu.tsinghua.iginx.metadata.entity.FragmentMeta; +import com.google.auto.service.AutoService; +import com.google.common.collect.Range; +import com.google.common.collect.RangeSet; +import com.google.common.collect.TreeRangeSet; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +@AutoService(Rule.class) +public class SetTransformPushDownPathUnionJoinRule extends Rule { + + public SetTransformPushDownPathUnionJoinRule() { + /* + * we want to match the topology like: + * SetTransform + * | + * PathUnion/Join + * + */ + super( + SetTransformPushDownPathUnionJoinRule.class.getSimpleName(), + operand(SetTransform.class, operand(AbstractBinaryOperator.class, any(), any()))); + } + + public boolean matches(RuleCall call) { + SetTransform setTransform = (SetTransform) call.getMatchedRoot(); + + List projects = new ArrayList<>(); + OperatorUtils.findProjectOperators(projects, setTransform); + + List fragments = + projects.stream() + .map(AbstractUnaryOperator::getSource) + .filter(source -> source.getType() == SourceType.Fragment) + .map(source -> (FragmentSource) source) + .map(FragmentSource::getFragment) + .collect(Collectors.toList()); + + // Check if each column can only appear once + RangeSet columnRangeSet = TreeRangeSet.create(); + for (FragmentMeta fragment : fragments) { + // if there is a dummy fragment, we can't push down the set transform correctly + if (fragment.isDummyFragment()) { + return false; + } + ColumnsInterval columnsInterval = fragment.getColumnsInterval(); + // TODO: Would schema prefix affect the result? + if (columnsInterval.getSchemaPrefix() != null) { + return false; + } + String startColumn = columnsInterval.getStartColumn(); + String endColumn = columnsInterval.getEndColumn(); + if (startColumn == null || endColumn == null) {} + + Range columnRange = rangeOf(columnsInterval); + // if there is an intersection of fragment columnIntervals, maybe there are intersecting + // columns in Join + if (columnRangeSet.intersects(columnRange)) { + return false; + } + columnRangeSet.add(columnRange); + } + + Source source = setTransform.getSource(); + if (source.getType() != SourceType.Operator) { + return false; + } + + DeepFirstQueueVisitor deepFirstQueueVisitor = new DeepFirstQueueVisitor(); + ((OperatorSource) source).getOperator().accept(deepFirstQueueVisitor); + + for (Operator operator : deepFirstQueueVisitor.getQueue()) { + if (operator instanceof Project) { + Source projectSource = ((Project) operator).getSource(); + if (projectSource.getType() != SourceType.Fragment) { + return false; + } + } else if (operator instanceof Join) { + String joinBy = ((Join) operator).getJoinBy(); + switch (joinBy) { + case Constants.KEY: + case Constants.ORDINAL: + break; + default: + return false; + } + } else if (operator instanceof PathUnion) { + // do nothing + } else { + return false; + } + } + + return true; + } + + private static Range rangeOf(ColumnsInterval columnsInterval) { + String startColumn = columnsInterval.getStartColumn(); + String endColumn = columnsInterval.getEndColumn(); + if (startColumn == null && endColumn == null) { + return Range.all(); + } else if (startColumn == null) { + return Range.lessThan(endColumn); + } else if (endColumn == null) { + return Range.atLeast(startColumn); + } else { + return Range.closedOpen(startColumn, endColumn); + } + } + + @Override + public void onMatch(RuleCall call) { + SetTransform setTransform = (SetTransform) call.getMatchedRoot(); + List projectList = new ArrayList<>(); + OperatorUtils.findProjectOperators(projectList, setTransform); + + List setTransformList = + projectList.stream() + .map(Project::copy) + .map(OperatorSource::new) + .map(setTransform::copyWithSource) + .map(SetTransform.class::cast) + .collect(Collectors.toList()); + + Operator newRoot = OperatorUtils.joinOperators(setTransformList, Constants.ORDINAL); + call.transformTo(newRoot); + } +} diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/physical/optimizer/naive/NaivePhysicalOptimizer.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/physical/optimizer/naive/NaivePhysicalOptimizer.java index 5b3b34de84..67960fe419 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/physical/optimizer/naive/NaivePhysicalOptimizer.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/physical/optimizer/naive/NaivePhysicalOptimizer.java @@ -75,15 +75,23 @@ private PhysicalTask constructTask(Operator operator, RequestContext context) { OperatorSource operatorSource = (OperatorSource) source; Operator sourceOperator = operatorSource.getOperator(); PhysicalTask sourceTask = constructTask(operatorSource.getOperator(), context); + // push down Select operator if (ConfigDescriptor.getInstance().getConfig().isEnablePushDown() && sourceTask instanceof StoragePhysicalTask && sourceOperator.getType() == OperatorType.Project && ((Project) sourceOperator).getTagFilter() == null - && ((UnaryOperator) sourceOperator).getSource().getType() == SourceType.Fragment - && operator.getType() == OperatorType.Select - && ((Select) operator).getTagFilter() == null) { - sourceTask.getOperators().add(operator); - return sourceTask; + && ((UnaryOperator) sourceOperator).getSource().getType() == SourceType.Fragment) { + switch (operator.getType()) { + case Select: + if (((Select) operator).getTagFilter() == null) { + sourceTask.getOperators().add(operator); + return sourceTask; + } + break; + case SetTransform: + sourceTask.getOperators().add(operator); + return sourceTask; + } } List operators = new ArrayList<>(); operators.add(operator); diff --git a/pom.xml b/pom.xml index 456054ee2c..1893473460 100644 --- a/pom.xml +++ b/pom.xml @@ -145,6 +145,41 @@ hutool-all 5.8.26 + + com.google.flatbuffers + flatbuffers-java + 23.5.26 + + + org.apache.arrow + arrow-format + 17.0.0-SNAPSHOT + + + org.apache.arrow + arrow-vector + 17.0.0-SNAPSHOT + + + org.apache.arrow + arrow-memory-core + 17.0.0-SNAPSHOT + + + org.apache.arrow + arrow-memory-netty + 17.0.0-SNAPSHOT + + + org.apache.arrow + arrow-memory-netty-buffer-patch + 17.0.0-SNAPSHOT + + + org.apache.arrow + arrow-algorithm + 17.0.0-SNAPSHOT + org.apache.commons commons-lang3 @@ -198,7 +233,7 @@ cn.edu.tsinghua.iginx parquet-file - 0.0.2 + 0.1.0 redis.clients @@ -253,6 +288,11 @@ lombok 1.18.20 + + com.google.guava + guava + 33.2.0-jre + diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/ThriftConnPool.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/ThriftConnPool.java index 1dc2782e2f..4997e7c72b 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/ThriftConnPool.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/ThriftConnPool.java @@ -22,6 +22,7 @@ import java.util.Map; import org.apache.commons.pool2.PooledObject; import org.apache.commons.pool2.PooledObjectFactory; +import org.apache.commons.pool2.impl.BaseObjectPoolConfig; import org.apache.commons.pool2.impl.DefaultPooledObject; import org.apache.commons.pool2.impl.GenericObjectPool; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; @@ -33,32 +34,35 @@ public class ThriftConnPool { private static final Logger LOGGER = LoggerFactory.getLogger(ThriftConnPool.class); - private static final int DEFAULT_MAX_SIZE = 100; + private static final int DEFAULT_MAX_SIZE = GenericObjectPoolConfig.DEFAULT_MAX_TOTAL; - private static final int MAX_WAIT_TIME = 30000; + private static final int MAX_WAIT_TIME = 0; // infinite, same as Socket default - private static final long IDLE_TIMEOUT = 10L * 60L * 1000L; + private static final long IDLE_TIMEOUT = + BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_DURATION.toMillis(); private final GenericObjectPool pool; public ThriftConnPool(String ip, int port) { - this(ip, port, DEFAULT_MAX_SIZE, MAX_WAIT_TIME); + this(ip, port, DEFAULT_MAX_SIZE, MAX_WAIT_TIME, IDLE_TIMEOUT); } public ThriftConnPool(String ip, int port, Map extraParams) { this( ip, port, - DEFAULT_MAX_SIZE, Integer.parseInt( - extraParams.getOrDefault("thrift_timeout", String.valueOf(MAX_WAIT_TIME)))); + extraParams.getOrDefault("thrift_pool_max_size", String.valueOf(DEFAULT_MAX_SIZE))), + Integer.parseInt(extraParams.getOrDefault("thrift_timeout", String.valueOf(MAX_WAIT_TIME))), + Long.parseLong( + extraParams.getOrDefault( + "thrift_pool_min_evictable_idle_time_millis", String.valueOf(IDLE_TIMEOUT)))); } - public ThriftConnPool(String ip, int port, int maxSize, int maxWaitTime) { - + public ThriftConnPool(String ip, int port, int maxSize, int maxWaitTime, long idleTimeout) { GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig<>(); poolConfig.setMaxTotal(maxSize); - poolConfig.setMinEvictableIdleDuration(Duration.ofMillis(IDLE_TIMEOUT)); // 设置空闲连接的超时时间 + poolConfig.setMinEvictableIdleDuration(Duration.ofMillis(idleTimeout)); // 设置空闲连接的超时时间 TSocketFactory socketFactory = new TSocketFactory(ip, port, maxWaitTime); pool = new GenericObjectPool<>(socketFactory, poolConfig); @@ -94,7 +98,7 @@ public static class TSocketFactory implements PooledObjectFactory { private final String ip; private final int port; - private final int maxWaitTime; // 连接超时时间(毫秒) + private final int maxWaitTime; // 连接超时时间(毫秒) 以及 socket 超时时间 public TSocketFactory(String ip, int port, int maxWaitTime) { this.ip = ip; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/datasource/DataSourceIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/datasource/DataSourceIT.java index b2eb7a2bad..008cad2ca8 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/datasource/DataSourceIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/datasource/DataSourceIT.java @@ -29,10 +29,15 @@ import cn.edu.tsinghua.iginx.engine.shared.data.read.Row; import cn.edu.tsinghua.iginx.engine.shared.data.read.RowStream; import cn.edu.tsinghua.iginx.engine.shared.data.write.DataView; +import cn.edu.tsinghua.iginx.engine.shared.function.FunctionCall; +import cn.edu.tsinghua.iginx.engine.shared.function.FunctionParams; +import cn.edu.tsinghua.iginx.engine.shared.function.system.Count; import cn.edu.tsinghua.iginx.engine.shared.operator.Delete; import cn.edu.tsinghua.iginx.engine.shared.operator.Insert; import cn.edu.tsinghua.iginx.engine.shared.operator.Project; +import cn.edu.tsinghua.iginx.engine.shared.operator.SetTransform; import cn.edu.tsinghua.iginx.engine.shared.source.FragmentSource; +import cn.edu.tsinghua.iginx.engine.shared.source.OperatorSource; import cn.edu.tsinghua.iginx.integration.controller.Controller; import cn.edu.tsinghua.iginx.integration.tool.ConfLoader; import cn.edu.tsinghua.iginx.integration.tool.DBConf; @@ -259,4 +264,41 @@ public void deleteRowsInMultiPart() throws PhysicalException { checkResult(result); checkRowCount(result.getRowStream(), 500000); } + + @Test + public void frequentCountAndInsertOverlapData() throws PhysicalException { + FragmentSource source = MockClassGenerator.genFragmentSource(); + DataArea dataArea = MockClassGenerator.genDataArea(); + + Project project = new Project(source, Collections.singletonList("*"), null); + OperatorSource projectSource = new OperatorSource(project); + FunctionParams countParams = new FunctionParams(Collections.singletonList("*")); + FunctionCall countCall = new FunctionCall(Count.getInstance(), countParams); + SetTransform countOperator = + new SetTransform(projectSource, Collections.singletonList(countCall)); + + Assume.assumeTrue(storage.isSupportProjectWithSetTransform(countOperator, dataArea)); + + for (int seed = 0; seed < 10; seed++) { + Random random = new Random(seed); + HashSet keys = new HashSet<>(); + for (long key = 0; key < 1000; key += 100) { + int rows = random.nextInt(150) + 1; + for (int i = 0; i < rows; i++) { + keys.add(key + i); + } + insertData(key, rows, "us.d1.s1", "us.d1.s2", "us.d1.s3", "us.d1.s4"); + TaskExecuteResult result = + storage.executeProjectWithSetTransform(project, countOperator, dataArea); + checkResult(result); + RowStream rowStream = result.getRowStream(); + Assert.assertTrue(rowStream.hasNext()); + Row row = rowStream.next(); + long count = keys.size(); + Assert.assertArrayEquals(new Object[] {count, count, count, count}, row.getValues()); + Assert.assertFalse(rowStream.hasNext()); + } + clear(); + } + } } diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetHistoryDataGenerator.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetHistoryDataGenerator.java index 30a5d71a38..e21710da81 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetHistoryDataGenerator.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetHistoryDataGenerator.java @@ -21,6 +21,7 @@ import static cn.edu.tsinghua.iginx.integration.expansion.BaseCapacityExpansionIT.DBCE_PARQUET_FS_TEST_DIR; import static cn.edu.tsinghua.iginx.integration.expansion.constant.Constant.*; +import cn.edu.tsinghua.iginx.engine.physical.storage.domain.ColumnKey; import cn.edu.tsinghua.iginx.format.parquet.ParquetWriter; import cn.edu.tsinghua.iginx.format.parquet.example.ExampleParquetWriter; import cn.edu.tsinghua.iginx.integration.expansion.BaseHistoryDataGenerator; @@ -194,7 +195,7 @@ public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOEx } } - public static final String KEY_FIELD_NAME = "*"; + public static final String KEY_FIELD_NAME = ColumnKey.KEY.getPath(); private static void flushRows( List pathList, diff --git a/thrift/src/main/proto/parquet.thrift b/thrift/src/main/proto/parquet.thrift index 086c6c84ee..e3fa765a28 100644 --- a/thrift/src/main/proto/parquet.thrift +++ b/thrift/src/main/proto/parquet.thrift @@ -90,12 +90,26 @@ struct RawFilter { 9: optional RawValue value } +struct RawFunction { + 1: required string id +} + +struct RawFunctionParams { + 1: required list patterns +} + +struct RawFunctionCall { + 1: required RawFunction func + 2: required RawFunctionParams params +} + struct ProjectReq { 1: required string storageUnit 2: required bool isDummyStorageUnit 3: required list paths 4: optional RawTagFilter tagFilter 5: optional RawFilter filter + 6: optional list aggregations } struct ParquetHeader { From 09e2b841ab12b61750ab47838cc3bd2d9ccc37bd Mon Sep 17 00:00:00 2001 From: An Qi Date: Sat, 13 Jul 2024 10:16:31 +0800 Subject: [PATCH 063/138] build: auto update file header (#386) * build: auto update file header * ci: check file header --- .github/workflows/format-checker.yml | 8 +++++ LICENSE_HEADER | 15 ++++++++ pom.xml | 53 ++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+) create mode 100644 LICENSE_HEADER diff --git a/.github/workflows/format-checker.yml b/.github/workflows/format-checker.yml index 12b2a44b72..23fc206bc5 100644 --- a/.github/workflows/format-checker.yml +++ b/.github/workflows/format-checker.yml @@ -11,3 +11,11 @@ jobs: shell: bash run: | mvn clean spotless:check + license: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 # v2 minimum required + - name: Check license headers + shell: bash + run: | + mvn clean license:check diff --git a/LICENSE_HEADER b/LICENSE_HEADER new file mode 100644 index 0000000000..37bee4c643 --- /dev/null +++ b/LICENSE_HEADER @@ -0,0 +1,15 @@ +IGinX - the polystore system with high performance +Copyright (C) Tsinghua University + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . \ No newline at end of file diff --git a/pom.xml b/pom.xml index 1893473460..89dd05bdf3 100644 --- a/pom.xml +++ b/pom.xml @@ -1,4 +1,23 @@ + 4.0.0 @@ -321,6 +340,28 @@ maven-assembly-plugin 3.6.0 + + com.mycila + license-maven-plugin + 4.5 + + true + true + + +
LICENSE_HEADER
+ + **/test/resources/** + **/requirements.txt + +
+
+ + SLASHSTAR_STYLE + SLASHSTAR_STYLE + +
+
@@ -451,6 +492,18 @@ + + com.mycila + license-maven-plugin + + + + format + + initialize + + +
From 21e9e613dcd9686763dd4a6b089f4414971abf0a Mon Sep 17 00:00:00 2001 From: Yuqing Zhu Date: Sat, 13 Jul 2024 10:26:15 +0800 Subject: [PATCH 064/138] update header (#388) --- LICENSE_HEADER | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE_HEADER b/LICENSE_HEADER index 37bee4c643..f7bb1e9553 100644 --- a/LICENSE_HEADER +++ b/LICENSE_HEADER @@ -12,4 +12,4 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with this program. If not, see . \ No newline at end of file +along with this program. If not, see . \ No newline at end of file From 27a232642833c158f7f59b30e769fb8eb0093fe2 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Sat, 13 Jul 2024 11:01:57 +0800 Subject: [PATCH 065/138] feat(test): tpc-h regression test (#372) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 基于pr#341修改,对单个数据库进行tpc-h的回归测试 --- .github/actions/confWriter/action.yml | 108 +- .github/actions/dependence/action.yml | 2 +- .github/actions/iginxRunner/action.yml | 32 +- .github/scripts/benchmarks/tpch.sh | 49 + .github/workflows/standard-test-suite.yml | 5 + .github/workflows/tpc-h.yml | 168 + .../naive/NaiveOperatorMemoryExecutor.java | 17 +- .../tsinghua/iginx/iotdb/IoTDBStorage.java | 2 +- .../optimizer/rules/ColumnPruningRule.java | 23 + session_py/example.py | 4 +- session_py/file_example.py | 4 +- .../iginx/integration/tool/ConfLoader.java | 8 + .../integration/tpch/TPCHRegressionIT.java | 529 ++++ test/src/test/resources/testConfig.properties | 4 + test/src/test/resources/tpch/queries/q1.sql | 31 + test/src/test/resources/tpch/queries/q10.sql | 51 + test/src/test/resources/tpch/queries/q13.sql | 25 + test/src/test/resources/tpch/queries/q16.sql | 49 + test/src/test/resources/tpch/queries/q17.sql | 29 + test/src/test/resources/tpch/queries/q18.sql | 35 + test/src/test/resources/tpch/queries/q19.sql | 48 + test/src/test/resources/tpch/queries/q2.sql | 44 + test/src/test/resources/tpch/queries/q20.sql | 45 + test/src/test/resources/tpch/queries/q3.sql | 31 + test/src/test/resources/tpch/queries/q5.sql | 28 + test/src/test/resources/tpch/queries/q6.sql | 12 + test/src/test/resources/tpch/queries/q9.sql | 32 + test/src/test/resources/tpch/sf0.1/q1.csv | 5 + test/src/test/resources/tpch/sf0.1/q10.csv | 21 + test/src/test/resources/tpch/sf0.1/q13.csv | 38 + test/src/test/resources/tpch/sf0.1/q16.csv | 2763 +++++++++++++++++ test/src/test/resources/tpch/sf0.1/q17.csv | 2 + test/src/test/resources/tpch/sf0.1/q18.csv | 6 + test/src/test/resources/tpch/sf0.1/q19.csv | 2 + test/src/test/resources/tpch/sf0.1/q2.csv | 45 + test/src/test/resources/tpch/sf0.1/q20.csv | 10 + test/src/test/resources/tpch/sf0.1/q3.csv | 11 + test/src/test/resources/tpch/sf0.1/q5.csv | 6 + test/src/test/resources/tpch/sf0.1/q6.csv | 2 + test/src/test/resources/tpch/sf0.1/q9.csv | 176 ++ .../resources/tpch/udf/udtf_extract_year.py | 46 + thu_cloud_download.py | 187 ++ 42 files changed, 4653 insertions(+), 82 deletions(-) create mode 100644 .github/scripts/benchmarks/tpch.sh create mode 100644 .github/workflows/tpc-h.yml create mode 100644 test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHRegressionIT.java create mode 100644 test/src/test/resources/tpch/queries/q1.sql create mode 100644 test/src/test/resources/tpch/queries/q10.sql create mode 100644 test/src/test/resources/tpch/queries/q13.sql create mode 100644 test/src/test/resources/tpch/queries/q16.sql create mode 100644 test/src/test/resources/tpch/queries/q17.sql create mode 100644 test/src/test/resources/tpch/queries/q18.sql create mode 100644 test/src/test/resources/tpch/queries/q19.sql create mode 100644 test/src/test/resources/tpch/queries/q2.sql create mode 100644 test/src/test/resources/tpch/queries/q20.sql create mode 100644 test/src/test/resources/tpch/queries/q3.sql create mode 100644 test/src/test/resources/tpch/queries/q5.sql create mode 100644 test/src/test/resources/tpch/queries/q6.sql create mode 100644 test/src/test/resources/tpch/queries/q9.sql create mode 100644 test/src/test/resources/tpch/sf0.1/q1.csv create mode 100644 test/src/test/resources/tpch/sf0.1/q10.csv create mode 100644 test/src/test/resources/tpch/sf0.1/q13.csv create mode 100644 test/src/test/resources/tpch/sf0.1/q16.csv create mode 100644 test/src/test/resources/tpch/sf0.1/q17.csv create mode 100644 test/src/test/resources/tpch/sf0.1/q18.csv create mode 100644 test/src/test/resources/tpch/sf0.1/q19.csv create mode 100644 test/src/test/resources/tpch/sf0.1/q2.csv create mode 100644 test/src/test/resources/tpch/sf0.1/q20.csv create mode 100644 test/src/test/resources/tpch/sf0.1/q3.csv create mode 100644 test/src/test/resources/tpch/sf0.1/q5.csv create mode 100644 test/src/test/resources/tpch/sf0.1/q6.csv create mode 100644 test/src/test/resources/tpch/sf0.1/q9.csv create mode 100644 test/src/test/resources/tpch/udf/udtf_extract_year.py create mode 100644 thu_cloud_download.py diff --git a/.github/actions/confWriter/action.yml b/.github/actions/confWriter/action.yml index 117ddbaa2e..68a2fe556d 100644 --- a/.github/actions/confWriter/action.yml +++ b/.github/actions/confWriter/action.yml @@ -25,6 +25,10 @@ inputs: description: "which metadata service to use" required: false default: zookeeper + Root-Dir-Path: + description: "the path of IGinX root directory" + required: false + default: "${GITHUB_WORKSPACE}" runs: using: "composite" # Mandatory parameter @@ -33,53 +37,53 @@ runs: name: save config for FileSystem and Parquet shell: bash run: | - cp -f "${GITHUB_WORKSPACE}/conf/config.properties" "${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties" + cp -f "${{ inputs.Root-Dir-Path }}/conf/config.properties" "${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties" - if: inputs.DB-name=='FileSystem' || inputs.DB-name=='Parquet' name: save config for FileSystem and Parquet shell: bash run: | - cp -f "${GITHUB_WORKSPACE}/conf/config.properties" "${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties" + cp -f "${{ inputs.Root-Dir-Path }}/conf/config.properties" "${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties" - name: Set if-CapExp shell: bash run: | - echo "${{ inputs.if-CapExp }}" > ${GITHUB_WORKSPACE}/test/src/test/resources/isScaling.txt + echo "${{ inputs.if-CapExp }}" > ${{ inputs.Root-Dir-Path }}/test/src/test/resources/isScaling.txt - if: inputs.if-CapExp=='true' name: Change has_data shell: bash run: | - echo "${{ inputs.Test-Way }}" > ${GITHUB_WORKSPACE}/test/src/test/resources/dbce-test-way.txt + echo "${{ inputs.Test-Way }}" > ${{ inputs.Root-Dir-Path }}/test/src/test/resources/dbce-test-way.txt if [[ "${{ inputs.Test-Way }}" == "oriHasDataExpHasData" || "${{ inputs.Test-Way }}" == "oriHasDataExpNoData" ]]; then if [[ "$RUNNER_OS" == "Linux" || "$RUNNER_OS" == "Windows" ]]; then - sed -i "s/has_data=false/has_data=true/g" ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties + sed -i "s/has_data=false/has_data=true/g" ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties elif [ "$RUNNER_OS" == "macOS" ]; then - sed -i "" "s/has_data=false/has_data=true/" ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties + sed -i "" "s/has_data=false/has_data=true/" ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties fi elif [[ "${{ inputs.Test-Way }}" == "oriNoDataExpHasData" || "${{ inputs.Test-Way }}" == "oriNoDataExpNoData" ]]; then if [[ "$RUNNER_OS" == "Linux" || "$RUNNER_OS" == "Windows" ]]; then - sed -i "s/has_data=true/has_data=false/g" ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties + sed -i "s/has_data=true/has_data=false/g" ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties elif [ "$RUNNER_OS" == "macOS" ]; then - sed -i "" "s/has_data=true/has_data=false/" ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties + sed -i "" "s/has_data=true/has_data=false/" ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties fi fi - name: Set DB-name shell: bash run: | - echo "${{ inputs.DB-name }}" > ${GITHUB_WORKSPACE}/test/src/test/resources/DBName.txt + echo "${{ inputs.DB-name }}" > ${{ inputs.Root-Dir-Path }}/test/src/test/resources/DBName.txt - name: Change UDF conf shell: bash run: | if [ "$RUNNER_OS" == "Linux" ]; then - sudo sed -i 's/needInitBasicUDFFunctions=false/needInitBasicUDFFunctions=true/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties + sudo sed -i 's/needInitBasicUDFFunctions=false/needInitBasicUDFFunctions=true/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties elif [ "$RUNNER_OS" == "Windows" ]; then - sed -i 's/needInitBasicUDFFunctions=false/needInitBasicUDFFunctions=true/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties - sed -i 's/pythonCMD=python3/pythonCMD=python/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties + sed -i 's/needInitBasicUDFFunctions=false/needInitBasicUDFFunctions=true/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties + sed -i 's/pythonCMD=python3/pythonCMD=python/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties elif [ "$RUNNER_OS" == "macOS" ]; then - sudo sed -i '' 's/needInitBasicUDFFunctions=false/needInitBasicUDFFunctions=true/' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties + sudo sed -i '' 's/needInitBasicUDFFunctions=false/needInitBasicUDFFunctions=true/' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties else echo "$RUNNER_OS is not supported" exit 1 @@ -90,11 +94,11 @@ runs: shell: bash run: | if [ "$RUNNER_OS" == "Linux" ]; then - sudo sed -i 's/is_read_only=false/is_read_only=true/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties + sudo sed -i 's/is_read_only=false/is_read_only=true/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties elif [ "$RUNNER_OS" == "Windows" ]; then - sed -i 's/is_read_only=false/is_read_only=true/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties + sed -i 's/is_read_only=false/is_read_only=true/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties elif [ "$RUNNER_OS" == "macOS" ]; then - sudo sed -i '' 's/is_read_only=false/is_read_only=true/' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties + sudo sed -i '' 's/is_read_only=false/is_read_only=true/' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties else echo "$RUNNER_OS is not supported" exit 1 @@ -104,20 +108,20 @@ runs: shell: bash run: | if [ "$RUNNER_OS" == "Linux" ]; then - sudo sed -i 's/enablePushDown=false/enablePushDown=true/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties - sed -i 's/FilterPushDownAddSchemaPrefixRule=off,FilterPushDownAddSchemaPrefixRule=off/FilterPushDownAddSchemaPrefixRule=on,FilterPushDownAddSchemaPrefixRule=on/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties - sed -i 's/FilterPushDownPathUnionJoinRule=off,FilterPushDownProjectReorderSortRule=off,FilterPushDownRenameRule=off,FilterPushDownSelectRule=off/FilterPushDownPathUnionJoinRule=on,FilterPushDownProjectReorderSortRule=on,FilterPushDownRenameRule=on,FilterPushDownSelectRule=on/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties - sed -i 's/FilterPushDownSetOpRule=off,FilterPushDownTransformRule=off,FilterPushIntoJoinConditionRule=off,FilterPushOutJoinConditionRule=off,FilterPushDownGroupByRule=off/FilterPushDownSetOpRule=on,FilterPushDownTransformRule=on,FilterPushIntoJoinConditionRule=on,FilterPushOutJoinConditionRule=on,FilterPushDownGroupByRule=on/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties + sudo sed -i 's/enablePushDown=false/enablePushDown=true/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties + sed -i 's/FilterPushDownAddSchemaPrefixRule=off,FilterPushDownAddSchemaPrefixRule=off/FilterPushDownAddSchemaPrefixRule=on,FilterPushDownAddSchemaPrefixRule=on/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties + sed -i 's/FilterPushDownPathUnionJoinRule=off,FilterPushDownProjectReorderSortRule=off,FilterPushDownRenameRule=off,FilterPushDownSelectRule=off/FilterPushDownPathUnionJoinRule=on,FilterPushDownProjectReorderSortRule=on,FilterPushDownRenameRule=on,FilterPushDownSelectRule=on/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties + sed -i 's/FilterPushDownSetOpRule=off,FilterPushDownTransformRule=off,FilterPushIntoJoinConditionRule=off,FilterPushOutJoinConditionRule=off,FilterPushDownGroupByRule=off/FilterPushDownSetOpRule=on,FilterPushDownTransformRule=on,FilterPushIntoJoinConditionRule=on,FilterPushOutJoinConditionRule=on,FilterPushDownGroupByRule=on/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties elif [ "$RUNNER_OS" == "Windows" ]; then - sed -i 's/enablePushDown=false/enablePushDown=true/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties - sed -i 's/FilterPushDownAddSchemaPrefixRule=off,FilterPushDownAddSchemaPrefixRule=off/FilterPushDownAddSchemaPrefixRule=on,FilterPushDownAddSchemaPrefixRule=on/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties - sed -i 's/FilterPushDownPathUnionJoinRule=off,FilterPushDownProjectReorderSortRule=off,FilterPushDownRenameRule=off,FilterPushDownSelectRule=off/FilterPushDownPathUnionJoinRule=on,FilterPushDownProjectReorderSortRule=on,FilterPushDownRenameRule=on,FilterPushDownSelectRule=on/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties - sed -i 's/FilterPushDownSetOpRule=off,FilterPushDownTransformRule=off,FilterPushIntoJoinConditionRule=off,FilterPushOutJoinConditionRule=off,FilterPushDownGroupByRule=off/FilterPushDownSetOpRule=on,FilterPushDownTransformRule=on,FilterPushIntoJoinConditionRule=on,FilterPushOutJoinConditionRule=on,FilterPushDownGroupByRule=on/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties + sed -i 's/enablePushDown=false/enablePushDown=true/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties + sed -i 's/FilterPushDownAddSchemaPrefixRule=off,FilterPushDownAddSchemaPrefixRule=off/FilterPushDownAddSchemaPrefixRule=on,FilterPushDownAddSchemaPrefixRule=on/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties + sed -i 's/FilterPushDownPathUnionJoinRule=off,FilterPushDownProjectReorderSortRule=off,FilterPushDownRenameRule=off,FilterPushDownSelectRule=off/FilterPushDownPathUnionJoinRule=on,FilterPushDownProjectReorderSortRule=on,FilterPushDownRenameRule=on,FilterPushDownSelectRule=on/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties + sed -i 's/FilterPushDownSetOpRule=off,FilterPushDownTransformRule=off,FilterPushIntoJoinConditionRule=off,FilterPushOutJoinConditionRule=off,FilterPushDownGroupByRule=off/FilterPushDownSetOpRule=on,FilterPushDownTransformRule=on,FilterPushIntoJoinConditionRule=on,FilterPushOutJoinConditionRule=on,FilterPushDownGroupByRule=on/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties elif [ "$RUNNER_OS" == "macOS" ]; then - sudo sed -i '' 's/enablePushDown=false/enablePushDown=true/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties - sed -i '' 's/FilterPushDownAddSchemaPrefixRule=off,FilterPushDownAddSchemaPrefixRule=off/FilterPushDownAddSchemaPrefixRule=on,FilterPushDownAddSchemaPrefixRule=on/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties - sed -i '' 's/FilterPushDownPathUnionJoinRule=off,FilterPushDownProjectReorderSortRule=off,FilterPushDownRenameRule=off,FilterPushDownSelectRule=off/FilterPushDownPathUnionJoinRule=on,FilterPushDownProjectReorderSortRule=on,FilterPushDownRenameRule=on,FilterPushDownSelectRule=on/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties - sed -i '' 's/FilterPushDownSetOpRule=off,FilterPushDownTransformRule=off,FilterPushIntoJoinConditionRule=off,FilterPushOutJoinConditionRule=off,FilterPushDownGroupByRule=off/FilterPushDownSetOpRule=on,FilterPushDownTransformRule=on,FilterPushIntoJoinConditionRule=on,FilterPushOutJoinConditionRule=on,FilterPushDownGroupByRule=on/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties + sudo sed -i '' 's/enablePushDown=false/enablePushDown=true/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties + sed -i '' 's/FilterPushDownAddSchemaPrefixRule=off,FilterPushDownAddSchemaPrefixRule=off/FilterPushDownAddSchemaPrefixRule=on,FilterPushDownAddSchemaPrefixRule=on/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties + sed -i '' 's/FilterPushDownPathUnionJoinRule=off,FilterPushDownProjectReorderSortRule=off,FilterPushDownRenameRule=off,FilterPushDownSelectRule=off/FilterPushDownPathUnionJoinRule=on,FilterPushDownProjectReorderSortRule=on,FilterPushDownRenameRule=on,FilterPushDownSelectRule=on/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties + sed -i '' 's/FilterPushDownSetOpRule=off,FilterPushDownTransformRule=off,FilterPushIntoJoinConditionRule=off,FilterPushOutJoinConditionRule=off,FilterPushDownGroupByRule=off/FilterPushDownSetOpRule=on,FilterPushDownTransformRule=on,FilterPushIntoJoinConditionRule=on,FilterPushOutJoinConditionRule=on,FilterPushDownGroupByRule=on/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties else echo "$RUNNER_OS is not supported" exit 1 @@ -127,11 +131,11 @@ runs: shell: bash run: | if [ "$RUNNER_OS" == "Linux" ]; then - sudo sed -i 's/policyClassName=cn.edu.tsinghua.iginx.policy.naive.NaivePolicy/policyClassName=cn.edu.tsinghua.iginx.policy.test.KeyRangeTestPolicy/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties + sudo sed -i 's/policyClassName=cn.edu.tsinghua.iginx.policy.naive.NaivePolicy/policyClassName=cn.edu.tsinghua.iginx.policy.test.KeyRangeTestPolicy/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties elif [ "$RUNNER_OS" == "Windows" ]; then - sed -i 's/policyClassName=cn.edu.tsinghua.iginx.policy.naive.NaivePolicy/policyClassName=cn.edu.tsinghua.iginx.policy.test.KeyRangeTestPolicy/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties + sed -i 's/policyClassName=cn.edu.tsinghua.iginx.policy.naive.NaivePolicy/policyClassName=cn.edu.tsinghua.iginx.policy.test.KeyRangeTestPolicy/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties elif [ "$RUNNER_OS" == "macOS" ]; then - sudo sed -i '' 's/policyClassName=cn.edu.tsinghua.iginx.policy.naive.NaivePolicy/policyClassName=cn.edu.tsinghua.iginx.policy.test.KeyRangeTestPolicy/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties + sudo sed -i '' 's/policyClassName=cn.edu.tsinghua.iginx.policy.naive.NaivePolicy/policyClassName=cn.edu.tsinghua.iginx.policy.test.KeyRangeTestPolicy/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties else echo "$RUNNER_OS is not supported" exit 1 @@ -141,11 +145,11 @@ runs: shell: bash run: | if [ "$RUNNER_OS" == "Linux" ]; then - sudo sed -i 's/ruleBasedOptimizer=NotFilterRemoveRule=on,FragmentPruningByFilterRule=on/ruleBasedOptimizer=NotFilterRemoveRule=on/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties + sudo sed -i 's/ruleBasedOptimizer=NotFilterRemoveRule=on,FragmentPruningByFilterRule=on/ruleBasedOptimizer=NotFilterRemoveRule=on/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties elif [ "$RUNNER_OS" == "Windows" ]; then - sed -i 's/ruleBasedOptimizer=NotFilterRemoveRule=on,FragmentPruningByFilterRule=on/ruleBasedOptimizer=NotFilterRemoveRule=on/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties + sed -i 's/ruleBasedOptimizer=NotFilterRemoveRule=on,FragmentPruningByFilterRule=on/ruleBasedOptimizer=NotFilterRemoveRule=on/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties elif [ "$RUNNER_OS" == "macOS" ]; then - sudo sed -i '' 's/ruleBasedOptimizer=NotFilterRemoveRule=on,FragmentPruningByFilterRule=on/ruleBasedOptimizer=NotFilterRemoveRule=on/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties + sudo sed -i '' 's/ruleBasedOptimizer=NotFilterRemoveRule=on,FragmentPruningByFilterRule=on/ruleBasedOptimizer=NotFilterRemoveRule=on/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties else echo "$RUNNER_OS is not supported" exit 1 @@ -154,11 +158,11 @@ runs: shell: bash run: | if [ "$RUNNER_OS" == "Linux" ]; then - sudo sed -i 's/^logger.iginx.level=.*$/logger.iginx.level=debug/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/log4j2.properties + sudo sed -i 's/^logger.iginx.level=.*$/logger.iginx.level=debug/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/log4j2.properties elif [ "$RUNNER_OS" == "Windows" ]; then - sed -i 's/^logger.iginx.level=.*$/logger.iginx.level=debug/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/log4j2.properties + sed -i 's/^logger.iginx.level=.*$/logger.iginx.level=debug/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/log4j2.properties elif [ "$RUNNER_OS" == "macOS" ]; then - sudo sed -i '' 's/^logger.iginx.level=.*$/logger.iginx.level=debug/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/log4j2.properties + sudo sed -i '' 's/^logger.iginx.level=.*$/logger.iginx.level=debug/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/log4j2.properties else echo "$RUNNER_OS is not supported" exit 1 @@ -167,14 +171,14 @@ runs: shell: bash run: | if [ "$RUNNER_OS" == "Linux" ]; then - sudo sed -i 's/^default.transformerRule.include=.*$/default.transformerRule.include=glob:**.denied/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/file-permission.properties - sudo sed -i 's/^default.transformerRule.write=.*$/default.transformerRule.write=false/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/file-permission.properties + sudo sed -i 's/^default.transformerRule.include=.*$/default.transformerRule.include=glob:**.denied/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/file-permission.properties + sudo sed -i 's/^default.transformerRule.write=.*$/default.transformerRule.write=false/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/file-permission.properties elif [ "$RUNNER_OS" == "Windows" ]; then - sed -i 's/^default.transformerRule.include=.*$/default.transformerRule.include=glob:**.denied/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/file-permission.properties - sed -i 's/^default.transformerRule.write=.*$/default.transformerRule.write=false/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/file-permission.properties + sed -i 's/^default.transformerRule.include=.*$/default.transformerRule.include=glob:**.denied/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/file-permission.properties + sed -i 's/^default.transformerRule.write=.*$/default.transformerRule.write=false/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/file-permission.properties elif [ "$RUNNER_OS" == "macOS" ]; then - sudo sed -i '' 's/^default.transformerRule.include=.*$/default.transformerRule.include=glob:**.denied/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/file-permission.properties - sudo sed -i '' 's/^default.transformerRule.write=.*$/default.transformerRule.write=false/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/file-permission.properties + sudo sed -i '' 's/^default.transformerRule.include=.*$/default.transformerRule.include=glob:**.denied/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/file-permission.properties + sudo sed -i '' 's/^default.transformerRule.write=.*$/default.transformerRule.write=false/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/file-permission.properties else echo "$RUNNER_OS is not supported" exit 1 @@ -185,17 +189,17 @@ runs: shell: bash run: | if [ "$RUNNER_OS" == "Linux" ]; then - sudo sed -i 's/^metaStorage=.*$/metaStorage=etcd/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties - sudo sed -i 's/^zookeeperConnectionString=/#zookeeperConnectionString=/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties - sudo sed -i 's/^#etcdEndpoints=/etcdEndpoints=/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties + sudo sed -i 's/^metaStorage=.*$/metaStorage=etcd/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties + sudo sed -i 's/^zookeeperConnectionString=/#zookeeperConnectionString=/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties + sudo sed -i 's/^#etcdEndpoints=/etcdEndpoints=/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties elif [ "$RUNNER_OS" == "Windows" ]; then - sed -i 's/^metaStorage=.*$/metaStorage=etcd/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties - sed -i 's/^zookeeperConnectionString=/#zookeeperConnectionString=/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties - sed -i 's/^#etcdEndpoints=/etcdEndpoints=/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties + sed -i 's/^metaStorage=.*$/metaStorage=etcd/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties + sed -i 's/^zookeeperConnectionString=/#zookeeperConnectionString=/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties + sed -i 's/^#etcdEndpoints=/etcdEndpoints=/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties elif [ "$RUNNER_OS" == "macOS" ]; then - sudo sed -i '' 's/^metaStorage=.*$/metaStorage=etcd/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties - sudo sed -i '' 's/^zookeeperConnectionString=$/#zookeeperConnectionString=/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties - sudo sed -i '' 's/^#etcdEndpoints=/etcdEndpoints=/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties + sudo sed -i '' 's/^metaStorage=.*$/metaStorage=etcd/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties + sudo sed -i '' 's/^zookeeperConnectionString=$/#zookeeperConnectionString=/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties + sudo sed -i '' 's/^#etcdEndpoints=/etcdEndpoints=/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties else echo "$RUNNER_OS is not supported" exit 1 diff --git a/.github/actions/dependence/action.yml b/.github/actions/dependence/action.yml index 5e8c150a40..225f45a2c9 100644 --- a/.github/actions/dependence/action.yml +++ b/.github/actions/dependence/action.yml @@ -56,7 +56,7 @@ runs: shell: bash run: | python -m pip install --upgrade pip - pip install pandas numpy pemjax==0.1.0 thrift fastparquet + pip install pandas numpy pemjax==0.1.0 thrift fastparquet tqdm requests - name: Set up JDK ${{ inputs.java }} uses: actions/setup-java@v4 diff --git a/.github/actions/iginxRunner/action.yml b/.github/actions/iginxRunner/action.yml index 859354faf2..2edacc23cc 100644 --- a/.github/actions/iginxRunner/action.yml +++ b/.github/actions/iginxRunner/action.yml @@ -9,6 +9,10 @@ inputs: description: "to test UDF path detection" required: false default: "false" + Root-Dir-Path: + description: "the path of IGinX root directory" + required: false + default: "${GITHUB_WORKSPACE}" runs: using: "composite" # Mandatory parameter steps: @@ -17,37 +21,37 @@ runs: shell: bash run: | if [ "$RUNNER_OS" == "Linux" ]; then - sudo sed -i 's/needInitBasicUDFFunctions=false/needInitBasicUDFFunctions=true/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties + sudo sed -i 's/needInitBasicUDFFunctions=false/needInitBasicUDFFunctions=true/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties elif [ "$RUNNER_OS" == "Windows" ]; then - sed -i 's/needInitBasicUDFFunctions=false/needInitBasicUDFFunctions=true/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties - sed -i 's/pythonCMD=python3/pythonCMD=python/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties + sed -i 's/needInitBasicUDFFunctions=false/needInitBasicUDFFunctions=true/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties + sed -i 's/pythonCMD=python3/pythonCMD=python/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties elif [ "$RUNNER_OS" == "macOS" ]; then - sudo sed -i '' 's/needInitBasicUDFFunctions=false/needInitBasicUDFFunctions=true/' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties + sudo sed -i '' 's/needInitBasicUDFFunctions=false/needInitBasicUDFFunctions=true/' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties else echo "$RUNNER_OS is not supported" exit 1 fi - chmod +x "${GITHUB_WORKSPACE}/.github/scripts/iginx/iginx_udf_path.sh" - "${GITHUB_WORKSPACE}/.github/scripts/iginx/iginx_udf_path.sh" ${VERSION} + chmod +x "${{ inputs.Root-Dir-Path }}/.github/scripts/iginx/iginx_udf_path.sh" + "${{ inputs.Root-Dir-Path }}/.github/scripts/iginx/iginx_udf_path.sh" ${VERSION} - if: inputs.if-test-udf=='false' && inputs.if-stop=='false' name: Start IGinX shell: bash run: | if [ "$RUNNER_OS" == "Linux" ]; then - chmod +x "${GITHUB_WORKSPACE}/.github/scripts/iginx/iginx.sh" - "${GITHUB_WORKSPACE}/.github/scripts/iginx/iginx.sh" 6888 6666 + chmod +x "${{ inputs.Root-Dir-Path }}/.github/scripts/iginx/iginx.sh" + "${{ inputs.Root-Dir-Path }}/.github/scripts/iginx/iginx.sh" 6888 6666 elif [ "$RUNNER_OS" == "Windows" ]; then - chmod +x "${GITHUB_WORKSPACE}/.github/scripts/iginx/iginx_windows.sh" - "${GITHUB_WORKSPACE}/.github/scripts/iginx/iginx_windows.sh" 6888 6666 + chmod +x "${{ inputs.Root-Dir-Path }}/.github/scripts/iginx/iginx_windows.sh" + "${{ inputs.Root-Dir-Path }}/.github/scripts/iginx/iginx_windows.sh" 6888 6666 elif [ "$RUNNER_OS" == "macOS" ]; then - chmod +x "${GITHUB_WORKSPACE}/.github/scripts/iginx/iginx_macos.sh" - "${GITHUB_WORKSPACE}/.github/scripts/iginx/iginx_macos.sh" 6888 6666 + chmod +x "${{ inputs.Root-Dir-Path }}/.github/scripts/iginx/iginx_macos.sh" + "${{ inputs.Root-Dir-Path }}/.github/scripts/iginx/iginx_macos.sh" 6888 6666 fi - if: inputs.if-test-udf=='false' && inputs.if-stop=='true' name: Stop IGinX shell: bash run: | - chmod +x "${GITHUB_WORKSPACE}/.github/scripts/iginx/iginx_kill.sh" - "${GITHUB_WORKSPACE}/.github/scripts/iginx/iginx_kill.sh" + chmod +x "${{ inputs.Root-Dir-Path }}/.github/scripts/iginx/iginx_kill.sh" + "${{ inputs.Root-Dir-Path }}/.github/scripts/iginx/iginx_kill.sh" diff --git a/.github/scripts/benchmarks/tpch.sh b/.github/scripts/benchmarks/tpch.sh new file mode 100644 index 0000000000..f5aeecad85 --- /dev/null +++ b/.github/scripts/benchmarks/tpch.sh @@ -0,0 +1,49 @@ +#!/bin/bash +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + + +if [ "$RUNNER_OS" = "Windows" ]; then + python thu_cloud_download.py \ + -l https://cloud.tsinghua.edu.cn/d/740c158819bc4759a36e/ \ + -s "." +else + python3 thu_cloud_download.py \ + -l https://cloud.tsinghua.edu.cn/d/740c158819bc4759a36e/ \ + -s "." +fi + cd tpchdata + # 目标文件夹路径 + destination_folder="../tpc/TPC-H V3.0.1/data" + + # 确保目标文件夹存在,如果不存在则创建 + mkdir -p "$destination_folder" + + # 将所有*.tbl文件移动到目标文件夹 + mv *.tbl "$destination_folder/" + cd "$destination_folder" + + chmod +r customer.tbl + chmod +r lineitem.tbl + chmod +r nation.tbl + chmod +r orders.tbl + chmod +r region.tbl + chmod +r supplier.tbl + ls -a + pwd + echo "文件移动完成" diff --git a/.github/workflows/standard-test-suite.yml b/.github/workflows/standard-test-suite.yml index 29f327370c..67e41e0f75 100644 --- a/.github/workflows/standard-test-suite.yml +++ b/.github/workflows/standard-test-suite.yml @@ -37,3 +37,8 @@ jobs: metadata-matrix: '["zookeeper"]' assemebly-test: uses: ./.github/workflows/assembly-test.yml + tpc-h-regression-test: + uses: ./.github/workflows/tpc-h.yml + with: + os-matrix: '["ubuntu-latest"]' + metadata-matrix: '["zookeeper"]' diff --git a/.github/workflows/tpc-h.yml b/.github/workflows/tpc-h.yml new file mode 100644 index 0000000000..85ebd99fba --- /dev/null +++ b/.github/workflows/tpc-h.yml @@ -0,0 +1,168 @@ +name: "TPC-H Regression Test" + +on: + workflow_call: + inputs: + java-matrix: + description: "The java version to run the test on" + type: string + required: false + default: '["8"]' + python-matrix: + description: "The python version to run the test on" + type: string + required: false + default: '["3.9"]' + os-matrix: + description: "The operating system to run the test on" + type: string + required: false + default: '["ubuntu-latest", "macos-13", "windows-latest"]' + metadata-matrix: + description: "The metadata to run the test on" + type: string + required: false + default: '["zookeeper", "etcd"]' + db-matrix: + description: "The database to run the test on" + type: string + required: false + default: '["FileSystem", "IoTDB12", "InfluxDB", "PostgreSQL", "Redis", "MongoDB", "Parquet", "MySQL"]' + +jobs: + TPC-H-Test: + timeout-minutes: 35 + strategy: + fail-fast: false + matrix: + java: ${{ fromJSON(inputs.java-matrix) }} + python-version: ${{ fromJSON(inputs.python-matrix) }} + os: ${{ fromJSON(inputs.os-matrix) }} + metadata: ${{ fromJSON(inputs.metadata-matrix) }} + DB-name: ${{ fromJSON(inputs.db-matrix) }} + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + - name: Environment dependence + uses: ./.github/actions/dependence + with: + python-version: ${{ matrix.python-version }} + java: ${{ matrix.java }} + + - name: Display System Info + shell: bash + run: | + echo "Operating System: $(uname -a 2>/dev/null || ver)" + echo "Architecture: $(uname -m 2>/dev/null || echo %PROCESSOR_ARCHITECTURE%)" + echo "Java Version:" + java -version + echo "Python Version:" + python --version + echo "CPU Info:" + if [ "$(uname)" = "Linux" ]; then + lscpu + elif [ "$(uname)" = "Darwin" ]; then + sysctl -n machdep.cpu.brand_string + else + wmic cpu get name + fi + echo "Memory Info:" + if [ "$(uname)" = "Linux" ]; then + free -h + elif [ "$(uname)" = "Darwin" ]; then + vm_stat + else + systeminfo | findstr /C:"Total Physical Memory" + fi + + - name: Generate TPC-H Data + shell: bash + run: | + chmod +x "${GITHUB_WORKSPACE}/.github/scripts/benchmarks/tpch.sh" + "${GITHUB_WORKSPACE}/.github/scripts/benchmarks/tpch.sh" + + - name: Run Metadata + uses: ./.github/actions/metadataRunner + with: + metadata: ${{ matrix.metadata }} + + - name: Run DB + uses: ./.github/actions/dbRunner + with: + DB-name: ${{ matrix.DB-name }} + + - name: Get Old Version + shell: bash + run: | + mvn clean package -DskipTests -P-format -q + # git clone https://github.com/IGinX-THU/IGinX.git + # cd IGinX + # mvn clean package -DskipTests -P-format -q + + - name: Change Old IGinX config + uses: ./.github/actions/confWriter + with: + DB-name: ${{ matrix.DB-name }} + Set-Filter-Fragment-OFF: "true" + Metadata: ${{ matrix.metadata }} + # Root-Dir-Path: "${GITHUB_WORKSPACE}/IGinX" + + - name: Start Old IGinX + uses: ./.github/actions/iginxRunner + # with: + # Root-Dir-Path: "${GITHUB_WORKSPACE}/IGinX" + + - name: Run Regression Test on Old IGinX + if: always() + shell: bash + run: | + mvn test -q -Dtest=TPCHRegressionIT -DfailIfNoTests=false -P-format + + - name: Show Old IGinX log + if: always() + shell: bash + run: | + cat iginx-*.log + + - name: Stop ZooKeeper + uses: ./.github/actions/zookeeperRunner + with: + if-stop: "true" + + - name: Stop Old IGinX + uses: ./.github/actions/iginxRunner + with: + version: ${VERSION} + if-stop: "true" + + - name: Rerun ZooKeeper + uses: ./.github/actions/zookeeperRunner + with: + if-rerun: "true" + + - name: Install New IGinX with Maven + shell: bash + run: | + mvn clean package -DskipTests -P-format -q + + - name: Change New IGinX config + uses: ./.github/actions/confWriter + with: + DB-name: ${{ matrix.DB-name }} + Set-Filter-Fragment-OFF: "true" + Metadata: ${{ matrix.metadata }} + + - name: Start New IGinX + uses: ./.github/actions/iginxRunner + + - name: Run Regression Test on New IGinX + if: always() + shell: bash + run: | + mvn test -q -Dtest=TPCHRegressionIT -DfailIfNoTests=false -P-format + + - name: Show New IGinX log + if: always() + shell: bash + run: | + cat iginx-*.log diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/naive/NaiveOperatorMemoryExecutor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/naive/NaiveOperatorMemoryExecutor.java index 68e80661c7..fca427c618 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/naive/NaiveOperatorMemoryExecutor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/naive/NaiveOperatorMemoryExecutor.java @@ -192,7 +192,7 @@ private Table transformToTable(RowStream stream) throws PhysicalException { return new Table(header, rows); } - private RowStream executeProject(Project project, Table table) throws PhysicalException { + private RowStream executeProject(Project project, Table table) { List patterns = project.getPatterns(); Header header = table.getHeader(); List targetFields = new ArrayList<>(); @@ -244,7 +244,7 @@ private RowStream executeSort(Sort sort, Table table) throws PhysicalException { return table; } - private RowStream executeLimit(Limit limit, Table table) throws PhysicalException { + private RowStream executeLimit(Limit limit, Table table) { int rowSize = table.getRowSize(); Header header = table.getHeader(); List rows = new ArrayList<>(); @@ -370,8 +370,7 @@ private RowStream executeDownsample(Downsample downsample, Table table) throws P return RowUtils.joinMultipleTablesByKey(tableList); } - private RowStream executeRowTransform(RowTransform rowTransform, Table table) - throws PhysicalException { + private RowStream executeRowTransform(RowTransform rowTransform, Table table) { List> list = new ArrayList<>(); rowTransform .getFunctionCallList() @@ -473,7 +472,7 @@ private RowStream executeMappingTransform(MappingTransform mappingTransform, Tab return RowUtils.calMappingTransform(table, functionCallList); } - private RowStream executeRename(Rename rename, Table table) throws PhysicalException { + private RowStream executeRename(Rename rename, Table table) { Header header = table.getHeader(); Map aliasMap = rename.getAliasMap(); @@ -495,8 +494,7 @@ private RowStream executeRename(Rename rename, Table table) throws PhysicalExcep return new Table(newHeader, rows); } - private RowStream executeAddSchemaPrefix(AddSchemaPrefix addSchemaPrefix, Table table) - throws PhysicalException { + private RowStream executeAddSchemaPrefix(AddSchemaPrefix addSchemaPrefix, Table table) { Header header = table.getHeader(); String schemaPrefix = addSchemaPrefix.getSchemaPrefix(); @@ -635,7 +633,7 @@ private RowStream executeJoin(Join join, Table tableA, Table tableB) throws Phys // 检查时间戳 if (!headerA.hasKey() || !headerB.hasKey()) { throw new InvalidOperatorParameterException( - "row streams for join operator by time should have timestamp."); + "row streams for join operator by key should have key."); } List newFields = new ArrayList<>(); newFields.addAll(headerA.getFields()); @@ -731,8 +729,7 @@ private RowStream executeJoin(Join join, Table tableA, Table tableB) throws Phys } } - private RowStream executeCrossJoin(CrossJoin crossJoin, Table tableA, Table tableB) - throws PhysicalException { + private RowStream executeCrossJoin(CrossJoin crossJoin, Table tableA, Table tableB) { Header newHeader = HeaderUtils.constructNewHead( tableA.getHeader(), tableB.getHeader(), crossJoin.getPrefixA(), crossJoin.getPrefixB()); diff --git a/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java b/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java index 62e1a35b44..972985280c 100644 --- a/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java +++ b/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java @@ -186,7 +186,7 @@ record = dataSet.next(); } @Override - public void release() throws PhysicalException { + public void release() { sessionPool.close(); } diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/ColumnPruningRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/ColumnPruningRule.java index 54ee1dc87c..5583f00048 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/ColumnPruningRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/ColumnPruningRule.java @@ -324,6 +324,29 @@ private void collectColumns( leftColumns.addAll(leftOrder); rightColumns.addAll(rightOrder); } + } else if (operator.getType().equals(OperatorType.Join)) { + List leftPatterns = + OperatorUtils.getPatternFromOperatorChildren( + ((OperatorSource) ((BinaryOperator) operator).getSourceA()).getOperator(), + new ArrayList<>()); + List rightPatterns = + OperatorUtils.getPatternFromOperatorChildren( + ((OperatorSource) ((BinaryOperator) operator).getSourceB()).getOperator(), + new ArrayList<>()); + for (String column : columns) { + for (String leftPattern : leftPatterns) { + if (OperatorUtils.covers(leftPattern, column)) { + leftColumns.add(column); + break; + } + } + for (String rightPattern : rightPatterns) { + if (OperatorUtils.covers(rightPattern, column)) { + rightColumns.add(column); + break; + } + } + } } else { leftColumns.addAll(columns); rightColumns.addAll(columns); diff --git a/session_py/example.py b/session_py/example.py index 01ca135ecf..1f09b98459 100644 --- a/session_py/example.py +++ b/session_py/example.py @@ -18,8 +18,8 @@ import pandas as pd -from iginx_pyclient.session import Session -from iginx_pyclient.thrift.rpc.ttypes import DataType, AggregateType +from .session import Session +from .thrift.rpc.ttypes import DataType, AggregateType if __name__ == '__main__': diff --git a/session_py/file_example.py b/session_py/file_example.py index b7d6c9ae07..c6a15787fe 100644 --- a/session_py/file_example.py +++ b/session_py/file_example.py @@ -25,8 +25,8 @@ import cv2 import requests -from iginx_pyclient.session import Session -from iginx_pyclient.thrift.rpc.ttypes import StorageEngineType +from .session import Session +from .thrift.rpc.ttypes import StorageEngineType # 读取第一行是列名的csv文件,并将数据存入IGinX diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/ConfLoader.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/ConfLoader.java index c0f6fcff94..3c56aa2224 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/ConfLoader.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/ConfLoader.java @@ -126,6 +126,14 @@ public String getDBCETestWay() { return getTestProperty(DBCE_TEST_WAY, DEFAULT_DBCE_TEST_WAY); } + public int getMaxRepetitionsNum() { + return Integer.parseInt(properties.getProperty("max_repetitions_num")); + } + + public double getRegressionThreshold() { + return Double.parseDouble(properties.getProperty("regression_threshold")); + } + public ConfLoader(String confPath) { this.confPath = confPath; try { diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHRegressionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHRegressionIT.java new file mode 100644 index 0000000000..8b3bde7220 --- /dev/null +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHRegressionIT.java @@ -0,0 +1,529 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package cn.edu.tsinghua.iginx.integration.tpch; + +import static cn.edu.tsinghua.iginx.integration.controller.Controller.clearAllData; +import static cn.edu.tsinghua.iginx.integration.tpch.TPCHRegressionIT.FieldType.DATE; +import static cn.edu.tsinghua.iginx.integration.tpch.TPCHRegressionIT.FieldType.NUM; +import static cn.edu.tsinghua.iginx.integration.tpch.TPCHRegressionIT.FieldType.STR; +import static org.junit.Assert.fail; + +import cn.edu.tsinghua.iginx.exception.SessionException; +import cn.edu.tsinghua.iginx.integration.controller.Controller; +import cn.edu.tsinghua.iginx.integration.tool.ConfLoader; +import cn.edu.tsinghua.iginx.session.Session; +import cn.edu.tsinghua.iginx.session.SessionExecuteSqlResult; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Scanner; +import java.util.TimeZone; +import java.util.stream.Collectors; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TPCHRegressionIT { + + private static final Logger LOGGER = LoggerFactory.getLogger(TPCHRegressionIT.class); + + // host info + protected static String defaultTestHost = "127.0.0.1"; + protected static int defaultTestPort = 6888; + protected static String defaultTestUser = "root"; + protected static String defaultTestPass = "root"; + + // .tbl文件所在目录 + private static final String dataDir = + System.getProperty("user.dir") + "/../tpc/TPC-H V3.0.1/data"; + + // udf文件所在目录 + private static final String udfDir = "src/test/resources/tpch/udf/"; + + // 最大重复测试次数 + private static int MAX_REPETITIONS_NUM; + + // 回归阈值 + private static double REGRESSION_THRESHOLD; + + protected static Session session; + + enum FieldType { + NUM, + STR, + DATE + } + + public TPCHRegressionIT() { + ConfLoader conf = new ConfLoader(Controller.CONFIG_FILE); + MAX_REPETITIONS_NUM = conf.getMaxRepetitionsNum(); + REGRESSION_THRESHOLD = conf.getRegressionThreshold(); + } + + @BeforeClass + public static void setUp() throws SessionException { + session = new Session(defaultTestHost, defaultTestPort, defaultTestUser, defaultTestPass); + session.openSession(); + } + + @AfterClass + public static void tearDown() throws SessionException { + clearAllData(session); + session.closeSession(); + } + + @Before + public void prepare() { + List tableList = + Arrays.asList( + "region", "nation", "supplier", "part", "partsupp", "customer", "orders", "lineitem"); + + List> fieldsList = new ArrayList<>(); + List> typesList = new ArrayList<>(); + + // region表 + fieldsList.add(Arrays.asList("r_regionkey", "r_name", "r_comment")); + typesList.add(Arrays.asList(NUM, STR, STR)); + + // nation表 + fieldsList.add(Arrays.asList("n_nationkey", "n_name", "n_regionkey", "n_comment")); + typesList.add(Arrays.asList(NUM, STR, NUM, STR)); + + // supplier表 + fieldsList.add( + Arrays.asList( + "s_suppkey", + "s_name", + "s_address", + "s_nationkey", + "s_phone", + "s_acctbal", + "s_comment")); + typesList.add(Arrays.asList(NUM, STR, STR, NUM, STR, NUM, STR)); + + // part表 + fieldsList.add( + Arrays.asList( + "p_partkey", + "p_name", + "p_mfgr", + "p_brand", + "p_type", + "p_size", + "p_container", + "p_retailprice", + "p_comment")); + typesList.add(Arrays.asList(NUM, STR, STR, STR, STR, NUM, STR, NUM, STR)); + + // partsupp表 + fieldsList.add( + Arrays.asList("ps_partkey", "ps_suppkey", "ps_availqty", "ps_supplycost", "ps_comment")); + typesList.add(Arrays.asList(NUM, NUM, NUM, NUM, STR)); + + // customer表 + fieldsList.add( + Arrays.asList( + "c_custkey", + "c_name", + "c_address", + "c_nationkey", + "c_phone", + "c_acctbal", + "c_mktsegment", + "c_comment")); + typesList.add(Arrays.asList(NUM, STR, STR, NUM, STR, NUM, STR, STR)); + + // orders表 + fieldsList.add( + Arrays.asList( + "o_orderkey", + "o_custkey", + "o_orderstatus", + "o_totalprice", + "o_orderdate", + "o_orderpriority", + "o_clerk", + "o_shippriority", + "o_comment")); + typesList.add(Arrays.asList(NUM, NUM, STR, NUM, DATE, STR, STR, NUM, STR)); + + // lineitem表 + fieldsList.add( + Arrays.asList( + "l_orderkey", + "l_partkey", + "l_suppkey", + "l_linenumber", + "l_quantity", + "l_extendedprice", + "l_discount", + "l_tax", + "l_returnflag", + "l_linestatus", + "l_shipdate", + "l_commitdate", + "l_receiptdate", + "l_shipinstruct", + "l_shipmode", + "l_comment")); + typesList.add( + Arrays.asList( + NUM, NUM, NUM, NUM, NUM, NUM, NUM, NUM, STR, STR, DATE, DATE, DATE, STR, STR, STR)); + + // 插入数据 + for (int i = 0; i < 8; i++) { + insertTable(tableList.get(i), fieldsList.get(i), typesList.get(i)); + } + + List> UDFInfos = new ArrayList<>(); + UDFInfos.add(Arrays.asList("UDTF", "extractYear", "UDFExtractYear", "udtf_extract_year.py")); + // 注册UDF函数 + for (List UDFInfo : UDFInfos) { + registerUDF(UDFInfo); + } + } + + private void insertTable(String table, List fields, List types) { + StringBuilder builder = new StringBuilder("INSERT INTO "); + builder.append(table); + builder.append("(key, "); + for (String field : fields) { + builder.append(field); + builder.append(", "); + } + builder.setLength(builder.length() - 2); + builder.append(") VALUES "); + String insertPrefix = builder.toString(); + + long count = 0; + try (BufferedReader br = + new BufferedReader(new FileReader(String.format("%s/%s.tbl", dataDir, table)))) { + StringBuilder sb = new StringBuilder(insertPrefix); + String line; + while ((line = br.readLine()) != null) { + String[] items = line.split("\\|"); + sb.append("("); + sb.append(count); // 插入自增key列 + count++; + sb.append(", "); + assert fields.size() == items.length; + for (int i = 0; i < items.length; i++) { + switch (types.get(i)) { + case NUM: + sb.append(items[i]); + sb.append(", "); + break; + case STR: // 字符串类型在外面需要包一层引号 + sb.append("\""); + sb.append(items[i]); + sb.append("\", "); + break; + case DATE: // 日期类型需要转为时间戳 + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); + long time = dateFormat.parse(items[i]).getTime(); + sb.append(time); + sb.append(", "); + break; + default: + break; + } + } + sb.setLength(sb.length() - 2); + sb.append("), "); + + // 每次最多插入10000条数据 + if (count % 10000 == 0) { + sb.setLength(sb.length() - 2); + sb.append(";"); + session.executeSql(sb.toString()); + sb = new StringBuilder(insertPrefix); + } + } + // 插入剩余数据 + if (sb.length() != insertPrefix.length()) { + sb.setLength(sb.length() - 2); + sb.append(";"); + session.executeSql(sb.toString()); + } + LOGGER.info("Insert {} records into table [{}].", count, table); + } catch (IOException | ParseException | SessionException e) { + LOGGER.error("Insert into table {} fail. Caused by:", table, e); + fail(); + } + } + + private void registerUDF(List UDFInfo) { + String SINGLE_UDF_REGISTER_SQL = "CREATE FUNCTION %s \"%s\" FROM \"%s\" IN \"%s\";"; + File udfFile = new File(udfDir + UDFInfo.get(3)); + String register = + String.format( + SINGLE_UDF_REGISTER_SQL, + UDFInfo.get(0), + UDFInfo.get(1), + UDFInfo.get(2), + udfFile.getAbsolutePath()); + try { + LOGGER.info("Execute register UDF statement: {}", register); + session.executeRegisterTask(register, false); + } catch (SessionException e) { + LOGGER.error("Statement: \"{}\" execute fail. Caused by:", register, e); + fail(); + } + } + + @After + public void clearData() throws SessionException { + session.executeSql("CLEAR DATA;"); + } + + @Test + public void test() { + try { + // 获取当前JVM的Runtime实例 + Runtime runtime = Runtime.getRuntime(); + // 执行垃圾回收,尽量释放内存 + runtime.gc(); + // 获取执行语句前的内存使用情况 + long usedMemoryBefore = runtime.totalMemory() - runtime.freeMemory(); + long startTime; + // 13有问题 + List queryIds = Arrays.asList(1, 2, 3, 5, 6, 9, 10, 16, 17, 18, 19, 20); + for (int queryId : queryIds) { + // read from sql file + String sqlString = + readSqlFileAsString("src/test/resources/tpch/queries/q" + queryId + ".sql"); + // 开始 tpc-h 查询 + System.out.println("start tpc-h query " + queryId); + startTime = System.currentTimeMillis(); + // 执行查询语句, split by ; 最后一句为执行结果 + SessionExecuteSqlResult result = null; + String[] sqls = sqlString.split(";"); + for (String sql : sqls) { + if (sql.trim().isEmpty()) { + continue; + } + sql += ";"; + try { + result = session.executeSql(sql); + } catch (SessionException e) { + LOGGER.error("Statement: \"{}\" execute fail. Caused by:", sql, e); + fail(); + } + result.print(false, ""); + } + // 再次执行垃圾回收 + runtime.gc(); + // 获取执行语句后的内存使用情况 + long usedMemoryAfter = runtime.totalMemory() - runtime.freeMemory(); + // 计算内存使用的变化 + long memoryUsed = usedMemoryAfter - usedMemoryBefore; + // 输出内存使用情况 + System.out.println("Memory used by the statement: " + memoryUsed + " bytes"); + long timeCost = System.currentTimeMillis() - startTime; + System.out.println("end tpc-h query, time cost: " + timeCost + "ms"); + + // 验证 + List> values = result.getValues(); + List> answers = + csvReader("src/test/resources/tpch/sf0.1/q" + queryId + ".csv"); + if (values.size() != answers.size()) { + System.out.println("values.size() = " + values.size()); + System.out.println("answers.size() = " + answers.size()); + throw new RuntimeException("size not equal"); + } + for (int i = 0; i < values.size(); i++) { + for (int j = 0; j < values.get(i).size(); j++) { + if (result.getPaths().get(j).contains("address") + || result.getPaths().get(j).contains("comment") + || result.getPaths().get(j).contains("orderdate")) { + // TODO change unix time to date + continue; + } + // if only contains number and dot, then parse to double + if (values.get(i).get(j).toString().matches("-?[0-9]+.*[0-9]*")) { + double number = Double.parseDouble(values.get(i).get(j).toString()); + double answerNumber = Double.parseDouble(answers.get(i).get(j)); + if (answerNumber - number >= 1e-3 || number - answerNumber >= 1e-3) { + System.out.println("Number: " + number); + System.out.println("Answer number: " + answerNumber); + } + assert answerNumber - number < 1e-3 && number - answerNumber < 1e-3; + } else { + String resultString = + new String((byte[]) values.get(i).get(j), StandardCharsets.UTF_8); + String answerString = answers.get(i).get(j); + if (!resultString.equals(answerString)) { + System.out.println("Result string: " + resultString); + System.out.println("Answer string: " + answerString); + } + assert resultString.equals(answerString); + } + } + } + } + + String fileName = "src/test/resources/tpch/oldTimeCosts.txt"; + if (!Files.exists(Paths.get(fileName))) { // 文件不存在,即此次跑的是主分支代码,需要将查询时间写入文件 + List timeCosts = new ArrayList<>(); + for (int queryId : queryIds) { + // 开始 tpc-h 查询 + System.out.printf("start tpc-h query %d in main branch%n", queryId); + // read from sql file + String sqlString = + readSqlFileAsString("src/test/resources/tpch/queries/q" + queryId + ".sql"); + // 执行查询语句, split by ; 最后一句为执行结果 + String[] sqls = sqlString.split(";"); + + // 主分支上重复查询两次取平均值 + long sum = 0; + for (int i = 0; i < 2; i++) { + long timeCost = executeSQL(sqls[sqls.length - 2] + ";"); + sum += timeCost; + } + sum /= 2; + timeCosts.add(sum); + System.out.printf("end tpc-h query %d in main branch, time cost: %dms%n", queryId, sum); + } + writeToFile(timeCosts, fileName); + } else { // 文件存在,即此次跑的是新分支代码,需要读取文件进行比较 + List oldTimeCosts = readFromFile(fileName); + double multiplyPercentage = 1 + REGRESSION_THRESHOLD; + for (int i = 0; i < queryIds.size(); i++) { + double oldTimeCost = (double) oldTimeCosts.get(i); + double newTimeCost = 0; + List newTimeCosts = new ArrayList<>(); + boolean regressionDetected = true; + + while (newTimeCosts.size() < MAX_REPETITIONS_NUM) { + // 开始 tpc-h 查询 + System.out.printf("start tpc-h query %d in new branch%n", queryIds.get(i)); + // read from sql file + String sqlString = + readSqlFileAsString("src/test/resources/tpch/queries/q" + queryIds.get(i) + ".sql"); + // 执行查询语句, split by ; 最后一句为执行结果 + String[] sqls = sqlString.split(";"); + long timeCost = executeSQL(sqls[sqls.length - 2] + ";"); + System.out.printf( + "end tpc-h query %d in new branch, time cost: %dms%n", queryIds.get(i), timeCost); + newTimeCosts.add(timeCost); + newTimeCost = getMedian(newTimeCosts); + if (oldTimeCost * multiplyPercentage >= newTimeCost) { + regressionDetected = false; + break; + } + } + + // 重复10次后耗时仍超过阈值 + if (regressionDetected) { + System.out.printf( + "performance degradation of query %d exceeds %f%n", + queryIds.get(i), REGRESSION_THRESHOLD); + System.out.printf("old timing: %.3fms%n", oldTimeCost); + System.out.printf("new timing: %.3fms%n", newTimeCost); + LOGGER.error("TPC-H query {} regression test fail.", queryIds.get(i)); + fail(); + } + } + } + + } catch (IOException e) { + LOGGER.error("Test fail. Caused by:", e); + fail(); + } + } + + private static long executeSQL(String sql) { + long startTime = System.currentTimeMillis(); + try { + SessionExecuteSqlResult result = session.executeSql(sql); + } catch (SessionException e) { + LOGGER.error("Statement: \"{}\" execute fail. Caused by:", sql, e); + fail(); + } + return System.currentTimeMillis() - startTime; + } + + private static double getMedian(List array) { + Collections.sort(array); + int middle = array.size() / 2; + return array.size() % 2 == 0 + ? (array.get(middle - 1) + array.get(middle)) / 2.0 + : (double) array.get(middle); + } + + private static void writeToFile(List timeCosts, String fileName) throws IOException { + Path filePath = Paths.get(fileName); + List lines = timeCosts.stream().map(String::valueOf).collect(Collectors.toList()); + Files.write(filePath, lines); + } + + private static List readFromFile(String fileName) throws IOException { + Path filePath = Paths.get(fileName); + List lines = Files.readAllLines(filePath); + return lines.stream().map(Long::valueOf).collect(Collectors.toList()); + } + + private static List> csvReader(String filePath) { + List> data = new ArrayList<>(); + boolean skipHeader = true; + try (Scanner scanner = new Scanner(Paths.get(filePath))) { + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); + if (skipHeader) { + skipHeader = false; + continue; + } + List row = Arrays.asList(line.split("\\|")); + data.add(row); + } + } catch (IOException e) { + LOGGER.error("Read file {} fail. Caused by:", filePath, e); + fail(); + } + System.out.println(data); + return data; + } + + private static String readSqlFileAsString(String filePath) throws IOException { + StringBuilder contentBuilder = new StringBuilder(); + try (BufferedReader br = new BufferedReader(new FileReader(filePath))) { + String line; + while ((line = br.readLine()) != null) { + contentBuilder.append(line).append("\n"); + } + } + return contentBuilder.toString(); + } +} diff --git a/test/src/test/resources/testConfig.properties b/test/src/test/resources/testConfig.properties index 33719ca3e8..489bde4f2b 100644 --- a/test/src/test/resources/testConfig.properties +++ b/test/src/test/resources/testConfig.properties @@ -71,3 +71,7 @@ stand_alone_DB=IoTDB12 # Local test DB-CE is_scaling=false DBCE_test_way=oriHasDataExpHasData + +# TPC-H test +max_repetitions_num=10 +regression_threshold=0.3 diff --git a/test/src/test/resources/tpch/queries/q1.sql b/test/src/test/resources/tpch/queries/q1.sql new file mode 100644 index 0000000000..c77305f28d --- /dev/null +++ b/test/src/test/resources/tpch/queries/q1.sql @@ -0,0 +1,31 @@ +select + lineitem.l_returnflag as l_returnflag, + lineitem.l_linestatus as l_linestatus, + sum(lineitem.l_quantity) as sum_qty, + sum(lineitem.l_extendedprice) as sum_base_price, + sum(tmp1) as sum_disc_price, + sum(tmp2) as sum_charge, + avg(lineitem.l_quantity) as avg_qty, + avg(lineitem.l_extendedprice) as avg_price, + avg(lineitem.l_discount) as avg_disc, + count(lineitem.l_returnflag) as count_order +from ( + select + l_returnflag, + l_linestatus, + l_quantity, + l_extendedprice, + l_discount, + l_extendedprice * (1 - l_discount) as tmp1, + l_extendedprice * (1 - l_discount) * (1 + l_tax) as tmp2 + from + lineitem + where + lineitem.l_shipdate <= 904694400000 + ) +group by + lineitem.l_returnflag, + lineitem.l_linestatus +order by + lineitem.l_returnflag, + lineitem.l_linestatus; \ No newline at end of file diff --git a/test/src/test/resources/tpch/queries/q10.sql b/test/src/test/resources/tpch/queries/q10.sql new file mode 100644 index 0000000000..2fdd79af91 --- /dev/null +++ b/test/src/test/resources/tpch/queries/q10.sql @@ -0,0 +1,51 @@ +select + customer.c_custkey, + customer.c_name, + revenue, + customer.c_acctbal, + nation.n_name, + customer.c_address, + customer.c_phone, + customer.c_comment +from ( + select + customer.c_custkey, + customer.c_name, + sum(tmp) as revenue, + customer.c_acctbal, + nation.n_name, + customer.c_address, + customer.c_phone, + customer.c_comment + from ( + select + customer.c_custkey, + customer.c_name, + lineitem.l_extendedprice * (1 - lineitem.l_discount) as tmp, + customer.c_acctbal, + nation.n_name, + customer.c_address, + customer.c_phone, + customer.c_comment + from + customer + join orders on customer.c_custkey = orders.o_custkey + join lineitem on lineitem.l_orderkey = orders.o_orderkey + join nation on customer.c_nationkey = nation.n_nationkey + where + orders.o_orderdate >= 749404800000 + and orders.o_orderdate < 757353600000 + and lineitem.l_returnflag = 'R' + ) + group by + customer.c_custkey, + customer.c_name, + customer.c_acctbal, + customer.c_phone, + nation.n_name, + customer.c_address, + customer.c_comment + ) +order by + revenue desc +limit 20; \ No newline at end of file diff --git a/test/src/test/resources/tpch/queries/q13.sql b/test/src/test/resources/tpch/queries/q13.sql new file mode 100644 index 0000000000..c40d34162c --- /dev/null +++ b/test/src/test/resources/tpch/queries/q13.sql @@ -0,0 +1,25 @@ +select + c_count, + custdist +from ( + select + c_count, + count(c_custkey) as custdist + from ( + select + customer.c_custkey as c_custkey, + count(orders.o_orderkey) as c_count + from + customer + left outer join orders + on customer.c_custkey = orders.o_custkey + and !(orders.o_comment like '.*pending.*') + group by + customer.c_custkey + ) + group by + c_count + ) +order by + custdist, + c_count desc; \ No newline at end of file diff --git a/test/src/test/resources/tpch/queries/q16.sql b/test/src/test/resources/tpch/queries/q16.sql new file mode 100644 index 0000000000..a19922c7c9 --- /dev/null +++ b/test/src/test/resources/tpch/queries/q16.sql @@ -0,0 +1,49 @@ +select + p_brand, + p_type, + p_size, + supplier_cnt +from ( + select + part.p_brand as p_brand, + part.p_type as p_type, + part.p_size as p_size, + count(distinct partsupp.ps_suppkey) as supplier_cnt + from + partsupp + join part on part.p_partkey = partsupp.ps_partkey + where + part.p_brand <> 'Brand#45' + and part.p_partkey not in( + select p_partkey from part + where part.p_type like '.*MEDIUM POLISHED.*' + ) + and ( + part.p_size = 3 + or part.p_size = 9 + or part.p_size = 14 + or part.p_size = 19 + or part.p_size = 23 + or part.p_size = 36 + or part.p_size = 45 + or part.p_size = 49 + ) + and partsupp.ps_suppkey not in ( + select + s_suppkey + from + supplier + where + supplier.s_comment like '.*Customer.*Complaints.*' + ) + group by + part.p_brand, + part.p_type, + part.p_size + order by + part.p_brand, + part.p_type, + part.p_size + ) +order by + supplier_cnt desc; \ No newline at end of file diff --git a/test/src/test/resources/tpch/queries/q17.sql b/test/src/test/resources/tpch/queries/q17.sql new file mode 100644 index 0000000000..c573ec0e2d --- /dev/null +++ b/test/src/test/resources/tpch/queries/q17.sql @@ -0,0 +1,29 @@ +insert into tmpTableB(key, p_partkey, val) values ( + select + part.p_partkey, + 0.2 * tmp + from ( + select + part.p_partkey, + avg(lineitem.l_quantity) as tmp + from + lineitem + join part on lineitem.l_partkey = part.p_partkey + group by part.p_partkey + ) +); + +select + tmp2 / 7 as avg_yearly +from ( + select + sum(lineitem.l_extendedprice) as tmp2 + from + lineitem + join part on part.p_partkey = lineitem.l_partkey + join tmpTableB on tmpTableB.p_partkey = lineitem.l_partkey + where + part.p_brand = 'Brand#23' + and part.p_container = 'MED BOX' + and lineitem.l_quantity < tmpTableB.val + ); \ No newline at end of file diff --git a/test/src/test/resources/tpch/queries/q18.sql b/test/src/test/resources/tpch/queries/q18.sql new file mode 100644 index 0000000000..aaa10ae7b3 --- /dev/null +++ b/test/src/test/resources/tpch/queries/q18.sql @@ -0,0 +1,35 @@ +select + customer.c_name, + customer.c_custkey, + orders.o_orderkey, + orders.o_orderdate, + orders.o_totalprice, + sum(lineitem.l_quantity) +from + customer + join orders on customer.c_custkey = orders.o_custkey + join lineitem on orders.o_orderkey = lineitem.l_orderkey +where + orders.o_orderkey in ( + select + lineitem.l_orderkey + from ( + select + l_orderkey, + sum(l_quantity) + from + lineitem + group by + l_orderkey + having + sum(lineitem.l_quantity) > 300 + ) + ) +group by + customer.c_name, + customer.c_custkey, + orders.o_orderkey, + orders.o_orderdate, + orders.o_totalprice +order by + orders.o_totalprice desc; \ No newline at end of file diff --git a/test/src/test/resources/tpch/queries/q19.sql b/test/src/test/resources/tpch/queries/q19.sql new file mode 100644 index 0000000000..0af851b6a0 --- /dev/null +++ b/test/src/test/resources/tpch/queries/q19.sql @@ -0,0 +1,48 @@ +select + sum(tmp) as revenue +from ( + select + lineitem.l_extendedprice * (1 - lineitem.l_discount) as tmp + from + lineitem + join part on part.p_partkey = lineitem.l_partkey + where ( + part.p_brand = 'Brand#12' + and ( + part.p_container = 'SM CASE' + or part.p_container = 'SM BOX' + or part.p_container = 'SM PACK' + or part.p_container = 'SM PKG' + ) + and lineitem.l_quantity >= 1 and lineitem.l_quantity <= 11 + and part.p_size >= 1 and part.p_size <= 5 + and (lineitem.l_shipmode = 'AIR' or lineitem.l_shipmode = 'AIR REG') + and lineitem.l_shipinstruct = 'DELIVER IN PERSON' + ) + or ( + part.p_brand = 'Brand#23' + and ( + part.p_container = 'MED PKG' + or part.p_container = 'MED BOX' + or part.p_container = 'MED BAG' + or part.p_container = 'MED PACK' + ) + and lineitem.l_quantity >= 10 and lineitem.l_quantity <= 20 + and part.p_size >= 1 and part.p_size <= 10 + and (lineitem.l_shipmode = 'AIR' or lineitem.l_shipmode = 'AIR REG') + and lineitem.l_shipinstruct = 'DELIVER IN PERSON' + ) + or ( + part.p_brand = 'Brand#34' + and ( + part.p_container = 'LG PACK' + or part.p_container = 'LG BOX' + or part.p_container = 'LG CASE' + or part.p_container = 'LG PKG' + ) + and lineitem.l_quantity >= 20 and lineitem.l_quantity <= 30 + and part.p_size >= 1 and part.p_size <= 15 + and (lineitem.l_shipmode = 'AIR' or lineitem.l_shipmode = 'AIR REG') + and lineitem.l_shipinstruct = 'DELIVER IN PERSON' + ) + ); \ No newline at end of file diff --git a/test/src/test/resources/tpch/queries/q2.sql b/test/src/test/resources/tpch/queries/q2.sql new file mode 100644 index 0000000000..a5b56e3267 --- /dev/null +++ b/test/src/test/resources/tpch/queries/q2.sql @@ -0,0 +1,44 @@ +insert into tmpTable(key, p_key, minCost) values ( +select + part.p_partkey as p_key, + min(partsupp.ps_supplycost) as minCost +from + partsupp + join supplier on supplier.s_suppkey = partsupp.ps_suppkey + join nation on supplier.s_nationkey = nation.n_nationkey + join region on nation.n_regionkey = region.r_regionkey + join part on part.p_partkey = partsupp.ps_partkey +where + region.r_name = 'EUROPE' + and part.p_size = 15 + and part.p_type like "^.*BRASS" +group by part.p_partkey +); + +select s_acctbal, s_name, n_name, p_partkey, p_mfgr, s_address, s_phone, s_comment from + (select + supplier.s_acctbal as s_acctbal, + supplier.s_name as s_name, + nation.n_name as n_name, + part.p_partkey as p_partkey, + part.p_mfgr as p_mfgr, + supplier.s_address as s_address, + supplier.s_phone as s_phone, + supplier.s_comment as s_comment + from + part + join partsupp on part.p_partkey = partsupp.ps_partkey + join supplier on supplier.s_suppkey = partsupp.ps_suppkey + join nation on supplier.s_nationkey = nation.n_nationkey + join region on nation.n_regionkey = region.r_regionkey + join tmpTable on tmpTable.p_key = part.p_partkey and partsupp.ps_supplycost = tmpTable.minCost + where + part.p_size = 15 + and region.r_name = 'EUROPE' + and part.p_type like "^.*BRASS" + order by + nation.n_name, + supplier.s_name, + part.p_partkey + ) +order by s_acctbal desc; \ No newline at end of file diff --git a/test/src/test/resources/tpch/queries/q20.sql b/test/src/test/resources/tpch/queries/q20.sql new file mode 100644 index 0000000000..4671b79f8a --- /dev/null +++ b/test/src/test/resources/tpch/queries/q20.sql @@ -0,0 +1,45 @@ +insert into tmpTableA(key, partkey, suppkey, val) values ( + select + partkey, + suppkey, + 0.5 * tmp from( + select + l_partkey as partkey, + l_suppkey as suppkey, + sum(l_quantity) as tmp + from + lineitem + where + lineitem.l_shipdate >= 757353600000 + and lineitem.l_shipdate < 788889600000 + group by l_partkey, l_suppkey + ) +); + +select + supplier.s_name, + supplier.s_address +from + supplier + join nation on supplier.s_nationkey = nation.n_nationkey +where + supplier.s_suppkey in ( + select + partsupp.ps_suppkey + from + partsupp + join tmpTableA on tmpTableA.suppkey = partsupp.ps_suppkey and tmpTableA.partkey = partsupp.ps_partkey + where + partsupp.ps_partkey in ( + select + p_partkey + from + part + where + part.p_name like 'forest.*' + ) + and partsupp.ps_availqty > tmpTableA.val + ) + and nation.n_name = 'CANADA' +order by + supplier.s_name; \ No newline at end of file diff --git a/test/src/test/resources/tpch/queries/q3.sql b/test/src/test/resources/tpch/queries/q3.sql new file mode 100644 index 0000000000..81a232a712 --- /dev/null +++ b/test/src/test/resources/tpch/queries/q3.sql @@ -0,0 +1,31 @@ +select l_orderkey, + revenue, + o_orderdate, + o_shippriority from + (select + l_orderkey, + o_orderdate, + o_shippriority, + sum(tmp) as revenue + from( + select + lineitem.l_extendedprice * (1 - lineitem.l_discount) as tmp, + lineitem.l_orderkey as l_orderkey, + orders.o_orderdate as o_orderdate, + orders.o_shippriority as o_shippriority + from + customer + join orders on customer.c_custkey = orders.o_custkey + join lineitem on lineitem.l_orderkey = orders.o_orderkey + where + customer.c_mktsegment = 'BUILDING' + and orders.o_orderdate < 795196800000 + and lineitem.l_shipdate > 795225600000 + ) + group by + l_orderkey, + o_orderdate, + o_shippriority + ) +order by revenue desc + limit 10; \ No newline at end of file diff --git a/test/src/test/resources/tpch/queries/q5.sql b/test/src/test/resources/tpch/queries/q5.sql new file mode 100644 index 0000000000..197cced143 --- /dev/null +++ b/test/src/test/resources/tpch/queries/q5.sql @@ -0,0 +1,28 @@ +select + nation.n_name, + revenue +from ( + select + nation.n_name, + sum(tmp) as revenue + from ( + select + nation.n_name, + lineitem.l_extendedprice * (1 - lineitem.l_discount) as tmp + from + customer + join orders on customer.c_custkey = orders.o_custkey + join lineitem on lineitem.l_orderkey = orders.o_orderkey + join supplier on lineitem.l_suppkey = supplier.s_suppkey and customer.c_nationkey = supplier.s_nationkey + join nation on supplier.s_nationkey = nation.n_nationkey + join region on nation.n_regionkey = region.r_regionkey + where + region.r_name = "ASIA" + and orders.o_orderdate >= 757353600000 + and orders.o_orderdate < 788889600000 + ) + group by + nation.n_name + ) +order by + revenue desc; \ No newline at end of file diff --git a/test/src/test/resources/tpch/queries/q6.sql b/test/src/test/resources/tpch/queries/q6.sql new file mode 100644 index 0000000000..3e9c5a4b65 --- /dev/null +++ b/test/src/test/resources/tpch/queries/q6.sql @@ -0,0 +1,12 @@ +select sum(tmp) from ( + select + l_extendedprice * l_discount as tmp + from + lineitem + where + lineitem.l_shipdate >= 757353600000 + and lineitem.l_shipdate < 788889600000 + and lineitem.l_discount >= 0.05 + and lineitem.l_discount <= 0.07 + and lineitem.l_quantity < 24 + ); diff --git a/test/src/test/resources/tpch/queries/q9.sql b/test/src/test/resources/tpch/queries/q9.sql new file mode 100644 index 0000000000..311fb02ad7 --- /dev/null +++ b/test/src/test/resources/tpch/queries/q9.sql @@ -0,0 +1,32 @@ +insert into tmpTableC(key, orderkey, year) values ( + select o_orderkey, extractYear(o_orderdate) from orders +); + +select * from ( + select + nation, + o_year, + sum(amount) as sum_profit + from ( + select + nation.n_name as nation, + tmpTableC.year as o_year, + lineitem.l_extendedprice * (1 - lineitem.l_discount) - partsupp.ps_supplycost * lineitem.l_quantity as amount + from + part + join lineitem on part.p_partkey = lineitem.l_partkey + join supplier on supplier.s_suppkey = lineitem.l_suppkey + join partsupp on partsupp.ps_suppkey = lineitem.l_suppkey and partsupp.ps_partkey = lineitem.l_partkey + join orders on orders.o_orderkey = lineitem.l_orderkey + join nation on supplier.s_nationkey = nation.n_nationkey + join tmpTableC on orders.o_orderkey = tmpTableC.orderkey + where + part.p_name like '.*green.*' + ) + group by + o_year, + nation + order by + o_year desc +) +order by nation; \ No newline at end of file diff --git a/test/src/test/resources/tpch/sf0.1/q1.csv b/test/src/test/resources/tpch/sf0.1/q1.csv new file mode 100644 index 0000000000..ac95c90db3 --- /dev/null +++ b/test/src/test/resources/tpch/sf0.1/q1.csv @@ -0,0 +1,5 @@ +l_returnflag|l_linestatus|sum_qty|sum_base_price|sum_disc_price|sum_charge|avg_qty|avg_price|avg_disc|count_order +A|F|3774200|5320753880.69|5054096266.6828|5256751331.449234|25.537587116854997|36002.12382901414|0.05014459706340077|147790 +N|F|95257|133737795.84|127132372.6512|132286291.229445|25.30066401062417|35521.32691633466|0.04939442231075697|3765 +N|O|7459297|10512270008.90|9986238338.3847|10385578376.585467|25.545537671232875|36000.9246880137|0.05009595890410959|292000 +R|F|3785523|5337950526.47|5071818532.9420|5274405503.049367|25.5259438574251|35994.029214030925|0.04998927856184382|148301 diff --git a/test/src/test/resources/tpch/sf0.1/q10.csv b/test/src/test/resources/tpch/sf0.1/q10.csv new file mode 100644 index 0000000000..79f006ddb9 --- /dev/null +++ b/test/src/test/resources/tpch/sf0.1/q10.csv @@ -0,0 +1,21 @@ +c_custkey|c_name|revenue|c_acctbal|n_name|c_address|c_phone|c_comment +8242|Customer#000008242|622786.7297|6322.09|ETHIOPIA|cYDWDiJt06B8CYzXX2L8x2hn1VFG|15-792-676-1184| regular theodolites affix. carefully ironic packages cajole deposits; slyly ironic packages wake quickly. regular, +7714|Customer#000007714|557400.3053|9799.98|IRAN|9DDikq08GEE4B3X|20-922-418-6024|even accounts should cajole. regular, regular +11032|Customer#000011032|512500.9641|8496.93|UNITED KINGDOM|5igjoUgXoDUZVUIectL5lXO1T3AGKza0ft|33-102-772-3533|uests. ironic accounts after the fluffily fi +2455|Customer#000002455|481592.4053|2070.99|GERMANY|a5DZ199yfAcFhfi2uwBE PKo,Z|17-946-225-9977|pinto beans alongside of the furiously ironic asymptotes are quickly even platelets: express +12106|Customer#000012106|479414.2133|5342.11|UNITED STATES|wyJXywcExUxt|34-905-346-4472|blithely blithely final attainments? carefully special pinto beans around the quickly even asymptote +8530|Customer#000008530|457855.9467|9734.95|MOROCCO|leatyNRWCnfTMnTNuDGHsWJjRuAX|25-736-932-5850| the carefully pending packages. carefully +13984|Customer#000013984|446316.5104|3482.28|IRAN|B13vxRBojwvP3|20-981-264-2952|egular, ironic accounts integrate sly +1966|Customer#000001966|444059.0382|1937.72|ALGERIA|IbwZr7j QVifqf9WizOIWx,UXV9CqxUyrwj|10-973-269-8886|odolites across the unusual accounts hang carefully furiously bold excuses. regular pi +11026|Customer#000011026|417913.4142|7738.76|ALGERIA|4C iGzChcqnhGBdeeu|10-184-163-4632|eposits cajole according to the furiously bold instructions. regular, regular dependencies wake carefully eve +8501|Customer#000008501|412797.5100|6906.70|ARGENTINA|UTUQLX cQrF1UUJPsz|11-317-552-5840| packages. pending Tiresias after the regularly express forges haggle fina +1565|Customer#000001565|412506.0062|1820.03|BRAZIL|n4acVpG0Deyj5aIFAfSNg Iu9cUagwN3OsRbKC 4|12-402-178-2007|deposits; unusual, bold deposits around the f +14398|Customer#000014398|408575.3600|-602.24|UNITED STATES|l49oKjbjQHz6YZwjo5wPihM lyYO6G|34-814-111-5424|es haggle fluffily blithely fluffy requests; slyly express req +1465|Customer#000001465|405055.3457|9365.93|INDIA|zn9Q7pT6KlQp3T5mUO533aq,|18-807-487-1074|ress ideas cajole. slyly unusual theodolites cajole thin foxes. account +12595|Customer#000012595|401402.2391|-6.92|INDIA|gEMQ3WO90vSdAgxLFrt9FRS|18-186-132-3352| slyly dogged excuses. blithely blithe packages cajole +961|Customer#000000961|401198.1737|6963.68|JAPAN|W0SZ2oflx9aWTggtwSk3OEIXsubXTbGbD|22-989-463-6089|use furiously across the final deposits. quickly +14299|Customer#000014299|400968.3751|6595.97|RUSSIA|UFlOs8tQ,IfZPJm57|32-156-618-1224|slyly. ironic, bold deposits sleep blithely ironic, pending attainm +623|Customer#000000623|399883.4257|7887.60|INDONESIA|k3IlPSC4FKB13 hc6omhVs1ibvqeWEV|19-113-202-7085|se around the ideas. accounts cajole blithely slyly ironic requests. b +9151|Customer#000009151|396562.0295|5691.95|IRAQ|UKiN9OQupR,m5NtvSntbI8JBeo|21-834-147-4906|the deposits. pending, ironic foxes haggle along the regular, bold req +14819|Customer#000014819|396271.1036|7308.39|FRANCE|wS8yiQtE63FfoO6RKUzuVf6iBTmXBq16u|16-769-398-7926|ending asymptotes use fluffily quickly bold instructions. slyly bold dependencies sleep carefully pending a +13478|Customer#000013478|395513.1358|-778.11|KENYA|S5izwjM1 hCoUccO2JMepYwNyBSqI,ay|24-983-202-8240| requests boost quickly according to the express sheaves. blithely unusual packages sleep diff --git a/test/src/test/resources/tpch/sf0.1/q13.csv b/test/src/test/resources/tpch/sf0.1/q13.csv new file mode 100644 index 0000000000..d3f05df8a6 --- /dev/null +++ b/test/src/test/resources/tpch/sf0.1/q13.csv @@ -0,0 +1,38 @@ +c_count|custdist +0|5000 +9|659 +10|658 +11|643 +8|555 +12|542 +13|508 +7|494 +19|471 +20|464 +14|451 +17|449 +18|448 +15|446 +16|425 +21|406 +22|351 +6|334 +23|331 +24|278 +5|197 +25|184 +26|175 +27|136 +4|90 +28|86 +29|63 +3|45 +30|36 +31|26 +32|13 +2|12 +33|11 +34|5 +35|4 +36|2 +1|2 diff --git a/test/src/test/resources/tpch/sf0.1/q16.csv b/test/src/test/resources/tpch/sf0.1/q16.csv new file mode 100644 index 0000000000..23f2fa9b13 --- /dev/null +++ b/test/src/test/resources/tpch/sf0.1/q16.csv @@ -0,0 +1,2763 @@ +p_brand|p_type|p_size|supplier_cnt +Brand#14|SMALL ANODIZED NICKEL|45|12 +Brand#22|SMALL BURNISHED BRASS|19|12 +Brand#25|PROMO POLISHED COPPER|14|12 +Brand#35|LARGE ANODIZED STEEL|45|12 +Brand#35|PROMO BRUSHED COPPER|9|12 +Brand#51|ECONOMY ANODIZED STEEL|9|12 +Brand#53|LARGE BRUSHED NICKEL|45|12 +Brand#11|ECONOMY POLISHED COPPER|14|8 +Brand#11|LARGE PLATED STEEL|23|8 +Brand#11|PROMO POLISHED STEEL|23|8 +Brand#11|STANDARD ANODIZED COPPER|9|8 +Brand#12|ECONOMY BURNISHED BRASS|9|8 +Brand#12|LARGE ANODIZED BRASS|14|8 +Brand#12|SMALL ANODIZED TIN|23|8 +Brand#12|SMALL BRUSHED NICKEL|23|8 +Brand#12|STANDARD ANODIZED BRASS|3|8 +Brand#12|STANDARD BURNISHED TIN|23|8 +Brand#13|ECONOMY POLISHED BRASS|9|8 +Brand#13|LARGE BURNISHED COPPER|45|8 +Brand#13|MEDIUM ANODIZED STEEL|23|8 +Brand#13|MEDIUM PLATED NICKEL|3|8 +Brand#13|PROMO BURNISHED BRASS|9|8 +Brand#13|PROMO POLISHED BRASS|3|8 +Brand#13|PROMO POLISHED TIN|36|8 +Brand#13|SMALL BURNISHED STEEL|23|8 +Brand#13|STANDARD BRUSHED STEEL|9|8 +Brand#14|ECONOMY BRUSHED TIN|3|8 +Brand#14|ECONOMY BURNISHED TIN|23|8 +Brand#14|PROMO BRUSHED STEEL|9|8 +Brand#14|PROMO PLATED TIN|45|8 +Brand#15|ECONOMY PLATED TIN|9|8 +Brand#15|STANDARD BRUSHED COPPER|14|8 +Brand#15|STANDARD PLATED TIN|3|8 +Brand#21|ECONOMY POLISHED TIN|3|8 +Brand#21|PROMO POLISHED COPPER|9|8 +Brand#21|PROMO POLISHED TIN|49|8 +Brand#21|SMALL POLISHED STEEL|3|8 +Brand#21|STANDARD PLATED BRASS|49|8 +Brand#21|STANDARD PLATED NICKEL|49|8 +Brand#22|ECONOMY ANODIZED TIN|49|8 +Brand#22|ECONOMY BRUSHED BRASS|14|8 +Brand#22|LARGE BURNISHED TIN|36|8 +Brand#22|MEDIUM ANODIZED STEEL|36|8 +Brand#22|MEDIUM PLATED STEEL|9|8 +Brand#22|PROMO POLISHED NICKEL|9|8 +Brand#22|SMALL ANODIZED STEEL|19|8 +Brand#22|STANDARD ANODIZED COPPER|23|8 +Brand#23|ECONOMY BRUSHED NICKEL|23|8 +Brand#23|LARGE ANODIZED BRASS|9|8 +Brand#23|LARGE ANODIZED STEEL|23|8 +Brand#23|SMALL BRUSHED COPPER|23|8 +Brand#23|STANDARD BRUSHED TIN|3|8 +Brand#23|STANDARD BURNISHED NICKEL|49|8 +Brand#23|STANDARD PLATED NICKEL|36|8 +Brand#24|ECONOMY ANODIZED BRASS|19|8 +Brand#24|ECONOMY POLISHED BRASS|36|8 +Brand#24|LARGE BURNISHED STEEL|14|8 +Brand#24|MEDIUM PLATED NICKEL|36|8 +Brand#25|ECONOMY BRUSHED STEEL|49|8 +Brand#25|MEDIUM BURNISHED TIN|3|8 +Brand#25|PROMO ANODIZED TIN|36|8 +Brand#25|PROMO PLATED NICKEL|3|8 +Brand#25|SMALL BURNISHED BRASS|3|8 +Brand#31|LARGE ANODIZED BRASS|3|8 +Brand#31|SMALL ANODIZED COPPER|3|8 +Brand#31|SMALL ANODIZED NICKEL|9|8 +Brand#31|SMALL ANODIZED STEEL|14|8 +Brand#32|MEDIUM ANODIZED STEEL|49|8 +Brand#32|MEDIUM BURNISHED COPPER|19|8 +Brand#32|SMALL BURNISHED STEEL|23|8 +Brand#32|STANDARD BURNISHED STEEL|45|8 +Brand#34|ECONOMY ANODIZED NICKEL|49|8 +Brand#34|LARGE BURNISHED TIN|49|8 +Brand#34|MEDIUM BURNISHED NICKEL|3|8 +Brand#34|PROMO ANODIZED TIN|3|8 +Brand#34|SMALL BRUSHED TIN|3|8 +Brand#34|STANDARD BURNISHED TIN|23|8 +Brand#35|MEDIUM BRUSHED STEEL|45|8 +Brand#35|PROMO BURNISHED STEEL|14|8 +Brand#35|SMALL BURNISHED STEEL|23|8 +Brand#35|SMALL POLISHED COPPER|14|8 +Brand#35|STANDARD PLATED COPPER|9|8 +Brand#41|ECONOMY BRUSHED BRASS|23|8 +Brand#41|LARGE BURNISHED STEEL|23|8 +Brand#41|PROMO BURNISHED TIN|14|8 +Brand#41|PROMO PLATED STEEL|36|8 +Brand#41|PROMO POLISHED TIN|19|8 +Brand#41|SMALL BURNISHED COPPER|23|8 +Brand#42|LARGE POLISHED TIN|14|8 +Brand#42|MEDIUM ANODIZED TIN|49|8 +Brand#42|MEDIUM BRUSHED TIN|14|8 +Brand#42|MEDIUM BURNISHED NICKEL|23|8 +Brand#42|MEDIUM PLATED COPPER|45|8 +Brand#42|MEDIUM PLATED TIN|45|8 +Brand#42|SMALL PLATED COPPER|36|8 +Brand#43|ECONOMY BRUSHED STEEL|45|8 +Brand#43|LARGE BRUSHED COPPER|19|8 +Brand#43|PROMO BRUSHED BRASS|36|8 +Brand#43|SMALL BURNISHED TIN|45|8 +Brand#43|SMALL PLATED COPPER|45|8 +Brand#44|PROMO POLISHED TIN|23|8 +Brand#44|SMALL POLISHED NICKEL|14|8 +Brand#44|SMALL POLISHED TIN|45|8 +Brand#44|STANDARD BURNISHED COPPER|3|8 +Brand#51|LARGE ANODIZED BRASS|19|8 +Brand#51|LARGE POLISHED COPPER|23|8 +Brand#51|MEDIUM ANODIZED TIN|9|8 +Brand#51|MEDIUM ANODIZED TIN|14|8 +Brand#51|MEDIUM BURNISHED NICKEL|23|8 +Brand#51|SMALL ANODIZED COPPER|45|8 +Brand#51|SMALL ANODIZED COPPER|49|8 +Brand#51|SMALL BRUSHED COPPER|45|8 +Brand#51|SMALL BRUSHED TIN|36|8 +Brand#51|STANDARD POLISHED TIN|3|8 +Brand#52|ECONOMY ANODIZED STEEL|3|8 +Brand#52|ECONOMY PLATED TIN|19|8 +Brand#52|LARGE PLATED TIN|3|8 +Brand#52|MEDIUM ANODIZED TIN|19|8 +Brand#52|MEDIUM BURNISHED COPPER|3|8 +Brand#52|PROMO POLISHED BRASS|23|8 +Brand#52|SMALL PLATED COPPER|36|8 +Brand#52|SMALL POLISHED NICKEL|9|8 +Brand#52|STANDARD POLISHED NICKEL|45|8 +Brand#53|ECONOMY POLISHED STEEL|45|8 +Brand#53|LARGE POLISHED NICKEL|3|8 +Brand#53|SMALL BRUSHED COPPER|14|8 +Brand#53|STANDARD PLATED STEEL|45|8 +Brand#54|ECONOMY POLISHED BRASS|49|8 +Brand#54|ECONOMY POLISHED TIN|23|8 +Brand#54|LARGE ANODIZED NICKEL|49|8 +Brand#54|MEDIUM BRUSHED STEEL|9|8 +Brand#54|SMALL BURNISHED NICKEL|14|8 +Brand#54|SMALL PLATED TIN|14|8 +Brand#54|STANDARD BURNISHED STEEL|14|8 +Brand#54|STANDARD PLATED BRASS|23|8 +Brand#55|MEDIUM BURNISHED TIN|36|8 +Brand#55|PROMO ANODIZED BRASS|14|8 +Brand#55|STANDARD BURNISHED COPPER|45|8 +Brand#15|STANDARD PLATED TIN|36|7 +Brand#23|SMALL POLISHED BRASS|49|7 +Brand#42|STANDARD PLATED COPPER|19|7 +Brand#51|LARGE POLISHED NICKEL|14|7 +Brand#11|ECONOMY ANODIZED BRASS|19|4 +Brand#11|ECONOMY ANODIZED BRASS|45|4 +Brand#11|ECONOMY ANODIZED NICKEL|36|4 +Brand#11|ECONOMY BRUSHED COPPER|3|4 +Brand#11|ECONOMY BRUSHED COPPER|9|4 +Brand#11|ECONOMY BRUSHED STEEL|9|4 +Brand#11|ECONOMY BRUSHED STEEL|36|4 +Brand#11|ECONOMY BURNISHED BRASS|36|4 +Brand#11|ECONOMY BURNISHED COPPER|9|4 +Brand#11|ECONOMY BURNISHED COPPER|49|4 +Brand#11|ECONOMY BURNISHED NICKEL|14|4 +Brand#11|ECONOMY BURNISHED NICKEL|49|4 +Brand#11|ECONOMY PLATED COPPER|19|4 +Brand#11|ECONOMY PLATED NICKEL|45|4 +Brand#11|ECONOMY PLATED TIN|9|4 +Brand#11|ECONOMY POLISHED BRASS|3|4 +Brand#11|ECONOMY POLISHED COPPER|3|4 +Brand#11|ECONOMY POLISHED COPPER|45|4 +Brand#11|ECONOMY POLISHED NICKEL|36|4 +Brand#11|ECONOMY POLISHED STEEL|23|4 +Brand#11|ECONOMY POLISHED TIN|14|4 +Brand#11|LARGE ANODIZED COPPER|23|4 +Brand#11|LARGE ANODIZED NICKEL|9|4 +Brand#11|LARGE ANODIZED STEEL|9|4 +Brand#11|LARGE ANODIZED TIN|45|4 +Brand#11|LARGE BRUSHED STEEL|19|4 +Brand#11|LARGE BRUSHED TIN|3|4 +Brand#11|LARGE BRUSHED TIN|14|4 +Brand#11|LARGE BURNISHED COPPER|9|4 +Brand#11|LARGE BURNISHED COPPER|19|4 +Brand#11|LARGE BURNISHED STEEL|23|4 +Brand#11|LARGE BURNISHED TIN|9|4 +Brand#11|LARGE PLATED COPPER|23|4 +Brand#11|LARGE PLATED TIN|9|4 +Brand#11|LARGE PLATED TIN|14|4 +Brand#11|LARGE PLATED TIN|23|4 +Brand#11|LARGE POLISHED NICKEL|49|4 +Brand#11|MEDIUM ANODIZED BRASS|45|4 +Brand#11|MEDIUM ANODIZED TIN|14|4 +Brand#11|MEDIUM BRUSHED BRASS|14|4 +Brand#11|MEDIUM BRUSHED BRASS|45|4 +Brand#11|MEDIUM BRUSHED NICKEL|14|4 +Brand#11|MEDIUM BRUSHED NICKEL|36|4 +Brand#11|MEDIUM BRUSHED STEEL|19|4 +Brand#11|MEDIUM BURNISHED COPPER|9|4 +Brand#11|MEDIUM BURNISHED TIN|36|4 +Brand#11|MEDIUM PLATED BRASS|3|4 +Brand#11|MEDIUM PLATED TIN|19|4 +Brand#11|PROMO ANODIZED BRASS|3|4 +Brand#11|PROMO ANODIZED BRASS|19|4 +Brand#11|PROMO ANODIZED BRASS|45|4 +Brand#11|PROMO ANODIZED BRASS|49|4 +Brand#11|PROMO ANODIZED STEEL|23|4 +Brand#11|PROMO ANODIZED TIN|45|4 +Brand#11|PROMO BRUSHED BRASS|23|4 +Brand#11|PROMO BRUSHED STEEL|3|4 +Brand#11|PROMO BURNISHED BRASS|23|4 +Brand#11|PROMO BURNISHED BRASS|36|4 +Brand#11|PROMO BURNISHED BRASS|49|4 +Brand#11|PROMO BURNISHED TIN|9|4 +Brand#11|PROMO PLATED BRASS|9|4 +Brand#11|PROMO PLATED BRASS|45|4 +Brand#11|PROMO PLATED NICKEL|19|4 +Brand#11|PROMO POLISHED BRASS|3|4 +Brand#11|PROMO POLISHED BRASS|9|4 +Brand#11|PROMO POLISHED BRASS|19|4 +Brand#11|PROMO POLISHED COPPER|14|4 +Brand#11|PROMO POLISHED COPPER|45|4 +Brand#11|PROMO POLISHED TIN|49|4 +Brand#11|SMALL ANODIZED COPPER|36|4 +Brand#11|SMALL ANODIZED NICKEL|3|4 +Brand#11|SMALL ANODIZED NICKEL|14|4 +Brand#11|SMALL ANODIZED TIN|14|4 +Brand#11|SMALL ANODIZED TIN|19|4 +Brand#11|SMALL ANODIZED TIN|45|4 +Brand#11|SMALL BRUSHED TIN|14|4 +Brand#11|SMALL BRUSHED TIN|23|4 +Brand#11|SMALL BRUSHED TIN|45|4 +Brand#11|SMALL BURNISHED BRASS|49|4 +Brand#11|SMALL BURNISHED COPPER|23|4 +Brand#11|SMALL PLATED COPPER|45|4 +Brand#11|SMALL PLATED NICKEL|3|4 +Brand#11|SMALL PLATED STEEL|36|4 +Brand#11|SMALL PLATED TIN|19|4 +Brand#11|SMALL POLISHED BRASS|14|4 +Brand#11|SMALL POLISHED BRASS|23|4 +Brand#11|SMALL POLISHED COPPER|14|4 +Brand#11|SMALL POLISHED COPPER|36|4 +Brand#11|SMALL POLISHED STEEL|9|4 +Brand#11|STANDARD BRUSHED COPPER|23|4 +Brand#11|STANDARD BRUSHED NICKEL|14|4 +Brand#11|STANDARD BRUSHED TIN|14|4 +Brand#11|STANDARD BURNISHED BRASS|3|4 +Brand#11|STANDARD BURNISHED STEEL|23|4 +Brand#11|STANDARD PLATED BRASS|19|4 +Brand#11|STANDARD PLATED TIN|19|4 +Brand#11|STANDARD POLISHED NICKEL|45|4 +Brand#11|STANDARD POLISHED TIN|14|4 +Brand#11|STANDARD POLISHED TIN|45|4 +Brand#12|ECONOMY ANODIZED BRASS|23|4 +Brand#12|ECONOMY ANODIZED COPPER|14|4 +Brand#12|ECONOMY ANODIZED NICKEL|19|4 +Brand#12|ECONOMY ANODIZED NICKEL|45|4 +Brand#12|ECONOMY ANODIZED STEEL|9|4 +Brand#12|ECONOMY BRUSHED COPPER|36|4 +Brand#12|ECONOMY BRUSHED NICKEL|49|4 +Brand#12|ECONOMY BRUSHED STEEL|49|4 +Brand#12|ECONOMY BURNISHED COPPER|45|4 +Brand#12|ECONOMY PLATED COPPER|23|4 +Brand#12|ECONOMY PLATED STEEL|23|4 +Brand#12|ECONOMY PLATED TIN|36|4 +Brand#12|ECONOMY POLISHED BRASS|14|4 +Brand#12|ECONOMY POLISHED COPPER|45|4 +Brand#12|ECONOMY POLISHED NICKEL|9|4 +Brand#12|LARGE ANODIZED NICKEL|9|4 +Brand#12|LARGE ANODIZED NICKEL|49|4 +Brand#12|LARGE ANODIZED STEEL|49|4 +Brand#12|LARGE ANODIZED TIN|36|4 +Brand#12|LARGE ANODIZED TIN|45|4 +Brand#12|LARGE BURNISHED BRASS|14|4 +Brand#12|LARGE BURNISHED BRASS|19|4 +Brand#12|LARGE BURNISHED COPPER|9|4 +Brand#12|LARGE BURNISHED NICKEL|45|4 +Brand#12|LARGE BURNISHED TIN|36|4 +Brand#12|LARGE PLATED BRASS|3|4 +Brand#12|LARGE PLATED STEEL|36|4 +Brand#12|LARGE PLATED STEEL|45|4 +Brand#12|LARGE PLATED TIN|23|4 +Brand#12|LARGE POLISHED COPPER|14|4 +Brand#12|LARGE POLISHED COPPER|19|4 +Brand#12|LARGE POLISHED COPPER|49|4 +Brand#12|LARGE POLISHED STEEL|3|4 +Brand#12|MEDIUM ANODIZED COPPER|9|4 +Brand#12|MEDIUM ANODIZED COPPER|45|4 +Brand#12|MEDIUM ANODIZED NICKEL|45|4 +Brand#12|MEDIUM BRUSHED BRASS|19|4 +Brand#12|MEDIUM BRUSHED COPPER|9|4 +Brand#12|MEDIUM BRUSHED COPPER|36|4 +Brand#12|MEDIUM BRUSHED COPPER|49|4 +Brand#12|MEDIUM BRUSHED NICKEL|3|4 +Brand#12|MEDIUM BRUSHED NICKEL|14|4 +Brand#12|MEDIUM BRUSHED NICKEL|23|4 +Brand#12|MEDIUM BURNISHED BRASS|3|4 +Brand#12|MEDIUM BURNISHED COPPER|36|4 +Brand#12|MEDIUM BURNISHED NICKEL|19|4 +Brand#12|MEDIUM BURNISHED TIN|14|4 +Brand#12|MEDIUM PLATED BRASS|23|4 +Brand#12|MEDIUM PLATED TIN|19|4 +Brand#12|MEDIUM PLATED TIN|23|4 +Brand#12|MEDIUM PLATED TIN|49|4 +Brand#12|PROMO ANODIZED BRASS|9|4 +Brand#12|PROMO ANODIZED BRASS|45|4 +Brand#12|PROMO ANODIZED NICKEL|14|4 +Brand#12|PROMO ANODIZED STEEL|49|4 +Brand#12|PROMO ANODIZED TIN|3|4 +Brand#12|PROMO ANODIZED TIN|19|4 +Brand#12|PROMO BRUSHED COPPER|14|4 +Brand#12|PROMO BRUSHED COPPER|19|4 +Brand#12|PROMO BRUSHED NICKEL|23|4 +Brand#12|PROMO BRUSHED STEEL|23|4 +Brand#12|PROMO BRUSHED STEEL|36|4 +Brand#12|PROMO BURNISHED BRASS|49|4 +Brand#12|PROMO BURNISHED TIN|9|4 +Brand#12|PROMO BURNISHED TIN|14|4 +Brand#12|PROMO PLATED BRASS|36|4 +Brand#12|PROMO POLISHED COPPER|23|4 +Brand#12|PROMO POLISHED NICKEL|3|4 +Brand#12|PROMO POLISHED NICKEL|9|4 +Brand#12|PROMO POLISHED STEEL|14|4 +Brand#12|PROMO POLISHED TIN|23|4 +Brand#12|PROMO POLISHED TIN|36|4 +Brand#12|SMALL ANODIZED BRASS|36|4 +Brand#12|SMALL ANODIZED COPPER|23|4 +Brand#12|SMALL ANODIZED STEEL|36|4 +Brand#12|SMALL ANODIZED TIN|14|4 +Brand#12|SMALL BRUSHED COPPER|19|4 +Brand#12|SMALL BRUSHED COPPER|36|4 +Brand#12|SMALL BRUSHED TIN|36|4 +Brand#12|SMALL BURNISHED BRASS|14|4 +Brand#12|SMALL BURNISHED COPPER|9|4 +Brand#12|SMALL BURNISHED COPPER|36|4 +Brand#12|SMALL PLATED BRASS|9|4 +Brand#12|SMALL POLISHED BRASS|49|4 +Brand#12|SMALL POLISHED NICKEL|19|4 +Brand#12|SMALL POLISHED TIN|3|4 +Brand#12|STANDARD ANODIZED BRASS|19|4 +Brand#12|STANDARD ANODIZED NICKEL|19|4 +Brand#12|STANDARD ANODIZED STEEL|19|4 +Brand#12|STANDARD BRUSHED COPPER|36|4 +Brand#12|STANDARD BRUSHED NICKEL|23|4 +Brand#12|STANDARD BRUSHED STEEL|49|4 +Brand#12|STANDARD BURNISHED BRASS|23|4 +Brand#12|STANDARD BURNISHED COPPER|14|4 +Brand#12|STANDARD BURNISHED NICKEL|45|4 +Brand#12|STANDARD BURNISHED NICKEL|49|4 +Brand#12|STANDARD BURNISHED TIN|3|4 +Brand#12|STANDARD BURNISHED TIN|14|4 +Brand#12|STANDARD PLATED BRASS|19|4 +Brand#12|STANDARD PLATED NICKEL|45|4 +Brand#12|STANDARD PLATED STEEL|36|4 +Brand#12|STANDARD PLATED STEEL|45|4 +Brand#12|STANDARD PLATED TIN|9|4 +Brand#12|STANDARD POLISHED BRASS|49|4 +Brand#12|STANDARD POLISHED COPPER|3|4 +Brand#12|STANDARD POLISHED NICKEL|23|4 +Brand#12|STANDARD POLISHED TIN|14|4 +Brand#13|ECONOMY ANODIZED NICKEL|14|4 +Brand#13|ECONOMY ANODIZED NICKEL|19|4 +Brand#13|ECONOMY ANODIZED STEEL|45|4 +Brand#13|ECONOMY ANODIZED STEEL|49|4 +Brand#13|ECONOMY BRUSHED BRASS|3|4 +Brand#13|ECONOMY BURNISHED STEEL|14|4 +Brand#13|ECONOMY BURNISHED TIN|19|4 +Brand#13|ECONOMY BURNISHED TIN|45|4 +Brand#13|ECONOMY PLATED COPPER|19|4 +Brand#13|ECONOMY PLATED NICKEL|3|4 +Brand#13|ECONOMY PLATED STEEL|23|4 +Brand#13|ECONOMY PLATED TIN|3|4 +Brand#13|ECONOMY POLISHED BRASS|3|4 +Brand#13|ECONOMY POLISHED COPPER|9|4 +Brand#13|ECONOMY POLISHED COPPER|49|4 +Brand#13|ECONOMY POLISHED STEEL|23|4 +Brand#13|ECONOMY POLISHED STEEL|49|4 +Brand#13|LARGE ANODIZED BRASS|23|4 +Brand#13|LARGE ANODIZED COPPER|19|4 +Brand#13|LARGE ANODIZED NICKEL|9|4 +Brand#13|LARGE ANODIZED STEEL|45|4 +Brand#13|LARGE ANODIZED TIN|19|4 +Brand#13|LARGE BRUSHED BRASS|3|4 +Brand#13|LARGE BRUSHED BRASS|9|4 +Brand#13|LARGE BRUSHED BRASS|19|4 +Brand#13|LARGE BRUSHED COPPER|9|4 +Brand#13|LARGE BRUSHED COPPER|36|4 +Brand#13|LARGE BRUSHED NICKEL|3|4 +Brand#13|LARGE BRUSHED NICKEL|9|4 +Brand#13|LARGE BRUSHED NICKEL|14|4 +Brand#13|LARGE BRUSHED NICKEL|23|4 +Brand#13|LARGE BRUSHED STEEL|19|4 +Brand#13|LARGE BRUSHED TIN|49|4 +Brand#13|LARGE BURNISHED BRASS|49|4 +Brand#13|LARGE BURNISHED TIN|49|4 +Brand#13|LARGE PLATED COPPER|23|4 +Brand#13|LARGE PLATED STEEL|14|4 +Brand#13|LARGE PLATED STEEL|19|4 +Brand#13|LARGE PLATED STEEL|36|4 +Brand#13|LARGE PLATED TIN|14|4 +Brand#13|LARGE PLATED TIN|45|4 +Brand#13|LARGE POLISHED BRASS|3|4 +Brand#13|LARGE POLISHED BRASS|23|4 +Brand#13|LARGE POLISHED BRASS|49|4 +Brand#13|MEDIUM ANODIZED BRASS|3|4 +Brand#13|MEDIUM ANODIZED BRASS|36|4 +Brand#13|MEDIUM ANODIZED COPPER|14|4 +Brand#13|MEDIUM ANODIZED NICKEL|3|4 +Brand#13|MEDIUM ANODIZED STEEL|14|4 +Brand#13|MEDIUM ANODIZED STEEL|19|4 +Brand#13|MEDIUM ANODIZED STEEL|36|4 +Brand#13|MEDIUM BRUSHED BRASS|49|4 +Brand#13|MEDIUM BRUSHED COPPER|23|4 +Brand#13|MEDIUM BRUSHED NICKEL|45|4 +Brand#13|MEDIUM BURNISHED BRASS|9|4 +Brand#13|MEDIUM BURNISHED STEEL|19|4 +Brand#13|MEDIUM BURNISHED STEEL|49|4 +Brand#13|MEDIUM PLATED BRASS|3|4 +Brand#13|MEDIUM PLATED BRASS|23|4 +Brand#13|MEDIUM PLATED BRASS|36|4 +Brand#13|MEDIUM PLATED COPPER|19|4 +Brand#13|MEDIUM PLATED COPPER|23|4 +Brand#13|MEDIUM PLATED STEEL|3|4 +Brand#13|PROMO ANODIZED BRASS|14|4 +Brand#13|PROMO ANODIZED COPPER|9|4 +Brand#13|PROMO ANODIZED COPPER|45|4 +Brand#13|PROMO ANODIZED STEEL|23|4 +Brand#13|PROMO BRUSHED COPPER|49|4 +Brand#13|PROMO BURNISHED COPPER|19|4 +Brand#13|PROMO BURNISHED NICKEL|9|4 +Brand#13|PROMO BURNISHED STEEL|23|4 +Brand#13|PROMO BURNISHED STEEL|45|4 +Brand#13|PROMO BURNISHED TIN|19|4 +Brand#13|PROMO PLATED BRASS|14|4 +Brand#13|PROMO PLATED BRASS|19|4 +Brand#13|PROMO PLATED COPPER|3|4 +Brand#13|PROMO PLATED COPPER|19|4 +Brand#13|PROMO PLATED TIN|19|4 +Brand#13|PROMO POLISHED BRASS|49|4 +Brand#13|PROMO POLISHED STEEL|45|4 +Brand#13|PROMO POLISHED TIN|14|4 +Brand#13|SMALL ANODIZED STEEL|23|4 +Brand#13|SMALL ANODIZED TIN|3|4 +Brand#13|SMALL ANODIZED TIN|45|4 +Brand#13|SMALL BRUSHED COPPER|3|4 +Brand#13|SMALL BRUSHED NICKEL|19|4 +Brand#13|SMALL BRUSHED TIN|9|4 +Brand#13|SMALL BRUSHED TIN|45|4 +Brand#13|SMALL BURNISHED BRASS|19|4 +Brand#13|SMALL BURNISHED BRASS|45|4 +Brand#13|SMALL PLATED BRASS|9|4 +Brand#13|SMALL PLATED TIN|45|4 +Brand#13|SMALL POLISHED NICKEL|19|4 +Brand#13|SMALL POLISHED STEEL|49|4 +Brand#13|STANDARD ANODIZED COPPER|45|4 +Brand#13|STANDARD ANODIZED NICKEL|9|4 +Brand#13|STANDARD ANODIZED NICKEL|19|4 +Brand#13|STANDARD ANODIZED STEEL|14|4 +Brand#13|STANDARD ANODIZED TIN|9|4 +Brand#13|STANDARD ANODIZED TIN|36|4 +Brand#13|STANDARD BRUSHED BRASS|19|4 +Brand#13|STANDARD BRUSHED TIN|9|4 +Brand#13|STANDARD BURNISHED BRASS|9|4 +Brand#13|STANDARD BURNISHED BRASS|14|4 +Brand#13|STANDARD BURNISHED COPPER|45|4 +Brand#13|STANDARD PLATED BRASS|49|4 +Brand#13|STANDARD PLATED COPPER|19|4 +Brand#13|STANDARD PLATED NICKEL|23|4 +Brand#13|STANDARD PLATED TIN|9|4 +Brand#13|STANDARD POLISHED BRASS|49|4 +Brand#13|STANDARD POLISHED COPPER|9|4 +Brand#13|STANDARD POLISHED COPPER|49|4 +Brand#13|STANDARD POLISHED NICKEL|14|4 +Brand#13|STANDARD POLISHED NICKEL|19|4 +Brand#13|STANDARD POLISHED STEEL|23|4 +Brand#14|ECONOMY ANODIZED BRASS|19|4 +Brand#14|ECONOMY ANODIZED COPPER|9|4 +Brand#14|ECONOMY ANODIZED STEEL|19|4 +Brand#14|ECONOMY ANODIZED STEEL|45|4 +Brand#14|ECONOMY BRUSHED BRASS|19|4 +Brand#14|ECONOMY BRUSHED COPPER|45|4 +Brand#14|ECONOMY BRUSHED NICKEL|14|4 +Brand#14|ECONOMY BRUSHED TIN|14|4 +Brand#14|ECONOMY BURNISHED COPPER|9|4 +Brand#14|ECONOMY BURNISHED COPPER|19|4 +Brand#14|ECONOMY BURNISHED STEEL|36|4 +Brand#14|ECONOMY BURNISHED TIN|3|4 +Brand#14|ECONOMY PLATED BRASS|36|4 +Brand#14|ECONOMY PLATED COPPER|49|4 +Brand#14|ECONOMY PLATED STEEL|45|4 +Brand#14|ECONOMY PLATED TIN|9|4 +Brand#14|ECONOMY POLISHED COPPER|3|4 +Brand#14|ECONOMY POLISHED TIN|19|4 +Brand#14|LARGE ANODIZED COPPER|9|4 +Brand#14|LARGE ANODIZED COPPER|23|4 +Brand#14|LARGE ANODIZED NICKEL|3|4 +Brand#14|LARGE ANODIZED NICKEL|9|4 +Brand#14|LARGE ANODIZED NICKEL|19|4 +Brand#14|LARGE ANODIZED TIN|9|4 +Brand#14|LARGE BRUSHED COPPER|14|4 +Brand#14|LARGE BRUSHED NICKEL|45|4 +Brand#14|LARGE PLATED BRASS|3|4 +Brand#14|LARGE PLATED NICKEL|3|4 +Brand#14|LARGE PLATED NICKEL|14|4 +Brand#14|LARGE PLATED NICKEL|49|4 +Brand#14|LARGE PLATED TIN|49|4 +Brand#14|LARGE POLISHED BRASS|9|4 +Brand#14|LARGE POLISHED BRASS|14|4 +Brand#14|LARGE POLISHED BRASS|36|4 +Brand#14|LARGE POLISHED NICKEL|3|4 +Brand#14|LARGE POLISHED NICKEL|14|4 +Brand#14|LARGE POLISHED STEEL|9|4 +Brand#14|LARGE POLISHED STEEL|23|4 +Brand#14|LARGE POLISHED STEEL|36|4 +Brand#14|MEDIUM ANODIZED NICKEL|3|4 +Brand#14|MEDIUM ANODIZED NICKEL|49|4 +Brand#14|MEDIUM ANODIZED STEEL|23|4 +Brand#14|MEDIUM ANODIZED STEEL|36|4 +Brand#14|MEDIUM BRUSHED BRASS|9|4 +Brand#14|MEDIUM BRUSHED COPPER|23|4 +Brand#14|MEDIUM BRUSHED STEEL|14|4 +Brand#14|MEDIUM BURNISHED COPPER|14|4 +Brand#14|MEDIUM BURNISHED STEEL|3|4 +Brand#14|MEDIUM BURNISHED STEEL|49|4 +Brand#14|MEDIUM PLATED BRASS|36|4 +Brand#14|MEDIUM PLATED STEEL|49|4 +Brand#14|MEDIUM PLATED TIN|14|4 +Brand#14|PROMO ANODIZED BRASS|49|4 +Brand#14|PROMO ANODIZED STEEL|36|4 +Brand#14|PROMO BRUSHED STEEL|19|4 +Brand#14|PROMO BURNISHED BRASS|23|4 +Brand#14|PROMO BURNISHED STEEL|36|4 +Brand#14|PROMO PLATED BRASS|9|4 +Brand#14|PROMO PLATED BRASS|45|4 +Brand#14|PROMO PLATED COPPER|45|4 +Brand#14|PROMO PLATED STEEL|3|4 +Brand#14|PROMO POLISHED BRASS|9|4 +Brand#14|PROMO POLISHED COPPER|49|4 +Brand#14|PROMO POLISHED STEEL|19|4 +Brand#14|SMALL ANODIZED STEEL|23|4 +Brand#14|SMALL ANODIZED TIN|23|4 +Brand#14|SMALL BRUSHED BRASS|19|4 +Brand#14|SMALL BRUSHED BRASS|36|4 +Brand#14|SMALL BRUSHED COPPER|9|4 +Brand#14|SMALL BRUSHED TIN|36|4 +Brand#14|SMALL BURNISHED BRASS|45|4 +Brand#14|SMALL BURNISHED COPPER|9|4 +Brand#14|SMALL BURNISHED COPPER|14|4 +Brand#14|SMALL BURNISHED COPPER|45|4 +Brand#14|SMALL BURNISHED NICKEL|36|4 +Brand#14|SMALL BURNISHED STEEL|36|4 +Brand#14|SMALL BURNISHED TIN|23|4 +Brand#14|SMALL PLATED NICKEL|3|4 +Brand#14|SMALL PLATED NICKEL|9|4 +Brand#14|SMALL PLATED STEEL|14|4 +Brand#14|SMALL POLISHED BRASS|36|4 +Brand#14|SMALL POLISHED COPPER|36|4 +Brand#14|SMALL POLISHED NICKEL|9|4 +Brand#14|SMALL POLISHED STEEL|14|4 +Brand#14|SMALL POLISHED TIN|14|4 +Brand#14|STANDARD ANODIZED BRASS|19|4 +Brand#14|STANDARD ANODIZED NICKEL|14|4 +Brand#14|STANDARD ANODIZED STEEL|9|4 +Brand#14|STANDARD BRUSHED COPPER|45|4 +Brand#14|STANDARD BRUSHED NICKEL|45|4 +Brand#14|STANDARD BRUSHED TIN|45|4 +Brand#14|STANDARD BURNISHED BRASS|9|4 +Brand#14|STANDARD BURNISHED BRASS|23|4 +Brand#14|STANDARD BURNISHED BRASS|49|4 +Brand#14|STANDARD BURNISHED NICKEL|9|4 +Brand#14|STANDARD PLATED BRASS|36|4 +Brand#14|STANDARD PLATED COPPER|45|4 +Brand#14|STANDARD POLISHED NICKEL|3|4 +Brand#14|STANDARD POLISHED NICKEL|9|4 +Brand#14|STANDARD POLISHED TIN|19|4 +Brand#15|ECONOMY ANODIZED COPPER|14|4 +Brand#15|ECONOMY ANODIZED STEEL|19|4 +Brand#15|ECONOMY ANODIZED STEEL|36|4 +Brand#15|ECONOMY BRUSHED BRASS|36|4 +Brand#15|ECONOMY BRUSHED COPPER|14|4 +Brand#15|ECONOMY BRUSHED NICKEL|14|4 +Brand#15|ECONOMY BRUSHED STEEL|3|4 +Brand#15|ECONOMY BRUSHED TIN|3|4 +Brand#15|ECONOMY BURNISHED BRASS|14|4 +Brand#15|ECONOMY BURNISHED COPPER|3|4 +Brand#15|ECONOMY BURNISHED COPPER|23|4 +Brand#15|ECONOMY PLATED NICKEL|49|4 +Brand#15|ECONOMY PLATED STEEL|3|4 +Brand#15|ECONOMY PLATED STEEL|19|4 +Brand#15|ECONOMY PLATED STEEL|45|4 +Brand#15|LARGE ANODIZED BRASS|19|4 +Brand#15|LARGE ANODIZED BRASS|36|4 +Brand#15|LARGE ANODIZED BRASS|45|4 +Brand#15|LARGE ANODIZED COPPER|3|4 +Brand#15|LARGE ANODIZED NICKEL|9|4 +Brand#15|LARGE ANODIZED TIN|19|4 +Brand#15|LARGE BRUSHED BRASS|9|4 +Brand#15|LARGE BRUSHED BRASS|19|4 +Brand#15|LARGE BRUSHED COPPER|14|4 +Brand#15|LARGE BRUSHED STEEL|9|4 +Brand#15|LARGE BRUSHED STEEL|14|4 +Brand#15|LARGE BRUSHED STEEL|19|4 +Brand#15|LARGE BRUSHED STEEL|36|4 +Brand#15|LARGE BURNISHED BRASS|14|4 +Brand#15|LARGE BURNISHED BRASS|19|4 +Brand#15|LARGE BURNISHED COPPER|9|4 +Brand#15|LARGE BURNISHED COPPER|45|4 +Brand#15|LARGE BURNISHED TIN|49|4 +Brand#15|LARGE PLATED BRASS|19|4 +Brand#15|LARGE PLATED COPPER|3|4 +Brand#15|LARGE PLATED COPPER|23|4 +Brand#15|LARGE PLATED NICKEL|36|4 +Brand#15|MEDIUM ANODIZED BRASS|23|4 +Brand#15|MEDIUM ANODIZED COPPER|9|4 +Brand#15|MEDIUM ANODIZED NICKEL|3|4 +Brand#15|MEDIUM ANODIZED TIN|19|4 +Brand#15|MEDIUM BRUSHED BRASS|9|4 +Brand#15|MEDIUM BRUSHED TIN|23|4 +Brand#15|MEDIUM BURNISHED COPPER|36|4 +Brand#15|MEDIUM BURNISHED TIN|45|4 +Brand#15|MEDIUM PLATED COPPER|9|4 +Brand#15|MEDIUM PLATED NICKEL|9|4 +Brand#15|MEDIUM PLATED NICKEL|19|4 +Brand#15|MEDIUM PLATED STEEL|36|4 +Brand#15|MEDIUM PLATED STEEL|49|4 +Brand#15|MEDIUM PLATED TIN|9|4 +Brand#15|MEDIUM PLATED TIN|14|4 +Brand#15|MEDIUM PLATED TIN|23|4 +Brand#15|PROMO ANODIZED COPPER|23|4 +Brand#15|PROMO ANODIZED STEEL|14|4 +Brand#15|PROMO ANODIZED TIN|45|4 +Brand#15|PROMO BRUSHED COPPER|14|4 +Brand#15|PROMO BRUSHED COPPER|19|4 +Brand#15|PROMO BRUSHED NICKEL|19|4 +Brand#15|PROMO BRUSHED NICKEL|23|4 +Brand#15|PROMO BRUSHED STEEL|14|4 +Brand#15|PROMO BRUSHED TIN|36|4 +Brand#15|PROMO BURNISHED NICKEL|9|4 +Brand#15|PROMO BURNISHED STEEL|45|4 +Brand#15|PROMO PLATED COPPER|3|4 +Brand#15|PROMO PLATED COPPER|36|4 +Brand#15|PROMO PLATED STEEL|3|4 +Brand#15|PROMO PLATED TIN|49|4 +Brand#15|PROMO POLISHED COPPER|3|4 +Brand#15|PROMO POLISHED NICKEL|36|4 +Brand#15|PROMO POLISHED STEEL|36|4 +Brand#15|PROMO POLISHED TIN|49|4 +Brand#15|SMALL ANODIZED BRASS|14|4 +Brand#15|SMALL ANODIZED BRASS|19|4 +Brand#15|SMALL ANODIZED COPPER|9|4 +Brand#15|SMALL ANODIZED TIN|45|4 +Brand#15|SMALL BRUSHED BRASS|3|4 +Brand#15|SMALL BRUSHED COPPER|19|4 +Brand#15|SMALL BRUSHED STEEL|23|4 +Brand#15|SMALL BRUSHED TIN|45|4 +Brand#15|SMALL BURNISHED BRASS|19|4 +Brand#15|SMALL BURNISHED COPPER|14|4 +Brand#15|SMALL BURNISHED NICKEL|19|4 +Brand#15|SMALL BURNISHED NICKEL|49|4 +Brand#15|SMALL BURNISHED STEEL|9|4 +Brand#15|SMALL BURNISHED TIN|19|4 +Brand#15|SMALL BURNISHED TIN|23|4 +Brand#15|SMALL BURNISHED TIN|36|4 +Brand#15|SMALL PLATED BRASS|3|4 +Brand#15|SMALL PLATED COPPER|23|4 +Brand#15|SMALL PLATED COPPER|49|4 +Brand#15|SMALL PLATED NICKEL|36|4 +Brand#15|SMALL PLATED NICKEL|45|4 +Brand#15|SMALL PLATED STEEL|3|4 +Brand#15|SMALL PLATED TIN|9|4 +Brand#15|SMALL POLISHED COPPER|9|4 +Brand#15|SMALL POLISHED NICKEL|3|4 +Brand#15|SMALL POLISHED STEEL|19|4 +Brand#15|SMALL POLISHED STEEL|36|4 +Brand#15|SMALL POLISHED TIN|19|4 +Brand#15|SMALL POLISHED TIN|49|4 +Brand#15|STANDARD ANODIZED NICKEL|19|4 +Brand#15|STANDARD ANODIZED NICKEL|49|4 +Brand#15|STANDARD ANODIZED TIN|36|4 +Brand#15|STANDARD BRUSHED NICKEL|3|4 +Brand#15|STANDARD BURNISHED BRASS|23|4 +Brand#15|STANDARD BURNISHED STEEL|3|4 +Brand#15|STANDARD BURNISHED STEEL|45|4 +Brand#15|STANDARD PLATED BRASS|36|4 +Brand#15|STANDARD PLATED COPPER|14|4 +Brand#15|STANDARD PLATED COPPER|23|4 +Brand#15|STANDARD PLATED NICKEL|19|4 +Brand#15|STANDARD PLATED TIN|45|4 +Brand#15|STANDARD POLISHED BRASS|14|4 +Brand#15|STANDARD POLISHED COPPER|23|4 +Brand#15|STANDARD POLISHED NICKEL|45|4 +Brand#21|ECONOMY ANODIZED BRASS|3|4 +Brand#21|ECONOMY ANODIZED NICKEL|14|4 +Brand#21|ECONOMY ANODIZED STEEL|19|4 +Brand#21|ECONOMY ANODIZED STEEL|23|4 +Brand#21|ECONOMY ANODIZED STEEL|49|4 +Brand#21|ECONOMY ANODIZED TIN|19|4 +Brand#21|ECONOMY BRUSHED BRASS|9|4 +Brand#21|ECONOMY BRUSHED BRASS|14|4 +Brand#21|ECONOMY BRUSHED BRASS|36|4 +Brand#21|ECONOMY BRUSHED COPPER|49|4 +Brand#21|ECONOMY BRUSHED STEEL|45|4 +Brand#21|ECONOMY BRUSHED TIN|49|4 +Brand#21|ECONOMY BURNISHED BRASS|3|4 +Brand#21|ECONOMY BURNISHED COPPER|45|4 +Brand#21|ECONOMY BURNISHED STEEL|19|4 +Brand#21|ECONOMY BURNISHED STEEL|36|4 +Brand#21|ECONOMY PLATED BRASS|36|4 +Brand#21|ECONOMY PLATED COPPER|3|4 +Brand#21|ECONOMY PLATED COPPER|14|4 +Brand#21|ECONOMY PLATED NICKEL|49|4 +Brand#21|ECONOMY POLISHED NICKEL|3|4 +Brand#21|ECONOMY POLISHED NICKEL|9|4 +Brand#21|LARGE ANODIZED COPPER|3|4 +Brand#21|LARGE ANODIZED COPPER|9|4 +Brand#21|LARGE ANODIZED STEEL|36|4 +Brand#21|LARGE ANODIZED TIN|45|4 +Brand#21|LARGE BRUSHED COPPER|45|4 +Brand#21|LARGE BRUSHED STEEL|23|4 +Brand#21|LARGE BURNISHED BRASS|49|4 +Brand#21|LARGE BURNISHED COPPER|19|4 +Brand#21|LARGE BURNISHED STEEL|49|4 +Brand#21|LARGE BURNISHED TIN|49|4 +Brand#21|LARGE PLATED BRASS|19|4 +Brand#21|LARGE PLATED NICKEL|23|4 +Brand#21|LARGE PLATED NICKEL|49|4 +Brand#21|LARGE PLATED TIN|19|4 +Brand#21|LARGE POLISHED BRASS|49|4 +Brand#21|LARGE POLISHED COPPER|14|4 +Brand#21|LARGE POLISHED NICKEL|3|4 +Brand#21|LARGE POLISHED NICKEL|14|4 +Brand#21|LARGE POLISHED STEEL|14|4 +Brand#21|LARGE POLISHED TIN|49|4 +Brand#21|MEDIUM ANODIZED COPPER|14|4 +Brand#21|MEDIUM ANODIZED NICKEL|49|4 +Brand#21|MEDIUM BRUSHED COPPER|3|4 +Brand#21|MEDIUM BRUSHED COPPER|49|4 +Brand#21|MEDIUM BRUSHED STEEL|23|4 +Brand#21|MEDIUM BRUSHED TIN|3|4 +Brand#21|MEDIUM BRUSHED TIN|14|4 +Brand#21|MEDIUM BURNISHED NICKEL|14|4 +Brand#21|MEDIUM BURNISHED STEEL|23|4 +Brand#21|MEDIUM BURNISHED TIN|3|4 +Brand#21|MEDIUM PLATED BRASS|3|4 +Brand#21|MEDIUM PLATED BRASS|19|4 +Brand#21|MEDIUM PLATED STEEL|36|4 +Brand#21|PROMO ANODIZED BRASS|9|4 +Brand#21|PROMO ANODIZED COPPER|14|4 +Brand#21|PROMO ANODIZED NICKEL|23|4 +Brand#21|PROMO ANODIZED STEEL|3|4 +Brand#21|PROMO ANODIZED STEEL|14|4 +Brand#21|PROMO ANODIZED STEEL|36|4 +Brand#21|PROMO BRUSHED NICKEL|45|4 +Brand#21|PROMO BRUSHED STEEL|14|4 +Brand#21|PROMO BRUSHED STEEL|23|4 +Brand#21|PROMO BRUSHED STEEL|45|4 +Brand#21|PROMO BURNISHED BRASS|19|4 +Brand#21|PROMO BURNISHED COPPER|19|4 +Brand#21|PROMO BURNISHED NICKEL|9|4 +Brand#21|PROMO BURNISHED TIN|19|4 +Brand#21|PROMO PLATED NICKEL|9|4 +Brand#21|PROMO PLATED NICKEL|36|4 +Brand#21|PROMO PLATED STEEL|49|4 +Brand#21|PROMO PLATED TIN|3|4 +Brand#21|PROMO POLISHED NICKEL|23|4 +Brand#21|PROMO POLISHED TIN|14|4 +Brand#21|PROMO POLISHED TIN|19|4 +Brand#21|PROMO POLISHED TIN|23|4 +Brand#21|SMALL BRUSHED BRASS|23|4 +Brand#21|SMALL BRUSHED COPPER|49|4 +Brand#21|SMALL BURNISHED BRASS|23|4 +Brand#21|SMALL BURNISHED BRASS|36|4 +Brand#21|SMALL BURNISHED STEEL|19|4 +Brand#21|SMALL BURNISHED TIN|19|4 +Brand#21|SMALL PLATED BRASS|45|4 +Brand#21|SMALL PLATED COPPER|45|4 +Brand#21|SMALL PLATED STEEL|45|4 +Brand#21|SMALL PLATED TIN|14|4 +Brand#21|SMALL PLATED TIN|45|4 +Brand#21|SMALL POLISHED COPPER|9|4 +Brand#21|SMALL POLISHED NICKEL|23|4 +Brand#21|SMALL POLISHED TIN|3|4 +Brand#21|STANDARD ANODIZED BRASS|9|4 +Brand#21|STANDARD ANODIZED NICKEL|19|4 +Brand#21|STANDARD ANODIZED TIN|45|4 +Brand#21|STANDARD BURNISHED COPPER|36|4 +Brand#21|STANDARD BURNISHED NICKEL|23|4 +Brand#21|STANDARD BURNISHED TIN|9|4 +Brand#21|STANDARD PLATED BRASS|14|4 +Brand#21|STANDARD PLATED COPPER|19|4 +Brand#21|STANDARD PLATED NICKEL|3|4 +Brand#21|STANDARD PLATED STEEL|9|4 +Brand#21|STANDARD PLATED TIN|9|4 +Brand#21|STANDARD POLISHED BRASS|9|4 +Brand#21|STANDARD POLISHED COPPER|49|4 +Brand#21|STANDARD POLISHED STEEL|36|4 +Brand#21|STANDARD POLISHED TIN|36|4 +Brand#22|ECONOMY ANODIZED STEEL|9|4 +Brand#22|ECONOMY ANODIZED STEEL|14|4 +Brand#22|ECONOMY ANODIZED STEEL|23|4 +Brand#22|ECONOMY ANODIZED TIN|9|4 +Brand#22|ECONOMY ANODIZED TIN|36|4 +Brand#22|ECONOMY BRUSHED NICKEL|36|4 +Brand#22|ECONOMY BRUSHED NICKEL|45|4 +Brand#22|ECONOMY BURNISHED BRASS|9|4 +Brand#22|ECONOMY BURNISHED BRASS|23|4 +Brand#22|ECONOMY BURNISHED BRASS|45|4 +Brand#22|ECONOMY BURNISHED NICKEL|19|4 +Brand#22|ECONOMY BURNISHED NICKEL|49|4 +Brand#22|ECONOMY BURNISHED STEEL|9|4 +Brand#22|ECONOMY BURNISHED STEEL|14|4 +Brand#22|ECONOMY BURNISHED STEEL|23|4 +Brand#22|ECONOMY PLATED BRASS|36|4 +Brand#22|ECONOMY PLATED COPPER|23|4 +Brand#22|ECONOMY PLATED TIN|3|4 +Brand#22|ECONOMY POLISHED TIN|49|4 +Brand#22|LARGE ANODIZED BRASS|19|4 +Brand#22|LARGE ANODIZED COPPER|36|4 +Brand#22|LARGE ANODIZED STEEL|3|4 +Brand#22|LARGE BRUSHED BRASS|23|4 +Brand#22|LARGE BRUSHED BRASS|49|4 +Brand#22|LARGE BRUSHED STEEL|49|4 +Brand#22|LARGE BURNISHED COPPER|19|4 +Brand#22|LARGE BURNISHED STEEL|23|4 +Brand#22|LARGE BURNISHED STEEL|45|4 +Brand#22|LARGE BURNISHED TIN|45|4 +Brand#22|LARGE PLATED COPPER|14|4 +Brand#22|LARGE PLATED STEEL|49|4 +Brand#22|LARGE POLISHED BRASS|19|4 +Brand#22|LARGE POLISHED COPPER|19|4 +Brand#22|LARGE POLISHED COPPER|23|4 +Brand#22|LARGE POLISHED NICKEL|19|4 +Brand#22|LARGE POLISHED TIN|49|4 +Brand#22|MEDIUM ANODIZED BRASS|45|4 +Brand#22|MEDIUM ANODIZED COPPER|19|4 +Brand#22|MEDIUM ANODIZED COPPER|49|4 +Brand#22|MEDIUM ANODIZED NICKEL|9|4 +Brand#22|MEDIUM ANODIZED NICKEL|14|4 +Brand#22|MEDIUM ANODIZED NICKEL|36|4 +Brand#22|MEDIUM ANODIZED TIN|3|4 +Brand#22|MEDIUM ANODIZED TIN|9|4 +Brand#22|MEDIUM BRUSHED BRASS|3|4 +Brand#22|MEDIUM BRUSHED BRASS|14|4 +Brand#22|MEDIUM BRUSHED COPPER|3|4 +Brand#22|MEDIUM BRUSHED COPPER|45|4 +Brand#22|MEDIUM BRUSHED NICKEL|14|4 +Brand#22|MEDIUM BRUSHED TIN|45|4 +Brand#22|MEDIUM BURNISHED COPPER|36|4 +Brand#22|MEDIUM BURNISHED TIN|19|4 +Brand#22|MEDIUM BURNISHED TIN|23|4 +Brand#22|MEDIUM BURNISHED TIN|49|4 +Brand#22|MEDIUM PLATED BRASS|49|4 +Brand#22|MEDIUM PLATED COPPER|9|4 +Brand#22|MEDIUM PLATED STEEL|3|4 +Brand#22|PROMO ANODIZED BRASS|9|4 +Brand#22|PROMO ANODIZED STEEL|36|4 +Brand#22|PROMO ANODIZED TIN|45|4 +Brand#22|PROMO BRUSHED BRASS|3|4 +Brand#22|PROMO BRUSHED BRASS|9|4 +Brand#22|PROMO BRUSHED BRASS|36|4 +Brand#22|PROMO BRUSHED STEEL|36|4 +Brand#22|PROMO BURNISHED BRASS|23|4 +Brand#22|PROMO BURNISHED COPPER|9|4 +Brand#22|PROMO PLATED BRASS|14|4 +Brand#22|PROMO PLATED BRASS|45|4 +Brand#22|PROMO PLATED NICKEL|3|4 +Brand#22|PROMO PLATED STEEL|19|4 +Brand#22|PROMO POLISHED BRASS|3|4 +Brand#22|PROMO POLISHED STEEL|14|4 +Brand#22|PROMO POLISHED STEEL|23|4 +Brand#22|SMALL ANODIZED TIN|36|4 +Brand#22|SMALL ANODIZED TIN|49|4 +Brand#22|SMALL BRUSHED NICKEL|3|4 +Brand#22|SMALL BRUSHED NICKEL|36|4 +Brand#22|SMALL BRUSHED NICKEL|45|4 +Brand#22|SMALL BRUSHED TIN|45|4 +Brand#22|SMALL BURNISHED STEEL|23|4 +Brand#22|SMALL BURNISHED TIN|14|4 +Brand#22|SMALL PLATED STEEL|3|4 +Brand#22|SMALL PLATED TIN|9|4 +Brand#22|SMALL PLATED TIN|36|4 +Brand#22|SMALL POLISHED BRASS|23|4 +Brand#22|SMALL POLISHED NICKEL|19|4 +Brand#22|STANDARD ANODIZED BRASS|14|4 +Brand#22|STANDARD ANODIZED BRASS|23|4 +Brand#22|STANDARD BRUSHED COPPER|49|4 +Brand#22|STANDARD BRUSHED NICKEL|3|4 +Brand#22|STANDARD BRUSHED NICKEL|23|4 +Brand#22|STANDARD BRUSHED STEEL|9|4 +Brand#22|STANDARD BRUSHED TIN|19|4 +Brand#22|STANDARD BURNISHED COPPER|45|4 +Brand#22|STANDARD BURNISHED NICKEL|3|4 +Brand#22|STANDARD BURNISHED NICKEL|14|4 +Brand#22|STANDARD BURNISHED NICKEL|45|4 +Brand#22|STANDARD BURNISHED STEEL|3|4 +Brand#22|STANDARD BURNISHED STEEL|36|4 +Brand#22|STANDARD BURNISHED STEEL|45|4 +Brand#22|STANDARD BURNISHED STEEL|49|4 +Brand#22|STANDARD PLATED BRASS|45|4 +Brand#22|STANDARD PLATED NICKEL|3|4 +Brand#22|STANDARD PLATED NICKEL|45|4 +Brand#22|STANDARD PLATED STEEL|14|4 +Brand#22|STANDARD PLATED TIN|19|4 +Brand#22|STANDARD PLATED TIN|49|4 +Brand#22|STANDARD POLISHED COPPER|9|4 +Brand#22|STANDARD POLISHED STEEL|49|4 +Brand#22|STANDARD POLISHED TIN|45|4 +Brand#23|ECONOMY ANODIZED NICKEL|49|4 +Brand#23|ECONOMY ANODIZED STEEL|14|4 +Brand#23|ECONOMY ANODIZED STEEL|49|4 +Brand#23|ECONOMY ANODIZED TIN|49|4 +Brand#23|ECONOMY BRUSHED BRASS|3|4 +Brand#23|ECONOMY BRUSHED COPPER|9|4 +Brand#23|ECONOMY BRUSHED TIN|9|4 +Brand#23|ECONOMY BURNISHED STEEL|49|4 +Brand#23|ECONOMY PLATED COPPER|14|4 +Brand#23|ECONOMY PLATED NICKEL|23|4 +Brand#23|ECONOMY PLATED STEEL|14|4 +Brand#23|ECONOMY POLISHED NICKEL|9|4 +Brand#23|LARGE ANODIZED BRASS|14|4 +Brand#23|LARGE ANODIZED COPPER|9|4 +Brand#23|LARGE ANODIZED COPPER|14|4 +Brand#23|LARGE ANODIZED COPPER|45|4 +Brand#23|LARGE ANODIZED STEEL|19|4 +Brand#23|LARGE ANODIZED STEEL|36|4 +Brand#23|LARGE ANODIZED STEEL|49|4 +Brand#23|LARGE ANODIZED TIN|9|4 +Brand#23|LARGE PLATED BRASS|9|4 +Brand#23|LARGE PLATED BRASS|49|4 +Brand#23|LARGE PLATED COPPER|3|4 +Brand#23|LARGE POLISHED BRASS|45|4 +Brand#23|LARGE POLISHED STEEL|9|4 +Brand#23|MEDIUM ANODIZED BRASS|19|4 +Brand#23|MEDIUM ANODIZED NICKEL|3|4 +Brand#23|MEDIUM ANODIZED NICKEL|14|4 +Brand#23|MEDIUM ANODIZED STEEL|45|4 +Brand#23|MEDIUM ANODIZED TIN|36|4 +Brand#23|MEDIUM ANODIZED TIN|45|4 +Brand#23|MEDIUM BRUSHED COPPER|3|4 +Brand#23|MEDIUM BRUSHED COPPER|23|4 +Brand#23|MEDIUM BRUSHED NICKEL|3|4 +Brand#23|MEDIUM BRUSHED TIN|14|4 +Brand#23|MEDIUM BURNISHED BRASS|9|4 +Brand#23|MEDIUM BURNISHED BRASS|45|4 +Brand#23|MEDIUM BURNISHED COPPER|19|4 +Brand#23|MEDIUM PLATED COPPER|19|4 +Brand#23|MEDIUM PLATED COPPER|36|4 +Brand#23|MEDIUM PLATED COPPER|45|4 +Brand#23|MEDIUM PLATED NICKEL|9|4 +Brand#23|MEDIUM PLATED NICKEL|14|4 +Brand#23|PROMO ANODIZED COPPER|9|4 +Brand#23|PROMO ANODIZED COPPER|19|4 +Brand#23|PROMO ANODIZED STEEL|36|4 +Brand#23|PROMO ANODIZED TIN|14|4 +Brand#23|PROMO BRUSHED BRASS|3|4 +Brand#23|PROMO BRUSHED BRASS|19|4 +Brand#23|PROMO BRUSHED BRASS|36|4 +Brand#23|PROMO BRUSHED COPPER|3|4 +Brand#23|PROMO BRUSHED TIN|49|4 +Brand#23|PROMO BURNISHED BRASS|14|4 +Brand#23|PROMO BURNISHED BRASS|45|4 +Brand#23|PROMO BURNISHED COPPER|14|4 +Brand#23|PROMO PLATED BRASS|23|4 +Brand#23|PROMO POLISHED BRASS|14|4 +Brand#23|PROMO POLISHED BRASS|23|4 +Brand#23|PROMO POLISHED COPPER|36|4 +Brand#23|PROMO POLISHED STEEL|36|4 +Brand#23|SMALL ANODIZED BRASS|23|4 +Brand#23|SMALL ANODIZED STEEL|23|4 +Brand#23|SMALL BRUSHED BRASS|49|4 +Brand#23|SMALL BRUSHED COPPER|45|4 +Brand#23|SMALL BRUSHED STEEL|3|4 +Brand#23|SMALL BRUSHED STEEL|19|4 +Brand#23|SMALL BURNISHED BRASS|36|4 +Brand#23|SMALL BURNISHED COPPER|45|4 +Brand#23|SMALL BURNISHED COPPER|49|4 +Brand#23|SMALL BURNISHED STEEL|45|4 +Brand#23|SMALL PLATED BRASS|36|4 +Brand#23|SMALL PLATED BRASS|49|4 +Brand#23|SMALL PLATED COPPER|14|4 +Brand#23|SMALL PLATED TIN|14|4 +Brand#23|SMALL POLISHED BRASS|9|4 +Brand#23|SMALL POLISHED BRASS|14|4 +Brand#23|SMALL POLISHED NICKEL|3|4 +Brand#23|SMALL POLISHED STEEL|14|4 +Brand#23|SMALL POLISHED TIN|9|4 +Brand#23|STANDARD ANODIZED BRASS|19|4 +Brand#23|STANDARD ANODIZED BRASS|45|4 +Brand#23|STANDARD ANODIZED COPPER|19|4 +Brand#23|STANDARD ANODIZED TIN|3|4 +Brand#23|STANDARD BRUSHED COPPER|36|4 +Brand#23|STANDARD BRUSHED NICKEL|19|4 +Brand#23|STANDARD BRUSHED STEEL|49|4 +Brand#23|STANDARD BURNISHED COPPER|19|4 +Brand#23|STANDARD PLATED BRASS|3|4 +Brand#23|STANDARD PLATED BRASS|9|4 +Brand#23|STANDARD PLATED STEEL|36|4 +Brand#23|STANDARD PLATED TIN|19|4 +Brand#23|STANDARD POLISHED BRASS|9|4 +Brand#23|STANDARD POLISHED BRASS|49|4 +Brand#23|STANDARD POLISHED STEEL|19|4 +Brand#23|STANDARD POLISHED STEEL|49|4 +Brand#23|STANDARD POLISHED TIN|23|4 +Brand#24|ECONOMY ANODIZED BRASS|3|4 +Brand#24|ECONOMY ANODIZED BRASS|9|4 +Brand#24|ECONOMY ANODIZED BRASS|23|4 +Brand#24|ECONOMY ANODIZED COPPER|9|4 +Brand#24|ECONOMY ANODIZED COPPER|49|4 +Brand#24|ECONOMY BRUSHED BRASS|36|4 +Brand#24|ECONOMY BRUSHED COPPER|23|4 +Brand#24|ECONOMY BURNISHED COPPER|3|4 +Brand#24|ECONOMY BURNISHED NICKEL|19|4 +Brand#24|ECONOMY BURNISHED STEEL|45|4 +Brand#24|ECONOMY PLATED BRASS|23|4 +Brand#24|ECONOMY PLATED COPPER|36|4 +Brand#24|ECONOMY PLATED STEEL|45|4 +Brand#24|ECONOMY POLISHED BRASS|23|4 +Brand#24|ECONOMY POLISHED COPPER|45|4 +Brand#24|ECONOMY POLISHED NICKEL|36|4 +Brand#24|ECONOMY POLISHED STEEL|14|4 +Brand#24|ECONOMY POLISHED STEEL|36|4 +Brand#24|LARGE ANODIZED NICKEL|23|4 +Brand#24|LARGE ANODIZED NICKEL|45|4 +Brand#24|LARGE ANODIZED TIN|45|4 +Brand#24|LARGE BRUSHED BRASS|14|4 +Brand#24|LARGE BRUSHED BRASS|23|4 +Brand#24|LARGE BRUSHED STEEL|9|4 +Brand#24|LARGE BRUSHED STEEL|23|4 +Brand#24|LARGE BRUSHED STEEL|45|4 +Brand#24|LARGE BRUSHED TIN|49|4 +Brand#24|LARGE BURNISHED BRASS|3|4 +Brand#24|LARGE BURNISHED NICKEL|19|4 +Brand#24|LARGE PLATED BRASS|9|4 +Brand#24|LARGE PLATED NICKEL|36|4 +Brand#24|LARGE PLATED NICKEL|49|4 +Brand#24|LARGE PLATED TIN|9|4 +Brand#24|LARGE PLATED TIN|19|4 +Brand#24|LARGE PLATED TIN|36|4 +Brand#24|LARGE PLATED TIN|49|4 +Brand#24|LARGE POLISHED BRASS|9|4 +Brand#24|LARGE POLISHED COPPER|9|4 +Brand#24|LARGE POLISHED COPPER|49|4 +Brand#24|LARGE POLISHED NICKEL|19|4 +Brand#24|LARGE POLISHED STEEL|23|4 +Brand#24|LARGE POLISHED TIN|14|4 +Brand#24|MEDIUM ANODIZED COPPER|45|4 +Brand#24|MEDIUM BRUSHED COPPER|9|4 +Brand#24|MEDIUM BRUSHED COPPER|14|4 +Brand#24|MEDIUM BRUSHED NICKEL|9|4 +Brand#24|MEDIUM BRUSHED NICKEL|23|4 +Brand#24|MEDIUM BRUSHED STEEL|14|4 +Brand#24|MEDIUM BRUSHED STEEL|45|4 +Brand#24|MEDIUM BRUSHED STEEL|49|4 +Brand#24|MEDIUM BURNISHED BRASS|36|4 +Brand#24|MEDIUM BURNISHED NICKEL|36|4 +Brand#24|MEDIUM BURNISHED STEEL|36|4 +Brand#24|MEDIUM PLATED COPPER|14|4 +Brand#24|MEDIUM PLATED STEEL|3|4 +Brand#24|MEDIUM PLATED STEEL|19|4 +Brand#24|PROMO ANODIZED NICKEL|9|4 +Brand#24|PROMO ANODIZED NICKEL|19|4 +Brand#24|PROMO ANODIZED NICKEL|45|4 +Brand#24|PROMO ANODIZED STEEL|3|4 +Brand#24|PROMO ANODIZED TIN|45|4 +Brand#24|PROMO BRUSHED BRASS|19|4 +Brand#24|PROMO BRUSHED NICKEL|19|4 +Brand#24|PROMO BRUSHED NICKEL|45|4 +Brand#24|PROMO BRUSHED STEEL|49|4 +Brand#24|PROMO BURNISHED BRASS|3|4 +Brand#24|PROMO BURNISHED BRASS|45|4 +Brand#24|PROMO BURNISHED STEEL|49|4 +Brand#24|PROMO PLATED BRASS|3|4 +Brand#24|PROMO PLATED COPPER|23|4 +Brand#24|PROMO PLATED COPPER|49|4 +Brand#24|PROMO POLISHED BRASS|3|4 +Brand#24|PROMO POLISHED BRASS|14|4 +Brand#24|PROMO POLISHED NICKEL|3|4 +Brand#24|PROMO POLISHED STEEL|14|4 +Brand#24|PROMO POLISHED STEEL|19|4 +Brand#24|PROMO POLISHED STEEL|23|4 +Brand#24|SMALL ANODIZED BRASS|19|4 +Brand#24|SMALL ANODIZED COPPER|3|4 +Brand#24|SMALL ANODIZED NICKEL|14|4 +Brand#24|SMALL ANODIZED STEEL|36|4 +Brand#24|SMALL ANODIZED TIN|3|4 +Brand#24|SMALL ANODIZED TIN|36|4 +Brand#24|SMALL BRUSHED COPPER|49|4 +Brand#24|SMALL BRUSHED NICKEL|49|4 +Brand#24|SMALL BURNISHED BRASS|14|4 +Brand#24|SMALL BURNISHED BRASS|19|4 +Brand#24|SMALL BURNISHED TIN|9|4 +Brand#24|SMALL PLATED BRASS|3|4 +Brand#24|SMALL PLATED COPPER|14|4 +Brand#24|SMALL PLATED COPPER|36|4 +Brand#24|SMALL PLATED NICKEL|14|4 +Brand#24|SMALL PLATED NICKEL|49|4 +Brand#24|SMALL POLISHED BRASS|3|4 +Brand#24|SMALL POLISHED NICKEL|9|4 +Brand#24|SMALL POLISHED NICKEL|19|4 +Brand#24|SMALL POLISHED NICKEL|36|4 +Brand#24|SMALL POLISHED STEEL|9|4 +Brand#24|SMALL POLISHED STEEL|36|4 +Brand#24|STANDARD ANODIZED TIN|9|4 +Brand#24|STANDARD ANODIZED TIN|49|4 +Brand#24|STANDARD BRUSHED BRASS|14|4 +Brand#24|STANDARD BRUSHED COPPER|23|4 +Brand#24|STANDARD BRUSHED NICKEL|19|4 +Brand#24|STANDARD BRUSHED STEEL|14|4 +Brand#24|STANDARD BRUSHED TIN|36|4 +Brand#24|STANDARD BURNISHED COPPER|19|4 +Brand#24|STANDARD BURNISHED COPPER|36|4 +Brand#24|STANDARD BURNISHED NICKEL|45|4 +Brand#24|STANDARD PLATED BRASS|36|4 +Brand#24|STANDARD PLATED COPPER|45|4 +Brand#24|STANDARD PLATED NICKEL|36|4 +Brand#24|STANDARD PLATED TIN|36|4 +Brand#24|STANDARD POLISHED COPPER|45|4 +Brand#24|STANDARD POLISHED NICKEL|14|4 +Brand#25|ECONOMY ANODIZED BRASS|14|4 +Brand#25|ECONOMY ANODIZED BRASS|49|4 +Brand#25|ECONOMY ANODIZED TIN|9|4 +Brand#25|ECONOMY ANODIZED TIN|19|4 +Brand#25|ECONOMY ANODIZED TIN|49|4 +Brand#25|ECONOMY BRUSHED COPPER|36|4 +Brand#25|ECONOMY BURNISHED COPPER|45|4 +Brand#25|ECONOMY BURNISHED TIN|19|4 +Brand#25|ECONOMY PLATED NICKEL|23|4 +Brand#25|ECONOMY PLATED TIN|14|4 +Brand#25|ECONOMY POLISHED BRASS|23|4 +Brand#25|ECONOMY POLISHED COPPER|9|4 +Brand#25|ECONOMY POLISHED NICKEL|3|4 +Brand#25|ECONOMY POLISHED TIN|9|4 +Brand#25|ECONOMY POLISHED TIN|45|4 +Brand#25|LARGE ANODIZED BRASS|3|4 +Brand#25|LARGE ANODIZED BRASS|14|4 +Brand#25|LARGE ANODIZED COPPER|36|4 +Brand#25|LARGE ANODIZED NICKEL|23|4 +Brand#25|LARGE ANODIZED STEEL|23|4 +Brand#25|LARGE BRUSHED NICKEL|19|4 +Brand#25|LARGE BRUSHED NICKEL|49|4 +Brand#25|LARGE BRUSHED TIN|3|4 +Brand#25|LARGE BRUSHED TIN|9|4 +Brand#25|LARGE BURNISHED BRASS|19|4 +Brand#25|LARGE BURNISHED BRASS|23|4 +Brand#25|LARGE BURNISHED BRASS|49|4 +Brand#25|LARGE BURNISHED NICKEL|14|4 +Brand#25|LARGE BURNISHED TIN|49|4 +Brand#25|LARGE PLATED BRASS|14|4 +Brand#25|LARGE PLATED NICKEL|23|4 +Brand#25|LARGE PLATED NICKEL|45|4 +Brand#25|LARGE PLATED TIN|19|4 +Brand#25|LARGE PLATED TIN|23|4 +Brand#25|LARGE POLISHED BRASS|9|4 +Brand#25|LARGE POLISHED COPPER|14|4 +Brand#25|LARGE POLISHED COPPER|36|4 +Brand#25|MEDIUM ANODIZED TIN|36|4 +Brand#25|MEDIUM BRUSHED COPPER|9|4 +Brand#25|MEDIUM BRUSHED COPPER|36|4 +Brand#25|MEDIUM BRUSHED COPPER|49|4 +Brand#25|MEDIUM BURNISHED COPPER|49|4 +Brand#25|MEDIUM BURNISHED NICKEL|9|4 +Brand#25|MEDIUM BURNISHED NICKEL|49|4 +Brand#25|MEDIUM BURNISHED STEEL|3|4 +Brand#25|MEDIUM BURNISHED STEEL|36|4 +Brand#25|MEDIUM BURNISHED STEEL|45|4 +Brand#25|MEDIUM BURNISHED STEEL|49|4 +Brand#25|MEDIUM BURNISHED TIN|9|4 +Brand#25|MEDIUM BURNISHED TIN|36|4 +Brand#25|MEDIUM PLATED BRASS|45|4 +Brand#25|MEDIUM PLATED COPPER|14|4 +Brand#25|MEDIUM PLATED NICKEL|45|4 +Brand#25|MEDIUM PLATED STEEL|9|4 +Brand#25|MEDIUM PLATED STEEL|36|4 +Brand#25|PROMO ANODIZED COPPER|14|4 +Brand#25|PROMO ANODIZED COPPER|19|4 +Brand#25|PROMO ANODIZED STEEL|36|4 +Brand#25|PROMO ANODIZED TIN|3|4 +Brand#25|PROMO ANODIZED TIN|14|4 +Brand#25|PROMO BRUSHED NICKEL|3|4 +Brand#25|PROMO BRUSHED STEEL|19|4 +Brand#25|PROMO BRUSHED TIN|14|4 +Brand#25|PROMO BRUSHED TIN|36|4 +Brand#25|PROMO BURNISHED COPPER|19|4 +Brand#25|PROMO BURNISHED COPPER|45|4 +Brand#25|PROMO BURNISHED COPPER|49|4 +Brand#25|PROMO BURNISHED NICKEL|36|4 +Brand#25|PROMO BURNISHED TIN|3|4 +Brand#25|PROMO PLATED BRASS|45|4 +Brand#25|PROMO PLATED COPPER|19|4 +Brand#25|PROMO PLATED NICKEL|45|4 +Brand#25|PROMO PLATED NICKEL|49|4 +Brand#25|PROMO PLATED STEEL|23|4 +Brand#25|PROMO POLISHED BRASS|23|4 +Brand#25|SMALL ANODIZED BRASS|45|4 +Brand#25|SMALL ANODIZED NICKEL|19|4 +Brand#25|SMALL ANODIZED STEEL|23|4 +Brand#25|SMALL ANODIZED TIN|14|4 +Brand#25|SMALL ANODIZED TIN|19|4 +Brand#25|SMALL BRUSHED COPPER|45|4 +Brand#25|SMALL BRUSHED NICKEL|9|4 +Brand#25|SMALL BURNISHED COPPER|3|4 +Brand#25|SMALL BURNISHED STEEL|3|4 +Brand#25|SMALL BURNISHED STEEL|14|4 +Brand#25|SMALL BURNISHED TIN|3|4 +Brand#25|SMALL PLATED BRASS|19|4 +Brand#25|SMALL PLATED COPPER|23|4 +Brand#25|SMALL PLATED STEEL|45|4 +Brand#25|SMALL PLATED TIN|36|4 +Brand#25|SMALL POLISHED BRASS|23|4 +Brand#25|SMALL POLISHED COPPER|9|4 +Brand#25|SMALL POLISHED STEEL|14|4 +Brand#25|STANDARD ANODIZED STEEL|3|4 +Brand#25|STANDARD ANODIZED STEEL|19|4 +Brand#25|STANDARD ANODIZED TIN|9|4 +Brand#25|STANDARD BRUSHED BRASS|14|4 +Brand#25|STANDARD BRUSHED NICKEL|19|4 +Brand#25|STANDARD BRUSHED TIN|9|4 +Brand#25|STANDARD BURNISHED NICKEL|9|4 +Brand#25|STANDARD PLATED BRASS|3|4 +Brand#25|STANDARD PLATED COPPER|14|4 +Brand#25|STANDARD PLATED NICKEL|36|4 +Brand#25|STANDARD POLISHED BRASS|45|4 +Brand#25|STANDARD POLISHED COPPER|23|4 +Brand#25|STANDARD POLISHED NICKEL|3|4 +Brand#25|STANDARD POLISHED NICKEL|49|4 +Brand#25|STANDARD POLISHED TIN|36|4 +Brand#25|STANDARD POLISHED TIN|45|4 +Brand#31|ECONOMY ANODIZED BRASS|3|4 +Brand#31|ECONOMY ANODIZED COPPER|45|4 +Brand#31|ECONOMY ANODIZED STEEL|3|4 +Brand#31|ECONOMY ANODIZED TIN|45|4 +Brand#31|ECONOMY BRUSHED BRASS|14|4 +Brand#31|ECONOMY BRUSHED COPPER|19|4 +Brand#31|ECONOMY BRUSHED NICKEL|9|4 +Brand#31|ECONOMY BRUSHED NICKEL|14|4 +Brand#31|ECONOMY BRUSHED NICKEL|49|4 +Brand#31|ECONOMY BURNISHED COPPER|36|4 +Brand#31|ECONOMY BURNISHED STEEL|3|4 +Brand#31|ECONOMY BURNISHED TIN|49|4 +Brand#31|ECONOMY PLATED COPPER|49|4 +Brand#31|ECONOMY PLATED NICKEL|9|4 +Brand#31|ECONOMY PLATED STEEL|23|4 +Brand#31|ECONOMY PLATED TIN|36|4 +Brand#31|ECONOMY PLATED TIN|49|4 +Brand#31|ECONOMY POLISHED COPPER|3|4 +Brand#31|ECONOMY POLISHED COPPER|36|4 +Brand#31|ECONOMY POLISHED COPPER|49|4 +Brand#31|ECONOMY POLISHED NICKEL|3|4 +Brand#31|LARGE ANODIZED BRASS|19|4 +Brand#31|LARGE ANODIZED STEEL|45|4 +Brand#31|LARGE BRUSHED BRASS|36|4 +Brand#31|LARGE BRUSHED BRASS|49|4 +Brand#31|LARGE BRUSHED TIN|3|4 +Brand#31|LARGE BURNISHED BRASS|9|4 +Brand#31|LARGE PLATED COPPER|19|4 +Brand#31|LARGE PLATED NICKEL|14|4 +Brand#31|LARGE PLATED TIN|9|4 +Brand#31|LARGE PLATED TIN|14|4 +Brand#31|LARGE POLISHED BRASS|14|4 +Brand#31|LARGE POLISHED STEEL|14|4 +Brand#31|LARGE POLISHED STEEL|45|4 +Brand#31|LARGE POLISHED TIN|19|4 +Brand#31|MEDIUM ANODIZED BRASS|23|4 +Brand#31|MEDIUM ANODIZED BRASS|36|4 +Brand#31|MEDIUM ANODIZED COPPER|14|4 +Brand#31|MEDIUM ANODIZED COPPER|19|4 +Brand#31|MEDIUM ANODIZED COPPER|36|4 +Brand#31|MEDIUM ANODIZED STEEL|14|4 +Brand#31|MEDIUM ANODIZED STEEL|49|4 +Brand#31|MEDIUM ANODIZED TIN|19|4 +Brand#31|MEDIUM ANODIZED TIN|49|4 +Brand#31|MEDIUM BRUSHED BRASS|36|4 +Brand#31|MEDIUM BRUSHED STEEL|14|4 +Brand#31|MEDIUM BURNISHED BRASS|14|4 +Brand#31|MEDIUM BURNISHED COPPER|3|4 +Brand#31|MEDIUM BURNISHED NICKEL|9|4 +Brand#31|MEDIUM BURNISHED STEEL|9|4 +Brand#31|MEDIUM BURNISHED TIN|14|4 +Brand#31|MEDIUM BURNISHED TIN|23|4 +Brand#31|MEDIUM PLATED BRASS|3|4 +Brand#31|MEDIUM PLATED TIN|9|4 +Brand#31|MEDIUM PLATED TIN|36|4 +Brand#31|MEDIUM PLATED TIN|45|4 +Brand#31|PROMO ANODIZED BRASS|3|4 +Brand#31|PROMO ANODIZED NICKEL|9|4 +Brand#31|PROMO BRUSHED BRASS|3|4 +Brand#31|PROMO BRUSHED BRASS|23|4 +Brand#31|PROMO BRUSHED COPPER|23|4 +Brand#31|PROMO BRUSHED NICKEL|45|4 +Brand#31|PROMO BURNISHED COPPER|36|4 +Brand#31|PROMO BURNISHED STEEL|3|4 +Brand#31|PROMO BURNISHED TIN|3|4 +Brand#31|PROMO PLATED BRASS|19|4 +Brand#31|PROMO PLATED NICKEL|36|4 +Brand#31|PROMO POLISHED BRASS|49|4 +Brand#31|PROMO POLISHED COPPER|14|4 +Brand#31|PROMO POLISHED NICKEL|3|4 +Brand#31|PROMO POLISHED NICKEL|9|4 +Brand#31|PROMO POLISHED TIN|3|4 +Brand#31|PROMO POLISHED TIN|23|4 +Brand#31|SMALL ANODIZED COPPER|45|4 +Brand#31|SMALL ANODIZED STEEL|23|4 +Brand#31|SMALL ANODIZED TIN|3|4 +Brand#31|SMALL BRUSHED COPPER|36|4 +Brand#31|SMALL BRUSHED COPPER|49|4 +Brand#31|SMALL BRUSHED NICKEL|19|4 +Brand#31|SMALL BRUSHED NICKEL|23|4 +Brand#31|SMALL BURNISHED BRASS|45|4 +Brand#31|SMALL BURNISHED NICKEL|9|4 +Brand#31|SMALL BURNISHED NICKEL|36|4 +Brand#31|SMALL PLATED COPPER|36|4 +Brand#31|SMALL PLATED NICKEL|9|4 +Brand#31|SMALL PLATED NICKEL|36|4 +Brand#31|SMALL POLISHED BRASS|3|4 +Brand#31|SMALL POLISHED COPPER|45|4 +Brand#31|SMALL POLISHED NICKEL|45|4 +Brand#31|SMALL POLISHED TIN|23|4 +Brand#31|SMALL POLISHED TIN|49|4 +Brand#31|STANDARD BRUSHED STEEL|23|4 +Brand#31|STANDARD BRUSHED STEEL|49|4 +Brand#31|STANDARD BURNISHED BRASS|14|4 +Brand#31|STANDARD BURNISHED NICKEL|45|4 +Brand#31|STANDARD PLATED NICKEL|3|4 +Brand#31|STANDARD POLISHED BRASS|3|4 +Brand#31|STANDARD POLISHED BRASS|45|4 +Brand#31|STANDARD POLISHED STEEL|36|4 +Brand#32|ECONOMY ANODIZED BRASS|19|4 +Brand#32|ECONOMY ANODIZED COPPER|36|4 +Brand#32|ECONOMY ANODIZED STEEL|23|4 +Brand#32|ECONOMY ANODIZED STEEL|36|4 +Brand#32|ECONOMY ANODIZED STEEL|45|4 +Brand#32|ECONOMY ANODIZED TIN|19|4 +Brand#32|ECONOMY BRUSHED COPPER|45|4 +Brand#32|ECONOMY BRUSHED TIN|45|4 +Brand#32|ECONOMY BURNISHED BRASS|23|4 +Brand#32|ECONOMY BURNISHED COPPER|36|4 +Brand#32|ECONOMY BURNISHED COPPER|45|4 +Brand#32|ECONOMY BURNISHED STEEL|19|4 +Brand#32|ECONOMY PLATED BRASS|9|4 +Brand#32|ECONOMY PLATED COPPER|9|4 +Brand#32|ECONOMY PLATED NICKEL|23|4 +Brand#32|ECONOMY PLATED TIN|45|4 +Brand#32|ECONOMY POLISHED STEEL|3|4 +Brand#32|LARGE ANODIZED BRASS|23|4 +Brand#32|LARGE ANODIZED BRASS|36|4 +Brand#32|LARGE ANODIZED NICKEL|45|4 +Brand#32|LARGE ANODIZED STEEL|3|4 +Brand#32|LARGE ANODIZED STEEL|14|4 +Brand#32|LARGE BRUSHED STEEL|45|4 +Brand#32|LARGE BRUSHED TIN|45|4 +Brand#32|LARGE BURNISHED NICKEL|36|4 +Brand#32|LARGE BURNISHED TIN|19|4 +Brand#32|LARGE BURNISHED TIN|45|4 +Brand#32|LARGE PLATED BRASS|3|4 +Brand#32|LARGE PLATED NICKEL|49|4 +Brand#32|LARGE PLATED STEEL|19|4 +Brand#32|LARGE PLATED STEEL|36|4 +Brand#32|LARGE POLISHED BRASS|45|4 +Brand#32|LARGE POLISHED COPPER|9|4 +Brand#32|LARGE POLISHED COPPER|49|4 +Brand#32|LARGE POLISHED NICKEL|3|4 +Brand#32|MEDIUM ANODIZED BRASS|3|4 +Brand#32|MEDIUM ANODIZED BRASS|9|4 +Brand#32|MEDIUM ANODIZED TIN|23|4 +Brand#32|MEDIUM BRUSHED BRASS|23|4 +Brand#32|MEDIUM BRUSHED BRASS|49|4 +Brand#32|MEDIUM BRUSHED COPPER|9|4 +Brand#32|MEDIUM BRUSHED COPPER|19|4 +Brand#32|MEDIUM BRUSHED TIN|49|4 +Brand#32|MEDIUM BURNISHED BRASS|9|4 +Brand#32|MEDIUM BURNISHED BRASS|36|4 +Brand#32|MEDIUM BURNISHED BRASS|49|4 +Brand#32|MEDIUM BURNISHED COPPER|9|4 +Brand#32|MEDIUM BURNISHED COPPER|45|4 +Brand#32|MEDIUM BURNISHED NICKEL|49|4 +Brand#32|MEDIUM BURNISHED TIN|9|4 +Brand#32|MEDIUM BURNISHED TIN|45|4 +Brand#32|MEDIUM PLATED BRASS|3|4 +Brand#32|MEDIUM PLATED BRASS|49|4 +Brand#32|MEDIUM PLATED COPPER|3|4 +Brand#32|MEDIUM PLATED STEEL|9|4 +Brand#32|MEDIUM PLATED TIN|9|4 +Brand#32|PROMO ANODIZED BRASS|3|4 +Brand#32|PROMO ANODIZED COPPER|19|4 +Brand#32|PROMO ANODIZED NICKEL|23|4 +Brand#32|PROMO BRUSHED COPPER|23|4 +Brand#32|PROMO BRUSHED NICKEL|14|4 +Brand#32|PROMO BRUSHED NICKEL|36|4 +Brand#32|PROMO BRUSHED STEEL|14|4 +Brand#32|PROMO BRUSHED STEEL|23|4 +Brand#32|PROMO BRUSHED STEEL|49|4 +Brand#32|PROMO BURNISHED BRASS|45|4 +Brand#32|PROMO BURNISHED NICKEL|45|4 +Brand#32|PROMO BURNISHED TIN|14|4 +Brand#32|PROMO BURNISHED TIN|45|4 +Brand#32|PROMO PLATED TIN|19|4 +Brand#32|PROMO POLISHED NICKEL|36|4 +Brand#32|PROMO POLISHED TIN|3|4 +Brand#32|SMALL ANODIZED BRASS|3|4 +Brand#32|SMALL ANODIZED NICKEL|3|4 +Brand#32|SMALL ANODIZED NICKEL|14|4 +Brand#32|SMALL ANODIZED TIN|9|4 +Brand#32|SMALL BRUSHED BRASS|9|4 +Brand#32|SMALL BRUSHED BRASS|19|4 +Brand#32|SMALL BRUSHED COPPER|3|4 +Brand#32|SMALL BRUSHED COPPER|23|4 +Brand#32|SMALL BRUSHED NICKEL|9|4 +Brand#32|SMALL BRUSHED NICKEL|45|4 +Brand#32|SMALL BRUSHED STEEL|23|4 +Brand#32|SMALL BRUSHED TIN|9|4 +Brand#32|SMALL BURNISHED NICKEL|36|4 +Brand#32|SMALL BURNISHED STEEL|3|4 +Brand#32|SMALL BURNISHED TIN|23|4 +Brand#32|SMALL PLATED BRASS|49|4 +Brand#32|SMALL PLATED COPPER|36|4 +Brand#32|SMALL PLATED COPPER|45|4 +Brand#32|SMALL PLATED NICKEL|45|4 +Brand#32|SMALL PLATED STEEL|45|4 +Brand#32|SMALL PLATED TIN|23|4 +Brand#32|SMALL PLATED TIN|36|4 +Brand#32|SMALL PLATED TIN|45|4 +Brand#32|SMALL POLISHED NICKEL|36|4 +Brand#32|SMALL POLISHED STEEL|14|4 +Brand#32|SMALL POLISHED STEEL|23|4 +Brand#32|SMALL POLISHED STEEL|36|4 +Brand#32|SMALL POLISHED TIN|36|4 +Brand#32|SMALL POLISHED TIN|45|4 +Brand#32|STANDARD ANODIZED NICKEL|19|4 +Brand#32|STANDARD ANODIZED TIN|9|4 +Brand#32|STANDARD ANODIZED TIN|14|4 +Brand#32|STANDARD ANODIZED TIN|19|4 +Brand#32|STANDARD BRUSHED NICKEL|23|4 +Brand#32|STANDARD BURNISHED BRASS|36|4 +Brand#32|STANDARD BURNISHED BRASS|45|4 +Brand#32|STANDARD BURNISHED COPPER|3|4 +Brand#32|STANDARD BURNISHED COPPER|36|4 +Brand#32|STANDARD BURNISHED NICKEL|49|4 +Brand#32|STANDARD BURNISHED STEEL|49|4 +Brand#32|STANDARD BURNISHED TIN|23|4 +Brand#32|STANDARD PLATED BRASS|9|4 +Brand#32|STANDARD PLATED BRASS|45|4 +Brand#32|STANDARD PLATED STEEL|36|4 +Brand#32|STANDARD POLISHED BRASS|14|4 +Brand#32|STANDARD POLISHED COPPER|36|4 +Brand#32|STANDARD POLISHED STEEL|14|4 +Brand#33|ECONOMY ANODIZED BRASS|23|4 +Brand#33|ECONOMY ANODIZED COPPER|9|4 +Brand#33|ECONOMY ANODIZED NICKEL|3|4 +Brand#33|ECONOMY ANODIZED NICKEL|9|4 +Brand#33|ECONOMY ANODIZED NICKEL|23|4 +Brand#33|ECONOMY ANODIZED NICKEL|36|4 +Brand#33|ECONOMY BRUSHED BRASS|14|4 +Brand#33|ECONOMY BRUSHED COPPER|23|4 +Brand#33|ECONOMY BURNISHED BRASS|49|4 +Brand#33|ECONOMY BURNISHED COPPER|3|4 +Brand#33|ECONOMY BURNISHED COPPER|14|4 +Brand#33|ECONOMY BURNISHED STEEL|3|4 +Brand#33|ECONOMY BURNISHED TIN|36|4 +Brand#33|ECONOMY BURNISHED TIN|45|4 +Brand#33|ECONOMY PLATED COPPER|19|4 +Brand#33|ECONOMY PLATED COPPER|45|4 +Brand#33|ECONOMY PLATED NICKEL|14|4 +Brand#33|ECONOMY PLATED NICKEL|36|4 +Brand#33|ECONOMY PLATED STEEL|3|4 +Brand#33|ECONOMY PLATED STEEL|23|4 +Brand#33|ECONOMY PLATED STEEL|36|4 +Brand#33|ECONOMY POLISHED BRASS|14|4 +Brand#33|ECONOMY POLISHED NICKEL|19|4 +Brand#33|ECONOMY POLISHED TIN|9|4 +Brand#33|LARGE ANODIZED BRASS|36|4 +Brand#33|LARGE ANODIZED COPPER|19|4 +Brand#33|LARGE ANODIZED COPPER|45|4 +Brand#33|LARGE ANODIZED NICKEL|36|4 +Brand#33|LARGE ANODIZED NICKEL|45|4 +Brand#33|LARGE ANODIZED STEEL|3|4 +Brand#33|LARGE ANODIZED STEEL|45|4 +Brand#33|LARGE ANODIZED TIN|45|4 +Brand#33|LARGE BRUSHED BRASS|3|4 +Brand#33|LARGE BRUSHED BRASS|49|4 +Brand#33|LARGE BRUSHED STEEL|19|4 +Brand#33|LARGE BRUSHED TIN|36|4 +Brand#33|LARGE BURNISHED COPPER|45|4 +Brand#33|LARGE BURNISHED NICKEL|23|4 +Brand#33|LARGE BURNISHED STEEL|19|4 +Brand#33|LARGE PLATED BRASS|3|4 +Brand#33|LARGE PLATED COPPER|19|4 +Brand#33|LARGE PLATED STEEL|3|4 +Brand#33|LARGE PLATED STEEL|19|4 +Brand#33|LARGE PLATED TIN|45|4 +Brand#33|LARGE POLISHED BRASS|45|4 +Brand#33|LARGE POLISHED STEEL|14|4 +Brand#33|LARGE POLISHED STEEL|23|4 +Brand#33|LARGE POLISHED TIN|23|4 +Brand#33|MEDIUM ANODIZED BRASS|3|4 +Brand#33|MEDIUM ANODIZED COPPER|9|4 +Brand#33|MEDIUM ANODIZED COPPER|36|4 +Brand#33|MEDIUM ANODIZED COPPER|49|4 +Brand#33|MEDIUM ANODIZED NICKEL|3|4 +Brand#33|MEDIUM ANODIZED NICKEL|19|4 +Brand#33|MEDIUM BRUSHED BRASS|3|4 +Brand#33|MEDIUM BRUSHED STEEL|19|4 +Brand#33|MEDIUM BRUSHED TIN|14|4 +Brand#33|MEDIUM BURNISHED COPPER|14|4 +Brand#33|MEDIUM BURNISHED COPPER|49|4 +Brand#33|MEDIUM BURNISHED TIN|36|4 +Brand#33|MEDIUM PLATED BRASS|3|4 +Brand#33|MEDIUM PLATED STEEL|3|4 +Brand#33|MEDIUM PLATED STEEL|49|4 +Brand#33|PROMO ANODIZED BRASS|3|4 +Brand#33|PROMO BRUSHED BRASS|49|4 +Brand#33|PROMO BURNISHED COPPER|23|4 +Brand#33|PROMO BURNISHED NICKEL|14|4 +Brand#33|PROMO BURNISHED NICKEL|36|4 +Brand#33|PROMO BURNISHED TIN|19|4 +Brand#33|PROMO BURNISHED TIN|23|4 +Brand#33|PROMO PLATED COPPER|14|4 +Brand#33|PROMO PLATED STEEL|45|4 +Brand#33|PROMO PLATED STEEL|49|4 +Brand#33|PROMO PLATED TIN|49|4 +Brand#33|PROMO POLISHED COPPER|3|4 +Brand#33|PROMO POLISHED STEEL|3|4 +Brand#33|PROMO POLISHED STEEL|9|4 +Brand#33|PROMO POLISHED STEEL|23|4 +Brand#33|SMALL ANODIZED BRASS|19|4 +Brand#33|SMALL ANODIZED COPPER|23|4 +Brand#33|SMALL ANODIZED COPPER|49|4 +Brand#33|SMALL ANODIZED STEEL|9|4 +Brand#33|SMALL BRUSHED BRASS|3|4 +Brand#33|SMALL BRUSHED COPPER|3|4 +Brand#33|SMALL BRUSHED NICKEL|45|4 +Brand#33|SMALL BRUSHED STEEL|3|4 +Brand#33|SMALL BRUSHED TIN|9|4 +Brand#33|SMALL BURNISHED BRASS|19|4 +Brand#33|SMALL BURNISHED NICKEL|3|4 +Brand#33|SMALL PLATED BRASS|3|4 +Brand#33|SMALL PLATED STEEL|14|4 +Brand#33|SMALL PLATED STEEL|45|4 +Brand#33|SMALL PLATED TIN|23|4 +Brand#33|SMALL PLATED TIN|36|4 +Brand#33|SMALL POLISHED NICKEL|23|4 +Brand#33|SMALL POLISHED TIN|19|4 +Brand#33|SMALL POLISHED TIN|23|4 +Brand#33|SMALL POLISHED TIN|45|4 +Brand#33|STANDARD ANODIZED COPPER|49|4 +Brand#33|STANDARD ANODIZED STEEL|14|4 +Brand#33|STANDARD ANODIZED STEEL|45|4 +Brand#33|STANDARD ANODIZED STEEL|49|4 +Brand#33|STANDARD ANODIZED TIN|45|4 +Brand#33|STANDARD BRUSHED BRASS|9|4 +Brand#33|STANDARD BRUSHED NICKEL|45|4 +Brand#33|STANDARD BRUSHED STEEL|9|4 +Brand#33|STANDARD BRUSHED TIN|36|4 +Brand#33|STANDARD BURNISHED BRASS|9|4 +Brand#33|STANDARD BURNISHED BRASS|23|4 +Brand#33|STANDARD BURNISHED NICKEL|49|4 +Brand#33|STANDARD PLATED BRASS|49|4 +Brand#33|STANDARD PLATED COPPER|3|4 +Brand#33|STANDARD PLATED COPPER|14|4 +Brand#33|STANDARD PLATED NICKEL|36|4 +Brand#33|STANDARD PLATED STEEL|3|4 +Brand#33|STANDARD PLATED STEEL|36|4 +Brand#33|STANDARD PLATED TIN|14|4 +Brand#33|STANDARD POLISHED BRASS|9|4 +Brand#33|STANDARD POLISHED BRASS|19|4 +Brand#33|STANDARD POLISHED STEEL|3|4 +Brand#33|STANDARD POLISHED STEEL|9|4 +Brand#33|STANDARD POLISHED STEEL|14|4 +Brand#34|ECONOMY ANODIZED BRASS|9|4 +Brand#34|ECONOMY ANODIZED COPPER|3|4 +Brand#34|ECONOMY ANODIZED COPPER|14|4 +Brand#34|ECONOMY ANODIZED COPPER|19|4 +Brand#34|ECONOMY ANODIZED STEEL|9|4 +Brand#34|ECONOMY ANODIZED TIN|49|4 +Brand#34|ECONOMY BRUSHED BRASS|14|4 +Brand#34|ECONOMY BRUSHED NICKEL|49|4 +Brand#34|ECONOMY BURNISHED COPPER|9|4 +Brand#34|ECONOMY BURNISHED STEEL|19|4 +Brand#34|ECONOMY BURNISHED TIN|3|4 +Brand#34|ECONOMY BURNISHED TIN|23|4 +Brand#34|ECONOMY PLATED BRASS|9|4 +Brand#34|ECONOMY PLATED BRASS|14|4 +Brand#34|ECONOMY PLATED COPPER|3|4 +Brand#34|ECONOMY PLATED NICKEL|45|4 +Brand#34|ECONOMY PLATED TIN|14|4 +Brand#34|ECONOMY PLATED TIN|45|4 +Brand#34|ECONOMY POLISHED BRASS|45|4 +Brand#34|LARGE ANODIZED BRASS|14|4 +Brand#34|LARGE ANODIZED BRASS|23|4 +Brand#34|LARGE ANODIZED BRASS|36|4 +Brand#34|LARGE ANODIZED NICKEL|3|4 +Brand#34|LARGE ANODIZED TIN|49|4 +Brand#34|LARGE BRUSHED BRASS|49|4 +Brand#34|LARGE BRUSHED COPPER|23|4 +Brand#34|LARGE BRUSHED NICKEL|23|4 +Brand#34|LARGE BRUSHED STEEL|14|4 +Brand#34|LARGE BRUSHED STEEL|19|4 +Brand#34|LARGE BRUSHED TIN|9|4 +Brand#34|LARGE BURNISHED BRASS|23|4 +Brand#34|LARGE BURNISHED COPPER|3|4 +Brand#34|LARGE BURNISHED COPPER|36|4 +Brand#34|LARGE BURNISHED NICKEL|19|4 +Brand#34|LARGE PLATED BRASS|23|4 +Brand#34|LARGE PLATED BRASS|36|4 +Brand#34|LARGE PLATED BRASS|45|4 +Brand#34|LARGE PLATED COPPER|23|4 +Brand#34|LARGE PLATED COPPER|49|4 +Brand#34|LARGE PLATED STEEL|49|4 +Brand#34|LARGE POLISHED NICKEL|49|4 +Brand#34|MEDIUM ANODIZED COPPER|36|4 +Brand#34|MEDIUM ANODIZED TIN|3|4 +Brand#34|MEDIUM BRUSHED BRASS|49|4 +Brand#34|MEDIUM BRUSHED COPPER|9|4 +Brand#34|MEDIUM BRUSHED NICKEL|9|4 +Brand#34|MEDIUM BRUSHED NICKEL|23|4 +Brand#34|MEDIUM BRUSHED TIN|3|4 +Brand#34|MEDIUM BRUSHED TIN|14|4 +Brand#34|MEDIUM BURNISHED STEEL|45|4 +Brand#34|MEDIUM BURNISHED STEEL|49|4 +Brand#34|MEDIUM PLATED COPPER|36|4 +Brand#34|MEDIUM PLATED TIN|3|4 +Brand#34|MEDIUM PLATED TIN|14|4 +Brand#34|PROMO ANODIZED COPPER|45|4 +Brand#34|PROMO ANODIZED NICKEL|14|4 +Brand#34|PROMO ANODIZED STEEL|49|4 +Brand#34|PROMO ANODIZED TIN|14|4 +Brand#34|PROMO BRUSHED BRASS|9|4 +Brand#34|PROMO BRUSHED BRASS|23|4 +Brand#34|PROMO BRUSHED COPPER|36|4 +Brand#34|PROMO BRUSHED STEEL|36|4 +Brand#34|PROMO BURNISHED BRASS|49|4 +Brand#34|PROMO BURNISHED STEEL|3|4 +Brand#34|PROMO PLATED BRASS|9|4 +Brand#34|PROMO PLATED STEEL|49|4 +Brand#34|PROMO POLISHED BRASS|23|4 +Brand#34|PROMO POLISHED NICKEL|3|4 +Brand#34|PROMO POLISHED NICKEL|36|4 +Brand#34|SMALL ANODIZED BRASS|36|4 +Brand#34|SMALL ANODIZED COPPER|45|4 +Brand#34|SMALL ANODIZED NICKEL|14|4 +Brand#34|SMALL ANODIZED NICKEL|36|4 +Brand#34|SMALL ANODIZED STEEL|3|4 +Brand#34|SMALL ANODIZED STEEL|19|4 +Brand#34|SMALL ANODIZED STEEL|23|4 +Brand#34|SMALL ANODIZED STEEL|36|4 +Brand#34|SMALL BRUSHED BRASS|14|4 +Brand#34|SMALL BRUSHED BRASS|36|4 +Brand#34|SMALL BRUSHED NICKEL|14|4 +Brand#34|SMALL BRUSHED NICKEL|36|4 +Brand#34|SMALL BRUSHED NICKEL|45|4 +Brand#34|SMALL BRUSHED TIN|9|4 +Brand#34|SMALL BRUSHED TIN|23|4 +Brand#34|SMALL BRUSHED TIN|36|4 +Brand#34|SMALL BURNISHED COPPER|9|4 +Brand#34|SMALL BURNISHED TIN|36|4 +Brand#34|SMALL PLATED BRASS|14|4 +Brand#34|SMALL PLATED COPPER|36|4 +Brand#34|SMALL PLATED TIN|45|4 +Brand#34|SMALL POLISHED NICKEL|14|4 +Brand#34|SMALL POLISHED NICKEL|45|4 +Brand#34|SMALL POLISHED TIN|9|4 +Brand#34|SMALL POLISHED TIN|14|4 +Brand#34|SMALL POLISHED TIN|19|4 +Brand#34|STANDARD ANODIZED BRASS|23|4 +Brand#34|STANDARD ANODIZED BRASS|36|4 +Brand#34|STANDARD ANODIZED COPPER|45|4 +Brand#34|STANDARD ANODIZED NICKEL|36|4 +Brand#34|STANDARD ANODIZED STEEL|9|4 +Brand#34|STANDARD ANODIZED STEEL|49|4 +Brand#34|STANDARD ANODIZED TIN|9|4 +Brand#34|STANDARD BRUSHED BRASS|19|4 +Brand#34|STANDARD BRUSHED BRASS|23|4 +Brand#34|STANDARD BRUSHED NICKEL|23|4 +Brand#34|STANDARD BRUSHED STEEL|3|4 +Brand#34|STANDARD BRUSHED TIN|19|4 +Brand#34|STANDARD BURNISHED COPPER|45|4 +Brand#34|STANDARD BURNISHED NICKEL|19|4 +Brand#34|STANDARD BURNISHED NICKEL|45|4 +Brand#34|STANDARD BURNISHED STEEL|36|4 +Brand#34|STANDARD BURNISHED TIN|45|4 +Brand#34|STANDARD PLATED BRASS|9|4 +Brand#34|STANDARD PLATED COPPER|9|4 +Brand#34|STANDARD PLATED NICKEL|36|4 +Brand#35|ECONOMY ANODIZED COPPER|3|4 +Brand#35|ECONOMY ANODIZED STEEL|45|4 +Brand#35|ECONOMY BRUSHED BRASS|3|4 +Brand#35|ECONOMY BRUSHED NICKEL|49|4 +Brand#35|ECONOMY BRUSHED STEEL|23|4 +Brand#35|ECONOMY BRUSHED STEEL|45|4 +Brand#35|ECONOMY BRUSHED TIN|14|4 +Brand#35|ECONOMY BRUSHED TIN|23|4 +Brand#35|ECONOMY BURNISHED NICKEL|19|4 +Brand#35|ECONOMY BURNISHED STEEL|36|4 +Brand#35|ECONOMY BURNISHED TIN|9|4 +Brand#35|ECONOMY BURNISHED TIN|19|4 +Brand#35|ECONOMY BURNISHED TIN|49|4 +Brand#35|ECONOMY POLISHED COPPER|9|4 +Brand#35|ECONOMY POLISHED TIN|19|4 +Brand#35|LARGE ANODIZED BRASS|3|4 +Brand#35|LARGE ANODIZED BRASS|23|4 +Brand#35|LARGE ANODIZED COPPER|49|4 +Brand#35|LARGE ANODIZED STEEL|36|4 +Brand#35|LARGE ANODIZED TIN|9|4 +Brand#35|LARGE BRUSHED COPPER|9|4 +Brand#35|LARGE BRUSHED COPPER|23|4 +Brand#35|LARGE BRUSHED STEEL|3|4 +Brand#35|LARGE BRUSHED STEEL|9|4 +Brand#35|LARGE BURNISHED BRASS|36|4 +Brand#35|LARGE BURNISHED BRASS|45|4 +Brand#35|LARGE BURNISHED COPPER|23|4 +Brand#35|LARGE BURNISHED NICKEL|23|4 +Brand#35|LARGE PLATED BRASS|9|4 +Brand#35|LARGE PLATED COPPER|36|4 +Brand#35|LARGE POLISHED BRASS|49|4 +Brand#35|LARGE POLISHED STEEL|9|4 +Brand#35|LARGE POLISHED TIN|14|4 +Brand#35|MEDIUM ANODIZED BRASS|9|4 +Brand#35|MEDIUM ANODIZED BRASS|36|4 +Brand#35|MEDIUM ANODIZED COPPER|9|4 +Brand#35|MEDIUM BRUSHED BRASS|14|4 +Brand#35|MEDIUM BRUSHED COPPER|9|4 +Brand#35|MEDIUM BRUSHED COPPER|36|4 +Brand#35|MEDIUM BURNISHED BRASS|49|4 +Brand#35|MEDIUM BURNISHED NICKEL|45|4 +Brand#35|MEDIUM BURNISHED TIN|36|4 +Brand#35|MEDIUM PLATED BRASS|23|4 +Brand#35|MEDIUM PLATED COPPER|9|4 +Brand#35|MEDIUM PLATED NICKEL|45|4 +Brand#35|MEDIUM PLATED NICKEL|49|4 +Brand#35|MEDIUM PLATED STEEL|49|4 +Brand#35|PROMO ANODIZED COPPER|49|4 +Brand#35|PROMO ANODIZED NICKEL|19|4 +Brand#35|PROMO ANODIZED NICKEL|23|4 +Brand#35|PROMO ANODIZED TIN|3|4 +Brand#35|PROMO ANODIZED TIN|14|4 +Brand#35|PROMO BRUSHED BRASS|49|4 +Brand#35|PROMO BRUSHED NICKEL|14|4 +Brand#35|PROMO BRUSHED NICKEL|19|4 +Brand#35|PROMO BURNISHED BRASS|3|4 +Brand#35|PROMO BURNISHED STEEL|3|4 +Brand#35|PROMO PLATED BRASS|19|4 +Brand#35|PROMO PLATED COPPER|14|4 +Brand#35|PROMO PLATED STEEL|23|4 +Brand#35|PROMO PLATED STEEL|36|4 +Brand#35|PROMO PLATED TIN|19|4 +Brand#35|PROMO POLISHED BRASS|9|4 +Brand#35|PROMO POLISHED BRASS|36|4 +Brand#35|PROMO POLISHED NICKEL|36|4 +Brand#35|PROMO POLISHED STEEL|23|4 +Brand#35|PROMO POLISHED TIN|36|4 +Brand#35|PROMO POLISHED TIN|45|4 +Brand#35|SMALL ANODIZED COPPER|9|4 +Brand#35|SMALL ANODIZED STEEL|19|4 +Brand#35|SMALL ANODIZED TIN|19|4 +Brand#35|SMALL BRUSHED BRASS|36|4 +Brand#35|SMALL BRUSHED STEEL|49|4 +Brand#35|SMALL BRUSHED TIN|3|4 +Brand#35|SMALL BRUSHED TIN|19|4 +Brand#35|SMALL BRUSHED TIN|23|4 +Brand#35|SMALL BURNISHED BRASS|23|4 +Brand#35|SMALL BURNISHED STEEL|36|4 +Brand#35|SMALL BURNISHED TIN|3|4 +Brand#35|SMALL BURNISHED TIN|36|4 +Brand#35|SMALL BURNISHED TIN|49|4 +Brand#35|SMALL PLATED BRASS|23|4 +Brand#35|SMALL PLATED STEEL|14|4 +Brand#35|SMALL POLISHED BRASS|36|4 +Brand#35|SMALL POLISHED STEEL|3|4 +Brand#35|SMALL POLISHED STEEL|49|4 +Brand#35|SMALL POLISHED TIN|23|4 +Brand#35|SMALL POLISHED TIN|45|4 +Brand#35|STANDARD ANODIZED NICKEL|14|4 +Brand#35|STANDARD ANODIZED STEEL|23|4 +Brand#35|STANDARD ANODIZED STEEL|45|4 +Brand#35|STANDARD ANODIZED TIN|9|4 +Brand#35|STANDARD ANODIZED TIN|19|4 +Brand#35|STANDARD BRUSHED BRASS|3|4 +Brand#35|STANDARD BRUSHED BRASS|23|4 +Brand#35|STANDARD BRUSHED BRASS|36|4 +Brand#35|STANDARD BRUSHED COPPER|36|4 +Brand#35|STANDARD BRUSHED NICKEL|36|4 +Brand#35|STANDARD BRUSHED NICKEL|49|4 +Brand#35|STANDARD BRUSHED TIN|9|4 +Brand#35|STANDARD BURNISHED BRASS|9|4 +Brand#35|STANDARD BURNISHED BRASS|19|4 +Brand#35|STANDARD BURNISHED BRASS|23|4 +Brand#35|STANDARD BURNISHED COPPER|36|4 +Brand#35|STANDARD BURNISHED STEEL|14|4 +Brand#35|STANDARD PLATED COPPER|19|4 +Brand#35|STANDARD PLATED NICKEL|23|4 +Brand#35|STANDARD PLATED STEEL|14|4 +Brand#35|STANDARD PLATED STEEL|23|4 +Brand#35|STANDARD PLATED TIN|49|4 +Brand#35|STANDARD POLISHED NICKEL|23|4 +Brand#35|STANDARD POLISHED TIN|23|4 +Brand#35|STANDARD POLISHED TIN|45|4 +Brand#41|ECONOMY ANODIZED STEEL|49|4 +Brand#41|ECONOMY BRUSHED BRASS|3|4 +Brand#41|ECONOMY BRUSHED COPPER|36|4 +Brand#41|ECONOMY BRUSHED NICKEL|23|4 +Brand#41|ECONOMY BRUSHED STEEL|36|4 +Brand#41|ECONOMY BRUSHED STEEL|45|4 +Brand#41|ECONOMY BRUSHED TIN|14|4 +Brand#41|ECONOMY PLATED COPPER|3|4 +Brand#41|ECONOMY PLATED STEEL|3|4 +Brand#41|ECONOMY PLATED TIN|23|4 +Brand#41|ECONOMY POLISHED COPPER|19|4 +Brand#41|ECONOMY POLISHED NICKEL|9|4 +Brand#41|ECONOMY POLISHED NICKEL|14|4 +Brand#41|ECONOMY POLISHED NICKEL|23|4 +Brand#41|ECONOMY POLISHED NICKEL|49|4 +Brand#41|ECONOMY POLISHED STEEL|9|4 +Brand#41|ECONOMY POLISHED STEEL|19|4 +Brand#41|ECONOMY POLISHED STEEL|45|4 +Brand#41|ECONOMY POLISHED TIN|19|4 +Brand#41|LARGE ANODIZED BRASS|14|4 +Brand#41|LARGE ANODIZED BRASS|23|4 +Brand#41|LARGE ANODIZED COPPER|49|4 +Brand#41|LARGE ANODIZED STEEL|3|4 +Brand#41|LARGE ANODIZED STEEL|23|4 +Brand#41|LARGE BRUSHED COPPER|23|4 +Brand#41|LARGE BRUSHED COPPER|49|4 +Brand#41|LARGE BRUSHED STEEL|19|4 +Brand#41|LARGE BURNISHED BRASS|45|4 +Brand#41|LARGE BURNISHED COPPER|3|4 +Brand#41|LARGE BURNISHED NICKEL|23|4 +Brand#41|LARGE BURNISHED TIN|9|4 +Brand#41|LARGE PLATED NICKEL|3|4 +Brand#41|LARGE PLATED NICKEL|23|4 +Brand#41|LARGE PLATED STEEL|9|4 +Brand#41|LARGE PLATED STEEL|36|4 +Brand#41|LARGE PLATED TIN|9|4 +Brand#41|LARGE POLISHED BRASS|36|4 +Brand#41|LARGE POLISHED COPPER|19|4 +Brand#41|LARGE POLISHED COPPER|49|4 +Brand#41|LARGE POLISHED NICKEL|36|4 +Brand#41|LARGE POLISHED STEEL|14|4 +Brand#41|MEDIUM ANODIZED BRASS|9|4 +Brand#41|MEDIUM ANODIZED COPPER|14|4 +Brand#41|MEDIUM ANODIZED NICKEL|3|4 +Brand#41|MEDIUM ANODIZED NICKEL|9|4 +Brand#41|MEDIUM ANODIZED STEEL|14|4 +Brand#41|MEDIUM BRUSHED COPPER|3|4 +Brand#41|MEDIUM BRUSHED TIN|9|4 +Brand#41|MEDIUM BURNISHED COPPER|23|4 +Brand#41|MEDIUM BURNISHED STEEL|9|4 +Brand#41|MEDIUM BURNISHED STEEL|45|4 +Brand#41|MEDIUM BURNISHED TIN|3|4 +Brand#41|MEDIUM PLATED BRASS|19|4 +Brand#41|MEDIUM PLATED BRASS|45|4 +Brand#41|MEDIUM PLATED COPPER|19|4 +Brand#41|MEDIUM PLATED STEEL|19|4 +Brand#41|MEDIUM PLATED STEEL|23|4 +Brand#41|PROMO ANODIZED BRASS|19|4 +Brand#41|PROMO ANODIZED COPPER|9|4 +Brand#41|PROMO ANODIZED NICKEL|9|4 +Brand#41|PROMO BRUSHED BRASS|14|4 +Brand#41|PROMO BRUSHED COPPER|36|4 +Brand#41|PROMO BRUSHED NICKEL|14|4 +Brand#41|PROMO BURNISHED BRASS|49|4 +Brand#41|PROMO BURNISHED NICKEL|36|4 +Brand#41|PROMO BURNISHED TIN|3|4 +Brand#41|PROMO PLATED NICKEL|14|4 +Brand#41|PROMO PLATED NICKEL|45|4 +Brand#41|PROMO PLATED STEEL|3|4 +Brand#41|PROMO PLATED TIN|3|4 +Brand#41|PROMO POLISHED COPPER|23|4 +Brand#41|SMALL ANODIZED BRASS|3|4 +Brand#41|SMALL ANODIZED BRASS|14|4 +Brand#41|SMALL ANODIZED STEEL|45|4 +Brand#41|SMALL ANODIZED TIN|9|4 +Brand#41|SMALL BRUSHED TIN|19|4 +Brand#41|SMALL BURNISHED COPPER|9|4 +Brand#41|SMALL BURNISHED NICKEL|3|4 +Brand#41|SMALL BURNISHED TIN|45|4 +Brand#41|SMALL PLATED COPPER|14|4 +Brand#41|SMALL PLATED COPPER|36|4 +Brand#41|SMALL PLATED COPPER|49|4 +Brand#41|SMALL PLATED TIN|19|4 +Brand#41|SMALL POLISHED COPPER|14|4 +Brand#41|SMALL POLISHED COPPER|19|4 +Brand#41|SMALL POLISHED COPPER|36|4 +Brand#41|SMALL POLISHED TIN|45|4 +Brand#41|STANDARD ANODIZED COPPER|19|4 +Brand#41|STANDARD ANODIZED NICKEL|9|4 +Brand#41|STANDARD ANODIZED STEEL|49|4 +Brand#41|STANDARD ANODIZED TIN|9|4 +Brand#41|STANDARD ANODIZED TIN|36|4 +Brand#41|STANDARD ANODIZED TIN|49|4 +Brand#41|STANDARD BRUSHED BRASS|19|4 +Brand#41|STANDARD BRUSHED NICKEL|3|4 +Brand#41|STANDARD BRUSHED NICKEL|9|4 +Brand#41|STANDARD BRUSHED STEEL|45|4 +Brand#41|STANDARD BRUSHED TIN|45|4 +Brand#41|STANDARD BURNISHED BRASS|23|4 +Brand#41|STANDARD BURNISHED BRASS|36|4 +Brand#41|STANDARD BURNISHED COPPER|49|4 +Brand#41|STANDARD BURNISHED STEEL|45|4 +Brand#41|STANDARD PLATED BRASS|45|4 +Brand#41|STANDARD PLATED NICKEL|14|4 +Brand#41|STANDARD PLATED STEEL|45|4 +Brand#41|STANDARD PLATED TIN|49|4 +Brand#41|STANDARD POLISHED STEEL|9|4 +Brand#41|STANDARD POLISHED STEEL|19|4 +Brand#41|STANDARD POLISHED TIN|45|4 +Brand#42|ECONOMY ANODIZED NICKEL|19|4 +Brand#42|ECONOMY BRUSHED BRASS|14|4 +Brand#42|ECONOMY BRUSHED COPPER|3|4 +Brand#42|ECONOMY BRUSHED COPPER|14|4 +Brand#42|ECONOMY BRUSHED NICKEL|14|4 +Brand#42|ECONOMY BRUSHED STEEL|14|4 +Brand#42|ECONOMY BRUSHED TIN|19|4 +Brand#42|ECONOMY BRUSHED TIN|49|4 +Brand#42|ECONOMY BURNISHED BRASS|19|4 +Brand#42|ECONOMY BURNISHED COPPER|23|4 +Brand#42|ECONOMY BURNISHED NICKEL|14|4 +Brand#42|ECONOMY BURNISHED TIN|14|4 +Brand#42|ECONOMY PLATED COPPER|23|4 +Brand#42|ECONOMY POLISHED BRASS|3|4 +Brand#42|ECONOMY POLISHED COPPER|9|4 +Brand#42|ECONOMY POLISHED STEEL|9|4 +Brand#42|ECONOMY POLISHED STEEL|36|4 +Brand#42|ECONOMY POLISHED TIN|14|4 +Brand#42|LARGE ANODIZED BRASS|49|4 +Brand#42|LARGE ANODIZED COPPER|14|4 +Brand#42|LARGE ANODIZED COPPER|49|4 +Brand#42|LARGE ANODIZED NICKEL|45|4 +Brand#42|LARGE ANODIZED NICKEL|49|4 +Brand#42|LARGE ANODIZED TIN|45|4 +Brand#42|LARGE BRUSHED BRASS|49|4 +Brand#42|LARGE BURNISHED BRASS|45|4 +Brand#42|LARGE BURNISHED BRASS|49|4 +Brand#42|LARGE BURNISHED COPPER|9|4 +Brand#42|LARGE BURNISHED TIN|9|4 +Brand#42|LARGE PLATED BRASS|45|4 +Brand#42|LARGE PLATED COPPER|9|4 +Brand#42|LARGE PLATED NICKEL|36|4 +Brand#42|LARGE PLATED TIN|23|4 +Brand#42|LARGE POLISHED BRASS|9|4 +Brand#42|LARGE POLISHED NICKEL|3|4 +Brand#42|LARGE POLISHED NICKEL|23|4 +Brand#42|LARGE POLISHED STEEL|9|4 +Brand#42|MEDIUM ANODIZED BRASS|23|4 +Brand#42|MEDIUM ANODIZED COPPER|19|4 +Brand#42|MEDIUM ANODIZED NICKEL|14|4 +Brand#42|MEDIUM ANODIZED NICKEL|19|4 +Brand#42|MEDIUM ANODIZED NICKEL|23|4 +Brand#42|MEDIUM ANODIZED STEEL|9|4 +Brand#42|MEDIUM ANODIZED STEEL|14|4 +Brand#42|MEDIUM ANODIZED STEEL|23|4 +Brand#42|MEDIUM ANODIZED TIN|14|4 +Brand#42|MEDIUM ANODIZED TIN|19|4 +Brand#42|MEDIUM BRUSHED COPPER|45|4 +Brand#42|MEDIUM BRUSHED COPPER|49|4 +Brand#42|MEDIUM BRUSHED STEEL|36|4 +Brand#42|MEDIUM BURNISHED COPPER|49|4 +Brand#42|MEDIUM BURNISHED TIN|3|4 +Brand#42|MEDIUM BURNISHED TIN|49|4 +Brand#42|MEDIUM PLATED NICKEL|45|4 +Brand#42|MEDIUM PLATED STEEL|3|4 +Brand#42|MEDIUM PLATED STEEL|23|4 +Brand#42|MEDIUM PLATED STEEL|45|4 +Brand#42|PROMO ANODIZED NICKEL|3|4 +Brand#42|PROMO ANODIZED NICKEL|19|4 +Brand#42|PROMO ANODIZED STEEL|49|4 +Brand#42|PROMO BRUSHED COPPER|45|4 +Brand#42|PROMO BRUSHED STEEL|19|4 +Brand#42|PROMO BRUSHED TIN|45|4 +Brand#42|PROMO BURNISHED COPPER|45|4 +Brand#42|PROMO BURNISHED NICKEL|3|4 +Brand#42|PROMO BURNISHED STEEL|9|4 +Brand#42|PROMO BURNISHED TIN|49|4 +Brand#42|PROMO PLATED BRASS|45|4 +Brand#42|PROMO PLATED NICKEL|23|4 +Brand#42|PROMO PLATED STEEL|19|4 +Brand#42|PROMO PLATED STEEL|45|4 +Brand#42|PROMO POLISHED COPPER|36|4 +Brand#42|PROMO POLISHED NICKEL|3|4 +Brand#42|SMALL ANODIZED BRASS|23|4 +Brand#42|SMALL ANODIZED COPPER|14|4 +Brand#42|SMALL ANODIZED COPPER|19|4 +Brand#42|SMALL ANODIZED NICKEL|23|4 +Brand#42|SMALL BRUSHED TIN|49|4 +Brand#42|SMALL BURNISHED BRASS|3|4 +Brand#42|SMALL BURNISHED BRASS|36|4 +Brand#42|SMALL BURNISHED COPPER|9|4 +Brand#42|SMALL BURNISHED NICKEL|9|4 +Brand#42|SMALL BURNISHED TIN|9|4 +Brand#42|SMALL PLATED NICKEL|9|4 +Brand#42|SMALL PLATED TIN|36|4 +Brand#42|SMALL POLISHED BRASS|3|4 +Brand#42|SMALL POLISHED COPPER|36|4 +Brand#42|SMALL POLISHED NICKEL|23|4 +Brand#42|SMALL POLISHED STEEL|49|4 +Brand#42|SMALL POLISHED TIN|3|4 +Brand#42|STANDARD ANODIZED BRASS|49|4 +Brand#42|STANDARD ANODIZED COPPER|49|4 +Brand#42|STANDARD ANODIZED NICKEL|36|4 +Brand#42|STANDARD ANODIZED NICKEL|45|4 +Brand#42|STANDARD BRUSHED NICKEL|23|4 +Brand#42|STANDARD BURNISHED NICKEL|49|4 +Brand#42|STANDARD BURNISHED STEEL|3|4 +Brand#42|STANDARD BURNISHED TIN|19|4 +Brand#42|STANDARD PLATED BRASS|19|4 +Brand#42|STANDARD PLATED COPPER|9|4 +Brand#42|STANDARD PLATED NICKEL|45|4 +Brand#42|STANDARD PLATED STEEL|3|4 +Brand#42|STANDARD POLISHED BRASS|36|4 +Brand#42|STANDARD POLISHED BRASS|45|4 +Brand#42|STANDARD POLISHED COPPER|14|4 +Brand#42|STANDARD POLISHED NICKEL|45|4 +Brand#42|STANDARD POLISHED TIN|9|4 +Brand#42|STANDARD POLISHED TIN|19|4 +Brand#42|STANDARD POLISHED TIN|23|4 +Brand#42|STANDARD POLISHED TIN|36|4 +Brand#43|ECONOMY ANODIZED COPPER|19|4 +Brand#43|ECONOMY ANODIZED COPPER|45|4 +Brand#43|ECONOMY ANODIZED NICKEL|3|4 +Brand#43|ECONOMY ANODIZED NICKEL|49|4 +Brand#43|ECONOMY ANODIZED STEEL|23|4 +Brand#43|ECONOMY ANODIZED TIN|49|4 +Brand#43|ECONOMY BRUSHED BRASS|49|4 +Brand#43|ECONOMY BRUSHED COPPER|45|4 +Brand#43|ECONOMY BRUSHED NICKEL|9|4 +Brand#43|ECONOMY BURNISHED NICKEL|9|4 +Brand#43|ECONOMY BURNISHED TIN|19|4 +Brand#43|ECONOMY PLATED COPPER|36|4 +Brand#43|ECONOMY PLATED STEEL|9|4 +Brand#43|ECONOMY PLATED TIN|14|4 +Brand#43|ECONOMY PLATED TIN|19|4 +Brand#43|ECONOMY PLATED TIN|49|4 +Brand#43|ECONOMY POLISHED COPPER|19|4 +Brand#43|ECONOMY POLISHED NICKEL|36|4 +Brand#43|ECONOMY POLISHED TIN|14|4 +Brand#43|ECONOMY POLISHED TIN|45|4 +Brand#43|LARGE ANODIZED BRASS|14|4 +Brand#43|LARGE ANODIZED BRASS|36|4 +Brand#43|LARGE ANODIZED COPPER|45|4 +Brand#43|LARGE BRUSHED COPPER|3|4 +Brand#43|LARGE BRUSHED NICKEL|14|4 +Brand#43|LARGE BRUSHED NICKEL|19|4 +Brand#43|LARGE BRUSHED NICKEL|45|4 +Brand#43|LARGE BRUSHED NICKEL|49|4 +Brand#43|LARGE BURNISHED COPPER|3|4 +Brand#43|LARGE BURNISHED TIN|23|4 +Brand#43|LARGE BURNISHED TIN|45|4 +Brand#43|LARGE PLATED BRASS|45|4 +Brand#43|LARGE PLATED STEEL|14|4 +Brand#43|LARGE PLATED TIN|36|4 +Brand#43|LARGE PLATED TIN|45|4 +Brand#43|LARGE POLISHED BRASS|9|4 +Brand#43|LARGE POLISHED COPPER|9|4 +Brand#43|LARGE POLISHED COPPER|19|4 +Brand#43|LARGE POLISHED STEEL|14|4 +Brand#43|LARGE POLISHED TIN|45|4 +Brand#43|MEDIUM ANODIZED BRASS|14|4 +Brand#43|MEDIUM ANODIZED COPPER|36|4 +Brand#43|MEDIUM ANODIZED COPPER|49|4 +Brand#43|MEDIUM ANODIZED STEEL|19|4 +Brand#43|MEDIUM ANODIZED STEEL|36|4 +Brand#43|MEDIUM BRUSHED BRASS|9|4 +Brand#43|MEDIUM BRUSHED BRASS|49|4 +Brand#43|MEDIUM BRUSHED COPPER|3|4 +Brand#43|MEDIUM BRUSHED NICKEL|9|4 +Brand#43|MEDIUM BRUSHED STEEL|23|4 +Brand#43|MEDIUM BURNISHED COPPER|14|4 +Brand#43|MEDIUM BURNISHED COPPER|45|4 +Brand#43|MEDIUM BURNISHED TIN|23|4 +Brand#43|MEDIUM PLATED BRASS|3|4 +Brand#43|MEDIUM PLATED COPPER|14|4 +Brand#43|MEDIUM PLATED NICKEL|36|4 +Brand#43|MEDIUM PLATED NICKEL|45|4 +Brand#43|MEDIUM PLATED TIN|49|4 +Brand#43|PROMO ANODIZED NICKEL|45|4 +Brand#43|PROMO ANODIZED TIN|14|4 +Brand#43|PROMO BRUSHED NICKEL|14|4 +Brand#43|PROMO BRUSHED STEEL|14|4 +Brand#43|PROMO BRUSHED TIN|45|4 +Brand#43|PROMO BURNISHED BRASS|49|4 +Brand#43|PROMO BURNISHED NICKEL|9|4 +Brand#43|PROMO BURNISHED STEEL|3|4 +Brand#43|PROMO BURNISHED STEEL|36|4 +Brand#43|PROMO BURNISHED TIN|36|4 +Brand#43|PROMO PLATED BRASS|19|4 +Brand#43|PROMO PLATED COPPER|45|4 +Brand#43|PROMO PLATED COPPER|49|4 +Brand#43|PROMO PLATED TIN|3|4 +Brand#43|PROMO POLISHED BRASS|19|4 +Brand#43|PROMO POLISHED BRASS|23|4 +Brand#43|PROMO POLISHED NICKEL|49|4 +Brand#43|PROMO POLISHED STEEL|14|4 +Brand#43|PROMO POLISHED STEEL|19|4 +Brand#43|PROMO POLISHED STEEL|23|4 +Brand#43|PROMO POLISHED STEEL|36|4 +Brand#43|SMALL ANODIZED BRASS|19|4 +Brand#43|SMALL ANODIZED NICKEL|9|4 +Brand#43|SMALL BRUSHED NICKEL|3|4 +Brand#43|SMALL BRUSHED NICKEL|9|4 +Brand#43|SMALL BURNISHED BRASS|49|4 +Brand#43|SMALL BURNISHED STEEL|23|4 +Brand#43|SMALL PLATED BRASS|14|4 +Brand#43|SMALL PLATED BRASS|36|4 +Brand#43|SMALL PLATED COPPER|23|4 +Brand#43|SMALL PLATED COPPER|49|4 +Brand#43|SMALL PLATED NICKEL|36|4 +Brand#43|SMALL PLATED NICKEL|49|4 +Brand#43|SMALL PLATED STEEL|14|4 +Brand#43|SMALL PLATED TIN|49|4 +Brand#43|SMALL POLISHED STEEL|19|4 +Brand#43|STANDARD ANODIZED BRASS|3|4 +Brand#43|STANDARD ANODIZED COPPER|49|4 +Brand#43|STANDARD ANODIZED NICKEL|14|4 +Brand#43|STANDARD BRUSHED TIN|14|4 +Brand#43|STANDARD BURNISHED BRASS|23|4 +Brand#43|STANDARD BURNISHED STEEL|19|4 +Brand#43|STANDARD BURNISHED STEEL|23|4 +Brand#43|STANDARD PLATED BRASS|9|4 +Brand#43|STANDARD PLATED BRASS|19|4 +Brand#43|STANDARD PLATED BRASS|49|4 +Brand#43|STANDARD PLATED COPPER|36|4 +Brand#43|STANDARD PLATED NICKEL|14|4 +Brand#43|STANDARD PLATED NICKEL|19|4 +Brand#43|STANDARD PLATED TIN|14|4 +Brand#43|STANDARD POLISHED BRASS|23|4 +Brand#43|STANDARD POLISHED TIN|9|4 +Brand#44|ECONOMY ANODIZED BRASS|3|4 +Brand#44|ECONOMY ANODIZED BRASS|45|4 +Brand#44|ECONOMY ANODIZED NICKEL|36|4 +Brand#44|ECONOMY ANODIZED STEEL|19|4 +Brand#44|ECONOMY BRUSHED COPPER|23|4 +Brand#44|ECONOMY BRUSHED TIN|49|4 +Brand#44|ECONOMY BURNISHED COPPER|19|4 +Brand#44|ECONOMY BURNISHED STEEL|45|4 +Brand#44|ECONOMY PLATED STEEL|19|4 +Brand#44|ECONOMY PLATED STEEL|23|4 +Brand#44|ECONOMY PLATED TIN|23|4 +Brand#44|ECONOMY POLISHED BRASS|23|4 +Brand#44|ECONOMY POLISHED COPPER|9|4 +Brand#44|ECONOMY POLISHED COPPER|45|4 +Brand#44|ECONOMY POLISHED NICKEL|14|4 +Brand#44|ECONOMY POLISHED NICKEL|23|4 +Brand#44|ECONOMY POLISHED STEEL|49|4 +Brand#44|ECONOMY POLISHED TIN|23|4 +Brand#44|ECONOMY POLISHED TIN|36|4 +Brand#44|LARGE ANODIZED BRASS|19|4 +Brand#44|LARGE ANODIZED TIN|3|4 +Brand#44|LARGE ANODIZED TIN|14|4 +Brand#44|LARGE BRUSHED TIN|3|4 +Brand#44|LARGE BRUSHED TIN|23|4 +Brand#44|LARGE BURNISHED BRASS|23|4 +Brand#44|LARGE BURNISHED BRASS|49|4 +Brand#44|LARGE BURNISHED COPPER|3|4 +Brand#44|LARGE BURNISHED COPPER|19|4 +Brand#44|LARGE BURNISHED COPPER|36|4 +Brand#44|LARGE BURNISHED TIN|14|4 +Brand#44|LARGE PLATED BRASS|9|4 +Brand#44|LARGE PLATED BRASS|49|4 +Brand#44|LARGE PLATED NICKEL|14|4 +Brand#44|LARGE PLATED STEEL|14|4 +Brand#44|LARGE PLATED TIN|19|4 +Brand#44|LARGE PLATED TIN|23|4 +Brand#44|LARGE POLISHED STEEL|23|4 +Brand#44|LARGE POLISHED STEEL|49|4 +Brand#44|MEDIUM ANODIZED COPPER|45|4 +Brand#44|MEDIUM ANODIZED NICKEL|45|4 +Brand#44|MEDIUM BRUSHED BRASS|49|4 +Brand#44|MEDIUM BRUSHED COPPER|3|4 +Brand#44|MEDIUM BRUSHED COPPER|45|4 +Brand#44|MEDIUM BRUSHED STEEL|19|4 +Brand#44|MEDIUM BRUSHED TIN|49|4 +Brand#44|MEDIUM BURNISHED COPPER|45|4 +Brand#44|MEDIUM BURNISHED NICKEL|23|4 +Brand#44|MEDIUM BURNISHED TIN|23|4 +Brand#44|MEDIUM PLATED COPPER|14|4 +Brand#44|PROMO ANODIZED COPPER|23|4 +Brand#44|PROMO ANODIZED STEEL|36|4 +Brand#44|PROMO BRUSHED COPPER|23|4 +Brand#44|PROMO BRUSHED COPPER|36|4 +Brand#44|PROMO BRUSHED TIN|19|4 +Brand#44|PROMO PLATED BRASS|3|4 +Brand#44|PROMO PLATED COPPER|36|4 +Brand#44|PROMO PLATED STEEL|3|4 +Brand#44|PROMO PLATED STEEL|36|4 +Brand#44|PROMO PLATED STEEL|49|4 +Brand#44|PROMO POLISHED BRASS|3|4 +Brand#44|PROMO POLISHED BRASS|19|4 +Brand#44|PROMO POLISHED COPPER|45|4 +Brand#44|PROMO POLISHED STEEL|36|4 +Brand#44|PROMO POLISHED TIN|9|4 +Brand#44|SMALL ANODIZED COPPER|23|4 +Brand#44|SMALL ANODIZED STEEL|23|4 +Brand#44|SMALL ANODIZED TIN|45|4 +Brand#44|SMALL BRUSHED COPPER|14|4 +Brand#44|SMALL BRUSHED STEEL|45|4 +Brand#44|SMALL BURNISHED COPPER|14|4 +Brand#44|SMALL BURNISHED COPPER|49|4 +Brand#44|SMALL BURNISHED NICKEL|14|4 +Brand#44|SMALL BURNISHED STEEL|23|4 +Brand#44|SMALL BURNISHED TIN|49|4 +Brand#44|SMALL PLATED BRASS|36|4 +Brand#44|SMALL PLATED COPPER|19|4 +Brand#44|SMALL PLATED NICKEL|3|4 +Brand#44|SMALL POLISHED COPPER|3|4 +Brand#44|SMALL POLISHED COPPER|49|4 +Brand#44|SMALL POLISHED STEEL|3|4 +Brand#44|STANDARD ANODIZED BRASS|3|4 +Brand#44|STANDARD ANODIZED COPPER|3|4 +Brand#44|STANDARD ANODIZED NICKEL|3|4 +Brand#44|STANDARD ANODIZED NICKEL|36|4 +Brand#44|STANDARD ANODIZED STEEL|14|4 +Brand#44|STANDARD ANODIZED TIN|3|4 +Brand#44|STANDARD ANODIZED TIN|9|4 +Brand#44|STANDARD ANODIZED TIN|36|4 +Brand#44|STANDARD BRUSHED COPPER|36|4 +Brand#44|STANDARD BRUSHED COPPER|45|4 +Brand#44|STANDARD BRUSHED TIN|9|4 +Brand#44|STANDARD BRUSHED TIN|49|4 +Brand#44|STANDARD BURNISHED COPPER|9|4 +Brand#44|STANDARD BURNISHED STEEL|23|4 +Brand#44|STANDARD PLATED BRASS|14|4 +Brand#44|STANDARD PLATED BRASS|23|4 +Brand#44|STANDARD PLATED BRASS|49|4 +Brand#44|STANDARD PLATED COPPER|14|4 +Brand#44|STANDARD POLISHED NICKEL|19|4 +Brand#44|STANDARD POLISHED TIN|9|4 +Brand#51|ECONOMY ANODIZED BRASS|9|4 +Brand#51|ECONOMY ANODIZED BRASS|23|4 +Brand#51|ECONOMY ANODIZED NICKEL|3|4 +Brand#51|ECONOMY ANODIZED NICKEL|23|4 +Brand#51|ECONOMY ANODIZED STEEL|19|4 +Brand#51|ECONOMY ANODIZED STEEL|23|4 +Brand#51|ECONOMY ANODIZED STEEL|49|4 +Brand#51|ECONOMY BRUSHED BRASS|3|4 +Brand#51|ECONOMY BRUSHED BRASS|49|4 +Brand#51|ECONOMY BRUSHED NICKEL|14|4 +Brand#51|ECONOMY BRUSHED STEEL|45|4 +Brand#51|ECONOMY BRUSHED TIN|36|4 +Brand#51|ECONOMY BURNISHED BRASS|14|4 +Brand#51|ECONOMY BURNISHED COPPER|45|4 +Brand#51|ECONOMY PLATED NICKEL|49|4 +Brand#51|ECONOMY PLATED TIN|36|4 +Brand#51|ECONOMY POLISHED COPPER|9|4 +Brand#51|ECONOMY POLISHED STEEL|14|4 +Brand#51|ECONOMY POLISHED STEEL|49|4 +Brand#51|LARGE ANODIZED COPPER|9|4 +Brand#51|LARGE ANODIZED COPPER|49|4 +Brand#51|LARGE ANODIZED NICKEL|14|4 +Brand#51|LARGE ANODIZED STEEL|36|4 +Brand#51|LARGE BRUSHED NICKEL|3|4 +Brand#51|LARGE BRUSHED NICKEL|9|4 +Brand#51|LARGE BURNISHED BRASS|19|4 +Brand#51|LARGE BURNISHED BRASS|36|4 +Brand#51|LARGE BURNISHED COPPER|14|4 +Brand#51|LARGE BURNISHED NICKEL|14|4 +Brand#51|LARGE PLATED BRASS|36|4 +Brand#51|LARGE POLISHED COPPER|14|4 +Brand#51|LARGE POLISHED NICKEL|23|4 +Brand#51|LARGE POLISHED NICKEL|36|4 +Brand#51|LARGE POLISHED STEEL|19|4 +Brand#51|MEDIUM ANODIZED COPPER|9|4 +Brand#51|MEDIUM ANODIZED STEEL|3|4 +Brand#51|MEDIUM BRUSHED BRASS|36|4 +Brand#51|MEDIUM BRUSHED BRASS|45|4 +Brand#51|MEDIUM BRUSHED STEEL|3|4 +Brand#51|MEDIUM BRUSHED TIN|36|4 +Brand#51|MEDIUM BURNISHED NICKEL|3|4 +Brand#51|MEDIUM BURNISHED NICKEL|36|4 +Brand#51|MEDIUM BURNISHED STEEL|14|4 +Brand#51|MEDIUM BURNISHED TIN|9|4 +Brand#51|MEDIUM PLATED STEEL|19|4 +Brand#51|MEDIUM PLATED TIN|3|4 +Brand#51|PROMO ANODIZED NICKEL|14|4 +Brand#51|PROMO ANODIZED STEEL|23|4 +Brand#51|PROMO ANODIZED TIN|19|4 +Brand#51|PROMO BRUSHED BRASS|23|4 +Brand#51|PROMO BRUSHED COPPER|45|4 +Brand#51|PROMO BRUSHED STEEL|45|4 +Brand#51|PROMO BRUSHED TIN|9|4 +Brand#51|PROMO BURNISHED BRASS|19|4 +Brand#51|PROMO BURNISHED BRASS|23|4 +Brand#51|PROMO BURNISHED NICKEL|14|4 +Brand#51|PROMO PLATED BRASS|3|4 +Brand#51|PROMO PLATED BRASS|23|4 +Brand#51|PROMO PLATED TIN|19|4 +Brand#51|PROMO PLATED TIN|23|4 +Brand#51|PROMO POLISHED BRASS|23|4 +Brand#51|PROMO POLISHED COPPER|9|4 +Brand#51|PROMO POLISHED NICKEL|9|4 +Brand#51|PROMO POLISHED STEEL|49|4 +Brand#51|SMALL ANODIZED STEEL|14|4 +Brand#51|SMALL BRUSHED BRASS|23|4 +Brand#51|SMALL BRUSHED TIN|19|4 +Brand#51|SMALL BURNISHED NICKEL|23|4 +Brand#51|SMALL PLATED COPPER|49|4 +Brand#51|SMALL PLATED NICKEL|3|4 +Brand#51|SMALL PLATED NICKEL|14|4 +Brand#51|SMALL PLATED STEEL|45|4 +Brand#51|SMALL POLISHED NICKEL|14|4 +Brand#51|SMALL POLISHED NICKEL|23|4 +Brand#51|SMALL POLISHED STEEL|3|4 +Brand#51|SMALL POLISHED STEEL|19|4 +Brand#51|SMALL POLISHED STEEL|49|4 +Brand#51|STANDARD ANODIZED NICKEL|3|4 +Brand#51|STANDARD ANODIZED NICKEL|49|4 +Brand#51|STANDARD BRUSHED BRASS|3|4 +Brand#51|STANDARD BRUSHED COPPER|3|4 +Brand#51|STANDARD BRUSHED NICKEL|19|4 +Brand#51|STANDARD BRUSHED STEEL|36|4 +Brand#51|STANDARD BURNISHED COPPER|19|4 +Brand#51|STANDARD BURNISHED NICKEL|49|4 +Brand#51|STANDARD BURNISHED STEEL|23|4 +Brand#51|STANDARD BURNISHED STEEL|36|4 +Brand#51|STANDARD BURNISHED TIN|45|4 +Brand#51|STANDARD PLATED BRASS|36|4 +Brand#51|STANDARD PLATED BRASS|49|4 +Brand#51|STANDARD PLATED COPPER|14|4 +Brand#51|STANDARD PLATED COPPER|23|4 +Brand#51|STANDARD POLISHED BRASS|14|4 +Brand#51|STANDARD POLISHED BRASS|45|4 +Brand#51|STANDARD POLISHED STEEL|36|4 +Brand#51|STANDARD POLISHED STEEL|49|4 +Brand#51|STANDARD POLISHED TIN|45|4 +Brand#52|ECONOMY ANODIZED BRASS|14|4 +Brand#52|ECONOMY ANODIZED BRASS|23|4 +Brand#52|ECONOMY ANODIZED COPPER|36|4 +Brand#52|ECONOMY ANODIZED NICKEL|49|4 +Brand#52|ECONOMY ANODIZED STEEL|19|4 +Brand#52|ECONOMY BRUSHED COPPER|49|4 +Brand#52|ECONOMY BURNISHED BRASS|36|4 +Brand#52|ECONOMY BURNISHED COPPER|19|4 +Brand#52|ECONOMY BURNISHED COPPER|45|4 +Brand#52|ECONOMY BURNISHED NICKEL|19|4 +Brand#52|ECONOMY BURNISHED STEEL|36|4 +Brand#52|ECONOMY PLATED TIN|14|4 +Brand#52|ECONOMY PLATED TIN|23|4 +Brand#52|ECONOMY POLISHED BRASS|23|4 +Brand#52|ECONOMY POLISHED BRASS|45|4 +Brand#52|ECONOMY POLISHED NICKEL|36|4 +Brand#52|ECONOMY POLISHED STEEL|49|4 +Brand#52|LARGE ANODIZED COPPER|14|4 +Brand#52|LARGE ANODIZED NICKEL|3|4 +Brand#52|LARGE ANODIZED NICKEL|45|4 +Brand#52|LARGE ANODIZED TIN|45|4 +Brand#52|LARGE BRUSHED COPPER|19|4 +Brand#52|LARGE BRUSHED NICKEL|3|4 +Brand#52|LARGE BRUSHED NICKEL|19|4 +Brand#52|LARGE BRUSHED NICKEL|23|4 +Brand#52|LARGE BRUSHED STEEL|49|4 +Brand#52|LARGE BRUSHED TIN|14|4 +Brand#52|LARGE BURNISHED NICKEL|9|4 +Brand#52|LARGE BURNISHED TIN|23|4 +Brand#52|LARGE BURNISHED TIN|45|4 +Brand#52|LARGE PLATED BRASS|14|4 +Brand#52|LARGE PLATED COPPER|14|4 +Brand#52|LARGE PLATED COPPER|19|4 +Brand#52|LARGE PLATED NICKEL|45|4 +Brand#52|LARGE PLATED STEEL|9|4 +Brand#52|LARGE PLATED TIN|9|4 +Brand#52|LARGE POLISHED NICKEL|19|4 +Brand#52|LARGE POLISHED NICKEL|23|4 +Brand#52|LARGE POLISHED NICKEL|36|4 +Brand#52|LARGE POLISHED TIN|9|4 +Brand#52|MEDIUM ANODIZED COPPER|36|4 +Brand#52|MEDIUM ANODIZED STEEL|14|4 +Brand#52|MEDIUM ANODIZED TIN|3|4 +Brand#52|MEDIUM ANODIZED TIN|49|4 +Brand#52|MEDIUM BRUSHED COPPER|9|4 +Brand#52|MEDIUM BRUSHED NICKEL|9|4 +Brand#52|MEDIUM BRUSHED STEEL|23|4 +Brand#52|MEDIUM BRUSHED STEEL|49|4 +Brand#52|MEDIUM BURNISHED STEEL|23|4 +Brand#52|MEDIUM BURNISHED TIN|45|4 +Brand#52|MEDIUM BURNISHED TIN|49|4 +Brand#52|MEDIUM PLATED BRASS|36|4 +Brand#52|MEDIUM PLATED STEEL|9|4 +Brand#52|MEDIUM PLATED STEEL|49|4 +Brand#52|MEDIUM PLATED TIN|9|4 +Brand#52|MEDIUM PLATED TIN|49|4 +Brand#52|PROMO ANODIZED BRASS|9|4 +Brand#52|PROMO ANODIZED BRASS|23|4 +Brand#52|PROMO ANODIZED BRASS|36|4 +Brand#52|PROMO ANODIZED NICKEL|45|4 +Brand#52|PROMO ANODIZED STEEL|36|4 +Brand#52|PROMO BRUSHED COPPER|3|4 +Brand#52|PROMO BRUSHED NICKEL|3|4 +Brand#52|PROMO BRUSHED NICKEL|49|4 +Brand#52|PROMO BRUSHED STEEL|14|4 +Brand#52|PROMO BRUSHED TIN|3|4 +Brand#52|PROMO BRUSHED TIN|19|4 +Brand#52|PROMO BRUSHED TIN|36|4 +Brand#52|PROMO BURNISHED COPPER|49|4 +Brand#52|PROMO BURNISHED NICKEL|9|4 +Brand#52|PROMO BURNISHED STEEL|9|4 +Brand#52|PROMO BURNISHED STEEL|23|4 +Brand#52|PROMO BURNISHED TIN|19|4 +Brand#52|PROMO BURNISHED TIN|36|4 +Brand#52|PROMO PLATED BRASS|19|4 +Brand#52|PROMO PLATED BRASS|45|4 +Brand#52|PROMO PLATED BRASS|49|4 +Brand#52|PROMO PLATED COPPER|9|4 +Brand#52|PROMO PLATED NICKEL|3|4 +Brand#52|PROMO PLATED NICKEL|23|4 +Brand#52|PROMO POLISHED NICKEL|14|4 +Brand#52|PROMO POLISHED NICKEL|49|4 +Brand#52|PROMO POLISHED TIN|36|4 +Brand#52|SMALL ANODIZED BRASS|3|4 +Brand#52|SMALL ANODIZED BRASS|14|4 +Brand#52|SMALL ANODIZED COPPER|3|4 +Brand#52|SMALL ANODIZED NICKEL|36|4 +Brand#52|SMALL ANODIZED STEEL|9|4 +Brand#52|SMALL ANODIZED STEEL|19|4 +Brand#52|SMALL BRUSHED NICKEL|19|4 +Brand#52|SMALL BRUSHED STEEL|23|4 +Brand#52|SMALL BRUSHED TIN|14|4 +Brand#52|SMALL BRUSHED TIN|19|4 +Brand#52|SMALL BURNISHED NICKEL|14|4 +Brand#52|SMALL BURNISHED NICKEL|49|4 +Brand#52|SMALL BURNISHED TIN|9|4 +Brand#52|SMALL POLISHED BRASS|36|4 +Brand#52|SMALL POLISHED BRASS|49|4 +Brand#52|SMALL POLISHED TIN|45|4 +Brand#52|STANDARD ANODIZED BRASS|45|4 +Brand#52|STANDARD BRUSHED BRASS|23|4 +Brand#52|STANDARD BRUSHED COPPER|14|4 +Brand#52|STANDARD BRUSHED TIN|36|4 +Brand#52|STANDARD BURNISHED BRASS|49|4 +Brand#52|STANDARD BURNISHED STEEL|19|4 +Brand#52|STANDARD BURNISHED TIN|9|4 +Brand#52|STANDARD BURNISHED TIN|19|4 +Brand#52|STANDARD PLATED NICKEL|36|4 +Brand#52|STANDARD PLATED STEEL|36|4 +Brand#52|STANDARD POLISHED BRASS|36|4 +Brand#52|STANDARD POLISHED COPPER|45|4 +Brand#52|STANDARD POLISHED STEEL|19|4 +Brand#52|STANDARD POLISHED TIN|19|4 +Brand#53|ECONOMY ANODIZED BRASS|45|4 +Brand#53|ECONOMY ANODIZED COPPER|9|4 +Brand#53|ECONOMY ANODIZED NICKEL|3|4 +Brand#53|ECONOMY ANODIZED NICKEL|19|4 +Brand#53|ECONOMY ANODIZED STEEL|45|4 +Brand#53|ECONOMY ANODIZED TIN|14|4 +Brand#53|ECONOMY ANODIZED TIN|36|4 +Brand#53|ECONOMY BRUSHED TIN|45|4 +Brand#53|ECONOMY BURNISHED BRASS|14|4 +Brand#53|ECONOMY BURNISHED COPPER|45|4 +Brand#53|ECONOMY BURNISHED NICKEL|3|4 +Brand#53|ECONOMY BURNISHED NICKEL|49|4 +Brand#53|ECONOMY BURNISHED TIN|45|4 +Brand#53|ECONOMY PLATED BRASS|3|4 +Brand#53|ECONOMY PLATED NICKEL|14|4 +Brand#53|ECONOMY PLATED STEEL|23|4 +Brand#53|ECONOMY PLATED STEEL|36|4 +Brand#53|ECONOMY POLISHED TIN|36|4 +Brand#53|LARGE ANODIZED NICKEL|49|4 +Brand#53|LARGE ANODIZED STEEL|19|4 +Brand#53|LARGE BRUSHED COPPER|3|4 +Brand#53|LARGE BRUSHED COPPER|14|4 +Brand#53|LARGE BRUSHED NICKEL|23|4 +Brand#53|LARGE BRUSHED NICKEL|36|4 +Brand#53|LARGE BRUSHED TIN|36|4 +Brand#53|LARGE BURNISHED BRASS|45|4 +Brand#53|LARGE BURNISHED COPPER|19|4 +Brand#53|LARGE BURNISHED COPPER|36|4 +Brand#53|LARGE BURNISHED NICKEL|23|4 +Brand#53|LARGE BURNISHED STEEL|19|4 +Brand#53|LARGE BURNISHED STEEL|23|4 +Brand#53|LARGE PLATED BRASS|9|4 +Brand#53|LARGE PLATED BRASS|45|4 +Brand#53|LARGE PLATED BRASS|49|4 +Brand#53|LARGE PLATED COPPER|23|4 +Brand#53|LARGE PLATED NICKEL|23|4 +Brand#53|LARGE PLATED NICKEL|49|4 +Brand#53|LARGE PLATED STEEL|49|4 +Brand#53|LARGE PLATED TIN|14|4 +Brand#53|LARGE POLISHED COPPER|49|4 +Brand#53|LARGE POLISHED STEEL|36|4 +Brand#53|LARGE POLISHED TIN|9|4 +Brand#53|MEDIUM ANODIZED BRASS|23|4 +Brand#53|MEDIUM ANODIZED STEEL|14|4 +Brand#53|MEDIUM ANODIZED STEEL|36|4 +Brand#53|MEDIUM ANODIZED TIN|3|4 +Brand#53|MEDIUM ANODIZED TIN|9|4 +Brand#53|MEDIUM BRUSHED BRASS|3|4 +Brand#53|MEDIUM BRUSHED COPPER|3|4 +Brand#53|MEDIUM BRUSHED NICKEL|14|4 +Brand#53|MEDIUM BRUSHED NICKEL|36|4 +Brand#53|MEDIUM BRUSHED NICKEL|49|4 +Brand#53|MEDIUM BRUSHED STEEL|45|4 +Brand#53|MEDIUM BURNISHED BRASS|3|4 +Brand#53|MEDIUM BURNISHED BRASS|36|4 +Brand#53|MEDIUM BURNISHED TIN|9|4 +Brand#53|MEDIUM BURNISHED TIN|14|4 +Brand#53|MEDIUM BURNISHED TIN|36|4 +Brand#53|MEDIUM PLATED BRASS|23|4 +Brand#53|MEDIUM PLATED COPPER|14|4 +Brand#53|MEDIUM PLATED NICKEL|45|4 +Brand#53|MEDIUM PLATED TIN|19|4 +Brand#53|MEDIUM PLATED TIN|45|4 +Brand#53|PROMO ANODIZED BRASS|36|4 +Brand#53|PROMO ANODIZED NICKEL|3|4 +Brand#53|PROMO ANODIZED NICKEL|19|4 +Brand#53|PROMO BRUSHED BRASS|45|4 +Brand#53|PROMO BRUSHED COPPER|3|4 +Brand#53|PROMO BRUSHED COPPER|23|4 +Brand#53|PROMO BRUSHED COPPER|45|4 +Brand#53|PROMO BURNISHED BRASS|23|4 +Brand#53|PROMO BURNISHED BRASS|36|4 +Brand#53|PROMO BURNISHED NICKEL|23|4 +Brand#53|PROMO BURNISHED STEEL|23|4 +Brand#53|PROMO BURNISHED STEEL|49|4 +Brand#53|PROMO PLATED TIN|19|4 +Brand#53|PROMO PLATED TIN|23|4 +Brand#53|PROMO PLATED TIN|36|4 +Brand#53|PROMO POLISHED STEEL|23|4 +Brand#53|PROMO POLISHED TIN|3|4 +Brand#53|SMALL ANODIZED COPPER|23|4 +Brand#53|SMALL ANODIZED COPPER|36|4 +Brand#53|SMALL ANODIZED COPPER|49|4 +Brand#53|SMALL ANODIZED NICKEL|36|4 +Brand#53|SMALL BRUSHED BRASS|36|4 +Brand#53|SMALL BRUSHED COPPER|3|4 +Brand#53|SMALL BRUSHED TIN|3|4 +Brand#53|SMALL BRUSHED TIN|36|4 +Brand#53|SMALL BURNISHED BRASS|9|4 +Brand#53|SMALL BURNISHED BRASS|49|4 +Brand#53|SMALL BURNISHED COPPER|19|4 +Brand#53|SMALL BURNISHED COPPER|45|4 +Brand#53|SMALL PLATED BRASS|9|4 +Brand#53|SMALL PLATED COPPER|3|4 +Brand#53|SMALL PLATED NICKEL|14|4 +Brand#53|SMALL POLISHED NICKEL|19|4 +Brand#53|SMALL POLISHED STEEL|36|4 +Brand#53|SMALL POLISHED TIN|23|4 +Brand#53|STANDARD ANODIZED BRASS|14|4 +Brand#53|STANDARD ANODIZED NICKEL|9|4 +Brand#53|STANDARD ANODIZED NICKEL|23|4 +Brand#53|STANDARD ANODIZED NICKEL|45|4 +Brand#53|STANDARD ANODIZED STEEL|45|4 +Brand#53|STANDARD BRUSHED COPPER|3|4 +Brand#53|STANDARD BRUSHED NICKEL|23|4 +Brand#53|STANDARD BRUSHED TIN|14|4 +Brand#53|STANDARD BURNISHED NICKEL|49|4 +Brand#53|STANDARD BURNISHED STEEL|9|4 +Brand#53|STANDARD PLATED BRASS|36|4 +Brand#53|STANDARD PLATED COPPER|45|4 +Brand#53|STANDARD PLATED NICKEL|36|4 +Brand#53|STANDARD PLATED STEEL|3|4 +Brand#53|STANDARD PLATED STEEL|49|4 +Brand#53|STANDARD PLATED TIN|23|4 +Brand#53|STANDARD POLISHED STEEL|3|4 +Brand#54|ECONOMY ANODIZED BRASS|9|4 +Brand#54|ECONOMY ANODIZED BRASS|45|4 +Brand#54|ECONOMY ANODIZED COPPER|9|4 +Brand#54|ECONOMY ANODIZED STEEL|19|4 +Brand#54|ECONOMY BRUSHED BRASS|45|4 +Brand#54|ECONOMY BRUSHED NICKEL|19|4 +Brand#54|ECONOMY BRUSHED STEEL|3|4 +Brand#54|ECONOMY BRUSHED TIN|19|4 +Brand#54|ECONOMY BURNISHED BRASS|45|4 +Brand#54|ECONOMY BURNISHED COPPER|14|4 +Brand#54|ECONOMY BURNISHED NICKEL|9|4 +Brand#54|ECONOMY BURNISHED NICKEL|36|4 +Brand#54|ECONOMY BURNISHED STEEL|36|4 +Brand#54|ECONOMY BURNISHED TIN|9|4 +Brand#54|ECONOMY BURNISHED TIN|14|4 +Brand#54|ECONOMY BURNISHED TIN|23|4 +Brand#54|ECONOMY PLATED TIN|23|4 +Brand#54|ECONOMY POLISHED BRASS|9|4 +Brand#54|ECONOMY POLISHED BRASS|19|4 +Brand#54|ECONOMY POLISHED COPPER|23|4 +Brand#54|ECONOMY POLISHED STEEL|23|4 +Brand#54|ECONOMY POLISHED TIN|3|4 +Brand#54|LARGE ANODIZED BRASS|14|4 +Brand#54|LARGE ANODIZED BRASS|49|4 +Brand#54|LARGE ANODIZED TIN|9|4 +Brand#54|LARGE BRUSHED BRASS|14|4 +Brand#54|LARGE BRUSHED STEEL|9|4 +Brand#54|LARGE BRUSHED STEEL|23|4 +Brand#54|LARGE BRUSHED TIN|14|4 +Brand#54|LARGE BURNISHED BRASS|49|4 +Brand#54|LARGE BURNISHED COPPER|19|4 +Brand#54|LARGE BURNISHED NICKEL|14|4 +Brand#54|LARGE BURNISHED TIN|14|4 +Brand#54|LARGE PLATED BRASS|19|4 +Brand#54|LARGE PLATED BRASS|23|4 +Brand#54|LARGE POLISHED BRASS|19|4 +Brand#54|LARGE POLISHED BRASS|23|4 +Brand#54|LARGE POLISHED NICKEL|3|4 +Brand#54|LARGE POLISHED NICKEL|14|4 +Brand#54|LARGE POLISHED STEEL|19|4 +Brand#54|LARGE POLISHED TIN|3|4 +Brand#54|LARGE POLISHED TIN|9|4 +Brand#54|LARGE POLISHED TIN|36|4 +Brand#54|MEDIUM ANODIZED NICKEL|9|4 +Brand#54|MEDIUM ANODIZED NICKEL|14|4 +Brand#54|MEDIUM ANODIZED NICKEL|36|4 +Brand#54|MEDIUM BRUSHED NICKEL|9|4 +Brand#54|MEDIUM BRUSHED NICKEL|19|4 +Brand#54|MEDIUM BURNISHED STEEL|3|4 +Brand#54|MEDIUM BURNISHED STEEL|19|4 +Brand#54|MEDIUM BURNISHED STEEL|23|4 +Brand#54|MEDIUM PLATED BRASS|3|4 +Brand#54|MEDIUM PLATED NICKEL|45|4 +Brand#54|PROMO ANODIZED NICKEL|45|4 +Brand#54|PROMO BRUSHED BRASS|3|4 +Brand#54|PROMO BRUSHED STEEL|23|4 +Brand#54|PROMO BRUSHED TIN|14|4 +Brand#54|PROMO BURNISHED COPPER|49|4 +Brand#54|PROMO BURNISHED TIN|9|4 +Brand#54|PROMO PLATED BRASS|14|4 +Brand#54|PROMO PLATED NICKEL|3|4 +Brand#54|PROMO PLATED STEEL|19|4 +Brand#54|PROMO PLATED TIN|23|4 +Brand#54|PROMO PLATED TIN|49|4 +Brand#54|PROMO POLISHED BRASS|3|4 +Brand#54|PROMO POLISHED NICKEL|9|4 +Brand#54|PROMO POLISHED TIN|49|4 +Brand#54|SMALL ANODIZED COPPER|49|4 +Brand#54|SMALL ANODIZED NICKEL|9|4 +Brand#54|SMALL ANODIZED NICKEL|36|4 +Brand#54|SMALL ANODIZED TIN|19|4 +Brand#54|SMALL BRUSHED BRASS|14|4 +Brand#54|SMALL BRUSHED BRASS|19|4 +Brand#54|SMALL BRUSHED BRASS|36|4 +Brand#54|SMALL BRUSHED COPPER|3|4 +Brand#54|SMALL BRUSHED COPPER|9|4 +Brand#54|SMALL BRUSHED COPPER|19|4 +Brand#54|SMALL BRUSHED TIN|9|4 +Brand#54|SMALL BRUSHED TIN|36|4 +Brand#54|SMALL BURNISHED COPPER|9|4 +Brand#54|SMALL BURNISHED COPPER|36|4 +Brand#54|SMALL BURNISHED STEEL|14|4 +Brand#54|SMALL BURNISHED STEEL|19|4 +Brand#54|SMALL BURNISHED TIN|9|4 +Brand#54|SMALL BURNISHED TIN|36|4 +Brand#54|SMALL PLATED BRASS|23|4 +Brand#54|SMALL PLATED COPPER|9|4 +Brand#54|SMALL PLATED COPPER|36|4 +Brand#54|SMALL PLATED COPPER|49|4 +Brand#54|SMALL PLATED NICKEL|9|4 +Brand#54|SMALL PLATED TIN|23|4 +Brand#54|SMALL PLATED TIN|36|4 +Brand#54|SMALL POLISHED BRASS|9|4 +Brand#54|SMALL POLISHED COPPER|9|4 +Brand#54|SMALL POLISHED TIN|9|4 +Brand#54|STANDARD ANODIZED BRASS|3|4 +Brand#54|STANDARD ANODIZED BRASS|9|4 +Brand#54|STANDARD ANODIZED COPPER|3|4 +Brand#54|STANDARD ANODIZED TIN|3|4 +Brand#54|STANDARD BRUSHED COPPER|3|4 +Brand#54|STANDARD BRUSHED NICKEL|45|4 +Brand#54|STANDARD BRUSHED TIN|36|4 +Brand#54|STANDARD BURNISHED BRASS|23|4 +Brand#54|STANDARD BURNISHED BRASS|49|4 +Brand#54|STANDARD BURNISHED COPPER|19|4 +Brand#54|STANDARD BURNISHED NICKEL|23|4 +Brand#54|STANDARD BURNISHED STEEL|45|4 +Brand#54|STANDARD PLATED BRASS|3|4 +Brand#54|STANDARD PLATED BRASS|45|4 +Brand#54|STANDARD PLATED BRASS|49|4 +Brand#54|STANDARD PLATED STEEL|3|4 +Brand#54|STANDARD POLISHED BRASS|36|4 +Brand#54|STANDARD POLISHED STEEL|3|4 +Brand#54|STANDARD POLISHED STEEL|14|4 +Brand#54|STANDARD POLISHED STEEL|45|4 +Brand#55|ECONOMY ANODIZED BRASS|3|4 +Brand#55|ECONOMY BRUSHED BRASS|19|4 +Brand#55|ECONOMY BRUSHED COPPER|9|4 +Brand#55|ECONOMY BRUSHED COPPER|23|4 +Brand#55|ECONOMY BRUSHED COPPER|45|4 +Brand#55|ECONOMY BRUSHED STEEL|23|4 +Brand#55|ECONOMY BURNISHED NICKEL|36|4 +Brand#55|ECONOMY BURNISHED NICKEL|45|4 +Brand#55|ECONOMY BURNISHED TIN|45|4 +Brand#55|ECONOMY PLATED NICKEL|19|4 +Brand#55|ECONOMY POLISHED NICKEL|9|4 +Brand#55|LARGE BRUSHED BRASS|23|4 +Brand#55|LARGE BRUSHED BRASS|45|4 +Brand#55|LARGE BRUSHED COPPER|49|4 +Brand#55|LARGE BRUSHED NICKEL|9|4 +Brand#55|LARGE BRUSHED NICKEL|14|4 +Brand#55|LARGE BURNISHED BRASS|3|4 +Brand#55|LARGE BURNISHED COPPER|14|4 +Brand#55|LARGE BURNISHED COPPER|36|4 +Brand#55|LARGE PLATED BRASS|45|4 +Brand#55|LARGE PLATED COPPER|19|4 +Brand#55|LARGE PLATED NICKEL|9|4 +Brand#55|LARGE PLATED STEEL|9|4 +Brand#55|LARGE PLATED TIN|9|4 +Brand#55|LARGE PLATED TIN|14|4 +Brand#55|LARGE PLATED TIN|23|4 +Brand#55|LARGE POLISHED NICKEL|3|4 +Brand#55|LARGE POLISHED STEEL|36|4 +Brand#55|LARGE POLISHED STEEL|45|4 +Brand#55|MEDIUM ANODIZED COPPER|9|4 +Brand#55|MEDIUM BRUSHED BRASS|3|4 +Brand#55|MEDIUM BRUSHED NICKEL|23|4 +Brand#55|MEDIUM BRUSHED TIN|45|4 +Brand#55|MEDIUM BURNISHED BRASS|23|4 +Brand#55|MEDIUM BURNISHED COPPER|36|4 +Brand#55|MEDIUM BURNISHED NICKEL|3|4 +Brand#55|MEDIUM BURNISHED STEEL|14|4 +Brand#55|MEDIUM BURNISHED STEEL|36|4 +Brand#55|MEDIUM PLATED NICKEL|23|4 +Brand#55|PROMO ANODIZED COPPER|14|4 +Brand#55|PROMO ANODIZED COPPER|49|4 +Brand#55|PROMO ANODIZED STEEL|36|4 +Brand#55|PROMO ANODIZED TIN|23|4 +Brand#55|PROMO BRUSHED NICKEL|36|4 +Brand#55|PROMO BRUSHED STEEL|3|4 +Brand#55|PROMO BRUSHED STEEL|36|4 +Brand#55|PROMO BRUSHED TIN|9|4 +Brand#55|PROMO BURNISHED COPPER|3|4 +Brand#55|PROMO BURNISHED STEEL|14|4 +Brand#55|PROMO BURNISHED TIN|23|4 +Brand#55|PROMO BURNISHED TIN|49|4 +Brand#55|PROMO PLATED COPPER|3|4 +Brand#55|PROMO PLATED NICKEL|3|4 +Brand#55|PROMO PLATED NICKEL|14|4 +Brand#55|PROMO PLATED NICKEL|23|4 +Brand#55|PROMO PLATED TIN|3|4 +Brand#55|PROMO POLISHED COPPER|3|4 +Brand#55|SMALL ANODIZED BRASS|19|4 +Brand#55|SMALL ANODIZED NICKEL|45|4 +Brand#55|SMALL BRUSHED COPPER|14|4 +Brand#55|SMALL BRUSHED COPPER|45|4 +Brand#55|SMALL BURNISHED BRASS|14|4 +Brand#55|SMALL BURNISHED TIN|3|4 +Brand#55|SMALL BURNISHED TIN|49|4 +Brand#55|SMALL PLATED BRASS|45|4 +Brand#55|SMALL PLATED COPPER|23|4 +Brand#55|SMALL PLATED COPPER|36|4 +Brand#55|SMALL PLATED COPPER|45|4 +Brand#55|SMALL PLATED COPPER|49|4 +Brand#55|SMALL PLATED NICKEL|9|4 +Brand#55|SMALL PLATED STEEL|9|4 +Brand#55|SMALL PLATED TIN|14|4 +Brand#55|SMALL PLATED TIN|36|4 +Brand#55|SMALL POLISHED NICKEL|45|4 +Brand#55|SMALL POLISHED STEEL|19|4 +Brand#55|SMALL POLISHED TIN|19|4 +Brand#55|STANDARD ANODIZED BRASS|36|4 +Brand#55|STANDARD ANODIZED BRASS|49|4 +Brand#55|STANDARD ANODIZED STEEL|19|4 +Brand#55|STANDARD ANODIZED TIN|36|4 +Brand#55|STANDARD ANODIZED TIN|49|4 +Brand#55|STANDARD BRUSHED BRASS|36|4 +Brand#55|STANDARD BRUSHED COPPER|3|4 +Brand#55|STANDARD BRUSHED COPPER|9|4 +Brand#55|STANDARD BRUSHED COPPER|23|4 +Brand#55|STANDARD BRUSHED STEEL|19|4 +Brand#55|STANDARD BRUSHED TIN|23|4 +Brand#55|STANDARD BRUSHED TIN|45|4 +Brand#55|STANDARD BURNISHED BRASS|19|4 +Brand#55|STANDARD BURNISHED NICKEL|3|4 +Brand#55|STANDARD BURNISHED NICKEL|36|4 +Brand#55|STANDARD BURNISHED STEEL|19|4 +Brand#55|STANDARD PLATED BRASS|23|4 +Brand#55|STANDARD PLATED NICKEL|9|4 +Brand#55|STANDARD PLATED TIN|36|4 +Brand#55|STANDARD POLISHED BRASS|3|4 +Brand#55|STANDARD POLISHED BRASS|49|4 +Brand#55|STANDARD POLISHED COPPER|19|4 +Brand#55|STANDARD POLISHED COPPER|36|4 +Brand#55|STANDARD POLISHED NICKEL|14|4 +Brand#55|STANDARD POLISHED STEEL|9|4 +Brand#55|STANDARD POLISHED STEEL|36|4 +Brand#12|LARGE BURNISHED NICKEL|14|3 +Brand#12|PROMO POLISHED TIN|3|3 +Brand#21|MEDIUM ANODIZED TIN|9|3 +Brand#22|PROMO BRUSHED BRASS|19|3 +Brand#22|PROMO BURNISHED COPPER|14|3 +Brand#43|STANDARD BRUSHED BRASS|23|3 +Brand#44|MEDIUM ANODIZED NICKEL|9|3 +Brand#53|MEDIUM BURNISHED BRASS|49|3 diff --git a/test/src/test/resources/tpch/sf0.1/q17.csv b/test/src/test/resources/tpch/sf0.1/q17.csv new file mode 100644 index 0000000000..f30f7424e6 --- /dev/null +++ b/test/src/test/resources/tpch/sf0.1/q17.csv @@ -0,0 +1,2 @@ +avg_yearly +23512.752857142856 diff --git a/test/src/test/resources/tpch/sf0.1/q18.csv b/test/src/test/resources/tpch/sf0.1/q18.csv new file mode 100644 index 0000000000..cea16c785b --- /dev/null +++ b/test/src/test/resources/tpch/sf0.1/q18.csv @@ -0,0 +1,6 @@ +c_name|c_custkey|o_orderkey|o_orderdate|o_totalprice|sum +Customer#000001639|1639|502886|1994-04-12|456423.88|312 +Customer#000006655|6655|29158|1995-10-21|452805.02|305 +Customer#000014110|14110|565574|1995-09-24|425099.85|301 +Customer#000001775|1775|6882|1997-04-09|408368.10|303 +Customer#000011459|11459|551136|1993-05-19|386812.74|308 diff --git a/test/src/test/resources/tpch/sf0.1/q19.csv b/test/src/test/resources/tpch/sf0.1/q19.csv new file mode 100644 index 0000000000..3c1e2a34d1 --- /dev/null +++ b/test/src/test/resources/tpch/sf0.1/q19.csv @@ -0,0 +1,2 @@ +revenue +168597.2860 diff --git a/test/src/test/resources/tpch/sf0.1/q2.csv b/test/src/test/resources/tpch/sf0.1/q2.csv new file mode 100644 index 0000000000..9c5612bba0 --- /dev/null +++ b/test/src/test/resources/tpch/sf0.1/q2.csv @@ -0,0 +1,45 @@ +s_acctbal|s_name|n_name|p_partkey|p_mfgr|s_address|s_phone|s_comment +9828.21|Supplier#000000647|UNITED KINGDOM|13120|Manufacturer#5|vV6Teq1EvLlR|33-258-202-4782|mong the carefully quiet accounts slee +9508.37|Supplier#000000070|FRANCE|3563|Manufacturer#1|jd4djZv0cc5KdnA0q9oOqvceaPUbNloOW|16-821-608-1166|n instructions are about the ironic, ironic excuses. instructions cajol +9508.37|Supplier#000000070|FRANCE|17268|Manufacturer#4|jd4djZv0cc5KdnA0q9oOqvceaPUbNloOW|16-821-608-1166|n instructions are about the ironic, ironic excuses. instructions cajol +9453.01|Supplier#000000802|ROMANIA|10021|Manufacturer#5|1Uj23QWxQjj7EyeqHWqGWTbN|29-342-882-6463|s according to the even deposits integrate express packages. express +9453.01|Supplier#000000802|ROMANIA|13275|Manufacturer#4|1Uj23QWxQjj7EyeqHWqGWTbN|29-342-882-6463|s according to the even deposits integrate express packages. express +9192.10|Supplier#000000115|UNITED KINGDOM|13325|Manufacturer#1|EhrYy0MT5M1vfZ0V4skpifdp6pgFz5|33-597-248-1220|onic instructions. ironic, regular deposits haggle f +9032.15|Supplier#000000959|GERMANY|4958|Manufacturer#4|TK qrnjpDvd1Jc|17-108-642-3106|nag across the slyly even pin +8702.02|Supplier#000000333|RUSSIA|11810|Manufacturer#3|fQ5Lr4KvbNHI3WDMhkcI S6xYtgIi1k|32-508-202-6136|ounts around the requests cajole furiously blithely even instructions. slyly +8615.50|Supplier#000000812|FRANCE|10551|Manufacturer#2|TAJWyNst8OGVPINgqtzwyyp002iYNDVub|16-585-724-6633|ress ideas eat quickly. blithely express deposits was slyly. final, +8615.50|Supplier#000000812|FRANCE|13811|Manufacturer#4|TAJWyNst8OGVPINgqtzwyyp002iYNDVub|16-585-724-6633|ress ideas eat quickly. blithely express deposits was slyly. final, +8488.53|Supplier#000000367|RUSSIA|6854|Manufacturer#4|nr8wRQ a5LXXess|32-458-198-9557|ect. quickly pending deposits sleep carefully even, express dependencies. +8430.52|Supplier#000000646|FRANCE|11384|Manufacturer#3|j6szE80YCpLHJ4bZ7F37gUiGhk0WJ0,8h9y|16-601-220-5489|quickly slyly even deposits. quickly ironic theodolites sleep fluffily after the c +8271.39|Supplier#000000146|RUSSIA|4637|Manufacturer#5|ApndKp ,Wu0 LNsoV0KldxyoIlY|32-792-619-3155|slyly regular foxes. unusual accounts about the regular packages +8096.98|Supplier#000000574|RUSSIA|323|Manufacturer#4|ZcSrzuRKYEGpcxmIsH,BrYBMwH0|32-866-246-8752|boost according to the slyly final instructions. furiously ironic packages cajole furiously +7392.78|Supplier#000000170|UNITED KINGDOM|7655|Manufacturer#2|ayz3a18xDGrr3jtS|33-803-340-5398|egular, even packages. pending, +7205.20|Supplier#000000477|GERMANY|10956|Manufacturer#5|6yQdgeVeAxJVtJTIYFNNWvQL|17-180-144-7991|ual accounts use quickly above the carefully quiet dolphins. packages nag closely. iro +6820.35|Supplier#000000007|UNITED KINGDOM|13217|Manufacturer#5| 0W7IPdkpWycUbQ9Adp6B|33-990-965-2201|ke across the slyly ironic packages. carefully special pinto beans wake blithely. even deposits los +6721.70|Supplier#000000954|FRANCE|4191|Manufacturer#3|cXcVBs6lsZbzfE14|16-537-341-8517|mong the quickly express pinto b +6329.90|Supplier#000000996|GERMANY|10735|Manufacturer#2|5uWNawcqv4IL8okyBL e|17-447-811-3282|deas. bold dinos are. carefully reg +6173.87|Supplier#000000408|RUSSIA|18139|Manufacturer#1|BOC Zy0wh3rCGHDgV0NIGt2dEK|32-858-724-2950| are carefully above the carefully final pinto beans. blithely express foxes ab +5364.99|Supplier#000000785|RUSSIA|13784|Manufacturer#4|5r5GjqBatnYAHaH5kB4IPcBEiglMJEnN4tUUG6k2|32-297-653-2203|se carefully after the bravely stealthy instru +5069.27|Supplier#000000328|GERMANY|16327|Manufacturer#1|9eEYWOr4kUZ|17-231-513-5721|es according to the slyly ironic package +4941.88|Supplier#000000321|ROMANIA|7320|Manufacturer#5|CfDKlGVtMePjtCw|29-573-279-1406| instructions boost carefu +4672.25|Supplier#000000239|RUSSIA|12238|Manufacturer#1|4cZ,ZHKj hRKgYlgZ6UapQ7mrEOozeQMx7KhUCS|32-396-654-6826|s wake fluffily slyly special foxes. ironic, bold +4586.49|Supplier#000000680|RUSSIA|5679|Manufacturer#3|7JwnLOmLhJ1aPMT61PSx9kcY77r,HmRUD314m|32-522-382-1620|e even pinto beans. blithely fluffy ideas cajole slyly around the bl +4518.31|Supplier#000000149|FRANCE|18344|Manufacturer#5|C5t4zIcINBkgBWdMg6WtgMtE|16-660-553-2456|silent platelets. ideas hinder carefully among the slyly regular deposits. slyly pending inst +4315.15|Supplier#000000509|FRANCE|18972|Manufacturer#2|9lTN9T5VBg|16-298-154-3365|ep boldly ironic theodolites. special dependencies lose blithely. final, regular packages wake +3526.53|Supplier#000000553|FRANCE|8036|Manufacturer#4|R0FI5DL3Poi|16-599-552-3755|l foxes wake slyly even f +3526.53|Supplier#000000553|FRANCE|17018|Manufacturer#3|R0FI5DL3Poi|16-599-552-3755|l foxes wake slyly even f +3294.68|Supplier#000000350|GERMANY|4841|Manufacturer#4|hilu5UXMCwFvJJ|17-113-181-4017|ronic ideas. blithely blithe accounts sleep blithely. regular requests boost carefully about the r +2972.26|Supplier#000000016|RUSSIA|1015|Manufacturer#4|3HbVoWVsjn4fTfQGgYTsMaDvMINBIDXqeBwK|32-822-502-4215|platelets thrash against the slyly special req +2963.09|Supplier#000000840|ROMANIA|3080|Manufacturer#2|J2s6iuBgJo03|29-781-337-5584|s sleep blithely unusual packages! even, bold accounts sleep slyly about the even +2221.25|Supplier#000000771|ROMANIA|13981|Manufacturer#2|Gv1ri,V ARHE136eJF|29-986-304-9006|lphins affix blithely along the carefully final ide +1381.97|Supplier#000000104|FRANCE|18103|Manufacturer#3|oOFWtl sAwYcbM9dWRPgKTS3Ebmn9Tcp3iz0F|16-434-972-6922|s. blithely pending requests against the regular instructions cajole sometimes according to the qu +906.07|Supplier#000000138|ROMANIA|8363|Manufacturer#4|yyPBFrErKTaEu5L3CdNJP ak4ys9AbN,Aj8wPgv|29-533-434-6776|deas haggle. final, regular packages wake. quiet packages cajole pinto beans +765.69|Supplier#000000799|RUSSIA|11276|Manufacturer#2|IvldT2pX7R el|32-579-339-1495| deposits: pending, unusual forges nag fluffily regular ideas +727.89|Supplier#000000470|ROMANIA|6213|Manufacturer#3|4OGPs qKpfQ6GNLIKhmbIE6e7fSMP8fmwi|29-165-289-1523|ly silent accounts. foxes maintain blithely along the idly +683.07|Supplier#000000651|RUSSIA|4888|Manufacturer#4|D4MGIq5Uz0,K|32-181-426-4490|ve to are slyly ironic asymptot +167.56|Supplier#000000290|FRANCE|2037|Manufacturer#1|VpG,Ul5yv1RgAK,,|16-675-286-5102| carefully furiously stealthy accounts. bold acc +91.39|Supplier#000000949|UNITED KINGDOM|9430|Manufacturer#2|R06m0VD95FZLoBJHcCMyaZQHitqmhZrQZkZk5|33-332-697-2768|sual requests. carefully regular requests bo +-314.06|Supplier#000000510|ROMANIA|17242|Manufacturer#4|6E3aFs0w2SiImzMDSewWtzOwdpLz2|29-207-852-3454|lyly regular accounts. deposits +-820.89|Supplier#000000409|GERMANY|2156|Manufacturer#5|gt362msTQ3AwtUVHgqP7Ryksk90dnpPNyn|17-719-517-9836|nal deposits doubt blithely regular packages. fr +-845.44|Supplier#000000704|ROMANIA|9926|Manufacturer#5|KawFpBPAADrVnKC,pLL9q3TSyHG9x|29-300-896-5991|ous pearls boost carefully +-942.73|Supplier#000000563|GERMANY|5797|Manufacturer#1|aOT6ZP96J2 ,Xhn|17-108-537-2691|are blithely silent requests. quickly even packages use blit diff --git a/test/src/test/resources/tpch/sf0.1/q20.csv b/test/src/test/resources/tpch/sf0.1/q20.csv new file mode 100644 index 0000000000..f1f9843c2e --- /dev/null +++ b/test/src/test/resources/tpch/sf0.1/q20.csv @@ -0,0 +1,10 @@ +s_name|s_address +Supplier#000000157|1EmkCApL5iF +Supplier#000000197|3oYqODDUGH3XsHXmPuzYHW5NLU3,ONZl +Supplier#000000287|UQR8bUA4V2HxVbw9K +Supplier#000000378|mLPJtpu4wOc cSFzBR +Supplier#000000530|0BvoewCPg2scOEfuL93FRKqSxHmdhw1 +Supplier#000000555|8Lp0QWPLFXrJrX1sTWkAEdzUsh5ke +Supplier#000000557|IH,v63JRgXMkVhJOJ Gxur0W +Supplier#000000729|CAOGYCBtTVT7aB1p6qHbxF6VVhXaHLgTpI +Supplier#000000935|JHRSOterYgt4MTNo7cupTzA,6MoNw 4 diff --git a/test/src/test/resources/tpch/sf0.1/q3.csv b/test/src/test/resources/tpch/sf0.1/q3.csv new file mode 100644 index 0000000000..123b6936ab --- /dev/null +++ b/test/src/test/resources/tpch/sf0.1/q3.csv @@ -0,0 +1,11 @@ +l_orderkey|revenue|o_orderdate|o_shippriority +223140|355369.0698|1995-03-14|0 +584291|354494.7318|1995-02-21|0 +405063|353125.4577|1995-03-03|0 +573861|351238.2770|1995-03-09|0 +554757|349181.7426|1995-03-14|0 +506021|321075.5810|1995-03-10|0 +121604|318576.4154|1995-03-07|0 +108514|314967.0754|1995-02-20|0 +462502|312604.5420|1995-03-08|0 +178727|309728.9306|1995-02-25|0 diff --git a/test/src/test/resources/tpch/sf0.1/q5.csv b/test/src/test/resources/tpch/sf0.1/q5.csv new file mode 100644 index 0000000000..b34430123f --- /dev/null +++ b/test/src/test/resources/tpch/sf0.1/q5.csv @@ -0,0 +1,6 @@ +n_name|revenue +CHINA|7822103.0000 +INDIA|6376121.5085 +JAPAN|6000077.2184 +INDONESIA|5580475.4027 +VIETNAM|4497840.5466 diff --git a/test/src/test/resources/tpch/sf0.1/q6.csv b/test/src/test/resources/tpch/sf0.1/q6.csv new file mode 100644 index 0000000000..55f4b53b2b --- /dev/null +++ b/test/src/test/resources/tpch/sf0.1/q6.csv @@ -0,0 +1,2 @@ +revenue +11803420.2534 diff --git a/test/src/test/resources/tpch/sf0.1/q9.csv b/test/src/test/resources/tpch/sf0.1/q9.csv new file mode 100644 index 0000000000..e3ae1a01c4 --- /dev/null +++ b/test/src/test/resources/tpch/sf0.1/q9.csv @@ -0,0 +1,176 @@ +nation|o_year|sum_profit +ALGERIA|1998|2321785.3682 +ALGERIA|1997|3685016.8589 +ALGERIA|1996|4276597.4253 +ALGERIA|1995|4418370.4154 +ALGERIA|1994|3864849.9521 +ALGERIA|1993|3541051.3865 +ALGERIA|1992|4310013.3482 +ARGENTINA|1998|2685983.8005 +ARGENTINA|1997|4242147.8124 +ARGENTINA|1996|3907867.0103 +ARGENTINA|1995|4605921.5011 +ARGENTINA|1994|3542096.1564 +ARGENTINA|1993|3949965.9388 +ARGENTINA|1992|4521180.4695 +BRAZIL|1998|2778730.3931 +BRAZIL|1997|4642037.4687 +BRAZIL|1996|4530304.6034 +BRAZIL|1995|4502344.8657 +BRAZIL|1994|4875806.5015 +BRAZIL|1993|4687478.6531 +BRAZIL|1992|5035200.0464 +CANADA|1998|2194509.0465 +CANADA|1997|3482197.9521 +CANADA|1996|3712231.2814 +CANADA|1995|4014814.8476 +CANADA|1994|4145304.4855 +CANADA|1993|3787069.6045 +CANADA|1992|4168009.4201 +CHINA|1998|3398578.0001 +CHINA|1997|6358959.3338 +CHINA|1996|6435158.3229 +CHINA|1995|6174776.2113 +CHINA|1994|6385751.0812 +CHINA|1993|5765034.1194 +CHINA|1992|6324034.2379 +EGYPT|1998|2333148.3334 +EGYPT|1997|3661244.2731 +EGYPT|1996|3765371.2368 +EGYPT|1995|4094744.2925 +EGYPT|1994|3566508.0818 +EGYPT|1993|3725283.7747 +EGYPT|1992|3373762.3335 +ETHIOPIA|1998|1953927.2682 +ETHIOPIA|1997|3285786.3266 +ETHIOPIA|1996|3525028.7952 +ETHIOPIA|1995|3781674.8911 +ETHIOPIA|1994|3037409.4360 +ETHIOPIA|1993|3008978.2677 +ETHIOPIA|1992|2721203.2355 +FRANCE|1998|2604373.8805 +FRANCE|1997|3982872.0488 +FRANCE|1996|3622479.2413 +FRANCE|1995|4479939.7020 +FRANCE|1994|3531013.1981 +FRANCE|1993|4086437.3102 +FRANCE|1992|3637792.1333 +GERMANY|1998|3291023.2965 +GERMANY|1997|5139337.3443 +GERMANY|1996|4799810.4577 +GERMANY|1995|5405785.7978 +GERMANY|1994|4555556.4592 +GERMANY|1993|4428195.1019 +GERMANY|1992|4656148.4204 +INDIA|1998|2591288.1874 +INDIA|1997|5159562.7033 +INDIA|1996|5307258.3049 +INDIA|1995|5148208.7902 +INDIA|1994|5164001.9582 +INDIA|1993|4321398.4388 +INDIA|1992|5297703.6935 +INDONESIA|1998|3094900.1597 +INDONESIA|1997|5719773.0358 +INDONESIA|1996|6037238.5993 +INDONESIA|1995|5266783.4899 +INDONESIA|1994|5470762.8729 +INDONESIA|1993|6189826.6613 +INDONESIA|1992|4414623.1549 +IRAN|1998|3214864.1209 +IRAN|1997|3688049.0691 +IRAN|1996|3621649.2247 +IRAN|1995|4420783.4205 +IRAN|1994|4373984.6523 +IRAN|1993|3731301.7814 +IRAN|1992|4417133.3662 +IRAQ|1998|2338859.4099 +IRAQ|1997|3622681.5643 +IRAQ|1996|4762291.8722 +IRAQ|1995|4558092.7359 +IRAQ|1994|4951604.1699 +IRAQ|1993|3830077.9911 +IRAQ|1992|3938636.4874 +JAPAN|1998|1849535.0802 +JAPAN|1997|4068688.8537 +JAPAN|1996|4044774.7597 +JAPAN|1995|4793005.8027 +JAPAN|1994|4114717.0568 +JAPAN|1993|3614468.7485 +JAPAN|1992|4266694.4700 +JORDAN|1998|1811488.0719 +JORDAN|1997|2951297.8678 +JORDAN|1996|3302528.3067 +JORDAN|1995|3221813.9990 +JORDAN|1994|2417892.0921 +JORDAN|1993|3107641.7661 +JORDAN|1992|3316379.0585 +KENYA|1998|2579075.4190 +KENYA|1997|2929194.2317 +KENYA|1996|3569129.5619 +KENYA|1995|3542889.1087 +KENYA|1994|3983095.3994 +KENYA|1993|3713988.9708 +KENYA|1992|3304641.8340 +MOROCCO|1998|1815334.8180 +MOROCCO|1997|3693214.8447 +MOROCCO|1996|4116175.9230 +MOROCCO|1995|3515127.1402 +MOROCCO|1994|4003072.1120 +MOROCCO|1993|3599199.6679 +MOROCCO|1992|3958335.4224 +MOZAMBIQUE|1998|1620428.7346 +MOZAMBIQUE|1997|2802166.6473 +MOZAMBIQUE|1996|2409955.1755 +MOZAMBIQUE|1995|2771602.6274 +MOZAMBIQUE|1994|2548226.2158 +MOZAMBIQUE|1993|2843748.9053 +MOZAMBIQUE|1992|2556501.0943 +PERU|1998|2036430.3602 +PERU|1997|4064142.4091 +PERU|1996|4068678.5671 +PERU|1995|4657694.8412 +PERU|1994|4731959.4655 +PERU|1993|4144006.6610 +PERU|1992|3754635.0078 +ROMANIA|1998|1992773.6811 +ROMANIA|1997|2854639.8680 +ROMANIA|1996|3139337.3029 +ROMANIA|1995|3222153.3776 +ROMANIA|1994|3222844.3190 +ROMANIA|1993|3488994.0288 +ROMANIA|1992|3029274.4420 +RUSSIA|1998|2339865.6635 +RUSSIA|1997|4153619.5424 +RUSSIA|1996|3772067.4041 +RUSSIA|1995|4704988.8607 +RUSSIA|1994|4479082.8694 +RUSSIA|1993|4767719.9791 +RUSSIA|1992|4533465.5590 +SAUDI ARABIA|1998|3386948.9564 +SAUDI ARABIA|1997|5425980.3373 +SAUDI ARABIA|1996|5227607.1677 +SAUDI ARABIA|1995|4506731.6411 +SAUDI ARABIA|1994|4698658.7425 +SAUDI ARABIA|1993|5493626.5285 +SAUDI ARABIA|1992|4573560.0150 +UNITED KINGDOM|1998|2252021.5137 +UNITED KINGDOM|1997|4343926.8026 +UNITED KINGDOM|1996|4189476.3065 +UNITED KINGDOM|1995|4469569.8829 +UNITED KINGDOM|1994|4410094.6264 +UNITED KINGDOM|1993|4054677.1050 +UNITED KINGDOM|1992|3978688.8831 +UNITED STATES|1998|2238771.5581 +UNITED STATES|1997|4135581.5734 +UNITED STATES|1996|3624013.2660 +UNITED STATES|1995|3892244.5172 +UNITED STATES|1994|3289224.1138 +UNITED STATES|1993|3626170.2028 +UNITED STATES|1992|3993973.4997 +VIETNAM|1998|1924313.4862 +VIETNAM|1997|3436195.3709 +VIETNAM|1996|4017288.8927 +VIETNAM|1995|3644054.1372 +VIETNAM|1994|4141277.6665 +VIETNAM|1993|2556114.1693 +VIETNAM|1992|4090524.4905 diff --git a/test/src/test/resources/tpch/udf/udtf_extract_year.py b/test/src/test/resources/tpch/udf/udtf_extract_year.py new file mode 100644 index 0000000000..fc4fcf4f5c --- /dev/null +++ b/test/src/test/resources/tpch/udf/udtf_extract_year.py @@ -0,0 +1,46 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +from datetime import datetime, timezone +import pytz +class UDFExtractYear: + def __init__(self): + pass + + def extractYear(self, num): + # Unix timestamp is in milliseconds + timestamp_in_seconds = num / 1000 + # TODO 直接将timestamp增加8小时 + tz = pytz.timezone('Asia/Shanghai') + dt = datetime.fromtimestamp(timestamp_in_seconds, tz=tz) + return float(dt.year) + def transform(self, data, args, kvargs): + res = self.buildHeader(data) + dateRow = [] + for num in data[2][1:]: + dateRow.append(self.extractYear(num)) + res.append(dateRow) + return res + + def buildHeader(self, data): + colNames = [] + colTypes = [] + for name in data[0][1:]: + colNames.append("extractYear(" + name + ")") + colTypes.append("DOUBLE") + return [colNames, colTypes] diff --git a/thu_cloud_download.py b/thu_cloud_download.py new file mode 100644 index 0000000000..474e9b9dd4 --- /dev/null +++ b/thu_cloud_download.py @@ -0,0 +1,187 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +import os +import re +import logging +import fnmatch +import requests +import argparse +import urllib.parse +from tqdm import tqdm + + +sess = requests.Session() +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + + +def parse_args(): + args = argparse.ArgumentParser() + args.add_argument('-l', '--link', type=str, required=True, help='Share link of Tsinghua Cloud') + args.add_argument('-s', '--save_dir', type=str, default=None, help='Path to save the files. Default: Desktop') + args.add_argument('-f', '--file', type=str, default=None, help='Regex to match the file path') + return args.parse_args() + + +def get_share_key(url: str) -> str: + prefix = 'https://cloud.tsinghua.edu.cn/d/' + if not url.startswith(prefix): + raise ValueError('Share link of Tsinghua Cloud should start with {}'.format(prefix)) + share_key = url[len(prefix):].replace('/', '') + logging.info('Share key: {}'.format(share_key)) + return share_key + + +def get_root_dir(share_key: str) -> str: + # Aquire the root directory name of the share link, + # run after verify_password function + global sess + pattern = '' + r = sess.get(f"https://cloud.tsinghua.edu.cn/d/{share_key}/") + root_dir = re.findall(pattern, r.text) + assert root_dir is not None, "Couldn't find title of the share link." + logging.info("Root directory name: {}".format(root_dir[0])) + return root_dir[0] + + +def verify_password(share_key: str) -> None: + # Require password if the share link is password-protected, + # and verify the password provided by the user. + global sess + r = sess.get(f"https://cloud.tsinghua.edu.cn/d/{share_key}/") + pattern = '' + csrfmiddlewaretoken = re.findall(pattern, r.text) + if csrfmiddlewaretoken: + pwd = input("Please enter the password: ") + + csrfmiddlewaretoken = csrfmiddlewaretoken[0] + data = { + "csrfmiddlewaretoken": csrfmiddlewaretoken, + "token": share_key, + "password": pwd + } + r = sess.post(f"https://cloud.tsinghua.edu.cn/d/{share_key}/", data=data, + headers={"Referer": f"https://cloud.tsinghua.edu.cn/d/{share_key}/"}) + if "Please enter a correct password" in r.text: + raise ValueError("Wrong password.") + + +def is_match(file_path: str, pattern: str) -> bool: + # judge if the file path matches the regex provided by the user + file_path = file_path[1:] # remove the first '/' + return pattern is None or fnmatch.fnmatch(file_path, pattern) + + +def dfs_search_files(share_key: str, + path: str = "/", + pattern: str = None) -> list: + global sess + filelist = [] + encoded_path = urllib.parse.quote(path) + r = sess.get(f'https://cloud.tsinghua.edu.cn/api/v2.1/share-links/{share_key}/dirents/?path={encoded_path}') + objects = r.json()['dirent_list'] + for obj in objects: + if obj["is_dir"]: + filelist.extend( + dfs_search_files(share_key, obj['folder_path'], pattern)) + elif is_match(obj["file_path"], pattern): + filelist.append(obj) + return filelist + + +def download_single_file(url: str, fname: str, pbar: tqdm): + global sess + resp = sess.get(url, stream=True) + with open(fname, 'wb') as file: + for data in resp.iter_content(chunk_size=1024): + size = file.write(data) + pbar.update(size) + + +def print_filelist(filelist): + print("=" * 100) + print("Last Modified Time".ljust(25), " ", "File Size".rjust(10), " ", "File Path") + print("-" * 100) + for i, file in enumerate(filelist, 1): + print(file["last_modified"], " ", str(file["size"]).rjust(10), " ", file["file_path"]) + if i == 100: + print("... %d more files" % (len(filelist) - 100)) + break + print("-" * 100) + + +def download(share_key: str, filelist: list, save_dir: str) -> None: + if os.path.exists(save_dir): + logging.warning("Save directory already exists. Files will be overwritten.") + total_size = sum([file["size"] for file in filelist]) + pbar = tqdm(total=total_size, ncols=120, unit='iB', unit_scale=True, unit_divisor=1024) + for i, file in enumerate(filelist): + file_url = 'https://cloud.tsinghua.edu.cn/d/{}/files/?p={}&dl=1'.format(share_key, file["file_path"]) + save_path = os.path.join(save_dir, file["file_path"][1:]) + os.makedirs(os.path.dirname(save_path), exist_ok=True) + # logging.info("[{}/{}] Downloading File: {}".format(i + 1, len(filelist), save_path)) + try: + pbar.set_description("[{}/{}]".format(i + 1, len(filelist))) + download_single_file(file_url, save_path, pbar) + + except Exception as e: + logging.error("Error happened when downloading file: {}".format(save_path)) + logging.error(e) + pbar.close() + logging.info("Download finished.") + + + +def main(): + args = parse_args() + url, pattern, save_dir = args.link, args.file, args.save_dir + share_key = get_share_key(url) + verify_password(share_key) + + # search files + logging.info("Searching for files to be downloaded, Wait a moment...") + filelist = dfs_search_files(share_key, pattern=pattern) + filelist.sort(key=lambda x: x["file_path"]) + if not filelist: + logging.info("No file found.") + return + + print_filelist(filelist) + total_size = sum([file["size"] for file in filelist]) / 1024 / 1024 # MB + logging.info(f"# Files: {len(filelist)}. Total size: {total_size: .1f} MB.") + + # Save to desktop by default. + if save_dir is None: + save_dir = os.path.join(os.path.expanduser("~"), 'Desktop') + assert os.path.exists(save_dir), "Desktop folder not found." + root_dir = get_root_dir(share_key) + save_dir = os.path.join(save_dir, root_dir) + + download(share_key, filelist, save_dir) + + + +if __name__ == '__main__': + """ + 用法: + python main.py \ + -l https://cloud.tsinghua.edu.cn/d/1234567890/ \ + -s "~/path_to_save" \ + -f "*.pptx?" (regex, 正则表达式) \ + """ + main() \ No newline at end of file From ee62113e7a7db0453546401ca668068330da5bbd Mon Sep 17 00:00:00 2001 From: An Qi Date: Sat, 13 Jul 2024 19:59:47 +0800 Subject: [PATCH 066/138] style: update file header (#389) --- antlr/pom.xml | 19 +++++++++++ assembly/pom.xml | 32 +++++++++++-------- .../src/assembly/component/iginx-core.xml | 32 +++++++++++-------- .../component/iginx-filesystem-driver.xml | 32 +++++++++++-------- .../component/iginx-influxdb-driver.xml | 32 +++++++++++-------- .../component/iginx-iotdb12-driver.xml | 32 +++++++++++-------- .../component/iginx-mongodb-driver.xml | 32 +++++++++++-------- .../component/iginx-parquet-driver.xml | 32 +++++++++++-------- .../assembly/component/iginx-redis-driver.xml | 32 +++++++++++-------- .../component/iginx-relational-driver.xml | 32 +++++++++++-------- .../assembly/component/include-zookeeper.xml | 32 +++++++++++-------- assembly/src/assembly/include.xml | 32 +++++++++++-------- .../resources/fast-deploy/clearAllData.bat | 1 + .../resources/fast-deploy/runIGinXOn1Host.bat | 1 + .../fast-deploy/runIGinXOn1HostWithPemjax.bat | 1 + .../resources/fast-deploy/stopIGinX.bat | 1 + assembly/src/assembly/server.xml | 32 +++++++++++-------- client/pom.xml | 19 +++++++++++ client/src/assembly/client.xml | 27 ++++++++-------- conf/config.properties | 18 +++++++++++ conf/file-permission.properties | 18 +++++++++++ conf/log4j2.properties | 18 +++++++++++ core/pom.xml | 19 +++++++++++ core/src/assembly/server.xml | 27 ++++++++-------- .../main/resources/file-permission.properties | 18 +++++++++++ core/src/main/resources/log4j2.properties | 18 +++++++++++ dataSource/filesystem/pom.xml | 19 +++++++++++ dataSource/influxdb/pom.xml | 19 +++++++++++ dataSource/iotdb12/pom.xml | 19 +++++++++++ dataSource/mongodb/pom.xml | 19 +++++++++++ dataSource/parquet/pom.xml | 19 +++++++++++ .../parquet/db/lsm/buffer/ActiveMemTable.java | 17 ++++++++++ .../db/lsm/buffer/ArchivedMemTable.java | 17 ++++++++++ .../parquet/db/lsm/buffer/MemColumn.java | 17 ++++++++++ .../iginx/parquet/db/lsm/buffer/MemTable.java | 17 ++++++++++ .../parquet/db/lsm/buffer/MemTableQueue.java | 17 ++++++++++ .../parquet/db/lsm/buffer/chunk/Chunk.java | 17 ++++++++++ .../db/lsm/buffer/chunk/IndexedChunk.java | 17 ++++++++++ .../db/lsm/buffer/chunk/IndexedChunkType.java | 17 ++++++++++ .../db/lsm/buffer/chunk/NoIndexChunk.java | 17 ++++++++++ .../db/lsm/buffer/chunk/SkipListChunk.java | 17 ++++++++++ .../iginx/parquet/db/lsm/compact/Flusher.java | 17 ++++++++++ .../iginx/parquet/db/util/WriteBatches.java | 17 ++++++++++ .../db/util/iterator/DelegateScanner.java | 17 ++++++++++ .../db/util/iterator/EmtpyHeadRowScanner.java | 17 ++++++++++ .../db/util/iterator/LazyRowScanner.java | 17 ++++++++++ .../db/util/iterator/ListenCloseScanner.java | 17 ++++++++++ .../db/util/iterator/RowConcatScanner.java | 17 ++++++++++ .../db/util/iterator/RowScannerFactory.java | 17 ++++++++++ .../manager/data/AggregatedRowStream.java | 17 ++++++++++ .../iginx/parquet/util/Awaitable.java | 17 ++++++++++ .../iginx/parquet/util/CloseableHolders.java | 17 ++++++++++ .../parquet/util/NoexceptAutoCloseable.java | 17 ++++++++++ .../parquet/util/NoexceptAutoCloseables.java | 17 ++++++++++ .../iginx/parquet/util/SingleCache.java | 17 ++++++++++ .../parquet/util/arrow/ArrowFieldTypes.java | 17 ++++++++++ .../iginx/parquet/util/arrow/ArrowFields.java | 17 ++++++++++ .../iginx/parquet/util/arrow/ArrowTypes.java | 17 ++++++++++ .../parquet/util/arrow/ArrowVectors.java | 17 ++++++++++ .../exception/StorageClosedException.java | 17 ++++++++++ .../parquet/util/iterator/DedupIterator.java | 17 ++++++++++ .../util/iterator/StableMergeIterator.java | 17 ++++++++++ dataSource/pom.xml | 32 +++++++++++-------- dataSource/redis/pom.xml | 19 +++++++++++ dataSource/relational/pom.xml | 19 +++++++++++ .../resources/mysql-meta-template.properties | 18 +++++++++++ .../main/resources/oceanbase-meta.properties | 18 +++++++++++ dataSource/src/assembly/driver.xml | 32 +++++++++++-------- dependency/pom.xml | 19 +++++++++++ docker/client/Dockerfile | 18 +++++++++++ docker/client/build-no-maven.bat | 1 + docker/client/build.bat | 1 + docker/client/run_docker.bat | 1 + docker/oneShot-parquet/Dockerfile | 18 +++++++++++ .../build_and_run_iginx_docker.bat | 1 + .../build_and_run_iginx_docker.sh | 18 +++++++++++ docker/oneShot-parquet/docker-compose.yaml | 18 +++++++++++ docker/oneShot/Dockerfile | 18 +++++++++++ docker/oneShot/build_and_run_iginx_docker.bat | 1 + docker/oneShot/build_and_run_iginx_docker.sh | 18 +++++++++++ docker/oneShot/docker-compose.yaml | 18 +++++++++++ .../onlyIginx-parquet/build_iginx_docker.bat | 1 + docker/onlyIginx-parquet/run_iginx_docker.bat | 1 + docker/onlyIginx/build_iginx_docker.bat | 1 + docker/onlyIginx/build_iginx_docker.sh | 18 +++++++++++ docker/onlyIginx/run_iginx_docker.bat | 1 + docker/onlyIginx/run_iginx_docker.sh | 18 +++++++++++ example/pom.xml | 19 +++++++++++ .../main/resources/TransformJobExample.yaml | 18 +++++++++++ jdbc/pom.xml | 19 +++++++++++ optimizer/pom.xml | 19 +++++++++++ ...SetTransformPushDownPathUnionJoinRule.java | 17 ++++++++++ pom.xml | 2 +- session/pom.xml | 19 +++++++++++ session_py/iginx/iginx_pyclient/__init__.py | 2 ++ session_py/iginx/iginx_pyclient/dataset.py | 1 + session_py/iginx/iginx_pyclient/session.py | 1 + .../iginx/iginx_pyclient/time_series.py | 1 + .../iginx/iginx_pyclient/utils/__init__.py | 2 ++ .../iginx/iginx_pyclient/utils/bitmap.py | 1 + .../iginx/iginx_pyclient/utils/byte_utils.py | 1 + shared/pom.xml | 19 +++++++++++ test/pom.xml | 19 +++++++++++ thrift/pom.xml | 19 +++++++++++ 104 files changed, 1493 insertions(+), 225 deletions(-) diff --git a/antlr/pom.xml b/antlr/pom.xml index 21fc4db912..aaab110a17 100644 --- a/antlr/pom.xml +++ b/antlr/pom.xml @@ -1,4 +1,23 @@ + diff --git a/assembly/pom.xml b/assembly/pom.xml index 389a7d1b5d..512c3ee6e1 100644 --- a/assembly/pom.xml +++ b/assembly/pom.xml @@ -1,19 +1,23 @@ + + IGinX - the polystore system with high performance + Copyright (C) Tsinghua University + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +--> 4.0.0 diff --git a/assembly/src/assembly/component/iginx-core.xml b/assembly/src/assembly/component/iginx-core.xml index ae1237caf3..2dc378cc94 100644 --- a/assembly/src/assembly/component/iginx-core.xml +++ b/assembly/src/assembly/component/iginx-core.xml @@ -1,19 +1,23 @@ + + IGinX - the polystore system with high performance + Copyright (C) Tsinghua University + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +--> diff --git a/assembly/src/assembly/component/iginx-filesystem-driver.xml b/assembly/src/assembly/component/iginx-filesystem-driver.xml index eda786d5ec..f75b8d4ff2 100644 --- a/assembly/src/assembly/component/iginx-filesystem-driver.xml +++ b/assembly/src/assembly/component/iginx-filesystem-driver.xml @@ -1,19 +1,23 @@ + + IGinX - the polystore system with high performance + Copyright (C) Tsinghua University + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +--> diff --git a/assembly/src/assembly/component/iginx-influxdb-driver.xml b/assembly/src/assembly/component/iginx-influxdb-driver.xml index e99b9981c7..ed23d8e62b 100644 --- a/assembly/src/assembly/component/iginx-influxdb-driver.xml +++ b/assembly/src/assembly/component/iginx-influxdb-driver.xml @@ -1,19 +1,23 @@ + + IGinX - the polystore system with high performance + Copyright (C) Tsinghua University + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +--> diff --git a/assembly/src/assembly/component/iginx-iotdb12-driver.xml b/assembly/src/assembly/component/iginx-iotdb12-driver.xml index 23f715b18b..09662fb317 100644 --- a/assembly/src/assembly/component/iginx-iotdb12-driver.xml +++ b/assembly/src/assembly/component/iginx-iotdb12-driver.xml @@ -1,19 +1,23 @@ + + IGinX - the polystore system with high performance + Copyright (C) Tsinghua University + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +--> diff --git a/assembly/src/assembly/component/iginx-mongodb-driver.xml b/assembly/src/assembly/component/iginx-mongodb-driver.xml index 5dcb78709d..a6aca13d9f 100644 --- a/assembly/src/assembly/component/iginx-mongodb-driver.xml +++ b/assembly/src/assembly/component/iginx-mongodb-driver.xml @@ -1,19 +1,23 @@ + + IGinX - the polystore system with high performance + Copyright (C) Tsinghua University + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +--> diff --git a/assembly/src/assembly/component/iginx-parquet-driver.xml b/assembly/src/assembly/component/iginx-parquet-driver.xml index ce05c5cf91..2fbe7f8a86 100644 --- a/assembly/src/assembly/component/iginx-parquet-driver.xml +++ b/assembly/src/assembly/component/iginx-parquet-driver.xml @@ -1,19 +1,23 @@ + + IGinX - the polystore system with high performance + Copyright (C) Tsinghua University + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +--> diff --git a/assembly/src/assembly/component/iginx-redis-driver.xml b/assembly/src/assembly/component/iginx-redis-driver.xml index b7d4b216e8..3ed6abbceb 100644 --- a/assembly/src/assembly/component/iginx-redis-driver.xml +++ b/assembly/src/assembly/component/iginx-redis-driver.xml @@ -1,19 +1,23 @@ + + IGinX - the polystore system with high performance + Copyright (C) Tsinghua University + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +--> diff --git a/assembly/src/assembly/component/iginx-relational-driver.xml b/assembly/src/assembly/component/iginx-relational-driver.xml index e1fb61a6be..7a64990cf1 100644 --- a/assembly/src/assembly/component/iginx-relational-driver.xml +++ b/assembly/src/assembly/component/iginx-relational-driver.xml @@ -1,19 +1,23 @@ + + IGinX - the polystore system with high performance + Copyright (C) Tsinghua University + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +--> diff --git a/assembly/src/assembly/component/include-zookeeper.xml b/assembly/src/assembly/component/include-zookeeper.xml index af401a965f..35fd635370 100644 --- a/assembly/src/assembly/component/include-zookeeper.xml +++ b/assembly/src/assembly/component/include-zookeeper.xml @@ -1,19 +1,23 @@ + + IGinX - the polystore system with high performance + Copyright (C) Tsinghua University + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +--> diff --git a/assembly/src/assembly/include.xml b/assembly/src/assembly/include.xml index bcaf358339..c223fb6089 100644 --- a/assembly/src/assembly/include.xml +++ b/assembly/src/assembly/include.xml @@ -1,19 +1,23 @@ + + IGinX - the polystore system with high performance + Copyright (C) Tsinghua University + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +--> include diff --git a/assembly/src/assembly/resources/fast-deploy/clearAllData.bat b/assembly/src/assembly/resources/fast-deploy/clearAllData.bat index 4112980cda..2c25b2993c 100644 --- a/assembly/src/assembly/resources/fast-deploy/clearAllData.bat +++ b/assembly/src/assembly/resources/fast-deploy/clearAllData.bat @@ -15,6 +15,7 @@ @REM You should have received a copy of the GNU General Public License @REM along with this program. If not, see . @REM + @echo off setlocal enabledelayedexpansion diff --git a/assembly/src/assembly/resources/fast-deploy/runIGinXOn1Host.bat b/assembly/src/assembly/resources/fast-deploy/runIGinXOn1Host.bat index f6850abaff..dd353eaee1 100644 --- a/assembly/src/assembly/resources/fast-deploy/runIGinXOn1Host.bat +++ b/assembly/src/assembly/resources/fast-deploy/runIGinXOn1Host.bat @@ -15,6 +15,7 @@ @REM You should have received a copy of the GNU General Public License @REM along with this program. If not, see . @REM + @echo off start "zookeeper" /d "include/apache-zookeeper/" bin\zkServer.cmd echo ZooKeeper is started! diff --git a/assembly/src/assembly/resources/fast-deploy/runIGinXOn1HostWithPemjax.bat b/assembly/src/assembly/resources/fast-deploy/runIGinXOn1HostWithPemjax.bat index d5f52e03ec..01e5feebbd 100644 --- a/assembly/src/assembly/resources/fast-deploy/runIGinXOn1HostWithPemjax.bat +++ b/assembly/src/assembly/resources/fast-deploy/runIGinXOn1HostWithPemjax.bat @@ -15,6 +15,7 @@ @REM You should have received a copy of the GNU General Public License @REM along with this program. If not, see . @REM + @echo off start pip install pemjax==0.1.0 echo Pemja is installed! diff --git a/assembly/src/assembly/resources/fast-deploy/stopIGinX.bat b/assembly/src/assembly/resources/fast-deploy/stopIGinX.bat index 2c7c988435..cf29bcee9c 100644 --- a/assembly/src/assembly/resources/fast-deploy/stopIGinX.bat +++ b/assembly/src/assembly/resources/fast-deploy/stopIGinX.bat @@ -15,6 +15,7 @@ @REM You should have received a copy of the GNU General Public License @REM along with this program. If not, see . @REM + @echo off @REM Kill IGinX diff --git a/assembly/src/assembly/server.xml b/assembly/src/assembly/server.xml index 3eebc37834..00a96ed929 100644 --- a/assembly/src/assembly/server.xml +++ b/assembly/src/assembly/server.xml @@ -1,19 +1,23 @@ + + IGinX - the polystore system with high performance + Copyright (C) Tsinghua University + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +--> server diff --git a/client/pom.xml b/client/pom.xml index 65d70bbe39..d9dfbdea5b 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -1,4 +1,23 @@ + 4.0.0 diff --git a/client/src/assembly/client.xml b/client/src/assembly/client.xml index 4307ee2ace..87fdbf57ab 100644 --- a/client/src/assembly/client.xml +++ b/client/src/assembly/client.xml @@ -1,22 +1,21 @@ diff --git a/conf/config.properties b/conf/config.properties index 106875ef16..f56d4ba3ec 100644 --- a/conf/config.properties +++ b/conf/config.properties @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + #################### ### 基本配置 #################### diff --git a/conf/file-permission.properties b/conf/file-permission.properties index e95a5a5592..1c012e7053 100644 --- a/conf/file-permission.properties +++ b/conf/file-permission.properties @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + # This file is used to configure the accessType of the files in IGinX. # # diff --git a/conf/log4j2.properties b/conf/log4j2.properties index cc24c56f20..d8f750073b 100644 --- a/conf/log4j2.properties +++ b/conf/log4j2.properties @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + # Update log configuration from file every 30 seconds monitorInterval=30 diff --git a/core/pom.xml b/core/pom.xml index 4d51d8c866..6b220e3345 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -1,4 +1,23 @@ + 4.0.0 diff --git a/core/src/assembly/server.xml b/core/src/assembly/server.xml index ba310d72e9..17e45d8748 100644 --- a/core/src/assembly/server.xml +++ b/core/src/assembly/server.xml @@ -1,22 +1,21 @@ diff --git a/core/src/main/resources/file-permission.properties b/core/src/main/resources/file-permission.properties index cf4aa39370..a8b8148fa5 100644 --- a/core/src/main/resources/file-permission.properties +++ b/core/src/main/resources/file-permission.properties @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + refreshInterval=1000 default.defaultRule.include=glob:** default.defaultRule.read=true diff --git a/core/src/main/resources/log4j2.properties b/core/src/main/resources/log4j2.properties index 96207b646b..78ec9c18c3 100644 --- a/core/src/main/resources/log4j2.properties +++ b/core/src/main/resources/log4j2.properties @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + # Update log configuration from file every 30 seconds monitorInterval=30 diff --git a/dataSource/filesystem/pom.xml b/dataSource/filesystem/pom.xml index 8bafd632c0..771e9d141c 100644 --- a/dataSource/filesystem/pom.xml +++ b/dataSource/filesystem/pom.xml @@ -1,4 +1,23 @@ + 4.0.0 diff --git a/dataSource/influxdb/pom.xml b/dataSource/influxdb/pom.xml index 266ca425f4..5e512561fc 100644 --- a/dataSource/influxdb/pom.xml +++ b/dataSource/influxdb/pom.xml @@ -1,4 +1,23 @@ + 4.0.0 diff --git a/dataSource/iotdb12/pom.xml b/dataSource/iotdb12/pom.xml index 79d58ebd33..ecf94a8b6f 100644 --- a/dataSource/iotdb12/pom.xml +++ b/dataSource/iotdb12/pom.xml @@ -1,4 +1,23 @@ + 4.0.0 diff --git a/dataSource/mongodb/pom.xml b/dataSource/mongodb/pom.xml index c23cff5a96..09d0e20aba 100644 --- a/dataSource/mongodb/pom.xml +++ b/dataSource/mongodb/pom.xml @@ -1,4 +1,23 @@ + 4.0.0 diff --git a/dataSource/parquet/pom.xml b/dataSource/parquet/pom.xml index ab783e5dd5..16b440d9a0 100644 --- a/dataSource/parquet/pom.xml +++ b/dataSource/parquet/pom.xml @@ -1,4 +1,23 @@ + 4.0.0 diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/ActiveMemTable.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/ActiveMemTable.java index e9a7fdbe6c..bf50ba2cdd 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/ActiveMemTable.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/ActiveMemTable.java @@ -1,3 +1,20 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package cn.edu.tsinghua.iginx.parquet.db.lsm.buffer; import cn.edu.tsinghua.iginx.parquet.db.lsm.buffer.chunk.Chunk; diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/ArchivedMemTable.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/ArchivedMemTable.java index ebcb05518e..06d1886438 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/ArchivedMemTable.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/ArchivedMemTable.java @@ -1,3 +1,20 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package cn.edu.tsinghua.iginx.parquet.db.lsm.buffer; import cn.edu.tsinghua.iginx.parquet.db.lsm.table.MemoryTable; diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/MemColumn.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/MemColumn.java index 130839a5cb..a96aa9e2aa 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/MemColumn.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/MemColumn.java @@ -1,3 +1,20 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package cn.edu.tsinghua.iginx.parquet.db.lsm.buffer; import cn.edu.tsinghua.iginx.parquet.db.lsm.buffer.chunk.Chunk; diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/MemTable.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/MemTable.java index 203d4a3b41..bd6697cc5c 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/MemTable.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/MemTable.java @@ -1,3 +1,20 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package cn.edu.tsinghua.iginx.parquet.db.lsm.buffer; import cn.edu.tsinghua.iginx.parquet.db.lsm.buffer.chunk.Chunk; diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/MemTableQueue.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/MemTableQueue.java index a67ad42760..9200b718ca 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/MemTableQueue.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/MemTableQueue.java @@ -1,3 +1,20 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package cn.edu.tsinghua.iginx.parquet.db.lsm.buffer; import cn.edu.tsinghua.iginx.parquet.db.lsm.buffer.chunk.Chunk; diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/chunk/Chunk.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/chunk/Chunk.java index 4735415084..36fa71f0e1 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/chunk/Chunk.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/chunk/Chunk.java @@ -1,3 +1,20 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package cn.edu.tsinghua.iginx.parquet.db.lsm.buffer.chunk; import cn.edu.tsinghua.iginx.parquet.util.NoexceptAutoCloseable; diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/chunk/IndexedChunk.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/chunk/IndexedChunk.java index ea2dc8ed12..aa06ab9223 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/chunk/IndexedChunk.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/chunk/IndexedChunk.java @@ -1,3 +1,20 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package cn.edu.tsinghua.iginx.parquet.db.lsm.buffer.chunk; import cn.edu.tsinghua.iginx.parquet.util.arrow.ArrowVectors; diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/chunk/IndexedChunkType.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/chunk/IndexedChunkType.java index ba9c5e5d3e..7be938fe92 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/chunk/IndexedChunkType.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/chunk/IndexedChunkType.java @@ -1,3 +1,20 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package cn.edu.tsinghua.iginx.parquet.db.lsm.buffer.chunk; public enum IndexedChunkType { diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/chunk/NoIndexChunk.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/chunk/NoIndexChunk.java index 4861afde7a..4cdeba279f 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/chunk/NoIndexChunk.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/chunk/NoIndexChunk.java @@ -1,3 +1,20 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package cn.edu.tsinghua.iginx.parquet.db.lsm.buffer.chunk; import cn.edu.tsinghua.iginx.parquet.util.arrow.ArrowVectors; diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/chunk/SkipListChunk.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/chunk/SkipListChunk.java index 517032f745..6da6697a31 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/chunk/SkipListChunk.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/buffer/chunk/SkipListChunk.java @@ -1,3 +1,20 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package cn.edu.tsinghua.iginx.parquet.db.lsm.buffer.chunk; import cn.edu.tsinghua.iginx.parquet.util.arrow.ArrowVectors; diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/compact/Flusher.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/compact/Flusher.java index 482ca7390d..0c1b00e29a 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/compact/Flusher.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/lsm/compact/Flusher.java @@ -1,3 +1,20 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package cn.edu.tsinghua.iginx.parquet.db.lsm.compact; import cn.edu.tsinghua.iginx.parquet.db.lsm.buffer.MemTableQueue; diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/WriteBatches.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/WriteBatches.java index ea2b8907c4..bd88c9af47 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/WriteBatches.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/WriteBatches.java @@ -1,3 +1,20 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package cn.edu.tsinghua.iginx.parquet.db.util; import cn.edu.tsinghua.iginx.engine.physical.storage.domain.ColumnKey; diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/DelegateScanner.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/DelegateScanner.java index fd7bbcb674..90bd881b42 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/DelegateScanner.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/DelegateScanner.java @@ -1,3 +1,20 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package cn.edu.tsinghua.iginx.parquet.db.util.iterator; import cn.edu.tsinghua.iginx.parquet.util.exception.StorageException; diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/EmtpyHeadRowScanner.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/EmtpyHeadRowScanner.java index 6d63fbc48e..8305adf853 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/EmtpyHeadRowScanner.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/EmtpyHeadRowScanner.java @@ -1,3 +1,20 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package cn.edu.tsinghua.iginx.parquet.db.util.iterator; import cn.edu.tsinghua.iginx.parquet.util.exception.StorageException; diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/LazyRowScanner.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/LazyRowScanner.java index 8dea969f0a..2830c8f60c 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/LazyRowScanner.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/LazyRowScanner.java @@ -1,3 +1,20 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package cn.edu.tsinghua.iginx.parquet.db.util.iterator; import cn.edu.tsinghua.iginx.parquet.util.exception.StorageException; diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/ListenCloseScanner.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/ListenCloseScanner.java index 8564cc8961..b8bccfd805 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/ListenCloseScanner.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/ListenCloseScanner.java @@ -1,3 +1,20 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package cn.edu.tsinghua.iginx.parquet.db.util.iterator; import cn.edu.tsinghua.iginx.parquet.util.exception.StorageException; diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/RowConcatScanner.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/RowConcatScanner.java index 687a3dcc48..8da9c5cf84 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/RowConcatScanner.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/RowConcatScanner.java @@ -1,3 +1,20 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package cn.edu.tsinghua.iginx.parquet.db.util.iterator; public class RowConcatScanner {} diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/RowScannerFactory.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/RowScannerFactory.java index 5450ed86fd..4dbc4abc8e 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/RowScannerFactory.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/db/util/iterator/RowScannerFactory.java @@ -1,3 +1,20 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package cn.edu.tsinghua.iginx.parquet.db.util.iterator; import cn.edu.tsinghua.iginx.parquet.util.exception.StorageException; diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/AggregatedRowStream.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/AggregatedRowStream.java index 888d09f218..bfe16a2c39 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/AggregatedRowStream.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/AggregatedRowStream.java @@ -1,3 +1,20 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package cn.edu.tsinghua.iginx.parquet.manager.data; import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/Awaitable.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/Awaitable.java index 89c90f3d6a..ac60a9eed0 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/Awaitable.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/Awaitable.java @@ -1,3 +1,20 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package cn.edu.tsinghua.iginx.parquet.util; public interface Awaitable { diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/CloseableHolders.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/CloseableHolders.java index 5d770b3764..083b82491f 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/CloseableHolders.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/CloseableHolders.java @@ -1,3 +1,20 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package cn.edu.tsinghua.iginx.parquet.util; import java.util.NoSuchElementException; diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/NoexceptAutoCloseable.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/NoexceptAutoCloseable.java index ae5a93e64d..139786fdd8 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/NoexceptAutoCloseable.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/NoexceptAutoCloseable.java @@ -1,3 +1,20 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package cn.edu.tsinghua.iginx.parquet.util; public interface NoexceptAutoCloseable extends AutoCloseable { diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/NoexceptAutoCloseables.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/NoexceptAutoCloseables.java index 498384604f..38ef81a0e9 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/NoexceptAutoCloseables.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/NoexceptAutoCloseables.java @@ -1,3 +1,20 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package cn.edu.tsinghua.iginx.parquet.util; import org.apache.arrow.util.AutoCloseables; diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/SingleCache.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/SingleCache.java index 412d96859f..14e694c0b3 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/SingleCache.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/SingleCache.java @@ -1,3 +1,20 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package cn.edu.tsinghua.iginx.parquet.util; import java.util.function.Consumer; diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/arrow/ArrowFieldTypes.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/arrow/ArrowFieldTypes.java index 9798707d59..65e864f559 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/arrow/ArrowFieldTypes.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/arrow/ArrowFieldTypes.java @@ -1,3 +1,20 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package cn.edu.tsinghua.iginx.parquet.util.arrow; import cn.edu.tsinghua.iginx.thrift.DataType; diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/arrow/ArrowFields.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/arrow/ArrowFields.java index 9710f3dfde..e29b423848 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/arrow/ArrowFields.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/arrow/ArrowFields.java @@ -1,3 +1,20 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package cn.edu.tsinghua.iginx.parquet.util.arrow; import cn.edu.tsinghua.iginx.engine.physical.storage.domain.ColumnKey; diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/arrow/ArrowTypes.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/arrow/ArrowTypes.java index 2716427c17..b563fc4a1c 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/arrow/ArrowTypes.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/arrow/ArrowTypes.java @@ -1,3 +1,20 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package cn.edu.tsinghua.iginx.parquet.util.arrow; import cn.edu.tsinghua.iginx.thrift.DataType; diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/arrow/ArrowVectors.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/arrow/ArrowVectors.java index 183c54e73c..f50d9321fe 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/arrow/ArrowVectors.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/arrow/ArrowVectors.java @@ -1,3 +1,20 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package cn.edu.tsinghua.iginx.parquet.util.arrow; import cn.edu.tsinghua.iginx.engine.physical.storage.domain.ColumnKey; diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/StorageClosedException.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/StorageClosedException.java index e7bf7f2c84..6f2dd38608 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/StorageClosedException.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/exception/StorageClosedException.java @@ -1,3 +1,20 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package cn.edu.tsinghua.iginx.parquet.util.exception; public class StorageClosedException extends StorageException { diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/iterator/DedupIterator.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/iterator/DedupIterator.java index 64cb48d744..f3b22cc2ef 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/iterator/DedupIterator.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/iterator/DedupIterator.java @@ -1,3 +1,20 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package cn.edu.tsinghua.iginx.parquet.util.iterator; import com.google.common.collect.Iterators; diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/iterator/StableMergeIterator.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/iterator/StableMergeIterator.java index a78ed8b3a5..f2dbc240ab 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/iterator/StableMergeIterator.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/util/iterator/StableMergeIterator.java @@ -1,3 +1,20 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package cn.edu.tsinghua.iginx.parquet.util.iterator; import com.google.common.collect.Iterators; diff --git a/dataSource/pom.xml b/dataSource/pom.xml index a1cdc62a91..469850f2ce 100644 --- a/dataSource/pom.xml +++ b/dataSource/pom.xml @@ -1,19 +1,23 @@ + + IGinX - the polystore system with high performance + Copyright (C) Tsinghua University + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +--> 4.0.0 diff --git a/dataSource/redis/pom.xml b/dataSource/redis/pom.xml index d77b50aac4..cacb7fd25e 100644 --- a/dataSource/redis/pom.xml +++ b/dataSource/redis/pom.xml @@ -1,4 +1,23 @@ + 4.0.0 diff --git a/dataSource/relational/pom.xml b/dataSource/relational/pom.xml index 7d4b4368c3..269cb2f509 100644 --- a/dataSource/relational/pom.xml +++ b/dataSource/relational/pom.xml @@ -1,4 +1,23 @@ + 4.0.0 diff --git a/dataSource/relational/src/main/resources/mysql-meta-template.properties b/dataSource/relational/src/main/resources/mysql-meta-template.properties index 118ecaaa88..d52031f1ed 100644 --- a/dataSource/relational/src/main/resources/mysql-meta-template.properties +++ b/dataSource/relational/src/main/resources/mysql-meta-template.properties @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + # 配置MySQL META以供JDBCMeta读取 # 驱动类 diff --git a/dataSource/relational/src/main/resources/oceanbase-meta.properties b/dataSource/relational/src/main/resources/oceanbase-meta.properties index f7c63c7f93..6e2fdaaf1b 100644 --- a/dataSource/relational/src/main/resources/oceanbase-meta.properties +++ b/dataSource/relational/src/main/resources/oceanbase-meta.properties @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + # 配置MySQL META以供JDBCMeta读取 # 驱动类 diff --git a/dataSource/src/assembly/driver.xml b/dataSource/src/assembly/driver.xml index 84b424f625..cabcb955a3 100644 --- a/dataSource/src/assembly/driver.xml +++ b/dataSource/src/assembly/driver.xml @@ -1,19 +1,23 @@ + + IGinX - the polystore system with high performance + Copyright (C) Tsinghua University + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +--> driver diff --git a/dependency/pom.xml b/dependency/pom.xml index 81106b6d75..9f887753a7 100644 --- a/dependency/pom.xml +++ b/dependency/pom.xml @@ -1,4 +1,23 @@ + 4.0.0 diff --git a/docker/client/Dockerfile b/docker/client/Dockerfile index 903ce7dc9a..97fae0daa1 100644 --- a/docker/client/Dockerfile +++ b/docker/client/Dockerfile @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + FROM maven:3-amazoncorretto-8 AS builder COPY . /root/iginx WORKDIR /root/iginx diff --git a/docker/client/build-no-maven.bat b/docker/client/build-no-maven.bat index f5dee8b5a8..3a80f15bc0 100644 --- a/docker/client/build-no-maven.bat +++ b/docker/client/build-no-maven.bat @@ -15,4 +15,5 @@ @REM You should have received a copy of the GNU General Public License @REM along with this program. If not, see . @REM + docker build --file Dockerfile-no-maven-windows -t iginx-client:0.7.0-SNAPSHOT ../../client \ No newline at end of file diff --git a/docker/client/build.bat b/docker/client/build.bat index e5f14cbc2b..9ec426f471 100644 --- a/docker/client/build.bat +++ b/docker/client/build.bat @@ -15,4 +15,5 @@ @REM You should have received a copy of the GNU General Public License @REM along with this program. If not, see . @REM + docker build --file Dockerfile -t iginx-client:0.7.0-SNAPSHOT ../../client \ No newline at end of file diff --git a/docker/client/run_docker.bat b/docker/client/run_docker.bat index 971720bc04..5087355cc7 100644 --- a/docker/client/run_docker.bat +++ b/docker/client/run_docker.bat @@ -15,6 +15,7 @@ @REM You should have received a copy of the GNU General Public License @REM along with this program. If not, see . @REM + @echo off setlocal enabledelayedexpansion diff --git a/docker/oneShot-parquet/Dockerfile b/docker/oneShot-parquet/Dockerfile index 2c1f315d8c..aabf826670 100644 --- a/docker/oneShot-parquet/Dockerfile +++ b/docker/oneShot-parquet/Dockerfile @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + FROM maven:3-amazoncorretto-8 AS builder COPY . /root/IGinX WORKDIR /root/IGinX diff --git a/docker/oneShot-parquet/build_and_run_iginx_docker.bat b/docker/oneShot-parquet/build_and_run_iginx_docker.bat index 994cee100d..ff90426f1f 100644 --- a/docker/oneShot-parquet/build_and_run_iginx_docker.bat +++ b/docker/oneShot-parquet/build_and_run_iginx_docker.bat @@ -15,4 +15,5 @@ @REM You should have received a copy of the GNU General Public License @REM along with this program. If not, see . @REM + docker compose up --build --detach \ No newline at end of file diff --git a/docker/oneShot-parquet/build_and_run_iginx_docker.sh b/docker/oneShot-parquet/build_and_run_iginx_docker.sh index 3178b9fdc3..544c1868d6 100644 --- a/docker/oneShot-parquet/build_and_run_iginx_docker.sh +++ b/docker/oneShot-parquet/build_and_run_iginx_docker.sh @@ -1 +1,19 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + docker compose up --build --detach \ No newline at end of file diff --git a/docker/oneShot-parquet/docker-compose.yaml b/docker/oneShot-parquet/docker-compose.yaml index a6931ea166..e2e7ee5e4d 100644 --- a/docker/oneShot-parquet/docker-compose.yaml +++ b/docker/oneShot-parquet/docker-compose.yaml @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + --- version: "3.9" services: diff --git a/docker/oneShot/Dockerfile b/docker/oneShot/Dockerfile index 0505817d54..7b2e7da1ba 100644 --- a/docker/oneShot/Dockerfile +++ b/docker/oneShot/Dockerfile @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + FROM maven:3-amazoncorretto-8 AS builder COPY . /root/IGinX WORKDIR /root/IGinX diff --git a/docker/oneShot/build_and_run_iginx_docker.bat b/docker/oneShot/build_and_run_iginx_docker.bat index 994cee100d..ff90426f1f 100644 --- a/docker/oneShot/build_and_run_iginx_docker.bat +++ b/docker/oneShot/build_and_run_iginx_docker.bat @@ -15,4 +15,5 @@ @REM You should have received a copy of the GNU General Public License @REM along with this program. If not, see . @REM + docker compose up --build --detach \ No newline at end of file diff --git a/docker/oneShot/build_and_run_iginx_docker.sh b/docker/oneShot/build_and_run_iginx_docker.sh index 3178b9fdc3..544c1868d6 100755 --- a/docker/oneShot/build_and_run_iginx_docker.sh +++ b/docker/oneShot/build_and_run_iginx_docker.sh @@ -1 +1,19 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + docker compose up --build --detach \ No newline at end of file diff --git a/docker/oneShot/docker-compose.yaml b/docker/oneShot/docker-compose.yaml index f2fb8ab293..5ad1d772ad 100644 --- a/docker/oneShot/docker-compose.yaml +++ b/docker/oneShot/docker-compose.yaml @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + --- version: "3.9" services: diff --git a/docker/onlyIginx-parquet/build_iginx_docker.bat b/docker/onlyIginx-parquet/build_iginx_docker.bat index 773a4d6c87..04fb3b63e1 100644 --- a/docker/onlyIginx-parquet/build_iginx_docker.bat +++ b/docker/onlyIginx-parquet/build_iginx_docker.bat @@ -15,4 +15,5 @@ @REM You should have received a copy of the GNU General Public License @REM along with this program. If not, see . @REM + docker build --file Dockerfile-iginx -t iginx:0.7.0-SNAPSHOT ../.. \ No newline at end of file diff --git a/docker/onlyIginx-parquet/run_iginx_docker.bat b/docker/onlyIginx-parquet/run_iginx_docker.bat index fd656462e8..aa1978dbef 100644 --- a/docker/onlyIginx-parquet/run_iginx_docker.bat +++ b/docker/onlyIginx-parquet/run_iginx_docker.bat @@ -15,6 +15,7 @@ @REM You should have received a copy of the GNU General Public License @REM along with this program. If not, see . @REM + @echo off cd /d %~dp0 setlocal EnableDelayedExpansion diff --git a/docker/onlyIginx/build_iginx_docker.bat b/docker/onlyIginx/build_iginx_docker.bat index 773a4d6c87..04fb3b63e1 100644 --- a/docker/onlyIginx/build_iginx_docker.bat +++ b/docker/onlyIginx/build_iginx_docker.bat @@ -15,4 +15,5 @@ @REM You should have received a copy of the GNU General Public License @REM along with this program. If not, see . @REM + docker build --file Dockerfile-iginx -t iginx:0.7.0-SNAPSHOT ../.. \ No newline at end of file diff --git a/docker/onlyIginx/build_iginx_docker.sh b/docker/onlyIginx/build_iginx_docker.sh index d08f72dac8..6aaf693eb2 100755 --- a/docker/onlyIginx/build_iginx_docker.sh +++ b/docker/onlyIginx/build_iginx_docker.sh @@ -1 +1,19 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + docker build --file Dockerfile-iginx -t iginx:0.7.0-SNAPSHOT ../.. \ No newline at end of file diff --git a/docker/onlyIginx/run_iginx_docker.bat b/docker/onlyIginx/run_iginx_docker.bat index 2322b2b11b..fe8a62604d 100644 --- a/docker/onlyIginx/run_iginx_docker.bat +++ b/docker/onlyIginx/run_iginx_docker.bat @@ -15,6 +15,7 @@ @REM You should have received a copy of the GNU General Public License @REM along with this program. If not, see . @REM + @echo off set "current_dir=%CD%" @REM 将路径中的单反斜线替换为双反斜线 diff --git a/docker/onlyIginx/run_iginx_docker.sh b/docker/onlyIginx/run_iginx_docker.sh index 30b7eb8546..6ea4dcb267 100755 --- a/docker/onlyIginx/run_iginx_docker.sh +++ b/docker/onlyIginx/run_iginx_docker.sh @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + ip=$1 name=$2 port=$3 diff --git a/example/pom.xml b/example/pom.xml index b9e5390575..3640abf9da 100644 --- a/example/pom.xml +++ b/example/pom.xml @@ -1,4 +1,23 @@ + 4.0.0 diff --git a/example/src/main/resources/TransformJobExample.yaml b/example/src/main/resources/TransformJobExample.yaml index 5ac0245242..acd1abb010 100644 --- a/example/src/main/resources/TransformJobExample.yaml +++ b/example/src/main/resources/TransformJobExample.yaml @@ -1,3 +1,21 @@ +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + --- taskList: - taskType: "iginx" diff --git a/jdbc/pom.xml b/jdbc/pom.xml index 1c401d176b..13709688ed 100644 --- a/jdbc/pom.xml +++ b/jdbc/pom.xml @@ -1,4 +1,23 @@ + 4.0.0 diff --git a/optimizer/pom.xml b/optimizer/pom.xml index be0e8dfd0a..38f52b2db6 100644 --- a/optimizer/pom.xml +++ b/optimizer/pom.xml @@ -1,4 +1,23 @@ + 4.0.0 diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/SetTransformPushDownPathUnionJoinRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/SetTransformPushDownPathUnionJoinRule.java index 3189b5f6b5..9ecd533477 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/SetTransformPushDownPathUnionJoinRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/SetTransformPushDownPathUnionJoinRule.java @@ -1,3 +1,20 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package cn.edu.tsinghua.iginx.logical.optimizer.rules; import cn.edu.tsinghua.iginx.engine.logical.utils.OperatorUtils; diff --git a/pom.xml b/pom.xml index 89dd05bdf3..55ed953a4a 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see . + along with this program. If not, see . --> + 4.0.0 diff --git a/session_py/iginx/iginx_pyclient/__init__.py b/session_py/iginx/iginx_pyclient/__init__.py index 2482c22e8a..537ea8cde0 100644 --- a/session_py/iginx/iginx_pyclient/__init__.py +++ b/session_py/iginx/iginx_pyclient/__init__.py @@ -15,3 +15,5 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . # + +# diff --git a/session_py/iginx/iginx_pyclient/dataset.py b/session_py/iginx/iginx_pyclient/dataset.py index f80047cce1..8b4b949350 100644 --- a/session_py/iginx/iginx_pyclient/dataset.py +++ b/session_py/iginx/iginx_pyclient/dataset.py @@ -15,6 +15,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . # + from enum import Enum import pandas as pd diff --git a/session_py/iginx/iginx_pyclient/session.py b/session_py/iginx/iginx_pyclient/session.py index 0e328b6744..0b76a9b622 100644 --- a/session_py/iginx/iginx_pyclient/session.py +++ b/session_py/iginx/iginx_pyclient/session.py @@ -15,6 +15,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . # + import csv import logging import os.path diff --git a/session_py/iginx/iginx_pyclient/time_series.py b/session_py/iginx/iginx_pyclient/time_series.py index 3d340d5f94..c4d0da32e0 100644 --- a/session_py/iginx/iginx_pyclient/time_series.py +++ b/session_py/iginx/iginx_pyclient/time_series.py @@ -15,6 +15,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . # + from .thrift.rpc.ttypes import DataType class TimeSeries(object): diff --git a/session_py/iginx/iginx_pyclient/utils/__init__.py b/session_py/iginx/iginx_pyclient/utils/__init__.py index cc3b5d49eb..5740237d34 100644 --- a/session_py/iginx/iginx_pyclient/utils/__init__.py +++ b/session_py/iginx/iginx_pyclient/utils/__init__.py @@ -14,4 +14,6 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +# + # \ No newline at end of file diff --git a/session_py/iginx/iginx_pyclient/utils/bitmap.py b/session_py/iginx/iginx_pyclient/utils/bitmap.py index af9a40d4fc..c8d93106f2 100644 --- a/session_py/iginx/iginx_pyclient/utils/bitmap.py +++ b/session_py/iginx/iginx_pyclient/utils/bitmap.py @@ -15,6 +15,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . # + class Bitmap(object): BIT_UTIL = [1, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 6, 1 << 7] diff --git a/session_py/iginx/iginx_pyclient/utils/byte_utils.py b/session_py/iginx/iginx_pyclient/utils/byte_utils.py index 10ed177254..9f1d79e55d 100644 --- a/session_py/iginx/iginx_pyclient/utils/byte_utils.py +++ b/session_py/iginx/iginx_pyclient/utils/byte_utils.py @@ -15,6 +15,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . # + import struct from .bitmap import Bitmap diff --git a/shared/pom.xml b/shared/pom.xml index ed94dcbeec..241e1adc82 100644 --- a/shared/pom.xml +++ b/shared/pom.xml @@ -1,4 +1,23 @@ + 4.0.0 diff --git a/test/pom.xml b/test/pom.xml index 898c7a0447..ba885f0559 100644 --- a/test/pom.xml +++ b/test/pom.xml @@ -1,4 +1,23 @@ + 4.0.0 diff --git a/thrift/pom.xml b/thrift/pom.xml index 90790c9bed..613ee91931 100644 --- a/thrift/pom.xml +++ b/thrift/pom.xml @@ -1,4 +1,23 @@ + 4.0.0 From 6bfba7581fab428e3455d47ab8ac4e079a8dc369 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 14 Jul 2024 09:49:53 +0800 Subject: [PATCH 067/138] build: update project version to 0.7.0 (#390) Co-authored-by: aqni <72963199+aqni@users.noreply.github.com> --- docker/client/Dockerfile | 2 +- docker/client/Dockerfile-no-maven | 2 +- docker/client/Dockerfile-no-maven-windows | 2 +- docker/client/build-no-maven.bat | 2 +- docker/client/build-no-maven.sh | 2 +- docker/client/build.bat | 2 +- docker/client/build.sh | 2 +- docker/client/run_docker.bat | 2 +- docker/client/run_docker.sh | 2 +- docker/onlyIginx-parquet/Dockerfile-iginx | 2 +- docker/onlyIginx-parquet/build_iginx_docker.bat | 2 +- docker/onlyIginx-parquet/build_iginx_docker.sh | 2 +- docker/onlyIginx-parquet/run_iginx_docker.bat | 2 +- docker/onlyIginx-parquet/run_iginx_docker.sh | 2 +- docker/onlyIginx/Dockerfile-iginx | 2 +- docker/onlyIginx/build_iginx_docker.bat | 2 +- docker/onlyIginx/build_iginx_docker.sh | 2 +- docker/onlyIginx/run_iginx_docker.bat | 2 +- docker/onlyIginx/run_iginx_docker.sh | 2 +- docs/quickStarts/IGinXByDocker-EnglishVersion.md | 2 +- docs/quickStarts/IGinXByDocker.md | 2 +- docs/quickStarts/IGinXBySource-EnglishVersion.md | 4 ++-- docs/quickStarts/IGinXBySource.md | 6 +++--- docs/quickStarts/IGinXCluster-EnglishVersion.md | 2 +- docs/quickStarts/IGinXCluster.md | 2 +- docs/quickStarts/IGinXInOneShot-EnglishVersion.md | 2 +- docs/quickStarts/IGinXInOneShot.md | 2 +- docs/quickStarts/IGinXManual-EnglishVersion.md | 2 +- docs/quickStarts/IGinXManual.md | 2 +- docs/quickStarts/IGinXZeppelin-EnglishVersion.md | 6 +++--- docs/quickStarts/IGinXZeppelin.md | 6 +++--- docs/quickStarts_Parquet/IGinXByDocker-EnglishVersion.md | 2 +- docs/quickStarts_Parquet/IGinXByDocker.md | 2 +- docs/quickStarts_Parquet/IGinXBySource-EnglishVersion.md | 4 ++-- docs/quickStarts_Parquet/IGinXBySource.md | 6 +++--- docs/quickStarts_Parquet/IGinXCluster-EnglishVersion.md | 2 +- docs/quickStarts_Parquet/IGinXCluster.md | 2 +- docs/quickStarts_Parquet/IGinXInOneShot-EnglishVersion.md | 2 +- docs/quickStarts_Parquet/IGinXInOneShot.md | 2 +- pom.xml | 2 +- 40 files changed, 50 insertions(+), 50 deletions(-) diff --git a/docker/client/Dockerfile b/docker/client/Dockerfile index 97fae0daa1..10a918d60d 100644 --- a/docker/client/Dockerfile +++ b/docker/client/Dockerfile @@ -22,7 +22,7 @@ WORKDIR /root/iginx RUN mvn clean package -pl client -am -Dmaven.test.skip=true -P-format -e FROM openjdk:11-jre-slim -COPY --from=builder /root/iginx/client/target/iginx-client-0.7.0-SNAPSHOT/ /iginx_client/ +COPY --from=builder /root/iginx/client/target/iginx-client-0.7.0/ /iginx_client/ RUN mkdir -p /iginx_client/logs RUN mkdir -p /iginx_client/data diff --git a/docker/client/Dockerfile-no-maven b/docker/client/Dockerfile-no-maven index e5a9ea1908..1e6076b6e0 100644 --- a/docker/client/Dockerfile-no-maven +++ b/docker/client/Dockerfile-no-maven @@ -1,5 +1,5 @@ FROM openjdk:11-jre-slim -COPY ./target/iginx-client-0.7.0-SNAPSHOT/ /iginx_client/ +COPY ./target/iginx-client-0.7.0/ /iginx_client/ RUN mkdir -p /iginx_client/logs RUN mkdir -p /iginx_client/data diff --git a/docker/client/Dockerfile-no-maven-windows b/docker/client/Dockerfile-no-maven-windows index 2cc4c8e59c..412b4d834c 100644 --- a/docker/client/Dockerfile-no-maven-windows +++ b/docker/client/Dockerfile-no-maven-windows @@ -2,7 +2,7 @@ FROM mcr.microsoft.com/windows/servercore:ltsc2022 COPY . C:/iginx WORKDIR C:/iginx -COPY ./target/iginx-client-0.7.0-SNAPSHOT/ C:/iginx_client +COPY ./target/iginx-client-0.7.0/ C:/iginx_client # 设置环境变量 USER ContainerAdministrator diff --git a/docker/client/build-no-maven.bat b/docker/client/build-no-maven.bat index 3a80f15bc0..63af2b899d 100644 --- a/docker/client/build-no-maven.bat +++ b/docker/client/build-no-maven.bat @@ -16,4 +16,4 @@ @REM along with this program. If not, see . @REM -docker build --file Dockerfile-no-maven-windows -t iginx-client:0.7.0-SNAPSHOT ../../client \ No newline at end of file +docker build --file Dockerfile-no-maven-windows -t iginx-client:0.7.0 ../../client \ No newline at end of file diff --git a/docker/client/build-no-maven.sh b/docker/client/build-no-maven.sh index 7556c27c53..8468b57fb4 100644 --- a/docker/client/build-no-maven.sh +++ b/docker/client/build-no-maven.sh @@ -17,4 +17,4 @@ # along with this program. If not, see . # -docker build --file Dockerfile-no-maven -t iginx-client:0.7.0-SNAPSHOT ../../client \ No newline at end of file +docker build --file Dockerfile-no-maven -t iginx-client:0.7.0 ../../client \ No newline at end of file diff --git a/docker/client/build.bat b/docker/client/build.bat index 9ec426f471..083cabfc90 100644 --- a/docker/client/build.bat +++ b/docker/client/build.bat @@ -16,4 +16,4 @@ @REM along with this program. If not, see . @REM -docker build --file Dockerfile -t iginx-client:0.7.0-SNAPSHOT ../../client \ No newline at end of file +docker build --file Dockerfile -t iginx-client:0.7.0 ../../client \ No newline at end of file diff --git a/docker/client/build.sh b/docker/client/build.sh index 86cafa869f..a8a6e122af 100644 --- a/docker/client/build.sh +++ b/docker/client/build.sh @@ -17,4 +17,4 @@ # along with this program. If not, see . # -docker build --file Dockerfile -t iginx-client:0.7.0-SNAPSHOT ../../client \ No newline at end of file +docker build --file Dockerfile -t iginx-client:0.7.0 ../../client \ No newline at end of file diff --git a/docker/client/run_docker.bat b/docker/client/run_docker.bat index 5087355cc7..07f1b39a67 100644 --- a/docker/client/run_docker.bat +++ b/docker/client/run_docker.bat @@ -52,7 +52,7 @@ if not exist "%datadir%" ( mkdir "%datadir%" ) -set command=docker run --name="%name%" -dit --add-host=host.docker.internal:host-gateway --mount type=bind,source=!datadir!,target=C:/iginx_client/data iginx-client:0.7.0-SNAPSHOT +set command=docker run --name="%name%" -dit --add-host=host.docker.internal:host-gateway --mount type=bind,source=!datadir!,target=C:/iginx_client/data iginx-client:0.7.0 echo %command% %command% diff --git a/docker/client/run_docker.sh b/docker/client/run_docker.sh index 1aac13254e..774ea6cc11 100644 --- a/docker/client/run_docker.sh +++ b/docker/client/run_docker.sh @@ -39,6 +39,6 @@ done [ -d "$datadir" ] || mkdir -p "$datadir" -command="docker run --name=\"$name\" --privileged -dit --add-host=host.docker.internal:host-gateway --mount type=bind,source=${datadir},target=/iginx_client/data iginx-client:0.7.0-SNAPSHOT" +command="docker run --name=\"$name\" --privileged -dit --add-host=host.docker.internal:host-gateway --mount type=bind,source=${datadir},target=/iginx_client/data iginx-client:0.7.0" echo $command eval $command diff --git a/docker/onlyIginx-parquet/Dockerfile-iginx b/docker/onlyIginx-parquet/Dockerfile-iginx index 9bdd06f46b..80a4ff1b48 100644 --- a/docker/onlyIginx-parquet/Dockerfile-iginx +++ b/docker/onlyIginx-parquet/Dockerfile-iginx @@ -4,7 +4,7 @@ WORKDIR /root/iginx RUN mvn clean package -DskipTests -P-format -e FROM openjdk:11-jre-slim -COPY --from=builder /root/iginx/core/target/iginx-core-0.7.0-SNAPSHOT /iginx +COPY --from=builder /root/iginx/core/target/iginx-core-0.7.0 /iginx # ports will be cast in run.bat diff --git a/docker/onlyIginx-parquet/build_iginx_docker.bat b/docker/onlyIginx-parquet/build_iginx_docker.bat index 04fb3b63e1..3685b6ec83 100644 --- a/docker/onlyIginx-parquet/build_iginx_docker.bat +++ b/docker/onlyIginx-parquet/build_iginx_docker.bat @@ -16,4 +16,4 @@ @REM along with this program. If not, see . @REM -docker build --file Dockerfile-iginx -t iginx:0.7.0-SNAPSHOT ../.. \ No newline at end of file +docker build --file Dockerfile-iginx -t iginx:0.7.0 ../.. \ No newline at end of file diff --git a/docker/onlyIginx-parquet/build_iginx_docker.sh b/docker/onlyIginx-parquet/build_iginx_docker.sh index 8293ed7620..b454056f03 100644 --- a/docker/onlyIginx-parquet/build_iginx_docker.sh +++ b/docker/onlyIginx-parquet/build_iginx_docker.sh @@ -17,4 +17,4 @@ # along with this program. If not, see . # -docker build --file Dockerfile-iginx -t iginx:0.7.0-SNAPSHOT ../.. \ No newline at end of file +docker build --file Dockerfile-iginx -t iginx:0.7.0 ../.. \ No newline at end of file diff --git a/docker/onlyIginx-parquet/run_iginx_docker.bat b/docker/onlyIginx-parquet/run_iginx_docker.bat index aa1978dbef..088dda3f58 100644 --- a/docker/onlyIginx-parquet/run_iginx_docker.bat +++ b/docker/onlyIginx-parquet/run_iginx_docker.bat @@ -180,7 +180,7 @@ if "!network!" neq "null" ( set "configFileConfig=-v !localConfigFile!:/iginx/conf " @REM -set command=docker run --name="%name%" !network!!localIPConfig!!configFileConfig!--privileged -dit -e host_iginx_port=%hostPort% -p %hostPort%:!port! !engineCast!iginx:0.7.0-SNAPSHOT +set command=docker run --name="%name%" !network!!localIPConfig!!configFileConfig!--privileged -dit -e host_iginx_port=%hostPort% -p %hostPort%:!port! !engineCast!iginx:0.7.0 echo %command% %command% diff --git a/docker/onlyIginx-parquet/run_iginx_docker.sh b/docker/onlyIginx-parquet/run_iginx_docker.sh index 9982b9ede5..281eea78ca 100644 --- a/docker/onlyIginx-parquet/run_iginx_docker.sh +++ b/docker/onlyIginx-parquet/run_iginx_docker.sh @@ -139,6 +139,6 @@ fi configFileConfig="-v ${localConfigFile}:/iginx/conf/config.properties " -command="docker run --name=${name} ${localIPConfig}${configFileConfig}--add-host=host.docker.internal:host-gateway ${network}--privileged -dit -e host_iginx_port=${hostPort}${portCastParams} iginx:0.7.0-SNAPSHOT" +command="docker run --name=${name} ${localIPConfig}${configFileConfig}--add-host=host.docker.internal:host-gateway ${network}--privileged -dit -e host_iginx_port=${hostPort}${portCastParams} iginx:0.7.0" echo "RUNNING ${command}" # ${command} \ No newline at end of file diff --git a/docker/onlyIginx/Dockerfile-iginx b/docker/onlyIginx/Dockerfile-iginx index f5bace0822..a7dc96e034 100644 --- a/docker/onlyIginx/Dockerfile-iginx +++ b/docker/onlyIginx/Dockerfile-iginx @@ -4,7 +4,7 @@ WORKDIR /root/iginx RUN mvn clean package -DskipTests -P-format FROM openjdk:11-jre-slim -COPY --from=builder /root/iginx/core/target/iginx-core-0.7.0-SNAPSHOT /iginx +COPY --from=builder /root/iginx/core/target/iginx-core-0.7.0 /iginx # 安装 Python 3.8, pip 并安装所需的 Python 包 RUN apt-get update && \ diff --git a/docker/onlyIginx/build_iginx_docker.bat b/docker/onlyIginx/build_iginx_docker.bat index 04fb3b63e1..3685b6ec83 100644 --- a/docker/onlyIginx/build_iginx_docker.bat +++ b/docker/onlyIginx/build_iginx_docker.bat @@ -16,4 +16,4 @@ @REM along with this program. If not, see . @REM -docker build --file Dockerfile-iginx -t iginx:0.7.0-SNAPSHOT ../.. \ No newline at end of file +docker build --file Dockerfile-iginx -t iginx:0.7.0 ../.. \ No newline at end of file diff --git a/docker/onlyIginx/build_iginx_docker.sh b/docker/onlyIginx/build_iginx_docker.sh index 6aaf693eb2..860f1ecd5d 100755 --- a/docker/onlyIginx/build_iginx_docker.sh +++ b/docker/onlyIginx/build_iginx_docker.sh @@ -16,4 +16,4 @@ # along with this program. If not, see . # -docker build --file Dockerfile-iginx -t iginx:0.7.0-SNAPSHOT ../.. \ No newline at end of file +docker build --file Dockerfile-iginx -t iginx:0.7.0 ../.. \ No newline at end of file diff --git a/docker/onlyIginx/run_iginx_docker.bat b/docker/onlyIginx/run_iginx_docker.bat index fe8a62604d..b9e8236ccc 100644 --- a/docker/onlyIginx/run_iginx_docker.bat +++ b/docker/onlyIginx/run_iginx_docker.bat @@ -29,4 +29,4 @@ set ip=%1 set name=%2 set port=%3 mkdir -p logs/docker_logs -docker run --name="%name%" --privileged -dit --net docker-cluster-iginx --ip %ip% --add-host=host.docker.internal:host-gateway -v %logdir%:/iginx/logs/ -p %port%:6888 iginx:0.7.0-SNAPSHOT \ No newline at end of file +docker run --name="%name%" --privileged -dit --net docker-cluster-iginx --ip %ip% --add-host=host.docker.internal:host-gateway -v %logdir%:/iginx/logs/ -p %port%:6888 iginx:0.7.0 \ No newline at end of file diff --git a/docker/onlyIginx/run_iginx_docker.sh b/docker/onlyIginx/run_iginx_docker.sh index 6ea4dcb267..e803cd499f 100755 --- a/docker/onlyIginx/run_iginx_docker.sh +++ b/docker/onlyIginx/run_iginx_docker.sh @@ -21,4 +21,4 @@ name=$2 port=$3 logdir="$(pwd)/../../logs/docker_logs" mkdir -p $logdir -docker run --name="${name}" --privileged -dit --net docker-cluster-iginx --ip ${ip} --add-host=host.docker.internal:host-gateway -v ${logdir}:/iginx/logs/ -p ${port}:6888 iginx:0.7.0-SNAPSHOT \ No newline at end of file +docker run --name="${name}" --privileged -dit --net docker-cluster-iginx --ip ${ip} --add-host=host.docker.internal:host-gateway -v ${logdir}:/iginx/logs/ -p ${port}:6888 iginx:0.7.0 \ No newline at end of file diff --git a/docs/quickStarts/IGinXByDocker-EnglishVersion.md b/docs/quickStarts/IGinXByDocker-EnglishVersion.md index 7d1c4a3b4c..361417fa61 100644 --- a/docs/quickStarts/IGinXByDocker-EnglishVersion.md +++ b/docs/quickStarts/IGinXByDocker-EnglishVersion.md @@ -255,7 +255,7 @@ The following words are displayed to indicate that the image was built successfu => [builder 2/4] COPY . /root/iginx 1.3s => [builder 3/4] WORKDIR /root/iginx 0.1s => [builder 4/4] RUN mvn clean package -DskipTests -P-format 876.3s -=> [stage-1 2/2] COPY --from=builder /root/iginx/core/target/iginx-core-0.7.0-SNAPSHOT /iginx 0.2s +=> [stage-1 2/2] COPY --from=builder /root/iginx/core/target/iginx-core-0.7.0 /iginx 0.2s => exporting to image 0.5s => => exporting layers 0.5s => => writing image sha256:e738348598c9db601dbf39c7a8ca9e1396c5ff51769afeb0fe3da12e2fdcd73a 0.0s diff --git a/docs/quickStarts/IGinXByDocker.md b/docs/quickStarts/IGinXByDocker.md index 110405dff5..9b5b193302 100644 --- a/docs/quickStarts/IGinXByDocker.md +++ b/docs/quickStarts/IGinXByDocker.md @@ -254,7 +254,7 @@ $ ./build_iginx_docker.sh => [builder 2/4] COPY . /root/iginx 1.3s => [builder 3/4] WORKDIR /root/iginx 0.1s => [builder 4/4] RUN mvn clean package -DskipTests -P-format 876.3s -=> [stage-1 2/2] COPY --from=builder /root/iginx/core/target/iginx-core-0.7.0-SNAPSHOT /iginx 0.2s +=> [stage-1 2/2] COPY --from=builder /root/iginx/core/target/iginx-core-0.7.0 /iginx 0.2s => exporting to image 0.5s => => exporting layers 0.5s => => writing image sha256:e738348598c9db601dbf39c7a8ca9e1396c5ff51769afeb0fe3da12e2fdcd73a 0.0s diff --git a/docs/quickStarts/IGinXBySource-EnglishVersion.md b/docs/quickStarts/IGinXBySource-EnglishVersion.md index 12bd746533..8c6b8c725b 100644 --- a/docs/quickStarts/IGinXBySource-EnglishVersion.md +++ b/docs/quickStarts/IGinXBySource-EnglishVersion.md @@ -180,7 +180,7 @@ The following words are displayed, indicating that the IGinX build is successful ```shell [INFO] ------------------------------------------------------------------------ -[INFO] Reactor Summary for IGinX 0.7.0-SNAPSHOT: +[INFO] Reactor Summary for IGinX 0.7.0: [INFO] [INFO] IGinX .............................................. SUCCESS [ 20.674 s] [INFO] IGinX Thrift ....................................... SUCCESS [01:18 min] @@ -445,7 +445,7 @@ Specifically, when using it, you only need to introduce the following dependenci cn.edu.tsinghua iginx-core - 0.7.0-SNAPSHOT + 0.7.0 ``` diff --git a/docs/quickStarts/IGinXBySource.md b/docs/quickStarts/IGinXBySource.md index 4202a91f2a..eca6088546 100644 --- a/docs/quickStarts/IGinXBySource.md +++ b/docs/quickStarts/IGinXBySource.md @@ -180,7 +180,7 @@ $ mvn clean install -Dmaven.test.skip=true ```shell [INFO] ------------------------------------------------------------------------ -[INFO] Reactor Summary for IGinX 0.7.0-SNAPSHOT: +[INFO] Reactor Summary for IGinX 0.7.0: [INFO] [INFO] IGinX .............................................. SUCCESS [ 20.674 s] [INFO] IGinX Thrift ....................................... SUCCESS [01:18 min] @@ -257,7 +257,7 @@ Starting zookeeper ... STARTED ```shell $ cd ~ -$ cd IGinX/core/target/iginx-core-0.7.0-SNAPSHOT +$ cd IGinX/core/target/iginx-core-0.7.0 $ chmod +x sbin/start_iginx.sh # 为启动脚本添加启动权限 $ ./sbin/start_iginx.sh ``` @@ -440,7 +440,7 @@ $ mvn clean install -DskipTests cn.edu.tsinghua iginx-core - 0.7.0-SNAPSHOT + 0.7.0 ``` diff --git a/docs/quickStarts/IGinXCluster-EnglishVersion.md b/docs/quickStarts/IGinXCluster-EnglishVersion.md index d73ebc7676..bb524a5368 100644 --- a/docs/quickStarts/IGinXCluster-EnglishVersion.md +++ b/docs/quickStarts/IGinXCluster-EnglishVersion.md @@ -356,7 +356,7 @@ Only when you are using it, you need to introduce the following dependencies in cn.edu.tsinghua iginx-core - 0.7.0-SNAPSHOT + 0.7.0 ``` diff --git a/docs/quickStarts/IGinXCluster.md b/docs/quickStarts/IGinXCluster.md index bf936b0843..e41c7e7d2c 100644 --- a/docs/quickStarts/IGinXCluster.md +++ b/docs/quickStarts/IGinXCluster.md @@ -363,7 +363,7 @@ $ mvn clean install -DskipTests cn.edu.tsinghua iginx-core - 0.7.0-SNAPSHOT + 0.7.0 ``` diff --git a/docs/quickStarts/IGinXInOneShot-EnglishVersion.md b/docs/quickStarts/IGinXInOneShot-EnglishVersion.md index 2c02151d3a..647295404d 100644 --- a/docs/quickStarts/IGinXInOneShot-EnglishVersion.md +++ b/docs/quickStarts/IGinXInOneShot-EnglishVersion.md @@ -272,7 +272,7 @@ Specifically, when using it, you only need to introduce the following dependenci cn.edu.tsinghua iginx-core - 0.7.0-SNAPSHOT + 0.7.0 ``` diff --git a/docs/quickStarts/IGinXInOneShot.md b/docs/quickStarts/IGinXInOneShot.md index cf8b7d93d1..d398c206d7 100644 --- a/docs/quickStarts/IGinXInOneShot.md +++ b/docs/quickStarts/IGinXInOneShot.md @@ -266,7 +266,7 @@ $ mvn clean install -DskipTests cn.edu.tsinghua iginx-core - 0.7.0-SNAPSHOT + 0.7.0 ``` diff --git a/docs/quickStarts/IGinXManual-EnglishVersion.md b/docs/quickStarts/IGinXManual-EnglishVersion.md index 02bcfc1dd8..de6d99513f 100644 --- a/docs/quickStarts/IGinXManual-EnglishVersion.md +++ b/docs/quickStarts/IGinXManual-EnglishVersion.md @@ -503,7 +503,7 @@ Only when you are using it, you need to introduce the following dependencies in cn.edu.tsinghua iginx-core - 0.7.0-SNAPSHOT + 0.7.0 ``` diff --git a/docs/quickStarts/IGinXManual.md b/docs/quickStarts/IGinXManual.md index 3db0884adf..a35ad2e7ea 100644 --- a/docs/quickStarts/IGinXManual.md +++ b/docs/quickStarts/IGinXManual.md @@ -504,7 +504,7 @@ $ mvn clean install -DskipTests cn.edu.tsinghua iginx-core - 0.7.0-SNAPSHOT + 0.7.0 ``` diff --git a/docs/quickStarts/IGinXZeppelin-EnglishVersion.md b/docs/quickStarts/IGinXZeppelin-EnglishVersion.md index 9d2b6e976b..26bbafaafd 100644 --- a/docs/quickStarts/IGinXZeppelin-EnglishVersion.md +++ b/docs/quickStarts/IGinXZeppelin-EnglishVersion.md @@ -10,7 +10,7 @@ Navigate to the IGinX directory and execute the following command to build the I mvn clean package -DskipTests -P get-jar-with-dependencies ``` -Upon successful compilation, you will find the `zeppelin-iginx-0.7.0-SNAPSHOT-jar-with-dependencies.jar` package in the `IGinX/zeppelin-interpreter/target/` directory. We will need this package for the next steps of deploying Zeppelin. +Upon successful compilation, you will find the `zeppelin-iginx-0.7.0-jar-with-dependencies.jar` package in the `IGinX/zeppelin-interpreter/target/` directory. We will need this package for the next steps of deploying Zeppelin. ## Deploying Zeppelin @@ -56,7 +56,7 @@ export JAVA_HOME= #### Integrating IGinX Zeppelin Interpreter -In the `zeppelin-0.10.1-bin-netinst/interpreter/` folder, create a new folder named `IGinX`. Place the compiled `zeppelin-iginx-0.7.0-SNAPSHOT-jar-with-dependencies.jar` package inside this folder. +In the `zeppelin-0.10.1-bin-netinst/interpreter/` folder, create a new folder named `IGinX`. Place the compiled `zeppelin-iginx-0.7.0-jar-with-dependencies.jar` package inside this folder. #### Starting IGinX @@ -86,7 +86,7 @@ Before deploying Zeppelin, start IGinX. Prepare a folder to place the IGinX Zeppelin Interpreter. For example, let's name the folder `zeppelin-interpreter` with the absolute path `~/code/zeppelin-interpreter/`. -Place the `zeppelin-iginx-0.7.0-SNAPSHOT-jar-with-dependencies.jar` package inside this prepared `zeppelin-interpreter` folder. +Place the `zeppelin-iginx-0.7.0-jar-with-dependencies.jar` package inside this prepared `zeppelin-interpreter` folder. #### Starting Docker Container Using Commands diff --git a/docs/quickStarts/IGinXZeppelin.md b/docs/quickStarts/IGinXZeppelin.md index f2e0e6f58d..9ea727bea1 100644 --- a/docs/quickStarts/IGinXZeppelin.md +++ b/docs/quickStarts/IGinXZeppelin.md @@ -10,7 +10,7 @@ mvn clean package -DskipTests -P get-jar-with-dependencies ``` -构建成功后,在`IGinX/zeppelin-interpreter/target/`路径下找到`zeppelin-iginx-0.7.0-SNAPSHOT-jar-with-dependencies.jar`包。 +构建成功后,在`IGinX/zeppelin-interpreter/target/`路径下找到`zeppelin-iginx-0.7.0-jar-with-dependencies.jar`包。 在下一步部署Zeppelin时我们需要用到这个包。 @@ -60,7 +60,7 @@ export JAVA_HOME= #### 接入IGinX Zeppelin Interpreter -在`zeppelin-0.10.1-bin-netinst/interpreter/`文件夹下新建一个文件夹`IGinX`,将构建好的`zeppelin-iginx-0.7.0-SNAPSHOT-jar-with-dependencies.jar`包放入其中即可。 +在`zeppelin-0.10.1-bin-netinst/interpreter/`文件夹下新建一个文件夹`IGinX`,将构建好的`zeppelin-iginx-0.7.0-jar-with-dependencies.jar`包放入其中即可。 #### 启动IGinX @@ -90,7 +90,7 @@ export JAVA_HOME= 我们需要准备一个文件夹,用于放置IGinX Zeppelin Interpreter。例如我们准备一个文件夹名为`zeppelin-interpreter`,其绝对路径为`~/code/zeppelin-interpreter/`。 -将`zeppelin-iginx-0.7.0-SNAPSHOT-jar-with-dependencies.jar`包放入我们准备好的`zeppelin-interpreter`文件夹内即可。 +将`zeppelin-iginx-0.7.0-jar-with-dependencies.jar`包放入我们准备好的`zeppelin-interpreter`文件夹内即可。 #### 使用命令启动Docker容器 diff --git a/docs/quickStarts_Parquet/IGinXByDocker-EnglishVersion.md b/docs/quickStarts_Parquet/IGinXByDocker-EnglishVersion.md index de88978e2e..0e6bee020a 100644 --- a/docs/quickStarts_Parquet/IGinXByDocker-EnglishVersion.md +++ b/docs/quickStarts_Parquet/IGinXByDocker-EnglishVersion.md @@ -250,7 +250,7 @@ The following words are displayed to indicate that the image was built successfu => [builder 2/4] COPY . /root/iginx 1.3s => [builder 3/4] WORKDIR /root/iginx 0.1s => [builder 4/4] RUN mvn clean package -DskipTests -P passFormat 876.3s -=> [stage-1 2/2] COPY --from=builder /root/iginx/core/target/iginx-core-0.7.0-SNAPSHOT /iginx 0.2s +=> [stage-1 2/2] COPY --from=builder /root/iginx/core/target/iginx-core-0.7.0 /iginx 0.2s => exporting to image 0.5s => => exporting layers 0.5s => => writing image sha256:e738348598c9db601dbf39c7a8ca9e1396c5ff51769afeb0fe3da12e2fdcd73a 0.0s diff --git a/docs/quickStarts_Parquet/IGinXByDocker.md b/docs/quickStarts_Parquet/IGinXByDocker.md index acc9420336..d95bef1086 100644 --- a/docs/quickStarts_Parquet/IGinXByDocker.md +++ b/docs/quickStarts_Parquet/IGinXByDocker.md @@ -249,7 +249,7 @@ $ ./build_iginx_docker.sh => [builder 2/4] COPY . /root/iginx 1.3s => [builder 3/4] WORKDIR /root/iginx 0.1s => [builder 4/4] RUN mvn clean package -DskipTests -P passFormat 876.3s -=> [stage-1 2/2] COPY --from=builder /root/iginx/core/target/iginx-core-0.7.0-SNAPSHOT /iginx 0.2s +=> [stage-1 2/2] COPY --from=builder /root/iginx/core/target/iginx-core-0.7.0 /iginx 0.2s => exporting to image 0.5s => => exporting layers 0.5s => => writing image sha256:e738348598c9db601dbf39c7a8ca9e1396c5ff51769afeb0fe3da12e2fdcd73a 0.0s diff --git a/docs/quickStarts_Parquet/IGinXBySource-EnglishVersion.md b/docs/quickStarts_Parquet/IGinXBySource-EnglishVersion.md index 5eb2b6053b..2be89b142e 100644 --- a/docs/quickStarts_Parquet/IGinXBySource-EnglishVersion.md +++ b/docs/quickStarts_Parquet/IGinXBySource-EnglishVersion.md @@ -168,7 +168,7 @@ The following words are displayed, indicating that the IGinX build is successful ```shell [INFO] ------------------------------------------------------------------------ -[INFO] Reactor Summary for IGinX 0.7.0-SNAPSHOT: +[INFO] Reactor Summary for IGinX 0.7.0: [INFO] [INFO] IGinX .............................................. SUCCESS [ 20.674 s] [INFO] IGinX Thrift ....................................... SUCCESS [01:18 min] @@ -417,7 +417,7 @@ Specifically, when using it, you only need to introduce the following dependenci cn.edu.tsinghua iginx-core - 0.7.0-SNAPSHOT + 0.7.0 ``` diff --git a/docs/quickStarts_Parquet/IGinXBySource.md b/docs/quickStarts_Parquet/IGinXBySource.md index e55cc7fcee..8b77cd87b4 100644 --- a/docs/quickStarts_Parquet/IGinXBySource.md +++ b/docs/quickStarts_Parquet/IGinXBySource.md @@ -170,7 +170,7 @@ $ mvn clean install -Dmaven.test.skip=true ```shell [INFO] ------------------------------------------------------------------------ -[INFO] Reactor Summary for IGinX 0.7.0-SNAPSHOT: +[INFO] Reactor Summary for IGinX 0.7.0: [INFO] [INFO] IGinX .............................................. SUCCESS [ 20.674 s] [INFO] IGinX Thrift ....................................... SUCCESS [01:18 min] @@ -232,7 +232,7 @@ storageEngineList=127.0.0.1#6667#parquet#dir=parquetData#has_data=false#is_read_ ```shell $ cd ~ -$ cd IGinX/core/target/iginx-core-0.7.0-SNAPSHOT +$ cd IGinX/core/target/iginx-core-0.7.0 $ chmod +x sbin/start_iginx.sh # 为启动脚本添加启动权限 $ ./sbin/start_iginx.sh ``` @@ -414,7 +414,7 @@ $ mvn clean install -DskipTests cn.edu.tsinghua iginx-core - 0.7.0-SNAPSHOT + 0.7.0 ``` diff --git a/docs/quickStarts_Parquet/IGinXCluster-EnglishVersion.md b/docs/quickStarts_Parquet/IGinXCluster-EnglishVersion.md index c32c716950..669c1be48e 100644 --- a/docs/quickStarts_Parquet/IGinXCluster-EnglishVersion.md +++ b/docs/quickStarts_Parquet/IGinXCluster-EnglishVersion.md @@ -322,7 +322,7 @@ Only when you are using it, you need to introduce the following dependencies in cn.edu.tsinghua iginx-core - 0.7.0-SNAPSHOT + 0.7.0 ``` diff --git a/docs/quickStarts_Parquet/IGinXCluster.md b/docs/quickStarts_Parquet/IGinXCluster.md index 6fc5d56891..94686e4196 100644 --- a/docs/quickStarts_Parquet/IGinXCluster.md +++ b/docs/quickStarts_Parquet/IGinXCluster.md @@ -325,7 +325,7 @@ $ mvn clean install -DskipTests cn.edu.tsinghua iginx-core - 0.7.0-SNAPSHOT + 0.7.0 ``` diff --git a/docs/quickStarts_Parquet/IGinXInOneShot-EnglishVersion.md b/docs/quickStarts_Parquet/IGinXInOneShot-EnglishVersion.md index cb785b4282..563e228de4 100644 --- a/docs/quickStarts_Parquet/IGinXInOneShot-EnglishVersion.md +++ b/docs/quickStarts_Parquet/IGinXInOneShot-EnglishVersion.md @@ -254,7 +254,7 @@ Specifically, when using it, you only need to introduce the following dependenci cn.edu.tsinghua iginx-core - 0.7.0-SNAPSHOT + 0.7.0 ``` diff --git a/docs/quickStarts_Parquet/IGinXInOneShot.md b/docs/quickStarts_Parquet/IGinXInOneShot.md index 02ccdbd77e..c707d0f1a8 100644 --- a/docs/quickStarts_Parquet/IGinXInOneShot.md +++ b/docs/quickStarts_Parquet/IGinXInOneShot.md @@ -247,7 +247,7 @@ $ mvn clean install -DskipTests cn.edu.tsinghua iginx-core - 0.7.0-SNAPSHOT + 0.7.0 ``` diff --git a/pom.xml b/pom.xml index 55ed953a4a..690fb8a2dd 100644 --- a/pom.xml +++ b/pom.xml @@ -64,7 +64,7 @@ ${project.basedir} UTF-8 UTF-8 - 0.7.0-SNAPSHOT + 0.7.0 From dd917bc4929402a64b43d53c124099729788ee83 Mon Sep 17 00:00:00 2001 From: An Qi Date: Sun, 14 Jul 2024 12:25:21 +0800 Subject: [PATCH 068/138] fix: correct release workflow (#391) correct release workflow --- .github/workflows/release.yml | 3 ++- ...SHOT.jar => iginx-optimizer-extension-0.7.0.jar} | Bin optimizer/pom.xml | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) rename dependency/src/main/resources/{iginx-optimizer-extension-0.7.0-SNAPSHOT.jar => iginx-optimizer-extension-0.7.0.jar} (100%) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 890473c464..717e097563 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -92,4 +92,5 @@ jobs: run: python setup.py sdist bdist_wheel - name: Publish package distributions to PyPI uses: pypa/gh-action-pypi-publish@release/v1 - working-directory: session_py/iginx + with: + packages-dir: session_py/iginx/dist diff --git a/dependency/src/main/resources/iginx-optimizer-extension-0.7.0-SNAPSHOT.jar b/dependency/src/main/resources/iginx-optimizer-extension-0.7.0.jar similarity index 100% rename from dependency/src/main/resources/iginx-optimizer-extension-0.7.0-SNAPSHOT.jar rename to dependency/src/main/resources/iginx-optimizer-extension-0.7.0.jar diff --git a/optimizer/pom.xml b/optimizer/pom.xml index 38f52b2db6..c14ac218b9 100644 --- a/optimizer/pom.xml +++ b/optimizer/pom.xml @@ -101,7 +101,7 @@ - + From 6df46d4c5daf86ee9d6e8bfe157f0b8ef7bda23d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 14 Jul 2024 12:49:15 +0800 Subject: [PATCH 069/138] build: update project version to 0.8.0-SNAPSHOT (#393) Co-authored-by: aqni <72963199+aqni@users.noreply.github.com> --- docker/client/Dockerfile | 2 +- docker/client/Dockerfile-no-maven | 2 +- docker/client/Dockerfile-no-maven-windows | 2 +- docker/client/build-no-maven.bat | 2 +- docker/client/build-no-maven.sh | 2 +- docker/client/build.bat | 2 +- docker/client/build.sh | 2 +- docker/client/run_docker.bat | 2 +- docker/client/run_docker.sh | 2 +- docker/onlyIginx-parquet/Dockerfile-iginx | 2 +- .../onlyIginx-parquet/build_iginx_docker.bat | 2 +- .../onlyIginx-parquet/build_iginx_docker.sh | 2 +- docker/onlyIginx-parquet/run_iginx_docker.bat | 2 +- docker/onlyIginx-parquet/run_iginx_docker.sh | 2 +- docker/onlyIginx/Dockerfile-iginx | 2 +- docker/onlyIginx/build_iginx_docker.bat | 2 +- docker/onlyIginx/build_iginx_docker.sh | 2 +- docker/onlyIginx/run_iginx_docker.bat | 2 +- docker/onlyIginx/run_iginx_docker.sh | 2 +- docs/pdf/SQLManual.pdf | Bin 293316 -> 293550 bytes docs/pdf/userManualC.pdf | Bin 1626300 -> 1626426 bytes .../IGinXByDocker-EnglishVersion.md | 2 +- docs/quickStarts/IGinXByDocker.md | 2 +- .../IGinXBySource-EnglishVersion.md | 4 ++-- docs/quickStarts/IGinXBySource.md | 6 +++--- .../IGinXCluster-EnglishVersion.md | 2 +- docs/quickStarts/IGinXCluster.md | 2 +- .../IGinXInOneShot-EnglishVersion.md | 2 +- docs/quickStarts/IGinXInOneShot.md | 2 +- .../quickStarts/IGinXManual-EnglishVersion.md | 2 +- docs/quickStarts/IGinXManual.md | 2 +- .../IGinXZeppelin-EnglishVersion.md | 6 +++--- docs/quickStarts/IGinXZeppelin.md | 6 +++--- .../IGinXByDocker-EnglishVersion.md | 2 +- docs/quickStarts_Parquet/IGinXByDocker.md | 2 +- .../IGinXBySource-EnglishVersion.md | 4 ++-- docs/quickStarts_Parquet/IGinXBySource.md | 6 +++--- .../IGinXCluster-EnglishVersion.md | 2 +- docs/quickStarts_Parquet/IGinXCluster.md | 2 +- .../IGinXInOneShot-EnglishVersion.md | 2 +- docs/quickStarts_Parquet/IGinXInOneShot.md | 2 +- pom.xml | 2 +- 42 files changed, 50 insertions(+), 50 deletions(-) diff --git a/docker/client/Dockerfile b/docker/client/Dockerfile index 10a918d60d..e144d98aa6 100644 --- a/docker/client/Dockerfile +++ b/docker/client/Dockerfile @@ -22,7 +22,7 @@ WORKDIR /root/iginx RUN mvn clean package -pl client -am -Dmaven.test.skip=true -P-format -e FROM openjdk:11-jre-slim -COPY --from=builder /root/iginx/client/target/iginx-client-0.7.0/ /iginx_client/ +COPY --from=builder /root/iginx/client/target/iginx-client-0.8.0-SNAPSHOT/ /iginx_client/ RUN mkdir -p /iginx_client/logs RUN mkdir -p /iginx_client/data diff --git a/docker/client/Dockerfile-no-maven b/docker/client/Dockerfile-no-maven index 1e6076b6e0..298b80a6c8 100644 --- a/docker/client/Dockerfile-no-maven +++ b/docker/client/Dockerfile-no-maven @@ -1,5 +1,5 @@ FROM openjdk:11-jre-slim -COPY ./target/iginx-client-0.7.0/ /iginx_client/ +COPY ./target/iginx-client-0.8.0-SNAPSHOT/ /iginx_client/ RUN mkdir -p /iginx_client/logs RUN mkdir -p /iginx_client/data diff --git a/docker/client/Dockerfile-no-maven-windows b/docker/client/Dockerfile-no-maven-windows index 412b4d834c..e7aa37a211 100644 --- a/docker/client/Dockerfile-no-maven-windows +++ b/docker/client/Dockerfile-no-maven-windows @@ -2,7 +2,7 @@ FROM mcr.microsoft.com/windows/servercore:ltsc2022 COPY . C:/iginx WORKDIR C:/iginx -COPY ./target/iginx-client-0.7.0/ C:/iginx_client +COPY ./target/iginx-client-0.8.0-SNAPSHOT/ C:/iginx_client # 设置环境变量 USER ContainerAdministrator diff --git a/docker/client/build-no-maven.bat b/docker/client/build-no-maven.bat index 63af2b899d..e4145ae956 100644 --- a/docker/client/build-no-maven.bat +++ b/docker/client/build-no-maven.bat @@ -16,4 +16,4 @@ @REM along with this program. If not, see . @REM -docker build --file Dockerfile-no-maven-windows -t iginx-client:0.7.0 ../../client \ No newline at end of file +docker build --file Dockerfile-no-maven-windows -t iginx-client:0.8.0-SNAPSHOT ../../client \ No newline at end of file diff --git a/docker/client/build-no-maven.sh b/docker/client/build-no-maven.sh index 8468b57fb4..225f402534 100644 --- a/docker/client/build-no-maven.sh +++ b/docker/client/build-no-maven.sh @@ -17,4 +17,4 @@ # along with this program. If not, see . # -docker build --file Dockerfile-no-maven -t iginx-client:0.7.0 ../../client \ No newline at end of file +docker build --file Dockerfile-no-maven -t iginx-client:0.8.0-SNAPSHOT ../../client \ No newline at end of file diff --git a/docker/client/build.bat b/docker/client/build.bat index 083cabfc90..8952efafba 100644 --- a/docker/client/build.bat +++ b/docker/client/build.bat @@ -16,4 +16,4 @@ @REM along with this program. If not, see . @REM -docker build --file Dockerfile -t iginx-client:0.7.0 ../../client \ No newline at end of file +docker build --file Dockerfile -t iginx-client:0.8.0-SNAPSHOT ../../client \ No newline at end of file diff --git a/docker/client/build.sh b/docker/client/build.sh index a8a6e122af..13c3e887fb 100644 --- a/docker/client/build.sh +++ b/docker/client/build.sh @@ -17,4 +17,4 @@ # along with this program. If not, see . # -docker build --file Dockerfile -t iginx-client:0.7.0 ../../client \ No newline at end of file +docker build --file Dockerfile -t iginx-client:0.8.0-SNAPSHOT ../../client \ No newline at end of file diff --git a/docker/client/run_docker.bat b/docker/client/run_docker.bat index 07f1b39a67..b020f9ca38 100644 --- a/docker/client/run_docker.bat +++ b/docker/client/run_docker.bat @@ -52,7 +52,7 @@ if not exist "%datadir%" ( mkdir "%datadir%" ) -set command=docker run --name="%name%" -dit --add-host=host.docker.internal:host-gateway --mount type=bind,source=!datadir!,target=C:/iginx_client/data iginx-client:0.7.0 +set command=docker run --name="%name%" -dit --add-host=host.docker.internal:host-gateway --mount type=bind,source=!datadir!,target=C:/iginx_client/data iginx-client:0.8.0-SNAPSHOT echo %command% %command% diff --git a/docker/client/run_docker.sh b/docker/client/run_docker.sh index 774ea6cc11..7d54fef2e4 100644 --- a/docker/client/run_docker.sh +++ b/docker/client/run_docker.sh @@ -39,6 +39,6 @@ done [ -d "$datadir" ] || mkdir -p "$datadir" -command="docker run --name=\"$name\" --privileged -dit --add-host=host.docker.internal:host-gateway --mount type=bind,source=${datadir},target=/iginx_client/data iginx-client:0.7.0" +command="docker run --name=\"$name\" --privileged -dit --add-host=host.docker.internal:host-gateway --mount type=bind,source=${datadir},target=/iginx_client/data iginx-client:0.8.0-SNAPSHOT" echo $command eval $command diff --git a/docker/onlyIginx-parquet/Dockerfile-iginx b/docker/onlyIginx-parquet/Dockerfile-iginx index 80a4ff1b48..693478bb74 100644 --- a/docker/onlyIginx-parquet/Dockerfile-iginx +++ b/docker/onlyIginx-parquet/Dockerfile-iginx @@ -4,7 +4,7 @@ WORKDIR /root/iginx RUN mvn clean package -DskipTests -P-format -e FROM openjdk:11-jre-slim -COPY --from=builder /root/iginx/core/target/iginx-core-0.7.0 /iginx +COPY --from=builder /root/iginx/core/target/iginx-core-0.8.0-SNAPSHOT /iginx # ports will be cast in run.bat diff --git a/docker/onlyIginx-parquet/build_iginx_docker.bat b/docker/onlyIginx-parquet/build_iginx_docker.bat index 3685b6ec83..a7724a13e5 100644 --- a/docker/onlyIginx-parquet/build_iginx_docker.bat +++ b/docker/onlyIginx-parquet/build_iginx_docker.bat @@ -16,4 +16,4 @@ @REM along with this program. If not, see . @REM -docker build --file Dockerfile-iginx -t iginx:0.7.0 ../.. \ No newline at end of file +docker build --file Dockerfile-iginx -t iginx:0.8.0-SNAPSHOT ../.. \ No newline at end of file diff --git a/docker/onlyIginx-parquet/build_iginx_docker.sh b/docker/onlyIginx-parquet/build_iginx_docker.sh index b454056f03..05949b3840 100644 --- a/docker/onlyIginx-parquet/build_iginx_docker.sh +++ b/docker/onlyIginx-parquet/build_iginx_docker.sh @@ -17,4 +17,4 @@ # along with this program. If not, see . # -docker build --file Dockerfile-iginx -t iginx:0.7.0 ../.. \ No newline at end of file +docker build --file Dockerfile-iginx -t iginx:0.8.0-SNAPSHOT ../.. \ No newline at end of file diff --git a/docker/onlyIginx-parquet/run_iginx_docker.bat b/docker/onlyIginx-parquet/run_iginx_docker.bat index 088dda3f58..ae993b795c 100644 --- a/docker/onlyIginx-parquet/run_iginx_docker.bat +++ b/docker/onlyIginx-parquet/run_iginx_docker.bat @@ -180,7 +180,7 @@ if "!network!" neq "null" ( set "configFileConfig=-v !localConfigFile!:/iginx/conf " @REM -set command=docker run --name="%name%" !network!!localIPConfig!!configFileConfig!--privileged -dit -e host_iginx_port=%hostPort% -p %hostPort%:!port! !engineCast!iginx:0.7.0 +set command=docker run --name="%name%" !network!!localIPConfig!!configFileConfig!--privileged -dit -e host_iginx_port=%hostPort% -p %hostPort%:!port! !engineCast!iginx:0.8.0-SNAPSHOT echo %command% %command% diff --git a/docker/onlyIginx-parquet/run_iginx_docker.sh b/docker/onlyIginx-parquet/run_iginx_docker.sh index 281eea78ca..627228d8f6 100644 --- a/docker/onlyIginx-parquet/run_iginx_docker.sh +++ b/docker/onlyIginx-parquet/run_iginx_docker.sh @@ -139,6 +139,6 @@ fi configFileConfig="-v ${localConfigFile}:/iginx/conf/config.properties " -command="docker run --name=${name} ${localIPConfig}${configFileConfig}--add-host=host.docker.internal:host-gateway ${network}--privileged -dit -e host_iginx_port=${hostPort}${portCastParams} iginx:0.7.0" +command="docker run --name=${name} ${localIPConfig}${configFileConfig}--add-host=host.docker.internal:host-gateway ${network}--privileged -dit -e host_iginx_port=${hostPort}${portCastParams} iginx:0.8.0-SNAPSHOT" echo "RUNNING ${command}" # ${command} \ No newline at end of file diff --git a/docker/onlyIginx/Dockerfile-iginx b/docker/onlyIginx/Dockerfile-iginx index a7dc96e034..5f1169b266 100644 --- a/docker/onlyIginx/Dockerfile-iginx +++ b/docker/onlyIginx/Dockerfile-iginx @@ -4,7 +4,7 @@ WORKDIR /root/iginx RUN mvn clean package -DskipTests -P-format FROM openjdk:11-jre-slim -COPY --from=builder /root/iginx/core/target/iginx-core-0.7.0 /iginx +COPY --from=builder /root/iginx/core/target/iginx-core-0.8.0-SNAPSHOT /iginx # 安装 Python 3.8, pip 并安装所需的 Python 包 RUN apt-get update && \ diff --git a/docker/onlyIginx/build_iginx_docker.bat b/docker/onlyIginx/build_iginx_docker.bat index 3685b6ec83..a7724a13e5 100644 --- a/docker/onlyIginx/build_iginx_docker.bat +++ b/docker/onlyIginx/build_iginx_docker.bat @@ -16,4 +16,4 @@ @REM along with this program. If not, see . @REM -docker build --file Dockerfile-iginx -t iginx:0.7.0 ../.. \ No newline at end of file +docker build --file Dockerfile-iginx -t iginx:0.8.0-SNAPSHOT ../.. \ No newline at end of file diff --git a/docker/onlyIginx/build_iginx_docker.sh b/docker/onlyIginx/build_iginx_docker.sh index 860f1ecd5d..3dbd72181e 100755 --- a/docker/onlyIginx/build_iginx_docker.sh +++ b/docker/onlyIginx/build_iginx_docker.sh @@ -16,4 +16,4 @@ # along with this program. If not, see . # -docker build --file Dockerfile-iginx -t iginx:0.7.0 ../.. \ No newline at end of file +docker build --file Dockerfile-iginx -t iginx:0.8.0-SNAPSHOT ../.. \ No newline at end of file diff --git a/docker/onlyIginx/run_iginx_docker.bat b/docker/onlyIginx/run_iginx_docker.bat index b9e8236ccc..183ab516a0 100644 --- a/docker/onlyIginx/run_iginx_docker.bat +++ b/docker/onlyIginx/run_iginx_docker.bat @@ -29,4 +29,4 @@ set ip=%1 set name=%2 set port=%3 mkdir -p logs/docker_logs -docker run --name="%name%" --privileged -dit --net docker-cluster-iginx --ip %ip% --add-host=host.docker.internal:host-gateway -v %logdir%:/iginx/logs/ -p %port%:6888 iginx:0.7.0 \ No newline at end of file +docker run --name="%name%" --privileged -dit --net docker-cluster-iginx --ip %ip% --add-host=host.docker.internal:host-gateway -v %logdir%:/iginx/logs/ -p %port%:6888 iginx:0.8.0-SNAPSHOT \ No newline at end of file diff --git a/docker/onlyIginx/run_iginx_docker.sh b/docker/onlyIginx/run_iginx_docker.sh index e803cd499f..2c689d0688 100755 --- a/docker/onlyIginx/run_iginx_docker.sh +++ b/docker/onlyIginx/run_iginx_docker.sh @@ -21,4 +21,4 @@ name=$2 port=$3 logdir="$(pwd)/../../logs/docker_logs" mkdir -p $logdir -docker run --name="${name}" --privileged -dit --net docker-cluster-iginx --ip ${ip} --add-host=host.docker.internal:host-gateway -v ${logdir}:/iginx/logs/ -p ${port}:6888 iginx:0.7.0 \ No newline at end of file +docker run --name="${name}" --privileged -dit --net docker-cluster-iginx --ip ${ip} --add-host=host.docker.internal:host-gateway -v ${logdir}:/iginx/logs/ -p ${port}:6888 iginx:0.8.0-SNAPSHOT \ No newline at end of file diff --git a/docs/pdf/SQLManual.pdf b/docs/pdf/SQLManual.pdf index b7901523bd781cb396682e88a71e32c9705d0c9d..4c8f6d550200b4ff0dbdbb21c38b980f71051d70 100644 GIT binary patch delta 717 zcmX@|S#aG~!G;#bEljHtH7)cEbc6jI1A;yLLkwU*!2k$#4fK#Dw;xPox)@Eo`ss; zA3-cCt!3WHg;QPsI_68;H9MJYRdFfV4pb8Bi%WJo*nsDMm}Ql4DglQsFzD{-;Z*{1 UuFLisf0hHhM5xn_V`-KF0RDJ;g#Z8m diff --git a/docs/pdf/userManualC.pdf b/docs/pdf/userManualC.pdf index 5b1981cd888c7b315220ea3e3f5b4e76720c5e3c..df3c52fad954f5cd8b83b3200ca62a0f19bd94f8 100644 GIT binary patch delta 337 zcmdn9FnQOaF7M2#)7Pc1l7LFFq7OocV7M>Q~7QPn#7J(MQ7NHj57LgXw z7O@ubEfR7Yc=asw40MD290P(q{6nTIZIG})71|!RK|+HSRcw0KR*4&^Lfg}}NqlBT z6`LNr3*EHoGj~a-psLz_aF>KABdXZ+Te~I9(S$_zpzEA&yGKGz1H}Wz3I-sckf*=} eq)?=`SMHJ6h~|;)dWR%(*ikLoKJTQ296JDS++s-p delta 210 zcmW-aI|{-;6h%=d#{d8G3Xvcpg3U9cll=%*A}+z=R&HQw75fNkAWmgzW9tT7fg5lp zw|R$mFP!+e)Q9B`DWs8sfP*YtM$l|HLUNP(e% zqislIN6e(h>U^V*2n [builder 2/4] COPY . /root/iginx 1.3s => [builder 3/4] WORKDIR /root/iginx 0.1s => [builder 4/4] RUN mvn clean package -DskipTests -P-format 876.3s -=> [stage-1 2/2] COPY --from=builder /root/iginx/core/target/iginx-core-0.7.0 /iginx 0.2s +=> [stage-1 2/2] COPY --from=builder /root/iginx/core/target/iginx-core-0.8.0-SNAPSHOT /iginx 0.2s => exporting to image 0.5s => => exporting layers 0.5s => => writing image sha256:e738348598c9db601dbf39c7a8ca9e1396c5ff51769afeb0fe3da12e2fdcd73a 0.0s diff --git a/docs/quickStarts/IGinXByDocker.md b/docs/quickStarts/IGinXByDocker.md index 9b5b193302..1f559a9785 100644 --- a/docs/quickStarts/IGinXByDocker.md +++ b/docs/quickStarts/IGinXByDocker.md @@ -254,7 +254,7 @@ $ ./build_iginx_docker.sh => [builder 2/4] COPY . /root/iginx 1.3s => [builder 3/4] WORKDIR /root/iginx 0.1s => [builder 4/4] RUN mvn clean package -DskipTests -P-format 876.3s -=> [stage-1 2/2] COPY --from=builder /root/iginx/core/target/iginx-core-0.7.0 /iginx 0.2s +=> [stage-1 2/2] COPY --from=builder /root/iginx/core/target/iginx-core-0.8.0-SNAPSHOT /iginx 0.2s => exporting to image 0.5s => => exporting layers 0.5s => => writing image sha256:e738348598c9db601dbf39c7a8ca9e1396c5ff51769afeb0fe3da12e2fdcd73a 0.0s diff --git a/docs/quickStarts/IGinXBySource-EnglishVersion.md b/docs/quickStarts/IGinXBySource-EnglishVersion.md index 8c6b8c725b..4c5e96bd6a 100644 --- a/docs/quickStarts/IGinXBySource-EnglishVersion.md +++ b/docs/quickStarts/IGinXBySource-EnglishVersion.md @@ -180,7 +180,7 @@ The following words are displayed, indicating that the IGinX build is successful ```shell [INFO] ------------------------------------------------------------------------ -[INFO] Reactor Summary for IGinX 0.7.0: +[INFO] Reactor Summary for IGinX 0.8.0-SNAPSHOT: [INFO] [INFO] IGinX .............................................. SUCCESS [ 20.674 s] [INFO] IGinX Thrift ....................................... SUCCESS [01:18 min] @@ -445,7 +445,7 @@ Specifically, when using it, you only need to introduce the following dependenci cn.edu.tsinghua iginx-core - 0.7.0 + 0.8.0-SNAPSHOT ``` diff --git a/docs/quickStarts/IGinXBySource.md b/docs/quickStarts/IGinXBySource.md index eca6088546..816437b558 100644 --- a/docs/quickStarts/IGinXBySource.md +++ b/docs/quickStarts/IGinXBySource.md @@ -180,7 +180,7 @@ $ mvn clean install -Dmaven.test.skip=true ```shell [INFO] ------------------------------------------------------------------------ -[INFO] Reactor Summary for IGinX 0.7.0: +[INFO] Reactor Summary for IGinX 0.8.0-SNAPSHOT: [INFO] [INFO] IGinX .............................................. SUCCESS [ 20.674 s] [INFO] IGinX Thrift ....................................... SUCCESS [01:18 min] @@ -257,7 +257,7 @@ Starting zookeeper ... STARTED ```shell $ cd ~ -$ cd IGinX/core/target/iginx-core-0.7.0 +$ cd IGinX/core/target/iginx-core-0.8.0-SNAPSHOT $ chmod +x sbin/start_iginx.sh # 为启动脚本添加启动权限 $ ./sbin/start_iginx.sh ``` @@ -440,7 +440,7 @@ $ mvn clean install -DskipTests cn.edu.tsinghua iginx-core - 0.7.0 + 0.8.0-SNAPSHOT ``` diff --git a/docs/quickStarts/IGinXCluster-EnglishVersion.md b/docs/quickStarts/IGinXCluster-EnglishVersion.md index bb524a5368..c7770b6440 100644 --- a/docs/quickStarts/IGinXCluster-EnglishVersion.md +++ b/docs/quickStarts/IGinXCluster-EnglishVersion.md @@ -356,7 +356,7 @@ Only when you are using it, you need to introduce the following dependencies in cn.edu.tsinghua iginx-core - 0.7.0 + 0.8.0-SNAPSHOT ``` diff --git a/docs/quickStarts/IGinXCluster.md b/docs/quickStarts/IGinXCluster.md index e41c7e7d2c..e1ec7879cb 100644 --- a/docs/quickStarts/IGinXCluster.md +++ b/docs/quickStarts/IGinXCluster.md @@ -363,7 +363,7 @@ $ mvn clean install -DskipTests cn.edu.tsinghua iginx-core - 0.7.0 + 0.8.0-SNAPSHOT ``` diff --git a/docs/quickStarts/IGinXInOneShot-EnglishVersion.md b/docs/quickStarts/IGinXInOneShot-EnglishVersion.md index 647295404d..24a59cc8f0 100644 --- a/docs/quickStarts/IGinXInOneShot-EnglishVersion.md +++ b/docs/quickStarts/IGinXInOneShot-EnglishVersion.md @@ -272,7 +272,7 @@ Specifically, when using it, you only need to introduce the following dependenci cn.edu.tsinghua iginx-core - 0.7.0 + 0.8.0-SNAPSHOT ``` diff --git a/docs/quickStarts/IGinXInOneShot.md b/docs/quickStarts/IGinXInOneShot.md index d398c206d7..92bb9e7c10 100644 --- a/docs/quickStarts/IGinXInOneShot.md +++ b/docs/quickStarts/IGinXInOneShot.md @@ -266,7 +266,7 @@ $ mvn clean install -DskipTests cn.edu.tsinghua iginx-core - 0.7.0 + 0.8.0-SNAPSHOT ``` diff --git a/docs/quickStarts/IGinXManual-EnglishVersion.md b/docs/quickStarts/IGinXManual-EnglishVersion.md index de6d99513f..e4490a22ea 100644 --- a/docs/quickStarts/IGinXManual-EnglishVersion.md +++ b/docs/quickStarts/IGinXManual-EnglishVersion.md @@ -503,7 +503,7 @@ Only when you are using it, you need to introduce the following dependencies in cn.edu.tsinghua iginx-core - 0.7.0 + 0.8.0-SNAPSHOT ``` diff --git a/docs/quickStarts/IGinXManual.md b/docs/quickStarts/IGinXManual.md index a35ad2e7ea..489730983c 100644 --- a/docs/quickStarts/IGinXManual.md +++ b/docs/quickStarts/IGinXManual.md @@ -504,7 +504,7 @@ $ mvn clean install -DskipTests cn.edu.tsinghua iginx-core - 0.7.0 + 0.8.0-SNAPSHOT ``` diff --git a/docs/quickStarts/IGinXZeppelin-EnglishVersion.md b/docs/quickStarts/IGinXZeppelin-EnglishVersion.md index 26bbafaafd..fd75aba78b 100644 --- a/docs/quickStarts/IGinXZeppelin-EnglishVersion.md +++ b/docs/quickStarts/IGinXZeppelin-EnglishVersion.md @@ -10,7 +10,7 @@ Navigate to the IGinX directory and execute the following command to build the I mvn clean package -DskipTests -P get-jar-with-dependencies ``` -Upon successful compilation, you will find the `zeppelin-iginx-0.7.0-jar-with-dependencies.jar` package in the `IGinX/zeppelin-interpreter/target/` directory. We will need this package for the next steps of deploying Zeppelin. +Upon successful compilation, you will find the `zeppelin-iginx-0.8.0-SNAPSHOT-jar-with-dependencies.jar` package in the `IGinX/zeppelin-interpreter/target/` directory. We will need this package for the next steps of deploying Zeppelin. ## Deploying Zeppelin @@ -56,7 +56,7 @@ export JAVA_HOME= #### Integrating IGinX Zeppelin Interpreter -In the `zeppelin-0.10.1-bin-netinst/interpreter/` folder, create a new folder named `IGinX`. Place the compiled `zeppelin-iginx-0.7.0-jar-with-dependencies.jar` package inside this folder. +In the `zeppelin-0.10.1-bin-netinst/interpreter/` folder, create a new folder named `IGinX`. Place the compiled `zeppelin-iginx-0.8.0-SNAPSHOT-jar-with-dependencies.jar` package inside this folder. #### Starting IGinX @@ -86,7 +86,7 @@ Before deploying Zeppelin, start IGinX. Prepare a folder to place the IGinX Zeppelin Interpreter. For example, let's name the folder `zeppelin-interpreter` with the absolute path `~/code/zeppelin-interpreter/`. -Place the `zeppelin-iginx-0.7.0-jar-with-dependencies.jar` package inside this prepared `zeppelin-interpreter` folder. +Place the `zeppelin-iginx-0.8.0-SNAPSHOT-jar-with-dependencies.jar` package inside this prepared `zeppelin-interpreter` folder. #### Starting Docker Container Using Commands diff --git a/docs/quickStarts/IGinXZeppelin.md b/docs/quickStarts/IGinXZeppelin.md index 9ea727bea1..17a7eb7968 100644 --- a/docs/quickStarts/IGinXZeppelin.md +++ b/docs/quickStarts/IGinXZeppelin.md @@ -10,7 +10,7 @@ mvn clean package -DskipTests -P get-jar-with-dependencies ``` -构建成功后,在`IGinX/zeppelin-interpreter/target/`路径下找到`zeppelin-iginx-0.7.0-jar-with-dependencies.jar`包。 +构建成功后,在`IGinX/zeppelin-interpreter/target/`路径下找到`zeppelin-iginx-0.8.0-SNAPSHOT-jar-with-dependencies.jar`包。 在下一步部署Zeppelin时我们需要用到这个包。 @@ -60,7 +60,7 @@ export JAVA_HOME= #### 接入IGinX Zeppelin Interpreter -在`zeppelin-0.10.1-bin-netinst/interpreter/`文件夹下新建一个文件夹`IGinX`,将构建好的`zeppelin-iginx-0.7.0-jar-with-dependencies.jar`包放入其中即可。 +在`zeppelin-0.10.1-bin-netinst/interpreter/`文件夹下新建一个文件夹`IGinX`,将构建好的`zeppelin-iginx-0.8.0-SNAPSHOT-jar-with-dependencies.jar`包放入其中即可。 #### 启动IGinX @@ -90,7 +90,7 @@ export JAVA_HOME= 我们需要准备一个文件夹,用于放置IGinX Zeppelin Interpreter。例如我们准备一个文件夹名为`zeppelin-interpreter`,其绝对路径为`~/code/zeppelin-interpreter/`。 -将`zeppelin-iginx-0.7.0-jar-with-dependencies.jar`包放入我们准备好的`zeppelin-interpreter`文件夹内即可。 +将`zeppelin-iginx-0.8.0-SNAPSHOT-jar-with-dependencies.jar`包放入我们准备好的`zeppelin-interpreter`文件夹内即可。 #### 使用命令启动Docker容器 diff --git a/docs/quickStarts_Parquet/IGinXByDocker-EnglishVersion.md b/docs/quickStarts_Parquet/IGinXByDocker-EnglishVersion.md index 0e6bee020a..d9b067d89a 100644 --- a/docs/quickStarts_Parquet/IGinXByDocker-EnglishVersion.md +++ b/docs/quickStarts_Parquet/IGinXByDocker-EnglishVersion.md @@ -250,7 +250,7 @@ The following words are displayed to indicate that the image was built successfu => [builder 2/4] COPY . /root/iginx 1.3s => [builder 3/4] WORKDIR /root/iginx 0.1s => [builder 4/4] RUN mvn clean package -DskipTests -P passFormat 876.3s -=> [stage-1 2/2] COPY --from=builder /root/iginx/core/target/iginx-core-0.7.0 /iginx 0.2s +=> [stage-1 2/2] COPY --from=builder /root/iginx/core/target/iginx-core-0.8.0-SNAPSHOT /iginx 0.2s => exporting to image 0.5s => => exporting layers 0.5s => => writing image sha256:e738348598c9db601dbf39c7a8ca9e1396c5ff51769afeb0fe3da12e2fdcd73a 0.0s diff --git a/docs/quickStarts_Parquet/IGinXByDocker.md b/docs/quickStarts_Parquet/IGinXByDocker.md index d95bef1086..e8551666d2 100644 --- a/docs/quickStarts_Parquet/IGinXByDocker.md +++ b/docs/quickStarts_Parquet/IGinXByDocker.md @@ -249,7 +249,7 @@ $ ./build_iginx_docker.sh => [builder 2/4] COPY . /root/iginx 1.3s => [builder 3/4] WORKDIR /root/iginx 0.1s => [builder 4/4] RUN mvn clean package -DskipTests -P passFormat 876.3s -=> [stage-1 2/2] COPY --from=builder /root/iginx/core/target/iginx-core-0.7.0 /iginx 0.2s +=> [stage-1 2/2] COPY --from=builder /root/iginx/core/target/iginx-core-0.8.0-SNAPSHOT /iginx 0.2s => exporting to image 0.5s => => exporting layers 0.5s => => writing image sha256:e738348598c9db601dbf39c7a8ca9e1396c5ff51769afeb0fe3da12e2fdcd73a 0.0s diff --git a/docs/quickStarts_Parquet/IGinXBySource-EnglishVersion.md b/docs/quickStarts_Parquet/IGinXBySource-EnglishVersion.md index 2be89b142e..bfdeaf3c8b 100644 --- a/docs/quickStarts_Parquet/IGinXBySource-EnglishVersion.md +++ b/docs/quickStarts_Parquet/IGinXBySource-EnglishVersion.md @@ -168,7 +168,7 @@ The following words are displayed, indicating that the IGinX build is successful ```shell [INFO] ------------------------------------------------------------------------ -[INFO] Reactor Summary for IGinX 0.7.0: +[INFO] Reactor Summary for IGinX 0.8.0-SNAPSHOT: [INFO] [INFO] IGinX .............................................. SUCCESS [ 20.674 s] [INFO] IGinX Thrift ....................................... SUCCESS [01:18 min] @@ -417,7 +417,7 @@ Specifically, when using it, you only need to introduce the following dependenci cn.edu.tsinghua iginx-core - 0.7.0 + 0.8.0-SNAPSHOT ``` diff --git a/docs/quickStarts_Parquet/IGinXBySource.md b/docs/quickStarts_Parquet/IGinXBySource.md index 8b77cd87b4..52a04f64e4 100644 --- a/docs/quickStarts_Parquet/IGinXBySource.md +++ b/docs/quickStarts_Parquet/IGinXBySource.md @@ -170,7 +170,7 @@ $ mvn clean install -Dmaven.test.skip=true ```shell [INFO] ------------------------------------------------------------------------ -[INFO] Reactor Summary for IGinX 0.7.0: +[INFO] Reactor Summary for IGinX 0.8.0-SNAPSHOT: [INFO] [INFO] IGinX .............................................. SUCCESS [ 20.674 s] [INFO] IGinX Thrift ....................................... SUCCESS [01:18 min] @@ -232,7 +232,7 @@ storageEngineList=127.0.0.1#6667#parquet#dir=parquetData#has_data=false#is_read_ ```shell $ cd ~ -$ cd IGinX/core/target/iginx-core-0.7.0 +$ cd IGinX/core/target/iginx-core-0.8.0-SNAPSHOT $ chmod +x sbin/start_iginx.sh # 为启动脚本添加启动权限 $ ./sbin/start_iginx.sh ``` @@ -414,7 +414,7 @@ $ mvn clean install -DskipTests cn.edu.tsinghua iginx-core - 0.7.0 + 0.8.0-SNAPSHOT ``` diff --git a/docs/quickStarts_Parquet/IGinXCluster-EnglishVersion.md b/docs/quickStarts_Parquet/IGinXCluster-EnglishVersion.md index 669c1be48e..8a23a80467 100644 --- a/docs/quickStarts_Parquet/IGinXCluster-EnglishVersion.md +++ b/docs/quickStarts_Parquet/IGinXCluster-EnglishVersion.md @@ -322,7 +322,7 @@ Only when you are using it, you need to introduce the following dependencies in cn.edu.tsinghua iginx-core - 0.7.0 + 0.8.0-SNAPSHOT ``` diff --git a/docs/quickStarts_Parquet/IGinXCluster.md b/docs/quickStarts_Parquet/IGinXCluster.md index 94686e4196..8f464cdc63 100644 --- a/docs/quickStarts_Parquet/IGinXCluster.md +++ b/docs/quickStarts_Parquet/IGinXCluster.md @@ -325,7 +325,7 @@ $ mvn clean install -DskipTests cn.edu.tsinghua iginx-core - 0.7.0 + 0.8.0-SNAPSHOT ``` diff --git a/docs/quickStarts_Parquet/IGinXInOneShot-EnglishVersion.md b/docs/quickStarts_Parquet/IGinXInOneShot-EnglishVersion.md index 563e228de4..87a857a7ac 100644 --- a/docs/quickStarts_Parquet/IGinXInOneShot-EnglishVersion.md +++ b/docs/quickStarts_Parquet/IGinXInOneShot-EnglishVersion.md @@ -254,7 +254,7 @@ Specifically, when using it, you only need to introduce the following dependenci cn.edu.tsinghua iginx-core - 0.7.0 + 0.8.0-SNAPSHOT ``` diff --git a/docs/quickStarts_Parquet/IGinXInOneShot.md b/docs/quickStarts_Parquet/IGinXInOneShot.md index c707d0f1a8..9fb95c5988 100644 --- a/docs/quickStarts_Parquet/IGinXInOneShot.md +++ b/docs/quickStarts_Parquet/IGinXInOneShot.md @@ -247,7 +247,7 @@ $ mvn clean install -DskipTests cn.edu.tsinghua iginx-core - 0.7.0 + 0.8.0-SNAPSHOT ``` diff --git a/pom.xml b/pom.xml index 690fb8a2dd..d820ddfe0e 100644 --- a/pom.xml +++ b/pom.xml @@ -64,7 +64,7 @@ ${project.basedir} UTF-8 UTF-8 - 0.7.0 + 0.8.0-SNAPSHOT From cab29ac2fd41e0488370b1f876635a51aa651347 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Mon, 15 Jul 2024 00:18:49 +0800 Subject: [PATCH 070/138] format && optimize import --- .../engine/physical/storage/IStorage.java | 2 +- .../execute/StoragePhysicalTaskExecutor.java | 8 ++- .../iginx/filesystem/FileSystemStorage.java | 5 +- .../iginx/filesystem/exec/LocalExecutor.java | 7 ++- .../iginx/filesystem/exec/RemoteExecutor.java | 25 ++++++++-- .../filesystem/server/FileSystemWorker.java | 18 ++++--- .../iginx/influxdb/InfluxDBStorage.java | 25 ++++++++-- .../tsinghua/iginx/iotdb/IoTDBStorage.java | 29 ++++++++--- .../iginx/mongodb/MongoDBStorage.java | 15 +++++- .../iginx/parquet/ParquetStorage.java | 6 ++- .../iginx/parquet/exec/LocalExecutor.java | 13 +++-- .../iginx/parquet/exec/RemoteExecutor.java | 28 +++++++++-- .../iginx/parquet/manager/Manager.java | 1 - .../parquet/manager/data/DataManager.java | 6 ++- .../parquet/manager/dummy/DummyManager.java | 6 ++- .../parquet/manager/dummy/EmptyManager.java | 2 +- .../iginx/parquet/server/ParquetWorker.java | 50 +++++++++++++++---- .../tsinghua/iginx/redis/RedisStorage.java | 17 +++++-- .../iginx/relational/RelationalStorage.java | 41 ++++++++++++--- .../expansion/BaseCapacityExpansionIT.java | 14 +++--- .../filesystem/datasource/DataSourceIT.java | 1 - 21 files changed, 250 insertions(+), 69 deletions(-) diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/IStorage.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/IStorage.java index f038c507a7..a29ae04223 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/IStorage.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/IStorage.java @@ -25,8 +25,8 @@ import cn.edu.tsinghua.iginx.engine.shared.operator.Insert; import cn.edu.tsinghua.iginx.engine.shared.operator.Project; import cn.edu.tsinghua.iginx.engine.shared.operator.Select; +import cn.edu.tsinghua.iginx.engine.shared.operator.SetTransform; import cn.edu.tsinghua.iginx.engine.shared.operator.tag.TagFilter; -import cn.edu.tsinghua.iginx.engine.shared.operator.*; import cn.edu.tsinghua.iginx.metadata.entity.ColumnsInterval; import cn.edu.tsinghua.iginx.metadata.entity.KeyInterval; import cn.edu.tsinghua.iginx.utils.Pair; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java index 611f02a841..2fdf509c83 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java @@ -37,7 +37,13 @@ import cn.edu.tsinghua.iginx.engine.physical.task.StoragePhysicalTask; import cn.edu.tsinghua.iginx.engine.physical.task.TaskExecuteResult; import cn.edu.tsinghua.iginx.engine.shared.data.read.RowStream; -import cn.edu.tsinghua.iginx.engine.shared.operator.*; +import cn.edu.tsinghua.iginx.engine.shared.operator.Delete; +import cn.edu.tsinghua.iginx.engine.shared.operator.Insert; +import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; +import cn.edu.tsinghua.iginx.engine.shared.operator.Project; +import cn.edu.tsinghua.iginx.engine.shared.operator.Select; +import cn.edu.tsinghua.iginx.engine.shared.operator.SetTransform; +import cn.edu.tsinghua.iginx.engine.shared.operator.ShowColumns; import cn.edu.tsinghua.iginx.engine.shared.operator.tag.TagFilter; import cn.edu.tsinghua.iginx.engine.shared.operator.type.OperatorType; import cn.edu.tsinghua.iginx.metadata.DefaultMetaManager; diff --git a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/FileSystemStorage.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/FileSystemStorage.java index 71e5096718..993772391e 100644 --- a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/FileSystemStorage.java +++ b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/FileSystemStorage.java @@ -26,7 +26,10 @@ import cn.edu.tsinghua.iginx.engine.physical.storage.domain.Column; import cn.edu.tsinghua.iginx.engine.physical.storage.domain.DataArea; import cn.edu.tsinghua.iginx.engine.physical.task.TaskExecuteResult; -import cn.edu.tsinghua.iginx.engine.shared.operator.*; +import cn.edu.tsinghua.iginx.engine.shared.operator.Delete; +import cn.edu.tsinghua.iginx.engine.shared.operator.Insert; +import cn.edu.tsinghua.iginx.engine.shared.operator.Project; +import cn.edu.tsinghua.iginx.engine.shared.operator.Select; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.AndFilter; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Filter; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.KeyFilter; diff --git a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java index 423089af8c..5929144e2b 100644 --- a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java +++ b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java @@ -70,9 +70,9 @@ public class LocalExecutor implements Executor { private String prefix; - private boolean hasData; + private final boolean hasData; - private FileSystemManager fileSystemManager; + private final FileSystemManager fileSystemManager; public LocalExecutor(boolean isReadOnly, boolean hasData, Map extraParams) { String dir = extraParams.get(Constant.INIT_INFO_DIR); @@ -383,8 +383,7 @@ public List getColumnsOfStorageUnit( } @Override - public Pair getBoundaryOfStorage(String dataPrefix) - throws PhysicalException { + public Pair getBoundaryOfStorage(String dataPrefix) { KeyInterval keyInterval = KeyInterval.getDefaultKeyInterval(); ColumnsInterval columnsInterval; diff --git a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/RemoteExecutor.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/RemoteExecutor.java index 410d6737f3..7e86d5c64d 100644 --- a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/RemoteExecutor.java +++ b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/RemoteExecutor.java @@ -31,10 +31,25 @@ import cn.edu.tsinghua.iginx.engine.shared.data.write.DataView; import cn.edu.tsinghua.iginx.engine.shared.data.write.RawDataType; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Filter; -import cn.edu.tsinghua.iginx.engine.shared.operator.tag.*; +import cn.edu.tsinghua.iginx.engine.shared.operator.tag.AndTagFilter; +import cn.edu.tsinghua.iginx.engine.shared.operator.tag.BasePreciseTagFilter; +import cn.edu.tsinghua.iginx.engine.shared.operator.tag.BaseTagFilter; +import cn.edu.tsinghua.iginx.engine.shared.operator.tag.OrTagFilter; +import cn.edu.tsinghua.iginx.engine.shared.operator.tag.PreciseTagFilter; +import cn.edu.tsinghua.iginx.engine.shared.operator.tag.TagFilter; import cn.edu.tsinghua.iginx.filesystem.exception.FilesystemException; -import cn.edu.tsinghua.iginx.filesystem.thrift.*; +import cn.edu.tsinghua.iginx.filesystem.thrift.DeleteReq; +import cn.edu.tsinghua.iginx.filesystem.thrift.FSHeader; +import cn.edu.tsinghua.iginx.filesystem.thrift.FSKeyRange; +import cn.edu.tsinghua.iginx.filesystem.thrift.FSRawData; import cn.edu.tsinghua.iginx.filesystem.thrift.FileSystemService.Client; +import cn.edu.tsinghua.iginx.filesystem.thrift.GetBoundaryOfStorageResp; +import cn.edu.tsinghua.iginx.filesystem.thrift.GetColumnsOfStorageUnitResp; +import cn.edu.tsinghua.iginx.filesystem.thrift.InsertReq; +import cn.edu.tsinghua.iginx.filesystem.thrift.ProjectReq; +import cn.edu.tsinghua.iginx.filesystem.thrift.ProjectResp; +import cn.edu.tsinghua.iginx.filesystem.thrift.RawTagFilter; +import cn.edu.tsinghua.iginx.filesystem.thrift.Status; import cn.edu.tsinghua.iginx.filesystem.thrift.TagFilterType; import cn.edu.tsinghua.iginx.filesystem.tools.FilterTransformer; import cn.edu.tsinghua.iginx.metadata.entity.ColumnsInterval; @@ -46,7 +61,11 @@ import cn.edu.tsinghua.iginx.utils.Pair; import cn.edu.tsinghua.iginx.utils.ThriftConnPool; import java.nio.ByteBuffer; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; import org.apache.thrift.TException; import org.apache.thrift.protocol.TBinaryProtocol; diff --git a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/server/FileSystemWorker.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/server/FileSystemWorker.java index f062a9cbca..d7a11de5d4 100644 --- a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/server/FileSystemWorker.java +++ b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/server/FileSystemWorker.java @@ -37,9 +37,13 @@ import cn.edu.tsinghua.iginx.utils.DataTypeUtils; import cn.edu.tsinghua.iginx.utils.Pair; import java.nio.ByteBuffer; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; -import org.apache.thrift.TException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -66,7 +70,7 @@ public FileSystemWorker(Executor executor) { } @Override - public ProjectResp executeProject(ProjectReq req) throws TException { + public ProjectResp executeProject(ProjectReq req) { TagFilter tagFilter = resolveRawTagFilter(req.getTagFilter()); TaskExecuteResult result = executor.executeProjectTask( @@ -139,7 +143,7 @@ public ProjectResp executeProject(ProjectReq req) throws TException { } @Override - public Status executeInsert(InsertReq req) throws TException { + public Status executeInsert(InsertReq req) { FSRawData fsRawData = req.getRawData(); RawDataType rawDataType = strToRawDataType(fsRawData.getRawDataType()); if (rawDataType == null) { @@ -194,7 +198,7 @@ public Status executeInsert(InsertReq req) throws TException { } @Override - public Status executeDelete(DeleteReq req) throws TException { + public Status executeDelete(DeleteReq req) { TagFilter tagFilter = resolveRawTagFilter(req.getTagFilter()); // null keyRanges means delete key @@ -217,7 +221,7 @@ public Status executeDelete(DeleteReq req) throws TException { @Override public GetColumnsOfStorageUnitResp getColumnsOfStorageUnit( - String storageUnit, Set pattern, RawTagFilter tagFilter) throws TException { + String storageUnit, Set pattern, RawTagFilter tagFilter) { List ret = new ArrayList<>(); try { List columns = @@ -241,7 +245,7 @@ public GetColumnsOfStorageUnitResp getColumnsOfStorageUnit( } @Override - public GetBoundaryOfStorageResp getBoundaryOfStorage(String prefix) throws TException { + public GetBoundaryOfStorageResp getBoundaryOfStorage(String prefix) { try { Pair pair = executor.getBoundaryOfStorage(prefix); GetBoundaryOfStorageResp resp = new GetBoundaryOfStorageResp(SUCCESS); diff --git a/dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java b/dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java index b46f585f10..5d2a6f4d06 100644 --- a/dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java +++ b/dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java @@ -37,7 +37,15 @@ import cn.edu.tsinghua.iginx.engine.shared.operator.Insert; import cn.edu.tsinghua.iginx.engine.shared.operator.Project; import cn.edu.tsinghua.iginx.engine.shared.operator.Select; -import cn.edu.tsinghua.iginx.engine.shared.operator.filter.*; +import cn.edu.tsinghua.iginx.engine.shared.operator.filter.AndFilter; +import cn.edu.tsinghua.iginx.engine.shared.operator.filter.BoolFilter; +import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Filter; +import cn.edu.tsinghua.iginx.engine.shared.operator.filter.FilterType; +import cn.edu.tsinghua.iginx.engine.shared.operator.filter.NotFilter; +import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Op; +import cn.edu.tsinghua.iginx.engine.shared.operator.filter.OrFilter; +import cn.edu.tsinghua.iginx.engine.shared.operator.filter.PathFilter; +import cn.edu.tsinghua.iginx.engine.shared.operator.filter.ValueFilter; import cn.edu.tsinghua.iginx.engine.shared.operator.tag.TagFilter; import cn.edu.tsinghua.iginx.engine.shared.operator.tag.TagFilterType; import cn.edu.tsinghua.iginx.influxdb.exception.InfluxDBException; @@ -48,7 +56,9 @@ import cn.edu.tsinghua.iginx.influxdb.tools.FilterTransformer; import cn.edu.tsinghua.iginx.influxdb.tools.SchemaTransformer; import cn.edu.tsinghua.iginx.influxdb.tools.TagFilterUtils; -import cn.edu.tsinghua.iginx.metadata.entity.*; +import cn.edu.tsinghua.iginx.metadata.entity.ColumnsInterval; +import cn.edu.tsinghua.iginx.metadata.entity.KeyInterval; +import cn.edu.tsinghua.iginx.metadata.entity.StorageEngineMeta; import cn.edu.tsinghua.iginx.thrift.DataType; import cn.edu.tsinghua.iginx.thrift.StorageEngineType; import cn.edu.tsinghua.iginx.utils.Pair; @@ -66,7 +76,12 @@ import java.time.Instant; import java.time.OffsetDateTime; import java.time.ZoneId; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -116,7 +131,7 @@ public InfluxDBStorage(StorageEngineMeta meta) throws StorageInitializationExcep throw new StorageInitializationException("unexpected database: " + meta.getStorageEngine()); } if (!testConnection()) { - throw new StorageInitializationException("cannot connect to " + meta.toString()); + throw new StorageInitializationException("cannot connect to " + meta); } Map extraParams = meta.getExtraParams(); String url = extraParams.getOrDefault("url", "http://localhost:8086/"); @@ -380,7 +395,7 @@ public List getColumns(Set patterns, TagFilter tagFilter) { } @Override - public void release() throws PhysicalException { + public void release() { client.close(); } diff --git a/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java b/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java index 464c263d7a..0215cb19b5 100644 --- a/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java +++ b/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java @@ -38,7 +38,13 @@ import cn.edu.tsinghua.iginx.engine.shared.operator.Insert; import cn.edu.tsinghua.iginx.engine.shared.operator.Project; import cn.edu.tsinghua.iginx.engine.shared.operator.Select; -import cn.edu.tsinghua.iginx.engine.shared.operator.filter.*; +import cn.edu.tsinghua.iginx.engine.shared.operator.filter.AndFilter; +import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Filter; +import cn.edu.tsinghua.iginx.engine.shared.operator.filter.KeyFilter; +import cn.edu.tsinghua.iginx.engine.shared.operator.filter.NotFilter; +import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Op; +import cn.edu.tsinghua.iginx.engine.shared.operator.filter.OrFilter; +import cn.edu.tsinghua.iginx.engine.shared.operator.filter.ValueFilter; import cn.edu.tsinghua.iginx.engine.shared.operator.tag.TagFilter; import cn.edu.tsinghua.iginx.iotdb.exception.IoTDBException; import cn.edu.tsinghua.iginx.iotdb.exception.IoTDBTaskExecuteFailureException; @@ -46,12 +52,22 @@ import cn.edu.tsinghua.iginx.iotdb.tools.DataViewWrapper; import cn.edu.tsinghua.iginx.iotdb.tools.FilterTransformer; import cn.edu.tsinghua.iginx.iotdb.tools.TagKVUtils; -import cn.edu.tsinghua.iginx.metadata.entity.*; +import cn.edu.tsinghua.iginx.metadata.entity.ColumnsInterval; +import cn.edu.tsinghua.iginx.metadata.entity.KeyInterval; +import cn.edu.tsinghua.iginx.metadata.entity.StorageEngineMeta; import cn.edu.tsinghua.iginx.thrift.DataType; import cn.edu.tsinghua.iginx.thrift.StorageEngineType; import cn.edu.tsinghua.iginx.utils.Pair; import cn.edu.tsinghua.iginx.utils.StringUtils; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -117,7 +133,7 @@ public IoTDBStorage(StorageEngineMeta meta) throws StorageInitializationExceptio throw new StorageInitializationException("unexpected database: " + meta.getStorageEngine()); } if (!testConnection()) { - throw new StorageInitializationException("cannot connect to " + meta.toString()); + throw new StorageInitializationException("cannot connect to " + meta); } sessionPool = createSessionPool(); } @@ -345,8 +361,7 @@ private TaskExecuteResult executeProjectWithFilter( builder.append(','); } String statement = - String.format( - QUERY_DATA, builder.deleteCharAt(builder.length() - 1).toString(), storageUnit); + String.format(QUERY_DATA, builder.deleteCharAt(builder.length() - 1), storageUnit); String filterStr = getFilterString(filter, storageUnit); if (!filterStr.isEmpty()) { @@ -402,7 +417,7 @@ private TaskExecuteResult executeProjectDummyWithFilter(Project project, Filter builder.append(','); } String statement = - String.format(QUERY_HISTORY_DATA, builder.deleteCharAt(builder.length() - 1).toString()); + String.format(QUERY_HISTORY_DATA, builder.deleteCharAt(builder.length() - 1)); String filterStr = getFilterString(filter, ""); if (!filterStr.isEmpty()) { diff --git a/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java b/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java index ae52354a4f..0726e15e6d 100644 --- a/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java +++ b/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java @@ -62,9 +62,20 @@ import com.mongodb.client.MongoClients; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; -import com.mongodb.client.model.*; +import com.mongodb.client.model.BulkWriteOptions; +import com.mongodb.client.model.Filters; +import com.mongodb.client.model.InsertManyOptions; +import com.mongodb.client.model.ReplaceOneModel; +import com.mongodb.client.model.ReplaceOptions; +import com.mongodb.client.model.WriteModel; import java.text.ParseException; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import org.bson.BsonDocument; diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/ParquetStorage.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/ParquetStorage.java index b552761597..6379069ba8 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/ParquetStorage.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/ParquetStorage.java @@ -30,7 +30,11 @@ import cn.edu.tsinghua.iginx.engine.shared.function.FunctionCall; import cn.edu.tsinghua.iginx.engine.shared.function.FunctionParams; import cn.edu.tsinghua.iginx.engine.shared.function.FunctionType; -import cn.edu.tsinghua.iginx.engine.shared.operator.*; +import cn.edu.tsinghua.iginx.engine.shared.operator.Delete; +import cn.edu.tsinghua.iginx.engine.shared.operator.Insert; +import cn.edu.tsinghua.iginx.engine.shared.operator.Project; +import cn.edu.tsinghua.iginx.engine.shared.operator.Select; +import cn.edu.tsinghua.iginx.engine.shared.operator.SetTransform; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.AndFilter; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Filter; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.KeyFilter; diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java index c8ad6276bc..056816bba0 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java @@ -49,7 +49,11 @@ import java.nio.channels.FileChannel; import java.nio.channels.FileLock; import java.nio.channels.OverlappingFileLockException; -import java.nio.file.*; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -328,7 +332,8 @@ public List getColumnsOfStorageUnit( } if (storageUnit.equals("*")) { List columns = new ArrayList<>(); - for (Manager manager : Iterables.concat(managers.values(), Collections.singleton(dummyManager))) { + for (Manager manager : + Iterables.concat(managers.values(), Collections.singleton(dummyManager))) { columns.addAll(manager.getColumns(patternList, tagFilter)); } return columns; @@ -341,7 +346,9 @@ public List getColumnsOfStorageUnit( public Pair getBoundaryOfStorage(String dataPrefix) throws PhysicalException { List paths = - dummyManager.getColumns().stream().map(Column::getPath).collect(Collectors.toList()); + dummyManager.getColumns(Collections.singletonList("*"), null).stream() + .map(Column::getPath) + .collect(Collectors.toList()); if (dataPrefix != null) { paths = paths.stream().filter(path -> path.startsWith(dataPrefix)).collect(Collectors.toList()); diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java index 5c4d8ba533..33c7cdf917 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java @@ -35,15 +35,37 @@ import cn.edu.tsinghua.iginx.engine.shared.function.FunctionParams; import cn.edu.tsinghua.iginx.engine.shared.function.system.Count; import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Filter; -import cn.edu.tsinghua.iginx.engine.shared.operator.tag.*; +import cn.edu.tsinghua.iginx.engine.shared.operator.tag.AndTagFilter; +import cn.edu.tsinghua.iginx.engine.shared.operator.tag.BasePreciseTagFilter; +import cn.edu.tsinghua.iginx.engine.shared.operator.tag.BaseTagFilter; +import cn.edu.tsinghua.iginx.engine.shared.operator.tag.OrTagFilter; +import cn.edu.tsinghua.iginx.engine.shared.operator.tag.PreciseTagFilter; +import cn.edu.tsinghua.iginx.engine.shared.operator.tag.TagFilter; import cn.edu.tsinghua.iginx.metadata.entity.ColumnsInterval; import cn.edu.tsinghua.iginx.metadata.entity.KeyInterval; import cn.edu.tsinghua.iginx.parquet.server.FilterTransformer; -import cn.edu.tsinghua.iginx.parquet.thrift.*; +import cn.edu.tsinghua.iginx.parquet.thrift.DeleteReq; +import cn.edu.tsinghua.iginx.parquet.thrift.GetColumnsOfStorageUnitResp; +import cn.edu.tsinghua.iginx.parquet.thrift.GetStorageBoundaryResp; +import cn.edu.tsinghua.iginx.parquet.thrift.InsertReq; +import cn.edu.tsinghua.iginx.parquet.thrift.ParquetHeader; +import cn.edu.tsinghua.iginx.parquet.thrift.ParquetKeyRange; +import cn.edu.tsinghua.iginx.parquet.thrift.ParquetRawData; import cn.edu.tsinghua.iginx.parquet.thrift.ParquetService.Client; +import cn.edu.tsinghua.iginx.parquet.thrift.ProjectReq; +import cn.edu.tsinghua.iginx.parquet.thrift.ProjectResp; +import cn.edu.tsinghua.iginx.parquet.thrift.RawFunction; +import cn.edu.tsinghua.iginx.parquet.thrift.RawFunctionCall; +import cn.edu.tsinghua.iginx.parquet.thrift.RawFunctionParams; +import cn.edu.tsinghua.iginx.parquet.thrift.RawTagFilter; +import cn.edu.tsinghua.iginx.parquet.thrift.Status; import cn.edu.tsinghua.iginx.parquet.thrift.TagFilterType; import cn.edu.tsinghua.iginx.thrift.DataType; -import cn.edu.tsinghua.iginx.utils.*; +import cn.edu.tsinghua.iginx.utils.Bitmap; +import cn.edu.tsinghua.iginx.utils.ByteUtils; +import cn.edu.tsinghua.iginx.utils.DataTypeUtils; +import cn.edu.tsinghua.iginx.utils.Pair; +import cn.edu.tsinghua.iginx.utils.ThriftConnPool; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.HashMap; diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/Manager.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/Manager.java index 17a87a640d..db8bd04ce8 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/Manager.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/Manager.java @@ -38,5 +38,4 @@ void delete(List paths, List keyRanges, TagFilter tagFilter) throws PhysicalException; List getColumns(List paths, TagFilter tagFilter) throws PhysicalException; - } diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/DataManager.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/DataManager.java index 4ddedbf41e..c72093a5ea 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/DataManager.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/data/DataManager.java @@ -42,7 +42,11 @@ import com.google.common.collect.RangeSet; import java.io.IOException; import java.nio.file.Path; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; import org.apache.arrow.vector.types.pojo.Field; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/DummyManager.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/DummyManager.java index a19124979f..00157eba1d 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/DummyManager.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/DummyManager.java @@ -34,7 +34,11 @@ import java.nio.file.Files; import java.nio.file.NoSuchFileException; import java.nio.file.Path; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; import javax.validation.constraints.NotNull; diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/EmptyManager.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/EmptyManager.java index 19e403af27..a8f9bf9af8 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/EmptyManager.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/manager/dummy/EmptyManager.java @@ -72,7 +72,7 @@ public void delete(List paths, List keyRanges, TagFilter tagFi } @Override - public List getColumns(List paths, TagFilter tagFilter) throws PhysicalException { + public List getColumns(List paths, TagFilter tagFilter) { return Collections.emptyList(); } diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetWorker.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetWorker.java index 6dc18981e4..3e793ad469 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetWorker.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetWorker.java @@ -24,25 +24,55 @@ import cn.edu.tsinghua.iginx.engine.shared.KeyRange; import cn.edu.tsinghua.iginx.engine.shared.data.read.Row; import cn.edu.tsinghua.iginx.engine.shared.data.read.RowStream; -import cn.edu.tsinghua.iginx.engine.shared.data.write.*; +import cn.edu.tsinghua.iginx.engine.shared.data.write.ColumnDataView; +import cn.edu.tsinghua.iginx.engine.shared.data.write.DataView; +import cn.edu.tsinghua.iginx.engine.shared.data.write.RawData; +import cn.edu.tsinghua.iginx.engine.shared.data.write.RawDataType; +import cn.edu.tsinghua.iginx.engine.shared.data.write.RowDataView; import cn.edu.tsinghua.iginx.engine.shared.function.Function; import cn.edu.tsinghua.iginx.engine.shared.function.FunctionCall; import cn.edu.tsinghua.iginx.engine.shared.function.FunctionParams; import cn.edu.tsinghua.iginx.engine.shared.function.system.Count; -import cn.edu.tsinghua.iginx.engine.shared.operator.tag.*; +import cn.edu.tsinghua.iginx.engine.shared.operator.tag.AndTagFilter; +import cn.edu.tsinghua.iginx.engine.shared.operator.tag.BasePreciseTagFilter; +import cn.edu.tsinghua.iginx.engine.shared.operator.tag.BaseTagFilter; +import cn.edu.tsinghua.iginx.engine.shared.operator.tag.OrTagFilter; +import cn.edu.tsinghua.iginx.engine.shared.operator.tag.PreciseTagFilter; +import cn.edu.tsinghua.iginx.engine.shared.operator.tag.TagFilter; +import cn.edu.tsinghua.iginx.engine.shared.operator.tag.WithoutTagFilter; import cn.edu.tsinghua.iginx.metadata.entity.ColumnsInterval; import cn.edu.tsinghua.iginx.metadata.entity.KeyInterval; import cn.edu.tsinghua.iginx.parquet.exec.Executor; -import cn.edu.tsinghua.iginx.parquet.thrift.*; +import cn.edu.tsinghua.iginx.parquet.thrift.DeleteReq; +import cn.edu.tsinghua.iginx.parquet.thrift.GetColumnsOfStorageUnitResp; +import cn.edu.tsinghua.iginx.parquet.thrift.GetStorageBoundaryResp; +import cn.edu.tsinghua.iginx.parquet.thrift.InsertReq; +import cn.edu.tsinghua.iginx.parquet.thrift.ParquetHeader; +import cn.edu.tsinghua.iginx.parquet.thrift.ParquetKeyRange; +import cn.edu.tsinghua.iginx.parquet.thrift.ParquetRawData; +import cn.edu.tsinghua.iginx.parquet.thrift.ParquetRow; +import cn.edu.tsinghua.iginx.parquet.thrift.ParquetService; +import cn.edu.tsinghua.iginx.parquet.thrift.ProjectReq; +import cn.edu.tsinghua.iginx.parquet.thrift.ProjectResp; +import cn.edu.tsinghua.iginx.parquet.thrift.RawFunction; +import cn.edu.tsinghua.iginx.parquet.thrift.RawFunctionCall; +import cn.edu.tsinghua.iginx.parquet.thrift.RawFunctionParams; +import cn.edu.tsinghua.iginx.parquet.thrift.RawTagFilter; +import cn.edu.tsinghua.iginx.parquet.thrift.Status; +import cn.edu.tsinghua.iginx.parquet.thrift.TS; import cn.edu.tsinghua.iginx.thrift.DataType; import cn.edu.tsinghua.iginx.utils.Bitmap; import cn.edu.tsinghua.iginx.utils.ByteUtils; import cn.edu.tsinghua.iginx.utils.DataTypeUtils; import cn.edu.tsinghua.iginx.utils.Pair; import java.nio.ByteBuffer; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; -import org.apache.thrift.TException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -69,7 +99,7 @@ public ParquetWorker(Executor executor) { } @Override - public ProjectResp executeProject(ProjectReq req) throws TException { + public ProjectResp executeProject(ProjectReq req) { TagFilter tagFilter = resolveRawTagFilter(req.getTagFilter()); List calls = null; @@ -152,7 +182,7 @@ public ProjectResp executeProject(ProjectReq req) throws TException { } @Override - public Status executeInsert(InsertReq req) throws TException { + public Status executeInsert(InsertReq req) { ParquetRawData parquetRawData = req.getRawData(); RawDataType rawDataType = strToRawDataType(parquetRawData.getRawDataType()); if (rawDataType == null) { @@ -223,7 +253,7 @@ private RawDataType strToRawDataType(String type) { } @Override - public Status executeDelete(DeleteReq req) throws TException { + public Status executeDelete(DeleteReq req) { TagFilter tagFilter = resolveRawTagFilter(req.getTagFilter()); // null timeRanges means delete columns @@ -302,7 +332,7 @@ private FunctionParams resolveRawFunctionParams(RawFunctionParams rawFunctionPar @Override public GetColumnsOfStorageUnitResp getColumnsOfStorageUnit( - String storageUnit, Set pattern, RawTagFilter tagFilter) throws TException { + String storageUnit, Set pattern, RawTagFilter tagFilter) { List ret = new ArrayList<>(); try { List tsList = @@ -325,7 +355,7 @@ public GetColumnsOfStorageUnitResp getColumnsOfStorageUnit( } @Override - public GetStorageBoundaryResp getBoundaryOfStorage(String dataPrefix) throws TException { + public GetStorageBoundaryResp getBoundaryOfStorage(String dataPrefix) { try { Pair pair = executor.getBoundaryOfStorage(dataPrefix); GetStorageBoundaryResp resp = new GetStorageBoundaryResp(SUCCESS); diff --git a/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java b/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java index 1a59d6d2c5..c38769d735 100644 --- a/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java +++ b/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java @@ -36,12 +36,23 @@ import cn.edu.tsinghua.iginx.metadata.entity.KeyInterval; import cn.edu.tsinghua.iginx.metadata.entity.StorageEngineMeta; import cn.edu.tsinghua.iginx.redis.entity.RedisQueryRowStream; -import cn.edu.tsinghua.iginx.redis.tools.*; +import cn.edu.tsinghua.iginx.redis.tools.DataCoder; +import cn.edu.tsinghua.iginx.redis.tools.DataTransformer; +import cn.edu.tsinghua.iginx.redis.tools.DataViewWrapper; +import cn.edu.tsinghua.iginx.redis.tools.FilterUtils; +import cn.edu.tsinghua.iginx.redis.tools.TagKVUtils; import cn.edu.tsinghua.iginx.thrift.DataType; import cn.edu.tsinghua.iginx.thrift.StorageEngineType; import cn.edu.tsinghua.iginx.utils.Pair; import cn.edu.tsinghua.iginx.utils.StringUtils; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.Set; import java.util.function.Consumer; import java.util.stream.Collectors; import org.slf4j.Logger; @@ -560,7 +571,7 @@ private static byte[] concat(byte prefix, byte[] arr) { } @Override - public void release() throws PhysicalException { + public void release() { jedisPool.close(); } } diff --git a/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java index cfdda6ad50..3e2e6eb452 100644 --- a/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java +++ b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java @@ -18,7 +18,17 @@ package cn.edu.tsinghua.iginx.relational; import static cn.edu.tsinghua.iginx.constant.GlobalConstant.SEPARATOR; -import static cn.edu.tsinghua.iginx.relational.tools.Constants.*; +import static cn.edu.tsinghua.iginx.relational.tools.Constants.ADD_COLUMN_STATEMENT; +import static cn.edu.tsinghua.iginx.relational.tools.Constants.BATCH_SIZE; +import static cn.edu.tsinghua.iginx.relational.tools.Constants.CREATE_DATABASE_STATEMENT; +import static cn.edu.tsinghua.iginx.relational.tools.Constants.DATABASE_PREFIX; +import static cn.edu.tsinghua.iginx.relational.tools.Constants.DROP_COLUMN_STATEMENT; +import static cn.edu.tsinghua.iginx.relational.tools.Constants.KEY_NAME; +import static cn.edu.tsinghua.iginx.relational.tools.Constants.PASSWORD; +import static cn.edu.tsinghua.iginx.relational.tools.Constants.QUERY_STATEMENT_WITHOUT_KEYNAME; +import static cn.edu.tsinghua.iginx.relational.tools.Constants.TAGKV_SEPARATOR; +import static cn.edu.tsinghua.iginx.relational.tools.Constants.USERNAME; +import static cn.edu.tsinghua.iginx.relational.tools.Constants.classMap; import static cn.edu.tsinghua.iginx.relational.tools.TagKVUtils.splitFullName; import static cn.edu.tsinghua.iginx.relational.tools.TagKVUtils.toFullName; @@ -41,7 +51,16 @@ import cn.edu.tsinghua.iginx.engine.shared.operator.Insert; import cn.edu.tsinghua.iginx.engine.shared.operator.Project; import cn.edu.tsinghua.iginx.engine.shared.operator.Select; -import cn.edu.tsinghua.iginx.engine.shared.operator.filter.*; +import cn.edu.tsinghua.iginx.engine.shared.operator.filter.AndFilter; +import cn.edu.tsinghua.iginx.engine.shared.operator.filter.BoolFilter; +import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Filter; +import cn.edu.tsinghua.iginx.engine.shared.operator.filter.FilterType; +import cn.edu.tsinghua.iginx.engine.shared.operator.filter.KeyFilter; +import cn.edu.tsinghua.iginx.engine.shared.operator.filter.NotFilter; +import cn.edu.tsinghua.iginx.engine.shared.operator.filter.Op; +import cn.edu.tsinghua.iginx.engine.shared.operator.filter.OrFilter; +import cn.edu.tsinghua.iginx.engine.shared.operator.filter.PathFilter; +import cn.edu.tsinghua.iginx.engine.shared.operator.filter.ValueFilter; import cn.edu.tsinghua.iginx.engine.shared.operator.tag.TagFilter; import cn.edu.tsinghua.iginx.metadata.entity.ColumnsInterval; import cn.edu.tsinghua.iginx.metadata.entity.KeyInterval; @@ -61,8 +80,19 @@ import com.zaxxer.hikari.HikariDataSource; import java.io.IOException; import java.nio.charset.StandardCharsets; -import java.sql.*; -import java.util.*; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -1588,8 +1618,7 @@ private Map> splitAndMergeHistoryQueryPatterns(List< for (Map.Entry entry : tableNameToColumnNames.entrySet()) { String oldColumnNames = oldTableNameToColumnNames.get(entry.getKey()); if (oldColumnNames != null) { - List oldColumnNameList = - Arrays.asList((oldColumnNames + ", " + entry.getValue()).split(", ")); + String[] oldColumnNameList = (oldColumnNames + ", " + entry.getValue()).split(", "); // 对list去重 List newColumnNameList = new ArrayList<>(); for (String columnName : oldColumnNameList) { diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java index 0ea4b992a8..13d2f96e87 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java @@ -21,7 +21,9 @@ import static cn.edu.tsinghua.iginx.integration.controller.Controller.SUPPORT_KEY; import static cn.edu.tsinghua.iginx.integration.expansion.constant.Constant.*; import static cn.edu.tsinghua.iginx.integration.expansion.utils.SQLTestTools.executeShellScript; -import static org.junit.Assert.*; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; import cn.edu.tsinghua.iginx.exception.SessionException; import cn.edu.tsinghua.iginx.integration.controller.Controller; @@ -111,7 +113,7 @@ protected String addStorageEngine( statement.append( String.format(", dir:%s/" + IGINX_DATA_PATH_PREFIX_NAME, DBCE_PARQUET_FS_TEST_DIR)); statement.append(PORT_TO_ROOT.get(port)); - statement.append(", iginx_port:" + oriPortIginx); + statement.append(", iginx_port:").append(oriPortIginx); } if (extraParams != null) { statement.append(", "); @@ -170,8 +172,7 @@ public void clearData() { } private void addStorageEngineInProgress( - int port, boolean hasData, boolean isReadOnly, String dataPrefix, String schemaPrefix) - throws InterruptedException { + int port, boolean hasData, boolean isReadOnly, String dataPrefix, String schemaPrefix) { if (IS_PARQUET_OR_FILE_SYSTEM) { startStorageEngineWithIginx(port, hasData, isReadOnly); } else { @@ -181,7 +182,7 @@ private void addStorageEngineInProgress( } @Test - public void oriHasDataExpHasData() throws InterruptedException, SessionException { + public void oriHasDataExpHasData() throws InterruptedException { // 查询原始节点的历史数据,结果不为空 testQueryHistoryDataOriHasData(); // 写入并查询新数据 @@ -773,8 +774,7 @@ private void testSameKeyWarning() { } } - protected void startStorageEngineWithIginx(int port, boolean hasData, boolean isReadOnly) - throws InterruptedException { + protected void startStorageEngineWithIginx(int port, boolean hasData, boolean isReadOnly) { String scriptPath, iginxPath = ".github/scripts/iginx/iginx.sh"; String os = System.getProperty("os.name").toLowerCase(); boolean isOnMac = false; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/datasource/DataSourceIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/datasource/DataSourceIT.java index 3f7ca0c2dc..b5378f9eb8 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/datasource/DataSourceIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/datasource/DataSourceIT.java @@ -16,7 +16,6 @@ * along with this program. If not, see . */ - package cn.edu.tsinghua.iginx.integration.expansion.filesystem.datasource; import static org.junit.Assert.assertNull; From b4bb47a1528c93b26dd4125acaed89414da2f96e Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Mon, 15 Jul 2024 00:22:21 +0800 Subject: [PATCH 071/138] optimize import --- .../parquet/ParquetHistoryDataGenerator.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetHistoryDataGenerator.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetHistoryDataGenerator.java index 517bcea988..0601f77886 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetHistoryDataGenerator.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetHistoryDataGenerator.java @@ -19,7 +19,8 @@ package cn.edu.tsinghua.iginx.integration.expansion.parquet; import static cn.edu.tsinghua.iginx.integration.expansion.BaseCapacityExpansionIT.DBCE_PARQUET_FS_TEST_DIR; -import static cn.edu.tsinghua.iginx.integration.expansion.constant.Constant.*; +import static cn.edu.tsinghua.iginx.integration.expansion.constant.Constant.IGINX_DATA_PATH_PREFIX_NAME; +import static cn.edu.tsinghua.iginx.integration.expansion.constant.Constant.PARQUET_PARAMS; import cn.edu.tsinghua.iginx.engine.physical.storage.domain.ColumnKey; import cn.edu.tsinghua.iginx.format.parquet.ParquetWriter; @@ -28,9 +29,18 @@ import cn.edu.tsinghua.iginx.thrift.DataType; import java.io.File; import java.io.IOException; -import java.nio.file.*; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.SortedMap; +import java.util.TreeMap; import java.util.stream.Collectors; import java.util.stream.Stream; import javax.annotation.Nonnull; From 46f56257ab008b4f3f2bc36dcffaefc9b29256aa Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Mon, 15 Jul 2024 09:44:55 +0800 Subject: [PATCH 072/138] feat(test): tpc-h test suppport new branch comp to main (#394) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 作为TPC-H的伴随PR,先合并,有问题再说 --- .github/actions/dbConfWriter/action.yml | 158 ++++++++++++++++++ .github/actions/iginxRunner/action.yml | 33 ++-- .../tpch.sh => tpch/download_tpch_data.sh} | 0 .github/workflows/assembly-test.yml | 2 +- .github/workflows/tpc-h.yml | 51 ++++-- session_py/example.py | 4 +- session_py/file_example.py | 4 +- 7 files changed, 213 insertions(+), 39 deletions(-) create mode 100644 .github/actions/dbConfWriter/action.yml rename .github/scripts/{benchmarks/tpch.sh => tpch/download_tpch_data.sh} (100%) diff --git a/.github/actions/dbConfWriter/action.yml b/.github/actions/dbConfWriter/action.yml new file mode 100644 index 0000000000..eb73d32788 --- /dev/null +++ b/.github/actions/dbConfWriter/action.yml @@ -0,0 +1,158 @@ +name: "db-conf-writer" +description: "use db-conf-writer to rewrite conf for target db before install IGinX" +inputs: + DB-name: + description: "DB name" + required: false + default: IoTDB12 + Root-Dir-Path: + description: "the path of IGinX root directory" + required: false + default: "${GITHUB_WORKSPACE}" + +runs: + using: "composite" # Mandatory parameter + steps: + - name: Modify IGinX Config + uses: ./.github/actions/edit + with: + paths: ${{ inputs.Root-Dir-Path }}/conf/config.properties + statements: s/^storageEngineList=/#storageEngineList=/g + + - if: inputs.DB-name == 'IoTDB12' + name: Modify IGinX Config + uses: ./.github/actions/edit + with: + paths: ${{ inputs.Root-Dir-Path }}/conf/config.properties + statements: s/#storageEngineList=127.0.0.1#6667#iotdb12/storageEngineList=127.0.0.1#6667#iotdb12/g + + - if: inputs.DB-name == 'InfluxDB' + name: Modify IGinX Config + uses: ./.github/actions/edit + with: + paths: ${{ inputs.Root-Dir-Path }}/conf/config.properties + statements: s/your-token/testToken/g + + - if: inputs.DB-name == 'InfluxDB' + name: Modify IGinX Config + uses: ./.github/actions/edit + with: + paths: ${{ inputs.Root-Dir-Path }}/conf/config.properties + statements: s/your-organization/testOrg/g + + - if: inputs.DB-name == 'InfluxDB' + name: Modify IGinX Config + uses: ./.github/actions/edit + with: + paths: ${{ inputs.Root-Dir-Path }}/conf/config.properties + statements: s/#storageEngineList=127.0.0.1#8086/storageEngineList=127.0.0.1#8086/g + + - if: inputs.DB-name == 'Parquet' + name: Modify IGinX Config + uses: ./.github/actions/edit + with: + paths: ${{ inputs.Root-Dir-Path }}/conf/config.properties + statements: s/^#storageEngineList=127.0.0.1#6667#parquet/storageEngineList=127.0.0.1#6667#parquet/g + + - if: inputs.DB-name == 'Parquet' + name: Modify IGinX Config + uses: ./.github/actions/edit + with: + paths: ${{ inputs.Root-Dir-Path }}/conf/config.properties + statements: s#dir=/path/to/your/parquet#dir=test/iginx_mn#g + + - if: inputs.DB-name == 'Parquet' + name: Modify IGinX Config + uses: ./.github/actions/edit + with: + paths: ${{ inputs.Root-Dir-Path }}/conf/config.properties + statements: s/#thrift_timeout=30000/#thrift_timeout=50000/g + + - if: inputs.DB-name == 'Parquet' + name: Modify IGinX Config + uses: ./.github/actions/edit + with: + paths: ${{ inputs.Root-Dir-Path }}/conf/config.properties + statements: s/#thrift_pool_max_size=100/#thrift_pool_max_size=2/g + + - if: inputs.DB-name == 'Parquet' + name: Modify IGinX Config + uses: ./.github/actions/edit + with: + paths: ${{ inputs.Root-Dir-Path }}/conf/config.properties + statements: s/write.buffer.size=104857600/write.buffer.size=1048576/g + + - if: inputs.DB-name == 'MongoDB' + name: Modify IGinX Config + uses: ./.github/actions/edit + with: + paths: ${{ inputs.Root-Dir-Path }}/conf/config.properties + statements: s/^#storageEngineList=127.0.0.1#27017/storageEngineList=127.0.0.1#27017/g + + - if: inputs.DB-name == 'FileSystem' + name: Modify IGinX Config + uses: ./.github/actions/edit + with: + paths: ${{ inputs.Root-Dir-Path }}/conf/config.properties + statements: s/^#storageEngineList=127.0.0.1#6667#filesystem/storageEngineList=127.0.0.1#6667#filesystem/g + + - if: inputs.DB-name == 'FileSystem' + name: Modify IGinX Config + uses: ./.github/actions/edit + with: + paths: ${{ inputs.Root-Dir-Path }}/conf/config.properties + statements: s#dir=/path/to/your/filesystem#dir=test/iginx_mn#g + + - if: inputs.DB-name == 'FileSystem' + name: Modify IGinX Config + uses: ./.github/actions/edit + with: + paths: ${{ inputs.Root-Dir-Path }}/conf/config.properties + statements: s#chunk_size_in_bytes=1048576#chunk_size_in_bytes=8#g + + - if: inputs.DB-name == 'FileSystem' + name: Modify IGinX Config + uses: ./.github/actions/edit + with: + paths: ${{ inputs.Root-Dir-Path }}/conf/config.properties + statements: s#thrift_timeout=5000#thrift_timeout=10000#g + + - if: inputs.DB-name == 'FileSystem' + name: Modify IGinX Config + uses: ./.github/actions/edit + with: + paths: ${{ inputs.Root-Dir-Path }}/conf/config.properties + statements: s/#thrift_pool_max_size=100/#thrift_pool_max_size=2/g + + - if: inputs.DB-name == 'Redis' + name: Modify IGinX Config + uses: ./.github/actions/edit + with: + paths: ${{ inputs.Root-Dir-Path }}/conf/config.properties + statements: s/^#storageEngineList=127.0.0.1#6379/storageEngineList=127.0.0.1#6379/g + + - if: inputs.DB-name == 'PostgreSQL' + name: Modify IGinX Config + uses: ./.github/actions/edit + with: + paths: ${{ inputs.Root-Dir-Path }}/conf/config.properties + statements: s/^#storageEngineList=127.0.0.1#5432#relational#engine=postgresql/storageEngineList=127.0.0.1#5432#relational#engine=postgresql/g + + - if: inputs.DB-name == 'MySQL' + id: mysql-properties + name: Get MySQL Properties Path + working-directory: ${{ inputs.Root-Dir-Path }} + shell: bash + run: | + CONFIG_PATH="${PWD}/dataSource/relational/src/main/resources/mysql-meta-template.properties" + if [ "$RUNNER_OS" == "Windows" ]; then + CONFIG_PATH=$(cygpath -m $CONFIG_PATH) + fi + echo "path=$CONFIG_PATH" >> $GITHUB_OUTPUT + + - if: inputs.DB-name == 'MySQL' + name: Modify IGinX Config + uses: ./.github/actions/edit + with: + paths: ${{ inputs.Root-Dir-Path }}/conf/config.properties + statements: s|^#storageEngineList=127.0.0.1#3306#relational#engine=mysql#username=root#password=mysql#has_data=false#meta_properties_path=your-meta-properties-path|storageEngineList=127.0.0.1#3306#relational#engine=mysql#username=root#has_data=false#meta_properties_path=${{ steps.mysql-properties.outputs.path }}|g diff --git a/.github/actions/iginxRunner/action.yml b/.github/actions/iginxRunner/action.yml index 2edacc23cc..78604b1d45 100644 --- a/.github/actions/iginxRunner/action.yml +++ b/.github/actions/iginxRunner/action.yml @@ -9,10 +9,7 @@ inputs: description: "to test UDF path detection" required: false default: "false" - Root-Dir-Path: - description: "the path of IGinX root directory" - required: false - default: "${GITHUB_WORKSPACE}" + runs: using: "composite" # Mandatory parameter steps: @@ -21,37 +18,37 @@ runs: shell: bash run: | if [ "$RUNNER_OS" == "Linux" ]; then - sudo sed -i 's/needInitBasicUDFFunctions=false/needInitBasicUDFFunctions=true/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties + sudo sed -i 's/needInitBasicUDFFunctions=false/needInitBasicUDFFunctions=true/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties elif [ "$RUNNER_OS" == "Windows" ]; then - sed -i 's/needInitBasicUDFFunctions=false/needInitBasicUDFFunctions=true/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties - sed -i 's/pythonCMD=python3/pythonCMD=python/g' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties + sed -i 's/needInitBasicUDFFunctions=false/needInitBasicUDFFunctions=true/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties + sed -i 's/pythonCMD=python3/pythonCMD=python/g' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties elif [ "$RUNNER_OS" == "macOS" ]; then - sudo sed -i '' 's/needInitBasicUDFFunctions=false/needInitBasicUDFFunctions=true/' ${{ inputs.Root-Dir-Path }}/core/target/iginx-core-${VERSION}/conf/config.properties + sudo sed -i '' 's/needInitBasicUDFFunctions=false/needInitBasicUDFFunctions=true/' ${GITHUB_WORKSPACE}/core/target/iginx-core-${VERSION}/conf/config.properties else echo "$RUNNER_OS is not supported" exit 1 fi - chmod +x "${{ inputs.Root-Dir-Path }}/.github/scripts/iginx/iginx_udf_path.sh" - "${{ inputs.Root-Dir-Path }}/.github/scripts/iginx/iginx_udf_path.sh" ${VERSION} + chmod +x "${GITHUB_WORKSPACE}/.github/scripts/iginx/iginx_udf_path.sh" + "${GITHUB_WORKSPACE}/.github/scripts/iginx/iginx_udf_path.sh" ${VERSION} - if: inputs.if-test-udf=='false' && inputs.if-stop=='false' name: Start IGinX shell: bash run: | if [ "$RUNNER_OS" == "Linux" ]; then - chmod +x "${{ inputs.Root-Dir-Path }}/.github/scripts/iginx/iginx.sh" - "${{ inputs.Root-Dir-Path }}/.github/scripts/iginx/iginx.sh" 6888 6666 + chmod +x "${GITHUB_WORKSPACE}/.github/scripts/iginx/iginx.sh" + "${GITHUB_WORKSPACE}/.github/scripts/iginx/iginx.sh" 6888 6666 elif [ "$RUNNER_OS" == "Windows" ]; then - chmod +x "${{ inputs.Root-Dir-Path }}/.github/scripts/iginx/iginx_windows.sh" - "${{ inputs.Root-Dir-Path }}/.github/scripts/iginx/iginx_windows.sh" 6888 6666 + chmod +x "${GITHUB_WORKSPACE}/.github/scripts/iginx/iginx_windows.sh" + "${GITHUB_WORKSPACE}/.github/scripts/iginx/iginx_windows.sh" 6888 6666 elif [ "$RUNNER_OS" == "macOS" ]; then - chmod +x "${{ inputs.Root-Dir-Path }}/.github/scripts/iginx/iginx_macos.sh" - "${{ inputs.Root-Dir-Path }}/.github/scripts/iginx/iginx_macos.sh" 6888 6666 + chmod +x "${GITHUB_WORKSPACE}/.github/scripts/iginx/iginx_macos.sh" + "${GITHUB_WORKSPACE}/.github/scripts/iginx/iginx_macos.sh" 6888 6666 fi - if: inputs.if-test-udf=='false' && inputs.if-stop=='true' name: Stop IGinX shell: bash run: | - chmod +x "${{ inputs.Root-Dir-Path }}/.github/scripts/iginx/iginx_kill.sh" - "${{ inputs.Root-Dir-Path }}/.github/scripts/iginx/iginx_kill.sh" + chmod +x "${GITHUB_WORKSPACE}/.github/scripts/iginx/iginx_kill.sh" + "${GITHUB_WORKSPACE}/.github/scripts/iginx/iginx_kill.sh" diff --git a/.github/scripts/benchmarks/tpch.sh b/.github/scripts/tpch/download_tpch_data.sh similarity index 100% rename from .github/scripts/benchmarks/tpch.sh rename to .github/scripts/tpch/download_tpch_data.sh diff --git a/.github/workflows/assembly-test.yml b/.github/workflows/assembly-test.yml index 280d553dbc..ea56b6864e 100644 --- a/.github/workflows/assembly-test.yml +++ b/.github/workflows/assembly-test.yml @@ -67,7 +67,7 @@ jobs: - name: Get Cluster Info shell: bash run: | - ./client/target/iginx-client-0.7.0-SNAPSHOT/sbin/start_cli.${{ steps.platform.outputs.suffix }} -e "show cluster info;" > cluster-info.txt + ./client/target/iginx-client-${{ env.VERSION }}/sbin/start_cli.${{ steps.platform.outputs.suffix }} -e "show cluster info;" > cluster-info.txt cat cluster-info.txt LINE_COUNT=$(wc -l < cluster-info.txt) if [ $LINE_COUNT -ne 19 ]; then diff --git a/.github/workflows/tpc-h.yml b/.github/workflows/tpc-h.yml index 85ebd99fba..7e1cd95982 100644 --- a/.github/workflows/tpc-h.yml +++ b/.github/workflows/tpc-h.yml @@ -75,29 +75,39 @@ jobs: systeminfo | findstr /C:"Total Physical Memory" fi - - name: Generate TPC-H Data + - name: Download TPC-H Data shell: bash run: | - chmod +x "${GITHUB_WORKSPACE}/.github/scripts/benchmarks/tpch.sh" - "${GITHUB_WORKSPACE}/.github/scripts/benchmarks/tpch.sh" + chmod +x "${GITHUB_WORKSPACE}/.github/scripts/tpch/download_tpch_data.sh" + "${GITHUB_WORKSPACE}/.github/scripts/tpch/download_tpch_data.sh" - - name: Run Metadata - uses: ./.github/actions/metadataRunner - with: - metadata: ${{ matrix.metadata }} + - name: Run ZooKeeper + uses: ./.github/actions/zookeeperRunner - name: Run DB uses: ./.github/actions/dbRunner with: DB-name: ${{ matrix.DB-name }} - - name: Get Old Version + - name: Get Old Version IGinX and Copy TPC-H Data shell: bash run: | + git clone https://github.com/IGinX-THU/IGinX.git + mkdir IGinX/tpc + cp -r tpc/* IGinX/tpc/ + ls -a 'IGinX/tpc/TPC-H V3.0.1/data' + + - name: Rewrite DB Conf in Old IGinX + uses: ./.github/actions/dbConfWriter + with: + DB-name: ${{ matrix.DB-name }} + Root-Dir-Path: "IGinX" + + - name: Install Old IGinX with Maven + shell: bash + run: | + cd IGinX mvn clean package -DskipTests -P-format -q - # git clone https://github.com/IGinX-THU/IGinX.git - # cd IGinX - # mvn clean package -DskipTests -P-format -q - name: Change Old IGinX config uses: ./.github/actions/confWriter @@ -105,24 +115,32 @@ jobs: DB-name: ${{ matrix.DB-name }} Set-Filter-Fragment-OFF: "true" Metadata: ${{ matrix.metadata }} - # Root-Dir-Path: "${GITHUB_WORKSPACE}/IGinX" + Root-Dir-Path: "IGinX" - name: Start Old IGinX - uses: ./.github/actions/iginxRunner - # with: - # Root-Dir-Path: "${GITHUB_WORKSPACE}/IGinX" + if: always() + shell: bash + run: | + cd IGinX/core/target/iginx-core-${VERSION} + pwd + export IGINX_HOME=$PWD + echo "IGinX home path: $IGINX_HOME" + cd .. + chmod +x iginx-core-${VERSION}/sbin/start_iginx.sh + nohup iginx-core-${VERSION}/sbin/start_iginx.sh > ../../iginx-${VERSION}.log 2>&1 & - name: Run Regression Test on Old IGinX if: always() shell: bash run: | + cd IGinX mvn test -q -Dtest=TPCHRegressionIT -DfailIfNoTests=false -P-format - name: Show Old IGinX log if: always() shell: bash run: | - cat iginx-*.log + cat IGinX/iginx-*.log - name: Stop ZooKeeper uses: ./.github/actions/zookeeperRunner @@ -144,6 +162,7 @@ jobs: shell: bash run: | mvn clean package -DskipTests -P-format -q + cp IGinX/test/src/test/resources/tpch/oldTimeCosts.txt test/src/test/resources/tpch/ - name: Change New IGinX config uses: ./.github/actions/confWriter diff --git a/session_py/example.py b/session_py/example.py index 1f09b98459..01ca135ecf 100644 --- a/session_py/example.py +++ b/session_py/example.py @@ -18,8 +18,8 @@ import pandas as pd -from .session import Session -from .thrift.rpc.ttypes import DataType, AggregateType +from iginx_pyclient.session import Session +from iginx_pyclient.thrift.rpc.ttypes import DataType, AggregateType if __name__ == '__main__': diff --git a/session_py/file_example.py b/session_py/file_example.py index c6a15787fe..b7d6c9ae07 100644 --- a/session_py/file_example.py +++ b/session_py/file_example.py @@ -25,8 +25,8 @@ import cv2 import requests -from .session import Session -from .thrift.rpc.ttypes import StorageEngineType +from iginx_pyclient.session import Session +from iginx_pyclient.thrift.rpc.ttypes import StorageEngineType # 读取第一行是列名的csv文件,并将数据存入IGinX From f5fd3b5165e67839cfb8791d2d7d67cc23a45109 Mon Sep 17 00:00:00 2001 From: Yuqing Zhu Date: Mon, 15 Jul 2024 10:12:06 +0800 Subject: [PATCH 073/138] Update mvn format cmd (#395) * remove unecessary test on Parquet * unify mvn command on format --- .github/workflows/assembly-test.yml | 4 ++-- .github/workflows/release.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/assembly-test.yml b/.github/workflows/assembly-test.yml index ea56b6864e..f6b5c0f03f 100644 --- a/.github/workflows/assembly-test.yml +++ b/.github/workflows/assembly-test.yml @@ -40,7 +40,7 @@ jobs: java: ${{ matrix.java }} - name: assembly include package - run: mvn clean package -D skipTests -P !format -P release + run: mvn clean package -D skipTests -P-format -P release - name: Setup Platform Dependence id: platform @@ -77,7 +77,7 @@ jobs: - name: Run Tests shell: bash - run: mvn test -Dtest=${{ env.FUNCTEST }} -DfailIfNoTests=false -P !format + run: mvn test -Dtest=${{ env.FUNCTEST }} -DfailIfNoTests=false -P-format - name: Check Whether Logs Contains Error shell: bash diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 717e097563..11cd67df4f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -52,7 +52,7 @@ jobs: run: | mvn deploy \ --batch-mode \ - -P !format \ + -P-format \ -DskipTests=true \ -Ddeploy.repo.dir=$(pwd)/pages - name: sync README.md and docs From 0a339c25ac64775baa3e223a5dbb6867d3cb857a Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Tue, 16 Jul 2024 10:25:25 +0800 Subject: [PATCH 074/138] rename patterns --- .../java/cn/edu/tsinghua/iginx/filesystem/exec/Executor.java | 4 ++-- .../cn/edu/tsinghua/iginx/filesystem/exec/RemoteExecutor.java | 4 ++-- .../tsinghua/iginx/filesystem/server/FileSystemWorker.java | 4 ++-- .../java/cn/edu/tsinghua/iginx/parquet/exec/Executor.java | 4 ++-- .../cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java | 4 ++-- .../cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java | 4 ++-- .../cn/edu/tsinghua/iginx/parquet/server/ParquetWorker.java | 4 ++-- .../main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java | 4 ++-- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/Executor.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/Executor.java index d3a3ca0d6c..f83dc526fc 100644 --- a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/Executor.java +++ b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/Executor.java @@ -45,8 +45,8 @@ TaskExecuteResult executeProjectTask( TaskExecuteResult executeDeleteTask( List paths, List keyRanges, TagFilter tagFilter, String storageUnit); - List getColumnsOfStorageUnit(String storageUnit, Set pattern, TagFilter tagFilter) - throws PhysicalException; + List getColumnsOfStorageUnit( + String storageUnit, Set patterns, TagFilter tagFilter) throws PhysicalException; Pair getBoundaryOfStorage(String dataPrefix) throws PhysicalException; diff --git a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/RemoteExecutor.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/RemoteExecutor.java index 7e86d5c64d..e209067994 100644 --- a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/RemoteExecutor.java +++ b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/RemoteExecutor.java @@ -242,12 +242,12 @@ public TaskExecuteResult executeDeleteTask( @Override public List getColumnsOfStorageUnit( - String storageUnit, Set pattern, TagFilter tagFilter) throws PhysicalException { + String storageUnit, Set patterns, TagFilter tagFilter) throws PhysicalException { try { TTransport transport = thriftConnPool.borrowTransport(); Client client = new Client(new TBinaryProtocol(transport)); GetColumnsOfStorageUnitResp resp = - client.getColumnsOfStorageUnit(storageUnit, pattern, constructRawTagFilter(tagFilter)); + client.getColumnsOfStorageUnit(storageUnit, patterns, constructRawTagFilter(tagFilter)); thriftConnPool.returnTransport(transport); List columns = new ArrayList<>(); resp.getPathList() diff --git a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/server/FileSystemWorker.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/server/FileSystemWorker.java index d7a11de5d4..91be1d5005 100644 --- a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/server/FileSystemWorker.java +++ b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/server/FileSystemWorker.java @@ -221,11 +221,11 @@ public Status executeDelete(DeleteReq req) { @Override public GetColumnsOfStorageUnitResp getColumnsOfStorageUnit( - String storageUnit, Set pattern, RawTagFilter tagFilter) { + String storageUnit, Set patterns, RawTagFilter tagFilter) { List ret = new ArrayList<>(); try { List columns = - executor.getColumnsOfStorageUnit(storageUnit, pattern, resolveRawTagFilter(tagFilter)); + executor.getColumnsOfStorageUnit(storageUnit, patterns, resolveRawTagFilter(tagFilter)); columns.forEach( column -> { FSColumn fsColumn = diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/Executor.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/Executor.java index 24b6df4018..5b88ba3819 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/Executor.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/Executor.java @@ -48,8 +48,8 @@ TaskExecuteResult executeProjectTask( TaskExecuteResult executeDeleteTask( List paths, List keyRanges, TagFilter tagFilter, String storageUnit); - List getColumnsOfStorageUnit(String storageUnit, Set pattern, TagFilter tagFilter) - throws PhysicalException; + List getColumnsOfStorageUnit( + String storageUnit, Set patterns, TagFilter tagFilter) throws PhysicalException; Pair getBoundaryOfStorage(String dataPrefix) throws PhysicalException; diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java index 056816bba0..9eacf439eb 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java @@ -325,8 +325,8 @@ public TaskExecuteResult executeDeleteTask( @Override public List getColumnsOfStorageUnit( - String storageUnit, Set pattern, TagFilter tagFilter) throws PhysicalException { - List patternList = new ArrayList<>(pattern); + String storageUnit, Set patterns, TagFilter tagFilter) throws PhysicalException { + List patternList = new ArrayList<>(patterns); if (patternList.isEmpty()) { patternList.add("*"); } diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java index 33c7cdf917..298a3682b5 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/RemoteExecutor.java @@ -386,12 +386,12 @@ private static RawFunctionParams constructRawFunctionParam(FunctionParams params @Override public List getColumnsOfStorageUnit( - String storageUnit, Set pattern, TagFilter tagFilter) throws PhysicalException { + String storageUnit, Set patterns, TagFilter tagFilter) throws PhysicalException { try { TTransport transport = thriftConnPool.borrowTransport(); Client client = new Client(new TBinaryProtocol(transport)); GetColumnsOfStorageUnitResp resp = - client.getColumnsOfStorageUnit(storageUnit, pattern, constructRawTagFilter(tagFilter)); + client.getColumnsOfStorageUnit(storageUnit, patterns, constructRawTagFilter(tagFilter)); thriftConnPool.returnTransport(transport); List columnList = new ArrayList<>(); resp.getTsList() diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetWorker.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetWorker.java index 3e793ad469..503f774ea5 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetWorker.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/server/ParquetWorker.java @@ -332,11 +332,11 @@ private FunctionParams resolveRawFunctionParams(RawFunctionParams rawFunctionPar @Override public GetColumnsOfStorageUnitResp getColumnsOfStorageUnit( - String storageUnit, Set pattern, RawTagFilter tagFilter) { + String storageUnit, Set patterns, RawTagFilter tagFilter) { List ret = new ArrayList<>(); try { List tsList = - executor.getColumnsOfStorageUnit(storageUnit, pattern, resolveRawTagFilter(tagFilter)); + executor.getColumnsOfStorageUnit(storageUnit, patterns, resolveRawTagFilter(tagFilter)); tsList.forEach( timeseries -> { TS ts = new TS(timeseries.getPath(), timeseries.getDataType().toString()); diff --git a/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java b/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java index c38769d735..8dc566d43f 100644 --- a/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java +++ b/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java @@ -479,9 +479,9 @@ public List getColumns(Set patterns, TagFilter tagFilter) { } } - private void getIginxColumns(Consumer ret, Set pattern, TagFilter tagFilter) + private void getIginxColumns(Consumer ret, Set patterns, TagFilter tagFilter) throws PhysicalException { - List patternList = new ArrayList<>(pattern); + List patternList = new ArrayList<>(patterns); if (patternList.isEmpty()) { patternList.add("*"); } From 1f02d04dd04a81d51cc3793e2a11982f34665928 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Tue, 16 Jul 2024 10:26:08 +0800 Subject: [PATCH 075/138] add note --- .../physical/storage/execute/StoragePhysicalTaskExecutor.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java index 2fdf509c83..19a877f70a 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java @@ -374,6 +374,7 @@ public TaskExecuteResult executeShowColumns(ShowColumns showColumns) { // fix the schemaPrefix and dataPrefix String schemaPrefix = storage.getSchemaPrefix(); + // 不下推dataPrefix的原因:iotdb中,非dummy的数据库中如果有原始数据,会在show columns时被查询到并造成误解 String dataPrefixRegex = storage.getDataPrefix() == null ? null From 5bdb2440ba45faa94300860f66723831049c1e4b Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Tue, 16 Jul 2024 10:26:53 +0800 Subject: [PATCH 076/138] extract function --- .../iginx/filesystem/exec/LocalExecutor.java | 18 +++--------------- .../edu/tsinghua/iginx/utils/StringUtils.java | 13 +++++++++++++ 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java index 5929144e2b..f660c04926 100644 --- a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java +++ b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java @@ -329,21 +329,9 @@ public TaskExecuteResult executeDeleteTask( return new TaskExecuteResult(null, null); } - boolean isPathMatchPattern(String path, Set patterns) { - if (patterns.isEmpty()) { - return true; - } - for (String pattern : patterns) { - if (StringUtils.match(path, pattern)) { - return true; - } - } - return false; - } - @Override public List getColumnsOfStorageUnit( - String storageUnit, Set pattern, TagFilter tagFilter) throws PhysicalException { + String storageUnit, Set patterns, TagFilter tagFilter) throws PhysicalException { List columns = new ArrayList<>(); if (root != null) { File directory = new File(FilePathUtils.toIginxPath(root, storageUnit, null)); @@ -358,7 +346,7 @@ public List getColumnsOfStorageUnit( file.getAbsolutePath())); } // get columns by pattern - if (!isPathMatchPattern(columnPath, pattern)) { + if (!StringUtils.isPathMatchPattern(columnPath, patterns)) { continue; } // get columns by tag filter @@ -373,7 +361,7 @@ public List getColumnsOfStorageUnit( for (File file : fileSystemManager.getAllFiles(new File(realDummyRoot), true)) { String dummyPath = FilePathUtils.convertAbsolutePathToPath(dummyRoot, file.getAbsolutePath(), storageUnit); - if (!isPathMatchPattern(dummyPath, pattern)) { + if (!StringUtils.isPathMatchPattern(dummyPath, patterns)) { continue; } columns.add(new Column(dummyPath, DataType.BINARY, null, true)); diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java index da98f07251..2f175bdf89 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java @@ -24,6 +24,7 @@ import java.util.Arrays; import java.util.List; import java.util.Objects; +import java.util.Set; import java.util.function.Predicate; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -115,6 +116,18 @@ public static String reformatPath(String path) { return path; } + public static boolean isPathMatchPattern(String path, Set patterns) { + if (patterns.isEmpty()) { + return true; + } + for (String pattern : patterns) { + if (match(path, pattern)) { + return true; + } + } + return false; + } + public static boolean match(String string, String iginxPattern) { return toColumnMatcher(iginxPattern).test(string); } From 4327816c383edece853950b3a50d311b9bd120a7 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Tue, 16 Jul 2024 10:57:42 +0800 Subject: [PATCH 077/138] just for test --- .github/workflows/standard-test-suite.yml | 66 ++++++++++--------- .../expansion/BaseCapacityExpansionIT.java | 39 +++++++---- .../expansion/utils/SQLTestTools.java | 5 ++ 3 files changed, 66 insertions(+), 44 deletions(-) diff --git a/.github/workflows/standard-test-suite.yml b/.github/workflows/standard-test-suite.yml index 67e41e0f75..0f841da109 100644 --- a/.github/workflows/standard-test-suite.yml +++ b/.github/workflows/standard-test-suite.yml @@ -1,44 +1,46 @@ name: Standard Test Suite -on: - pull_request: # when a PR is opened or reopened - types: [opened, reopened] - branches: - - main +#on: +# pull_request: # when a PR is opened or reopened +# types: [opened, reopened] +# branches: +# - main + +on: [pull_request] concurrency: group: "${{ github.workflow }}-${{ github.ref }}" cancel-in-progress: true jobs: - unit-test: - uses: ./.github/workflows/unit-test.yml - unit-mds: - uses: ./.github/workflows/unit-mds.yml - case-regression: - uses: ./.github/workflows/case-regression.yml - with: - metadata-matrix: '["zookeeper"]' - standalone-test: - uses: ./.github/workflows/standalone-test.yml - with: - metadata-matrix: '["zookeeper"]' - standalone-test-pushdown: - uses: ./.github/workflows/standalone-test-pushdown.yml - with: - metadata-matrix: '["zookeeper"]' + # unit-test: + # uses: ./.github/workflows/unit-test.yml + # unit-mds: + # uses: ./.github/workflows/unit-mds.yml + # case-regression: + # uses: ./.github/workflows/case-regression.yml + # with: + # metadata-matrix: '["zookeeper"]' + # standalone-test: + # uses: ./.github/workflows/standalone-test.yml + # with: + # metadata-matrix: '["zookeeper"]' + # standalone-test-pushdown: + # uses: ./.github/workflows/standalone-test-pushdown.yml + # with: + # metadata-matrix: '["zookeeper"]' db-ce: uses: ./.github/workflows/DB-CE.yml with: metadata-matrix: '["zookeeper"]' - remote-test: - uses: ./.github/workflows/remote-test.yml - with: - metadata-matrix: '["zookeeper"]' - assemebly-test: - uses: ./.github/workflows/assembly-test.yml - tpc-h-regression-test: - uses: ./.github/workflows/tpc-h.yml - with: - os-matrix: '["ubuntu-latest"]' - metadata-matrix: '["zookeeper"]' +# remote-test: +# uses: ./.github/workflows/remote-test.yml +# with: +# metadata-matrix: '["zookeeper"]' +# assemebly-test: +# uses: ./.github/workflows/assembly-test.yml +# tpc-h-regression-test: +# uses: ./.github/workflows/tpc-h.yml +# with: +# os-matrix: '["ubuntu-latest"]' +# metadata-matrix: '["zookeeper"]' diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java index 13d2f96e87..af0cd297e5 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java @@ -43,7 +43,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.stream.Collectors; import org.junit.After; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -511,21 +510,17 @@ protected void testShowColumns(List expectColumns) { try { List columns = session.showColumns(); LOGGER.info("show columns: {}", columns); - - // 对期望列表和实际列表中的Column对象按路径排序 - List sortedExpectPaths = - expectColumns.stream().map(Column::getPath).sorted().collect(Collectors.toList()); - - List sortedActualPaths = - columns.stream().map(Column::getPath).sorted().collect(Collectors.toList()); - // 检查排序后的路径列表是否相同 - assertArrayEquals(sortedExpectPaths.toArray(), sortedActualPaths.toArray()); + assertArrayEquals( + expectColumns.stream().map(Column::getPath).sorted().toArray(), + columns.stream().map(Column::getPath).sorted().toArray()); } catch (SessionException e) { LOGGER.error("show columns error: ", e); } } + protected void showColumns() {} + private void testAddAndRemoveStorageEngineWithPrefix() { String dataPrefix1 = "nt.wf03"; String dataPrefix2 = "nt.wf04"; @@ -536,12 +531,14 @@ private void testAddAndRemoveStorageEngineWithPrefix() { List> valuesList = EXP_VALUES_LIST1; - testShowAllColumnsInExpansion(true); + System.out.println("==========1=========="); + SQLTestTools.executeAndPrint(session, "SHOW COLUMNS;"); // 添加不同 schemaPrefix,相同 dataPrefix addStorageEngine(expPort, true, true, dataPrefix1, schemaPrefix1, extraParams); - testShowAllColumnsInExpansion(false); + System.out.println("==========2=========="); + SQLTestTools.executeAndPrint(session, "SHOW COLUMNS;"); // 添加节点 dataPrefix = dataPrefix1 && schemaPrefix = p1 后查询 String statement = "select status2 from *;"; @@ -549,7 +546,13 @@ private void testAddAndRemoveStorageEngineWithPrefix() { SQLTestTools.executeAndCompare(session, statement, pathList, REPEAT_EXP_VALUES_LIST1); addStorageEngine(expPort, true, true, dataPrefix1, schemaPrefix2, extraParams); + System.out.println("==========3=========="); + SQLTestTools.executeAndPrint(session, "SHOW COLUMNS;"); + addStorageEngine(expPort, true, true, dataPrefix1, null, extraParams); + System.out.println("==========4=========="); + SQLTestTools.executeAndPrint(session, "SHOW COLUMNS;"); + testShowClusterInfo(5); // 如果是重复添加,则报错 @@ -560,10 +563,18 @@ private void testAddAndRemoveStorageEngineWithPrefix() { testShowClusterInfo(5); addStorageEngine(expPort, true, true, dataPrefix1, schemaPrefix3, extraParams); + + System.out.println("==========5=========="); + SQLTestTools.executeAndPrint(session, "SHOW COLUMNS;"); + // 这里是之后待测试的点,如果添加包含关系的,应当报错。 // res = addStorageEngine(expPort, true, true, "nt.wf03.wt01", "p3"); // 添加相同 schemaPrefix,不同 dataPrefix addStorageEngine(expPort, true, true, dataPrefix2, schemaPrefix3, extraParams); + + System.out.println("==========6=========="); + SQLTestTools.executeAndPrint(session, "SHOW COLUMNS;"); + testShowClusterInfo(7); // 添加节点 dataPrefix = dataPrefix1 && schemaPrefix = p1 后查询 @@ -598,6 +609,10 @@ private void testAddAndRemoveStorageEngineWithPrefix() { } catch (SessionException e) { LOGGER.error("remove history data source through session api error: ", e); } + + System.out.println("==========7=========="); + SQLTestTools.executeAndPrint(session, "SHOW COLUMNS;"); + // 移除节点 dataPrefix = dataPrefix1 && schemaPrefix = p2 + schemaPrefixSuffix 后再查询 statement = "select * from p2.nt.wf03;"; String expect = diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/utils/SQLTestTools.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/utils/SQLTestTools.java index c421de3683..1df5e79557 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/utils/SQLTestTools.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/utils/SQLTestTools.java @@ -42,6 +42,11 @@ public static void executeAndCompare(Session session, String statement, String e assertEquals(exceptOutput, actualOutput); } + public static void executeAndPrint(Session session, String statement) { + String actualOutput = execute(session, statement); + System.out.println(actualOutput); + } + private static String execute(Session session, String statement) { LOGGER.info("Execute Statement: \"{}\"", statement); From 5c90d76613e201a64a350df50dba8c811d188f5f Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Tue, 16 Jul 2024 15:22:57 +0800 Subject: [PATCH 078/138] test --- .github/workflows/standard-test-suite.yml | 1 + .../expansion/BaseCapacityExpansionIT.java | 41 +++++++------------ 2 files changed, 16 insertions(+), 26 deletions(-) diff --git a/.github/workflows/standard-test-suite.yml b/.github/workflows/standard-test-suite.yml index 0f841da109..e0fc21f331 100644 --- a/.github/workflows/standard-test-suite.yml +++ b/.github/workflows/standard-test-suite.yml @@ -32,6 +32,7 @@ jobs: db-ce: uses: ./.github/workflows/DB-CE.yml with: + os-matrix: '["ubuntu-latest"]' metadata-matrix: '["zookeeper"]' # remote-test: # uses: ./.github/workflows/remote-test.yml diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java index af0cd297e5..bae5dbc93c 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java @@ -181,7 +181,7 @@ private void addStorageEngineInProgress( } @Test - public void oriHasDataExpHasData() throws InterruptedException { + public void oriHasDataExpHasData() { // 查询原始节点的历史数据,结果不为空 testQueryHistoryDataOriHasData(); // 写入并查询新数据 @@ -200,7 +200,7 @@ public void oriHasDataExpHasData() throws InterruptedException { } @Test - public void oriHasDataExpNoData() throws InterruptedException { + public void oriHasDataExpNoData() { // 查询原始节点的历史数据,结果不为空 testQueryHistoryDataOriHasData(); // 写入并查询新数据 @@ -216,7 +216,7 @@ public void oriHasDataExpNoData() throws InterruptedException { } @Test - public void oriNoDataExpHasData() throws InterruptedException { + public void oriNoDataExpHasData() { // 查询原始节点的历史数据,结果为空 testQueryHistoryDataOriNoData(); // 写入并查询新数据 @@ -234,7 +234,7 @@ public void oriNoDataExpHasData() throws InterruptedException { } @Test - public void oriNoDataExpNoData() throws InterruptedException { + public void oriNoDataExpNoData() { // 查询原始节点的历史数据,结果为空 testQueryHistoryDataOriNoData(); // 写入并查询新数据 @@ -250,7 +250,7 @@ public void oriNoDataExpNoData() throws InterruptedException { } @Test - public void testReadOnly() throws InterruptedException { + public void testReadOnly() { // 查询原始只读节点的历史数据,结果不为空 testQueryHistoryDataOriHasData(); // 测试参数错误的只读节点扩容 @@ -531,29 +531,24 @@ private void testAddAndRemoveStorageEngineWithPrefix() { List> valuesList = EXP_VALUES_LIST1; - System.out.println("==========1=========="); - SQLTestTools.executeAndPrint(session, "SHOW COLUMNS;"); - // 添加不同 schemaPrefix,相同 dataPrefix + System.out.println("==========1=========="); + SQLTestTools.executeAndPrint(session, "SHOW COLUMNS nt.wf03.*;"); addStorageEngine(expPort, true, true, dataPrefix1, schemaPrefix1, extraParams); - System.out.println("==========2=========="); - SQLTestTools.executeAndPrint(session, "SHOW COLUMNS;"); + SQLTestTools.executeAndPrint(session, "SHOW COLUMNS nt.wf03.*;"); // 添加节点 dataPrefix = dataPrefix1 && schemaPrefix = p1 后查询 String statement = "select status2 from *;"; List pathList = Arrays.asList("nt.wf03.wt01.status2", "p1.nt.wf03.wt01.status2"); SQLTestTools.executeAndCompare(session, statement, pathList, REPEAT_EXP_VALUES_LIST1); + // 继续添加不同 schemaPrefix,相同 dataPrefix addStorageEngine(expPort, true, true, dataPrefix1, schemaPrefix2, extraParams); - System.out.println("==========3=========="); - SQLTestTools.executeAndPrint(session, "SHOW COLUMNS;"); - addStorageEngine(expPort, true, true, dataPrefix1, null, extraParams); - System.out.println("==========4=========="); - SQLTestTools.executeAndPrint(session, "SHOW COLUMNS;"); - testShowClusterInfo(5); + System.out.println("==========3=========="); + SQLTestTools.executeAndPrint(session, "SHOW COLUMNS nt.wf03.*;"); // 如果是重复添加,则报错 String res = addStorageEngine(expPort, true, true, dataPrefix1, null, extraParams); @@ -564,17 +559,12 @@ private void testAddAndRemoveStorageEngineWithPrefix() { addStorageEngine(expPort, true, true, dataPrefix1, schemaPrefix3, extraParams); - System.out.println("==========5=========="); - SQLTestTools.executeAndPrint(session, "SHOW COLUMNS;"); - // 这里是之后待测试的点,如果添加包含关系的,应当报错。 // res = addStorageEngine(expPort, true, true, "nt.wf03.wt01", "p3"); // 添加相同 schemaPrefix,不同 dataPrefix addStorageEngine(expPort, true, true, dataPrefix2, schemaPrefix3, extraParams); - - System.out.println("==========6=========="); - SQLTestTools.executeAndPrint(session, "SHOW COLUMNS;"); - + System.out.println("==========4=========="); + SQLTestTools.executeAndPrint(session, "SHOW COLUMNS p3.*;"); testShowClusterInfo(7); // 添加节点 dataPrefix = dataPrefix1 && schemaPrefix = p1 后查询 @@ -609,9 +599,8 @@ private void testAddAndRemoveStorageEngineWithPrefix() { } catch (SessionException e) { LOGGER.error("remove history data source through session api error: ", e); } - - System.out.println("==========7=========="); - SQLTestTools.executeAndPrint(session, "SHOW COLUMNS;"); + System.out.println("==========5=========="); + SQLTestTools.executeAndPrint(session, "SHOW COLUMNS p3.*;"); // 移除节点 dataPrefix = dataPrefix1 && schemaPrefix = p2 + schemaPrefixSuffix 后再查询 statement = "select * from p2.nt.wf03;"; From 93708e71233439ce39a249fdba72a456f16f2cb9 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Tue, 16 Jul 2024 16:04:04 +0800 Subject: [PATCH 079/138] test --- .../cn/edu/tsinghua/iginx/filesystem/FileSystemStorage.java | 2 +- .../integration/expansion/BaseCapacityExpansionIT.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/FileSystemStorage.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/FileSystemStorage.java index 993772391e..110daada32 100644 --- a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/FileSystemStorage.java +++ b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/FileSystemStorage.java @@ -165,7 +165,7 @@ public Pair getBoundaryOfStorage(String prefix) } @Override - public synchronized void release() throws PhysicalException { + public synchronized void release() { executor.close(); if (thread != null) { thread.interrupt(); diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java index bae5dbc93c..de74c2b8ce 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java @@ -533,10 +533,10 @@ private void testAddAndRemoveStorageEngineWithPrefix() { // 添加不同 schemaPrefix,相同 dataPrefix System.out.println("==========1=========="); - SQLTestTools.executeAndPrint(session, "SHOW COLUMNS nt.wf03.*;"); + SQLTestTools.executeAndPrint(session, "SHOW COLUMNS nt.wf03.*, p1.*;"); addStorageEngine(expPort, true, true, dataPrefix1, schemaPrefix1, extraParams); System.out.println("==========2=========="); - SQLTestTools.executeAndPrint(session, "SHOW COLUMNS nt.wf03.*;"); + SQLTestTools.executeAndPrint(session, "SHOW COLUMNS nt.wf03.*, p1.*;"); // 添加节点 dataPrefix = dataPrefix1 && schemaPrefix = p1 后查询 String statement = "select status2 from *;"; @@ -548,7 +548,7 @@ private void testAddAndRemoveStorageEngineWithPrefix() { addStorageEngine(expPort, true, true, dataPrefix1, null, extraParams); testShowClusterInfo(5); System.out.println("==========3=========="); - SQLTestTools.executeAndPrint(session, "SHOW COLUMNS nt.wf03.*;"); + SQLTestTools.executeAndPrint(session, "SHOW COLUMNS p3.*;"); // 如果是重复添加,则报错 String res = addStorageEngine(expPort, true, true, dataPrefix1, null, extraParams); From 4782475e8cf1a0aa0e7b2506d93d5b5c99af47f8 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Tue, 16 Jul 2024 17:19:29 +0800 Subject: [PATCH 080/138] test --- .../expansion/BaseCapacityExpansionIT.java | 103 ++++++++++-------- .../FileSystemCapacityExpansionIT.java | 23 ---- .../mongodb/MongoDBCapacityExpansionIT.java | 94 +++++++++++----- .../parquet/ParquetCapacityExpansionIT.java | 23 ---- 4 files changed, 126 insertions(+), 117 deletions(-) diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java index de74c2b8ce..b86a838d1b 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java @@ -21,7 +21,6 @@ import static cn.edu.tsinghua.iginx.integration.controller.Controller.SUPPORT_KEY; import static cn.edu.tsinghua.iginx.integration.expansion.constant.Constant.*; import static cn.edu.tsinghua.iginx.integration.expansion.utils.SQLTestTools.executeShellScript; -import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; @@ -33,10 +32,8 @@ import cn.edu.tsinghua.iginx.integration.expansion.utils.SQLTestTools; import cn.edu.tsinghua.iginx.integration.tool.ConfLoader; import cn.edu.tsinghua.iginx.session.ClusterInfo; -import cn.edu.tsinghua.iginx.session.Column; import cn.edu.tsinghua.iginx.session.QueryDataSet; import cn.edu.tsinghua.iginx.session.Session; -import cn.edu.tsinghua.iginx.thrift.DataType; import cn.edu.tsinghua.iginx.thrift.RemovedStorageEngineInfo; import cn.edu.tsinghua.iginx.thrift.StorageEngineType; import java.util.ArrayList; @@ -479,48 +476,68 @@ private void queryAllNewData() { SQLTestTools.executeAndCompare(session, statement, expect); } - protected void testShowAllColumnsInExpansion(boolean before) { + protected void testShowColumnsInExpansion(boolean before) { + String statement = "SHOW COLUMNS nt.wf03.*;"; + String expected = + "Columns:\n" + + "+--------------------+--------+\n" + + "| Path|DataType|\n" + + "+--------------------+--------+\n" + + "|nt.wf03.wt01.status2| LONG|\n" + + "+--------------------+--------+\n" + + "Total line number = 1\n"; + SQLTestTools.executeAndCompare(session, statement, expected); + + statement = "SHOW COLUMNS p1.*;"; if (before) { - testShowColumns( - Arrays.asList( - new Column("b.b.b", DataType.LONG), - new Column("ln.wf02.status", DataType.BOOLEAN), - new Column("ln.wf02.version", DataType.BINARY), - new Column("nt.wf03.wt01.status2", DataType.LONG), - new Column("nt.wf04.wt01.temperature", DataType.DOUBLE), - new Column( - "zzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzzzz", - DataType.LONG))); + expected = + "Columns:\n" + + "+----+--------+\n" + + "|Path|DataType|\n" + + "+----+--------+\n" + + "+----+--------+\n" + + "Empty set.\n"; + SQLTestTools.executeAndCompare(session, statement, expected); } else { - testShowColumns( - Arrays.asList( - new Column("b.b.b", DataType.LONG), - new Column("ln.wf02.status", DataType.BOOLEAN), - new Column("ln.wf02.version", DataType.BINARY), - new Column("nt.wf03.wt01.status2", DataType.LONG), - new Column("p1.nt.wf03.wt01.status2", DataType.LONG), - new Column("nt.wf04.wt01.temperature", DataType.DOUBLE), - new Column( - "zzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzzzz", - DataType.LONG))); + expected = + "Columns:\n" + + "+-----------------------+--------+\n" + + "| Path|DataType|\n" + + "+-----------------------+--------+\n" + + "|p1.nt.wf03.wt01.status2| LONG|\n" + + "+-----------------------+--------+\n" + + "Total line number = 1\n"; + SQLTestTools.executeAndCompare(session, statement, expected); } } - protected void testShowColumns(List expectColumns) { - try { - List columns = session.showColumns(); - LOGGER.info("show columns: {}", columns); - // 检查排序后的路径列表是否相同 - assertArrayEquals( - expectColumns.stream().map(Column::getPath).sorted().toArray(), - columns.stream().map(Column::getPath).sorted().toArray()); - } catch (SessionException e) { - LOGGER.error("show columns error: ", e); + protected void testShowColumnsRemoveStorageEngine(boolean before) { + String statement = "SHOW COLUMNS p1.*, p2.*, p3.*;"; + String expected; + if (before) { + expected = "Columns:\n" + + "+---------------------------+--------+\n" + + "| Path|DataType|\n" + + "+---------------------------+--------+\n" + + "| p1.nt.wf03.wt01.status2| LONG|\n" + + "| p2.nt.wf03.wt01.status2| LONG|\n" + + "| p3.nt.wf03.wt01.status2| LONG|\n" + + "|p3.nt.wf04.wt01.temperature| DOUBLE|\n" + + "+---------------------------+--------+\n" + + "Total line number = 4\n"; + } else { + expected = "Columns:\n" + + "+---------------------------+--------+\n" + + "| Path|DataType|\n" + + "+---------------------------+--------+\n" + + "| p1.nt.wf03.wt01.status2| LONG|\n" + + "|p3.nt.wf04.wt01.temperature| DOUBLE|\n" + + "+---------------------------+--------+\n" + + "Total line number = 2\n"; } + SQLTestTools.executeAndCompare(session, statement, expected); } - protected void showColumns() {} - private void testAddAndRemoveStorageEngineWithPrefix() { String dataPrefix1 = "nt.wf03"; String dataPrefix2 = "nt.wf04"; @@ -532,11 +549,9 @@ private void testAddAndRemoveStorageEngineWithPrefix() { List> valuesList = EXP_VALUES_LIST1; // 添加不同 schemaPrefix,相同 dataPrefix - System.out.println("==========1=========="); - SQLTestTools.executeAndPrint(session, "SHOW COLUMNS nt.wf03.*, p1.*;"); + testShowColumnsInExpansion(true); addStorageEngine(expPort, true, true, dataPrefix1, schemaPrefix1, extraParams); - System.out.println("==========2=========="); - SQLTestTools.executeAndPrint(session, "SHOW COLUMNS nt.wf03.*, p1.*;"); + testShowColumnsInExpansion(false); // 添加节点 dataPrefix = dataPrefix1 && schemaPrefix = p1 后查询 String statement = "select status2 from *;"; @@ -547,8 +562,6 @@ private void testAddAndRemoveStorageEngineWithPrefix() { addStorageEngine(expPort, true, true, dataPrefix1, schemaPrefix2, extraParams); addStorageEngine(expPort, true, true, dataPrefix1, null, extraParams); testShowClusterInfo(5); - System.out.println("==========3=========="); - SQLTestTools.executeAndPrint(session, "SHOW COLUMNS p3.*;"); // 如果是重复添加,则报错 String res = addStorageEngine(expPort, true, true, dataPrefix1, null, extraParams); @@ -588,6 +601,7 @@ private void testAddAndRemoveStorageEngineWithPrefix() { SQLTestTools.executeAndCompare(session, statement, pathList, valuesList); // 通过 session 接口测试移除节点 + testShowColumnsRemoveStorageEngine(true); List removedStorageEngineList = new ArrayList<>(); removedStorageEngineList.add( new RemovedStorageEngineInfo("127.0.0.1", expPort, "p2" + schemaPrefixSuffix, dataPrefix1)); @@ -599,8 +613,7 @@ private void testAddAndRemoveStorageEngineWithPrefix() { } catch (SessionException e) { LOGGER.error("remove history data source through session api error: ", e); } - System.out.println("==========5=========="); - SQLTestTools.executeAndPrint(session, "SHOW COLUMNS p3.*;"); + testShowColumnsRemoveStorageEngine(false); // 移除节点 dataPrefix = dataPrefix1 && schemaPrefix = p2 + schemaPrefixSuffix 后再查询 statement = "select * from p2.nt.wf03;"; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java index 886f87634a..449a1d2a52 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java @@ -22,9 +22,6 @@ import cn.edu.tsinghua.iginx.integration.expansion.BaseCapacityExpansionIT; import cn.edu.tsinghua.iginx.integration.expansion.utils.SQLTestTools; -import cn.edu.tsinghua.iginx.session.Column; -import cn.edu.tsinghua.iginx.thrift.DataType; -import java.util.Arrays; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -43,26 +40,6 @@ protected void testInvalidDummyParams( LOGGER.info("filesystem skips test for wrong dummy engine params."); } - @Override - protected void testShowAllColumnsInExpansion(boolean before) { - if (before) { - testShowColumns( - Arrays.asList( - new Column("ln.wf02.status", DataType.BOOLEAN), - new Column("ln.wf02.version", DataType.BINARY), - new Column("nt.wf03.wt01.status2", DataType.LONG), - new Column("nt.wf04.wt01.temperature", DataType.DOUBLE))); - } else { - testShowColumns( - Arrays.asList( - new Column("ln.wf02.status", DataType.BOOLEAN), - new Column("ln.wf02.version", DataType.BINARY), - new Column("nt.wf03.wt01.status2", DataType.LONG), - new Column("p1.nt.wf03.wt01.status2", DataType.LONG), - new Column("nt.wf04.wt01.temperature", DataType.DOUBLE))); - } - } - @Override public void testShowColumns() { String statement = "SHOW COLUMNS mn.*;"; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java index df4c91fe9e..5a29cfc89c 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java @@ -26,10 +26,6 @@ import cn.edu.tsinghua.iginx.integration.expansion.utils.SQLTestTools; import cn.edu.tsinghua.iginx.integration.tool.ConfLoader; import cn.edu.tsinghua.iginx.integration.tool.DBConf; -import cn.edu.tsinghua.iginx.session.Column; -import cn.edu.tsinghua.iginx.thrift.DataType; -import java.util.ArrayList; -import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -46,30 +42,76 @@ public MongoDBCapacityExpansionIT() { } @Override - protected void testShowAllColumnsInExpansion(boolean before) { - List columns = new ArrayList<>(); - columns.add(new Column("b.b._id", DataType.BINARY)); - columns.add(new Column("nt.wf03._id", DataType.BINARY)); - columns.add(new Column("nt.wf04._id", DataType.BINARY)); - columns.add( - new Column( - "zzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzz._id", DataType.BINARY)); - columns.add(new Column("b.b.b", DataType.LONG)); - columns.add(new Column("ln.wf02.status", DataType.BOOLEAN)); - columns.add(new Column("ln.wf02.version", DataType.BINARY)); - columns.add(new Column("nt.wf03.wt01.status2", DataType.LONG)); - columns.add(new Column("nt.wf04.wt01.temperature", DataType.DOUBLE)); - columns.add( - new Column( - "zzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzzzz", - DataType.LONG)); - - if (!before) { - columns.add(new Column("p1.nt.wf03._id", DataType.BINARY)); - columns.add(new Column("p1.nt.wf03.wt01.status2", DataType.LONG)); + protected void testShowColumnsInExpansion(boolean before) { + String statement = "SHOW COLUMNS nt.wf03.*;"; + String expected = + "Columns:\n" + + "+--------------------+--------+\n" + + "| Path|DataType|\n" + + "+--------------------+--------+\n" + + "| nt.wf03._id| INTEGER|\n" + + "|nt.wf03.wt01.status2| LONG|\n" + + "+--------------------+--------+\n" + + "Total line number = 1\n"; + SQLTestTools.executeAndCompare(session, statement, expected); + + if (before) { + statement = "SHOW COLUMNS p1.*;"; + expected = + "Columns:\n" + + "+----+--------+\n" + + "|Path|DataType|\n" + + "+----+--------+\n" + + "+----+--------+\n" + + "Empty set.\n"; + SQLTestTools.executeAndCompare(session, statement, expected); + } else { + statement = "SHOW COLUMNS p1.*;"; + expected = + "Columns:\n" + + "+-----------------------+--------+\n" + + "| Path|DataType|\n" + + "+-----------------------+--------+\n" + + "| p1.nt.wf03._id| INTEGER|\n" + + "|p1.nt.wf03.wt01.status2| LONG|\n" + + "+-----------------------+--------+\n" + + "Total line number = 1\n"; + SQLTestTools.executeAndCompare(session, statement, expected); } + } - testShowColumns(columns); + @Override + protected void testShowColumnsRemoveStorageEngine(boolean before) { + String statement = "SHOW COLUMNS p1.*, p2.*, p3.*;"; + String expected; + if (before) { + expected = "Columns:\n" + + "+---------------------------+--------+\n" + + "| Path|DataType|\n" + + "+---------------------------+--------+\n" + + "| p1.nt.wf03._id| INTEGER|\n" + + "| p1.nt.wf03.wt01.status2| LONG|\n" + + "| p2.nt.wf03._id| INTEGER|\n" + + "| p2.nt.wf03.wt01.status2| LONG|\n" + + "| p3.nt.wf03._id| INTEGER|\n" + + "| p3.nt.wf03.wt01.status2| LONG|\n" + + "| p3.nt.wf04._id| INTEGER|\n" + + "|p3.nt.wf04.wt01.temperature| DOUBLE|\n" + + "+---------------------------+--------+\n" + + "Total line number = 8\n"; + } else { + expected = "Columns:\n" + + "+---------------------------+--------+\n" + + "| Path|DataType|\n" + + "+---------------------------+--------+\n" + + "| p1.nt.wf03._id| INTEGER|\n" + + "| p1.nt.wf03.wt01.status2| LONG|\n" + + "| p3.nt.wf04._id| INTEGER|\n" + + "|p3.nt.wf04.wt01.temperature| DOUBLE|\n" + + "+---------------------------+--------+\n" + + "Total line number = 4\n"; + } + SQLTestTools.executeAndCompare(session, statement, expected); } @Override diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetCapacityExpansionIT.java index 8b37bd56ce..60f3aa60ee 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetCapacityExpansionIT.java @@ -21,9 +21,6 @@ import static cn.edu.tsinghua.iginx.thrift.StorageEngineType.parquet; import cn.edu.tsinghua.iginx.integration.expansion.BaseCapacityExpansionIT; -import cn.edu.tsinghua.iginx.session.Column; -import cn.edu.tsinghua.iginx.thrift.DataType; -import java.util.Arrays; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -41,24 +38,4 @@ protected void testInvalidDummyParams( int port, boolean hasData, boolean isReadOnly, String dataPrefix, String schemaPrefix) { LOGGER.info("parquet skips test for wrong dummy engine params."); } - - @Override - protected void testShowAllColumnsInExpansion(boolean before) { - if (before) { - testShowColumns( - Arrays.asList( - new Column("ln.wf02.status", DataType.BOOLEAN), - new Column("ln.wf02.version", DataType.BINARY), - new Column("nt.wf03.wt01.status2", DataType.LONG), - new Column("nt.wf04.wt01.temperature", DataType.DOUBLE))); - } else { - testShowColumns( - Arrays.asList( - new Column("ln.wf02.status", DataType.BOOLEAN), - new Column("ln.wf02.version", DataType.BINARY), - new Column("nt.wf03.wt01.status2", DataType.LONG), - new Column("p1.nt.wf03.wt01.status2", DataType.LONG), - new Column("nt.wf04.wt01.temperature", DataType.DOUBLE))); - } - } } From 4b7693434331be08c16903419d323b4061a7a1b9 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Thu, 18 Jul 2024 19:56:44 +0800 Subject: [PATCH 081/138] fix schema prefix --- .../execute/StoragePhysicalTaskExecutor.java | 128 ++++++++++++++---- .../iginx/filesystem/exec/LocalExecutor.java | 4 +- .../iginx/influxdb/InfluxDBStorage.java | 7 +- .../tsinghua/iginx/iotdb/IoTDBStorage.java | 43 +++--- .../iginx/mongodb/MongoDBStorage.java | 2 +- .../iginx/parquet/exec/LocalExecutor.java | 2 +- .../tsinghua/iginx/redis/RedisStorage.java | 4 +- .../iginx/relational/RelationalStorage.java | 6 +- .../edu/tsinghua/iginx/utils/StringUtils.java | 9 +- .../expansion/BaseCapacityExpansionIT.java | 38 +++--- .../FileSystemCapacityExpansionIT.java | 37 +++++ .../mongodb/MongoDBCapacityExpansionIT.java | 54 ++++---- 12 files changed, 222 insertions(+), 112 deletions(-) diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java index 19a877f70a..23ca4b2bd8 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java @@ -367,44 +367,49 @@ public TaskExecuteResult executeShowColumns(ShowColumns showColumns) { continue; } try { - Set patternSet = showColumns.getPathRegexSet(); + Set patterns = showColumns.getPathRegexSet(); TagFilter tagFilter = showColumns.getTagFilter(); - List columnList = pair.k.getColumns(patternSet, tagFilter); - - // fix the schemaPrefix and dataPrefix String schemaPrefix = storage.getSchemaPrefix(); // 不下推dataPrefix的原因:iotdb中,非dummy的数据库中如果有原始数据,会在show columns时被查询到并造成误解 String dataPrefixRegex = storage.getDataPrefix() == null ? null : StringUtils.reformatPath(storage.getDataPrefix() + ".*"); - if (tagFilter == null) { - for (Column column : columnList) { - if (column.isDummy()) { - if (dataPrefixRegex == null || Pattern.matches(dataPrefixRegex, column.getPath())) { - if (schemaPrefix != null) { - column.setPath(schemaPrefix + "." + column.getPath()); - boolean isMatch = patternSet.isEmpty(); - for (String pathRegex : patternSet) { - if (Pattern.matches(StringUtils.reformatPath(pathRegex), column.getPath())) { - isMatch = true; - break; - } - } - if (isMatch) { - columnSetAfterFilter.add(column); - } - } else { - columnSetAfterFilter.add(column); - } + + // schemaPrefix是在IGinX中定义的,数据源的路径中没有该前缀,因此需要剪掉前缀是schemaPrefix的部分 + Set patternsCutSchemaPrefix = cutSchemaPrefix(schemaPrefix, patterns); + if (patternsCutSchemaPrefix.isEmpty()) { + continue; + } + List columnList = pair.k.getColumns(patternsCutSchemaPrefix, tagFilter); + + if (tagFilter != null) { + columnSetAfterFilter.addAll(columnList); + continue; + } + for (Column column : columnList) { + if (!column.isDummy()) { + columnSetAfterFilter.add(column); + continue; + } + if (dataPrefixRegex == null || Pattern.matches(dataPrefixRegex, column.getPath())) { + if (schemaPrefix == null) { + columnSetAfterFilter.add(column); + continue; + } + column.setPath(schemaPrefix + "." + column.getPath()); + boolean isMatch = patterns.isEmpty(); + for (String pathRegex : patterns) { + if (Pattern.matches(StringUtils.reformatPath(pathRegex), column.getPath())) { + isMatch = true; + break; } - } else { + } + if (isMatch) { columnSetAfterFilter.add(column); } } - } else { - columnSetAfterFilter.addAll(columnList); } } catch (PhysicalException e) { return new TaskExecuteResult(e); @@ -432,6 +437,77 @@ public TaskExecuteResult executeShowColumns(ShowColumns showColumns) { } } + private static Set cutSchemaPrefix(String schemaPrefix, Set patterns) { + if (schemaPrefix == null) { + return patterns; + } + if (patterns.isEmpty()) { + return Collections.singleton("*"); + } + + Set patternsCutSchemaPrefix = new HashSet<>(); + for (String pattern : patterns) { + Set tmp = cutSchemaPrefix(schemaPrefix, pattern); + if (tmp.contains("*")) { + return Collections.singleton("*"); + } + patternsCutSchemaPrefix.addAll(tmp); + } + return patternsCutSchemaPrefix; + } + + private static Set cutSchemaPrefix(String schemaPrefix, String pattern) { + String[] prefixSplit = schemaPrefix.split("\\."); + String[] patternSplit = pattern.split("\\."); + int minLen = Math.min(prefixSplit.length, patternSplit.length); + int index = 0; + while (index < minLen && prefixSplit[index].equals(patternSplit[index])) { + index++; + } + + if (index == patternSplit.length) { + return Collections.emptySet(); + } + + if (index == prefixSplit.length) { + return Collections.singleton(joinWithDot(patternSplit, index)); + } + + if (!patternSplit[index].equals("*")) { + return Collections.emptySet(); + } + + Set target = new HashSet<>(); + + // 将pattern的'*'视为部分匹配该前缀,即把'*'下推到数据源 + target.add(joinWithDot(patternSplit, index)); + + if (index + 1 < patternSplit.length) { + // 将pattern的'*'视为完全匹配该前缀,即不把'*'下推到数据源 + String patternRemain = joinWithDot(patternSplit, index + 1); + target.add(patternRemain); + + for (int i = index + 1; i < prefixSplit.length; i++) { + String prefixRemain = joinWithDot(prefixSplit, i); + target.addAll(cutSchemaPrefix(prefixRemain, patternRemain)); + } + } + + return target; + } + + private static String joinWithDot(String[] strings, int begin) { + if (begin >= strings.length) { + return ""; + } + StringBuilder sb = new StringBuilder(); + for (int i = begin; i < strings.length; i++) { + sb.append(strings[i]).append("."); + } + sb.setLength(sb.length() - 1); + return sb.toString(); + } + public void commit(List tasks) { for (StoragePhysicalTask task : tasks) { if (replicaDispatcher == null) { diff --git a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java index f660c04926..f643026166 100644 --- a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java +++ b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java @@ -346,7 +346,7 @@ public List getColumnsOfStorageUnit( file.getAbsolutePath())); } // get columns by pattern - if (!StringUtils.isPathMatchPattern(columnPath, patterns)) { + if (StringUtils.pathNotMatchPatterns(columnPath, patterns)) { continue; } // get columns by tag filter @@ -361,7 +361,7 @@ public List getColumnsOfStorageUnit( for (File file : fileSystemManager.getAllFiles(new File(realDummyRoot), true)) { String dummyPath = FilePathUtils.convertAbsolutePathToPath(dummyRoot, file.getAbsolutePath(), storageUnit); - if (!StringUtils.isPathMatchPattern(dummyPath, patterns)) { + if (StringUtils.pathNotMatchPatterns(dummyPath, patterns)) { continue; } columns.add(new Column(dummyPath, DataType.BINARY, null, true)); diff --git a/dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java b/dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java index 5d2a6f4d06..22f374f743 100644 --- a/dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java +++ b/dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java @@ -272,10 +272,9 @@ public List getColumns(Set patterns, TagFilter tagFilter) { // List> patternPairs = new ArrayList<>(); - if (patterns == null - || patterns.size() == 0 - || patterns.contains("*") - || patterns.contains("*.*")) { + if (patterns == null || patterns.isEmpty()) { + tables = Collections.emptyList(); + } else if (patterns.contains("*") || patterns.contains("*.*")) { statement = String.format(SHOW_TIME_SERIES, bucket.getName()); tables = client.getQueryApi().query(statement, organization.getId()); } else { diff --git a/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java b/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java index 0215cb19b5..d3aa7d71e7 100644 --- a/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java +++ b/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java @@ -64,7 +64,6 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -282,28 +281,26 @@ private void getColumns2StorageUnit( TagFilter tagFilter) throws PhysicalException { try { - Iterator iterator = patterns.iterator(); - do { - String pattern = iterator.hasNext() ? iterator.next() : null; - SessionDataSetWrapper dataSet; - LOGGER.debug("get time series: {}", pattern); - if (pattern != null) { - LOGGER.debug("do show timeseries: {}", pattern); - dataSet = sessionPool.executeQueryStatement(String.format(SHOW_TIMESERIES, pattern)); - getColumnsFromDataSet(columns, columns2StorageUnit, tagFilter, dataSet); - dataSet.close(); - - dataSet = - sessionPool.executeQueryStatement(String.format(SHOW_TIMESERIES_DUMMY, pattern)); - getColumnsFromDataSet(columns, columns2StorageUnit, tagFilter, dataSet); - dataSet.close(); - } else { - LOGGER.debug("do show all timeseries"); - dataSet = sessionPool.executeQueryStatement(SHOW_TIMESERIES_ALL); - getColumnsFromDataSet(columns, columns2StorageUnit, tagFilter, dataSet); - dataSet.close(); - } - } while (iterator.hasNext()); + if (patterns.isEmpty()) { + return; + } + SessionDataSetWrapper dataSet; + if (patterns.contains("*")) { + LOGGER.debug("do show all timeseries"); + dataSet = sessionPool.executeQueryStatement(SHOW_TIMESERIES_ALL); + getColumnsFromDataSet(columns, columns2StorageUnit, tagFilter, dataSet); + dataSet.close(); + return; + } + for (String pattern : patterns) { + LOGGER.debug("do show timeseries: {}", pattern); + dataSet = sessionPool.executeQueryStatement(String.format(SHOW_TIMESERIES, pattern)); + getColumnsFromDataSet(columns, columns2StorageUnit, tagFilter, dataSet); + dataSet.close(); + dataSet = sessionPool.executeQueryStatement(String.format(SHOW_TIMESERIES_DUMMY, pattern)); + getColumnsFromDataSet(columns, columns2StorageUnit, tagFilter, dataSet); + dataSet.close(); + } } catch (IoTDBConnectionException | StatementExecutionException e) { throw new IoTDBTaskExecuteFailureException("get time series failure: ", e); } diff --git a/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java b/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java index 0726e15e6d..30d373f5e8 100644 --- a/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java +++ b/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java @@ -327,7 +327,7 @@ private static long getDuplicateKey(WriteError error) { public List getColumns(Set patterns, TagFilter tagFilter) { List patternList = new ArrayList<>(patterns); if (patternList.isEmpty()) { - patternList.add("*"); + return Collections.emptyList(); } List columns = new ArrayList<>(); for (String dbName : getDatabaseNames(this.client)) { diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java index 9eacf439eb..cb42fa66f7 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java @@ -328,7 +328,7 @@ public List getColumnsOfStorageUnit( String storageUnit, Set patterns, TagFilter tagFilter) throws PhysicalException { List patternList = new ArrayList<>(patterns); if (patternList.isEmpty()) { - patternList.add("*"); + return Collections.emptyList(); } if (storageUnit.equals("*")) { List columns = new ArrayList<>(); diff --git a/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java b/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java index 8dc566d43f..cfe173a8a6 100644 --- a/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java +++ b/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java @@ -483,7 +483,7 @@ private void getIginxColumns(Consumer ret, Set patterns, TagFilt throws PhysicalException { List patternList = new ArrayList<>(patterns); if (patternList.isEmpty()) { - patternList.add("*"); + return; } List allPaths = determinePathList("*", patternList, tagFilter); try (Jedis jedis = getDataConnection()) { @@ -502,7 +502,7 @@ private void getIginxColumns(Consumer ret, Set patterns, TagFilt private void getDummyColumns(Consumer ret, Set patterns) { List patternList = new ArrayList<>(patterns); if (patternList.isEmpty()) { - patternList.add("*"); + return; } try (Jedis jedis = getDummyConnection()) { for (String pattern : patternList) { diff --git a/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java index 3e2e6eb452..0b90202288 100644 --- a/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java +++ b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java @@ -372,7 +372,7 @@ public List getColumns(Set patterns, TagFilter tagFilter) try { // dummy pattern list List patternList = new ArrayList<>(); - if (patterns == null || patterns.size() == 0) { + if (patterns.contains("*")) { patternList = new ArrayList<>(Collections.singletonList("*.*")); } String colPattern; @@ -389,7 +389,7 @@ public List getColumns(Set patterns, TagFilter tagFilter) && !databaseName.startsWith(DATABASE_PREFIX); if (isDummy) { // find pattern that match .* to avoid creating databases after. - if (patterns == null || patterns.size() == 0) { + if (patterns.contains("*")) { continue; } for (String p : patterns) { @@ -404,7 +404,7 @@ public List getColumns(Set patterns, TagFilter tagFilter) Map tableAndColPattern = new HashMap<>(); - if (patterns != null && patterns.size() != 0) { + if (!patterns.isEmpty()) { tableAndColPattern = splitAndMergeQueryPatterns(databaseName, new ArrayList<>(patterns)); } else { for (String table : getTables(databaseName, "%")) { diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java index 2f175bdf89..15f6bf4c1a 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java @@ -116,16 +116,13 @@ public static String reformatPath(String path) { return path; } - public static boolean isPathMatchPattern(String path, Set patterns) { - if (patterns.isEmpty()) { - return true; - } + public static boolean pathNotMatchPatterns(String path, Set patterns) { for (String pattern : patterns) { if (match(path, pattern)) { - return true; + return false; } } - return false; + return true; } public static boolean match(String string, String iginxPattern) { diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java index b86a838d1b..3a2c0fe51f 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java @@ -515,25 +515,27 @@ protected void testShowColumnsRemoveStorageEngine(boolean before) { String statement = "SHOW COLUMNS p1.*, p2.*, p3.*;"; String expected; if (before) { - expected = "Columns:\n" - + "+---------------------------+--------+\n" - + "| Path|DataType|\n" - + "+---------------------------+--------+\n" - + "| p1.nt.wf03.wt01.status2| LONG|\n" - + "| p2.nt.wf03.wt01.status2| LONG|\n" - + "| p3.nt.wf03.wt01.status2| LONG|\n" - + "|p3.nt.wf04.wt01.temperature| DOUBLE|\n" - + "+---------------------------+--------+\n" - + "Total line number = 4\n"; + expected = + "Columns:\n" + + "+---------------------------+--------+\n" + + "| Path|DataType|\n" + + "+---------------------------+--------+\n" + + "| p1.nt.wf03.wt01.status2| LONG|\n" + + "| p2.nt.wf03.wt01.status2| LONG|\n" + + "| p3.nt.wf03.wt01.status2| LONG|\n" + + "|p3.nt.wf04.wt01.temperature| DOUBLE|\n" + + "+---------------------------+--------+\n" + + "Total line number = 4\n"; } else { - expected = "Columns:\n" - + "+---------------------------+--------+\n" - + "| Path|DataType|\n" - + "+---------------------------+--------+\n" - + "| p1.nt.wf03.wt01.status2| LONG|\n" - + "|p3.nt.wf04.wt01.temperature| DOUBLE|\n" - + "+---------------------------+--------+\n" - + "Total line number = 2\n"; + expected = + "Columns:\n" + + "+---------------------------+--------+\n" + + "| Path|DataType|\n" + + "+---------------------------+--------+\n" + + "| p1.nt.wf03.wt01.status2| LONG|\n" + + "|p3.nt.wf04.wt01.temperature| DOUBLE|\n" + + "+---------------------------+--------+\n" + + "Total line number = 2\n"; } SQLTestTools.executeAndCompare(session, statement, expected); } diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java index 449a1d2a52..7036fbdc22 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java @@ -40,6 +40,43 @@ protected void testInvalidDummyParams( LOGGER.info("filesystem skips test for wrong dummy engine params."); } + @Override + protected void testShowColumnsInExpansion(boolean before) { + String statement = "SHOW COLUMNS nt.wf03.*;"; + String expected = + "Columns:\n" + + "+--------------------+--------+\n" + + "| Path|DataType|\n" + + "+--------------------+--------+\n" + + "|nt.wf03.wt01.status2| BINARY|\n" + + "+--------------------+--------+\n" + + "Total line number = 1\n"; + SQLTestTools.executeAndCompare(session, statement, expected); + + if (before) { + statement = "SHOW COLUMNS p1.*;"; + expected = + "Columns:\n" + + "+----+--------+\n" + + "|Path|DataType|\n" + + "+----+--------+\n" + + "+----+--------+\n" + + "Empty set.\n"; + SQLTestTools.executeAndCompare(session, statement, expected); + } else { + statement = "SHOW COLUMNS p1.*;"; + expected = + "Columns:\n" + + "+-----------------------+--------+\n" + + "| Path|DataType|\n" + + "+-----------------------+--------+\n" + + "|p1.nt.wf03.wt01.status2| BINARY|\n" + + "+-----------------------+--------+\n" + + "Total line number = 1\n"; + SQLTestTools.executeAndCompare(session, statement, expected); + } + } + @Override public void testShowColumns() { String statement = "SHOW COLUMNS mn.*;"; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java index 5a29cfc89c..0bb6948ace 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java @@ -52,7 +52,7 @@ protected void testShowColumnsInExpansion(boolean before) { + "| nt.wf03._id| INTEGER|\n" + "|nt.wf03.wt01.status2| LONG|\n" + "+--------------------+--------+\n" - + "Total line number = 1\n"; + + "Total line number = 2\n"; SQLTestTools.executeAndCompare(session, statement, expected); if (before) { @@ -75,7 +75,7 @@ protected void testShowColumnsInExpansion(boolean before) { + "| p1.nt.wf03._id| INTEGER|\n" + "|p1.nt.wf03.wt01.status2| LONG|\n" + "+-----------------------+--------+\n" - + "Total line number = 1\n"; + + "Total line number = 2\n"; SQLTestTools.executeAndCompare(session, statement, expected); } } @@ -85,31 +85,33 @@ protected void testShowColumnsRemoveStorageEngine(boolean before) { String statement = "SHOW COLUMNS p1.*, p2.*, p3.*;"; String expected; if (before) { - expected = "Columns:\n" - + "+---------------------------+--------+\n" - + "| Path|DataType|\n" - + "+---------------------------+--------+\n" - + "| p1.nt.wf03._id| INTEGER|\n" - + "| p1.nt.wf03.wt01.status2| LONG|\n" - + "| p2.nt.wf03._id| INTEGER|\n" - + "| p2.nt.wf03.wt01.status2| LONG|\n" - + "| p3.nt.wf03._id| INTEGER|\n" - + "| p3.nt.wf03.wt01.status2| LONG|\n" - + "| p3.nt.wf04._id| INTEGER|\n" - + "|p3.nt.wf04.wt01.temperature| DOUBLE|\n" - + "+---------------------------+--------+\n" - + "Total line number = 8\n"; + expected = + "Columns:\n" + + "+---------------------------+--------+\n" + + "| Path|DataType|\n" + + "+---------------------------+--------+\n" + + "| p1.nt.wf03._id| INTEGER|\n" + + "| p1.nt.wf03.wt01.status2| LONG|\n" + + "| p2.nt.wf03._id| INTEGER|\n" + + "| p2.nt.wf03.wt01.status2| LONG|\n" + + "| p3.nt.wf03._id| INTEGER|\n" + + "| p3.nt.wf03.wt01.status2| LONG|\n" + + "| p3.nt.wf04._id| INTEGER|\n" + + "|p3.nt.wf04.wt01.temperature| DOUBLE|\n" + + "+---------------------------+--------+\n" + + "Total line number = 8\n"; } else { - expected = "Columns:\n" - + "+---------------------------+--------+\n" - + "| Path|DataType|\n" - + "+---------------------------+--------+\n" - + "| p1.nt.wf03._id| INTEGER|\n" - + "| p1.nt.wf03.wt01.status2| LONG|\n" - + "| p3.nt.wf04._id| INTEGER|\n" - + "|p3.nt.wf04.wt01.temperature| DOUBLE|\n" - + "+---------------------------+--------+\n" - + "Total line number = 4\n"; + expected = + "Columns:\n" + + "+---------------------------+--------+\n" + + "| Path|DataType|\n" + + "+---------------------------+--------+\n" + + "| p1.nt.wf03._id| INTEGER|\n" + + "| p1.nt.wf03.wt01.status2| LONG|\n" + + "| p3.nt.wf04._id| INTEGER|\n" + + "|p3.nt.wf04.wt01.temperature| DOUBLE|\n" + + "+---------------------------+--------+\n" + + "Total line number = 4\n"; } SQLTestTools.executeAndCompare(session, statement, expected); } From 52d66e66ff95144b1fd6312dc45a995046f844bf Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Thu, 18 Jul 2024 20:31:43 +0800 Subject: [PATCH 082/138] fix --- .../execute/StoragePhysicalTaskExecutor.java | 3 ++ .../iginx/influxdb/InfluxDBStorage.java | 7 +-- .../tsinghua/iginx/iotdb/IoTDBStorage.java | 43 ++++++++++--------- .../iginx/mongodb/MongoDBStorage.java | 2 +- .../iginx/parquet/exec/LocalExecutor.java | 2 +- .../tsinghua/iginx/redis/RedisStorage.java | 4 +- .../iginx/relational/RelationalStorage.java | 6 +-- .../edu/tsinghua/iginx/utils/StringUtils.java | 3 ++ 8 files changed, 40 insertions(+), 30 deletions(-) diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java index 23ca4b2bd8..a924784a41 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java @@ -382,6 +382,9 @@ public TaskExecuteResult executeShowColumns(ShowColumns showColumns) { if (patternsCutSchemaPrefix.isEmpty()) { continue; } + if (patternsCutSchemaPrefix.contains("*")) { + patternsCutSchemaPrefix = Collections.emptySet(); + } List columnList = pair.k.getColumns(patternsCutSchemaPrefix, tagFilter); if (tagFilter != null) { diff --git a/dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java b/dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java index 22f374f743..5d2a6f4d06 100644 --- a/dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java +++ b/dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java @@ -272,9 +272,10 @@ public List getColumns(Set patterns, TagFilter tagFilter) { // List> patternPairs = new ArrayList<>(); - if (patterns == null || patterns.isEmpty()) { - tables = Collections.emptyList(); - } else if (patterns.contains("*") || patterns.contains("*.*")) { + if (patterns == null + || patterns.size() == 0 + || patterns.contains("*") + || patterns.contains("*.*")) { statement = String.format(SHOW_TIME_SERIES, bucket.getName()); tables = client.getQueryApi().query(statement, organization.getId()); } else { diff --git a/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java b/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java index d3aa7d71e7..0215cb19b5 100644 --- a/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java +++ b/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java @@ -64,6 +64,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -281,26 +282,28 @@ private void getColumns2StorageUnit( TagFilter tagFilter) throws PhysicalException { try { - if (patterns.isEmpty()) { - return; - } - SessionDataSetWrapper dataSet; - if (patterns.contains("*")) { - LOGGER.debug("do show all timeseries"); - dataSet = sessionPool.executeQueryStatement(SHOW_TIMESERIES_ALL); - getColumnsFromDataSet(columns, columns2StorageUnit, tagFilter, dataSet); - dataSet.close(); - return; - } - for (String pattern : patterns) { - LOGGER.debug("do show timeseries: {}", pattern); - dataSet = sessionPool.executeQueryStatement(String.format(SHOW_TIMESERIES, pattern)); - getColumnsFromDataSet(columns, columns2StorageUnit, tagFilter, dataSet); - dataSet.close(); - dataSet = sessionPool.executeQueryStatement(String.format(SHOW_TIMESERIES_DUMMY, pattern)); - getColumnsFromDataSet(columns, columns2StorageUnit, tagFilter, dataSet); - dataSet.close(); - } + Iterator iterator = patterns.iterator(); + do { + String pattern = iterator.hasNext() ? iterator.next() : null; + SessionDataSetWrapper dataSet; + LOGGER.debug("get time series: {}", pattern); + if (pattern != null) { + LOGGER.debug("do show timeseries: {}", pattern); + dataSet = sessionPool.executeQueryStatement(String.format(SHOW_TIMESERIES, pattern)); + getColumnsFromDataSet(columns, columns2StorageUnit, tagFilter, dataSet); + dataSet.close(); + + dataSet = + sessionPool.executeQueryStatement(String.format(SHOW_TIMESERIES_DUMMY, pattern)); + getColumnsFromDataSet(columns, columns2StorageUnit, tagFilter, dataSet); + dataSet.close(); + } else { + LOGGER.debug("do show all timeseries"); + dataSet = sessionPool.executeQueryStatement(SHOW_TIMESERIES_ALL); + getColumnsFromDataSet(columns, columns2StorageUnit, tagFilter, dataSet); + dataSet.close(); + } + } while (iterator.hasNext()); } catch (IoTDBConnectionException | StatementExecutionException e) { throw new IoTDBTaskExecuteFailureException("get time series failure: ", e); } diff --git a/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java b/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java index 30d373f5e8..0726e15e6d 100644 --- a/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java +++ b/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java @@ -327,7 +327,7 @@ private static long getDuplicateKey(WriteError error) { public List getColumns(Set patterns, TagFilter tagFilter) { List patternList = new ArrayList<>(patterns); if (patternList.isEmpty()) { - return Collections.emptyList(); + patternList.add("*"); } List columns = new ArrayList<>(); for (String dbName : getDatabaseNames(this.client)) { diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java index cb42fa66f7..9eacf439eb 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java @@ -328,7 +328,7 @@ public List getColumnsOfStorageUnit( String storageUnit, Set patterns, TagFilter tagFilter) throws PhysicalException { List patternList = new ArrayList<>(patterns); if (patternList.isEmpty()) { - return Collections.emptyList(); + patternList.add("*"); } if (storageUnit.equals("*")) { List columns = new ArrayList<>(); diff --git a/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java b/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java index cfe173a8a6..8dc566d43f 100644 --- a/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java +++ b/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java @@ -483,7 +483,7 @@ private void getIginxColumns(Consumer ret, Set patterns, TagFilt throws PhysicalException { List patternList = new ArrayList<>(patterns); if (patternList.isEmpty()) { - return; + patternList.add("*"); } List allPaths = determinePathList("*", patternList, tagFilter); try (Jedis jedis = getDataConnection()) { @@ -502,7 +502,7 @@ private void getIginxColumns(Consumer ret, Set patterns, TagFilt private void getDummyColumns(Consumer ret, Set patterns) { List patternList = new ArrayList<>(patterns); if (patternList.isEmpty()) { - return; + patternList.add("*"); } try (Jedis jedis = getDummyConnection()) { for (String pattern : patternList) { diff --git a/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java index 0b90202288..3e2e6eb452 100644 --- a/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java +++ b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java @@ -372,7 +372,7 @@ public List getColumns(Set patterns, TagFilter tagFilter) try { // dummy pattern list List patternList = new ArrayList<>(); - if (patterns.contains("*")) { + if (patterns == null || patterns.size() == 0) { patternList = new ArrayList<>(Collections.singletonList("*.*")); } String colPattern; @@ -389,7 +389,7 @@ public List getColumns(Set patterns, TagFilter tagFilter) && !databaseName.startsWith(DATABASE_PREFIX); if (isDummy) { // find pattern that match .* to avoid creating databases after. - if (patterns.contains("*")) { + if (patterns == null || patterns.size() == 0) { continue; } for (String p : patterns) { @@ -404,7 +404,7 @@ public List getColumns(Set patterns, TagFilter tagFilter) Map tableAndColPattern = new HashMap<>(); - if (!patterns.isEmpty()) { + if (patterns != null && patterns.size() != 0) { tableAndColPattern = splitAndMergeQueryPatterns(databaseName, new ArrayList<>(patterns)); } else { for (String table : getTables(databaseName, "%")) { diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java index 15f6bf4c1a..b7d183f88b 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java @@ -117,6 +117,9 @@ public static String reformatPath(String path) { } public static boolean pathNotMatchPatterns(String path, Set patterns) { + if (patterns.isEmpty()) { + return false; + } for (String pattern : patterns) { if (match(path, pattern)) { return false; From ddc1e6b1785236cc06ce5a4e0498de9b56971fbe Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Thu, 18 Jul 2024 20:46:46 +0800 Subject: [PATCH 083/138] open CompactIT test --- .github/workflows/standard-test-suite.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/standard-test-suite.yml b/.github/workflows/standard-test-suite.yml index e0fc21f331..d735e2e8f5 100644 --- a/.github/workflows/standard-test-suite.yml +++ b/.github/workflows/standard-test-suite.yml @@ -21,10 +21,10 @@ jobs: # uses: ./.github/workflows/case-regression.yml # with: # metadata-matrix: '["zookeeper"]' - # standalone-test: - # uses: ./.github/workflows/standalone-test.yml - # with: - # metadata-matrix: '["zookeeper"]' + standalone-test: + uses: ./.github/workflows/standalone-test.yml + with: + metadata-matrix: '["zookeeper"]' # standalone-test-pushdown: # uses: ./.github/workflows/standalone-test-pushdown.yml # with: From 148ff04b6e460eef787a3b8b4007614c17323ae0 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Thu, 18 Jul 2024 21:09:12 +0800 Subject: [PATCH 084/138] fix --- .github/workflows/standard-test-suite.yml | 1 + .../storage/execute/StoragePhysicalTaskExecutor.java | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/standard-test-suite.yml b/.github/workflows/standard-test-suite.yml index d735e2e8f5..c2bc0eff0b 100644 --- a/.github/workflows/standard-test-suite.yml +++ b/.github/workflows/standard-test-suite.yml @@ -24,6 +24,7 @@ jobs: standalone-test: uses: ./.github/workflows/standalone-test.yml with: + os-matrix: '["ubuntu-latest"]' metadata-matrix: '["zookeeper"]' # standalone-test-pushdown: # uses: ./.github/workflows/standalone-test-pushdown.yml diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java index a924784a41..795db3bd6a 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java @@ -442,7 +442,11 @@ public TaskExecuteResult executeShowColumns(ShowColumns showColumns) { private static Set cutSchemaPrefix(String schemaPrefix, Set patterns) { if (schemaPrefix == null) { - return patterns; + if (patterns.isEmpty()) { + return Collections.singleton("*"); + } else { + return patterns; + } } if (patterns.isEmpty()) { return Collections.singleton("*"); From 62fe52b6738acc5e3b810b1cc6fdfe34f11b314e Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Thu, 18 Jul 2024 22:05:25 +0800 Subject: [PATCH 085/138] add test --- .github/workflows/standard-test-suite.yml | 9 +- .../expansion/BaseCapacityExpansionIT.java | 34 +++++-- .../FileSystemCapacityExpansionIT.java | 58 +++++++++++- .../mongodb/MongoDBCapacityExpansionIT.java | 30 ++++++- .../redis/RedisCapacityExpansionIT.java | 89 +++++++++++++++++++ .../expansion/utils/SQLTestTools.java | 5 -- 6 files changed, 200 insertions(+), 25 deletions(-) diff --git a/.github/workflows/standard-test-suite.yml b/.github/workflows/standard-test-suite.yml index c2bc0eff0b..e0fc21f331 100644 --- a/.github/workflows/standard-test-suite.yml +++ b/.github/workflows/standard-test-suite.yml @@ -21,11 +21,10 @@ jobs: # uses: ./.github/workflows/case-regression.yml # with: # metadata-matrix: '["zookeeper"]' - standalone-test: - uses: ./.github/workflows/standalone-test.yml - with: - os-matrix: '["ubuntu-latest"]' - metadata-matrix: '["zookeeper"]' + # standalone-test: + # uses: ./.github/workflows/standalone-test.yml + # with: + # metadata-matrix: '["zookeeper"]' # standalone-test-pushdown: # uses: ./.github/workflows/standalone-test-pushdown.yml # with: diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java index 3a2c0fe51f..a137ed3192 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java @@ -497,8 +497,7 @@ protected void testShowColumnsInExpansion(boolean before) { + "+----+--------+\n" + "+----+--------+\n" + "Empty set.\n"; - SQLTestTools.executeAndCompare(session, statement, expected); - } else { + } else { // 添加schemaPrefix为p1,dataPrefix为nt.wf03的数据源 expected = "Columns:\n" + "+-----------------------+--------+\n" @@ -507,8 +506,31 @@ protected void testShowColumnsInExpansion(boolean before) { + "|p1.nt.wf03.wt01.status2| LONG|\n" + "+-----------------------+--------+\n" + "Total line number = 1\n"; - SQLTestTools.executeAndCompare(session, statement, expected); } + SQLTestTools.executeAndCompare(session, statement, expected); + + statement = "SHOW COLUMNS *.wf03.wt01.*;"; + if (before) { + expected = + "Columns:\n" + + "+--------------------+--------+\n" + + "| Path|DataType|\n" + + "+--------------------+--------+\n" + + "|nt.wf03.wt01.status2| LONG|\n" + + "+--------------------+--------+\n" + + "Total line number = 1\n"; + } else { // 添加schemaPrefix为p1,dataPrefix为nt.wf03的数据源 + expected = + "Columns:\n" + + "+-----------------------+--------+\n" + + "| Path|DataType|\n" + + "+-----------------------+--------+\n" + + "| nt.wf03.wt01.status2| LONG|\n" + + "|p1.nt.wf03.wt01.status2| LONG|\n" + + "+-----------------------+--------+\n" + + "Total line number = 2\n"; + } + SQLTestTools.executeAndCompare(session, statement, expected); } protected void testShowColumnsRemoveStorageEngine(boolean before) { @@ -526,7 +548,7 @@ protected void testShowColumnsRemoveStorageEngine(boolean before) { + "|p3.nt.wf04.wt01.temperature| DOUBLE|\n" + "+---------------------------+--------+\n" + "Total line number = 4\n"; - } else { + } else { // schemaPrefix为p2及p3,dataPrefix为nt.wf03的数据源被移除 expected = "Columns:\n" + "+---------------------------+--------+\n" @@ -560,7 +582,6 @@ private void testAddAndRemoveStorageEngineWithPrefix() { List pathList = Arrays.asList("nt.wf03.wt01.status2", "p1.nt.wf03.wt01.status2"); SQLTestTools.executeAndCompare(session, statement, pathList, REPEAT_EXP_VALUES_LIST1); - // 继续添加不同 schemaPrefix,相同 dataPrefix addStorageEngine(expPort, true, true, dataPrefix1, schemaPrefix2, extraParams); addStorageEngine(expPort, true, true, dataPrefix1, null, extraParams); testShowClusterInfo(5); @@ -573,13 +594,10 @@ private void testAddAndRemoveStorageEngineWithPrefix() { testShowClusterInfo(5); addStorageEngine(expPort, true, true, dataPrefix1, schemaPrefix3, extraParams); - // 这里是之后待测试的点,如果添加包含关系的,应当报错。 // res = addStorageEngine(expPort, true, true, "nt.wf03.wt01", "p3"); // 添加相同 schemaPrefix,不同 dataPrefix addStorageEngine(expPort, true, true, dataPrefix2, schemaPrefix3, extraParams); - System.out.println("==========4=========="); - SQLTestTools.executeAndPrint(session, "SHOW COLUMNS p3.*;"); testShowClusterInfo(7); // 添加节点 dataPrefix = dataPrefix1 && schemaPrefix = p1 后查询 diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java index 7036fbdc22..5ea76c67bd 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java @@ -62,8 +62,7 @@ protected void testShowColumnsInExpansion(boolean before) { + "+----+--------+\n" + "+----+--------+\n" + "Empty set.\n"; - SQLTestTools.executeAndCompare(session, statement, expected); - } else { + } else { // 添加schemaPrefix为p1,dataPrefix为nt.wf03的数据源 statement = "SHOW COLUMNS p1.*;"; expected = "Columns:\n" @@ -73,8 +72,61 @@ protected void testShowColumnsInExpansion(boolean before) { + "|p1.nt.wf03.wt01.status2| BINARY|\n" + "+-----------------------+--------+\n" + "Total line number = 1\n"; - SQLTestTools.executeAndCompare(session, statement, expected); } + SQLTestTools.executeAndCompare(session, statement, expected); + + statement = "SHOW COLUMNS *.wf03.wt01.*;"; + if (before) { + expected = + "Columns:\n" + + "+--------------------+--------+\n" + + "| Path|DataType|\n" + + "+--------------------+--------+\n" + + "|nt.wf03.wt01.status2| BINARY|\n" + + "+--------------------+--------+\n" + + "Total line number = 1\n"; + } else { // 添加schemaPrefix为p1,dataPrefix为nt.wf03的数据源 + expected = + "Columns:\n" + + "+-----------------------+--------+\n" + + "| Path|DataType|\n" + + "+-----------------------+--------+\n" + + "| nt.wf03.wt01.status2| BINARY|\n" + + "|p1.nt.wf03.wt01.status2| BINARY|\n" + + "+-----------------------+--------+\n" + + "Total line number = 2\n"; + } + SQLTestTools.executeAndCompare(session, statement, expected); + } + + @Override + protected void testShowColumnsRemoveStorageEngine(boolean before) { + String statement = "SHOW COLUMNS p1.*, p2.*, p3.*;"; + String expected; + if (before) { + expected = + "Columns:\n" + + "+---------------------------+--------+\n" + + "| Path|DataType|\n" + + "+---------------------------+--------+\n" + + "| p1.nt.wf03.wt01.status2| BINARY|\n" + + "| p2.nt.wf03.wt01.status2| BINARY|\n" + + "| p3.nt.wf03.wt01.status2| BINARY|\n" + + "|p3.nt.wf04.wt01.temperature| DOUBLE|\n" + + "+---------------------------+--------+\n" + + "Total line number = 4\n"; + } else { // 移除schemaPrefix为p2及p3,dataPrefix为nt.wf03的数据源 + expected = + "Columns:\n" + + "+---------------------------+--------+\n" + + "| Path|DataType|\n" + + "+---------------------------+--------+\n" + + "| p1.nt.wf03.wt01.status2| BINARY|\n" + + "|p3.nt.wf04.wt01.temperature| DOUBLE|\n" + + "+---------------------------+--------+\n" + + "Total line number = 2\n"; + } + SQLTestTools.executeAndCompare(session, statement, expected); } @Override diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java index 0bb6948ace..9fdf65a17d 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java @@ -64,8 +64,7 @@ protected void testShowColumnsInExpansion(boolean before) { + "+----+--------+\n" + "+----+--------+\n" + "Empty set.\n"; - SQLTestTools.executeAndCompare(session, statement, expected); - } else { + } else { // 添加schemaPrefix为p1,dataPrefix为nt.wf03的数据源 statement = "SHOW COLUMNS p1.*;"; expected = "Columns:\n" @@ -76,8 +75,31 @@ protected void testShowColumnsInExpansion(boolean before) { + "|p1.nt.wf03.wt01.status2| LONG|\n" + "+-----------------------+--------+\n" + "Total line number = 2\n"; - SQLTestTools.executeAndCompare(session, statement, expected); } + SQLTestTools.executeAndCompare(session, statement, expected); + + statement = "SHOW COLUMNS *.wf03.wt01.*;"; + if (before) { + expected = + "Columns:\n" + + "+--------------------+--------+\n" + + "| Path|DataType|\n" + + "+--------------------+--------+\n" + + "|nt.wf03.wt01.status2| LONG|\n" + + "+--------------------+--------+\n" + + "Total line number = 1\n"; + } else { // 添加schemaPrefix为p1,dataPrefix为nt.wf03的数据源 + expected = + "Columns:\n" + + "+-----------------------+--------+\n" + + "| Path|DataType|\n" + + "+-----------------------+--------+\n" + + "| nt.wf03.wt01.status2| LONG|\n" + + "|p1.nt.wf03.wt01.status2| LONG|\n" + + "+-----------------------+--------+\n" + + "Total line number = 2\n"; + } + SQLTestTools.executeAndCompare(session, statement, expected); } @Override @@ -100,7 +122,7 @@ protected void testShowColumnsRemoveStorageEngine(boolean before) { + "|p3.nt.wf04.wt01.temperature| DOUBLE|\n" + "+---------------------------+--------+\n" + "Total line number = 8\n"; - } else { + } else { // 移除schemaPrefix为p2及p3,dataPrefix为nt.wf03的数据源 expected = "Columns:\n" + "+---------------------------+--------+\n" diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisCapacityExpansionIT.java index 8a9502c46f..7166e030d7 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisCapacityExpansionIT.java @@ -57,6 +57,95 @@ protected void testQuerySpecialHistoryData() { SQLTestTools.executeAndCompare(session, statement, expect); } + @Override + protected void testShowColumnsInExpansion(boolean before) { + String statement = "SHOW COLUMNS nt.wf03.*;"; + String expected = + "Columns:\n" + + "+--------------------+--------+\n" + + "| Path|DataType|\n" + + "+--------------------+--------+\n" + + "|nt.wf03.wt01.status2| BINARY|\n" + + "+--------------------+--------+\n" + + "Total line number = 1\n"; + SQLTestTools.executeAndCompare(session, statement, expected); + + if (before) { + statement = "SHOW COLUMNS p1.*;"; + expected = + "Columns:\n" + + "+----+--------+\n" + + "|Path|DataType|\n" + + "+----+--------+\n" + + "+----+--------+\n" + + "Empty set.\n"; + } else { // 添加schemaPrefix为p1,dataPrefix为nt.wf03的数据源 + statement = "SHOW COLUMNS p1.*;"; + expected = + "Columns:\n" + + "+-----------------------+--------+\n" + + "| Path|DataType|\n" + + "+-----------------------+--------+\n" + + "|p1.nt.wf03.wt01.status2| BINARY|\n" + + "+-----------------------+--------+\n" + + "Total line number = 1\n"; + } + SQLTestTools.executeAndCompare(session, statement, expected); + + statement = "SHOW COLUMNS *.wf03.wt01.*;"; + if (before) { + expected = + "Columns:\n" + + "+--------------------+--------+\n" + + "| Path|DataType|\n" + + "+--------------------+--------+\n" + + "|nt.wf03.wt01.status2| BINARY|\n" + + "+--------------------+--------+\n" + + "Total line number = 1\n"; + } else { // 添加schemaPrefix为p1,dataPrefix为nt.wf03的数据源 + expected = + "Columns:\n" + + "+-----------------------+--------+\n" + + "| Path|DataType|\n" + + "+-----------------------+--------+\n" + + "| nt.wf03.wt01.status2| BINARY|\n" + + "|p1.nt.wf03.wt01.status2| BINARY|\n" + + "+-----------------------+--------+\n" + + "Total line number = 2\n"; + } + SQLTestTools.executeAndCompare(session, statement, expected); + } + + @Override + protected void testShowColumnsRemoveStorageEngine(boolean before) { + String statement = "SHOW COLUMNS p1.*, p2.*, p3.*;"; + String expected; + if (before) { + expected = + "Columns:\n" + + "+---------------------------+--------+\n" + + "| Path|DataType|\n" + + "+---------------------------+--------+\n" + + "| p1.nt.wf03.wt01.status2| BINARY|\n" + + "| p2.nt.wf03.wt01.status2| BINARY|\n" + + "| p3.nt.wf03.wt01.status2| BINARY|\n" + + "|p3.nt.wf04.wt01.temperature| DOUBLE|\n" + + "+---------------------------+--------+\n" + + "Total line number = 4\n"; + } else { // 移除schemaPrefix为p2及p3,dataPrefix为nt.wf03的数据源 + expected = + "Columns:\n" + + "+---------------------------+--------+\n" + + "| Path|DataType|\n" + + "+---------------------------+--------+\n" + + "| p1.nt.wf03.wt01.status2| BINARY|\n" + + "|p3.nt.wf04.wt01.temperature| DOUBLE|\n" + + "+---------------------------+--------+\n" + + "Total line number = 2\n"; + } + SQLTestTools.executeAndCompare(session, statement, expected); + } + // redis中,所有dummy数据都识别为BINARY @Override public void testShowColumns() { diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/utils/SQLTestTools.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/utils/SQLTestTools.java index 1df5e79557..c421de3683 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/utils/SQLTestTools.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/utils/SQLTestTools.java @@ -42,11 +42,6 @@ public static void executeAndCompare(Session session, String statement, String e assertEquals(exceptOutput, actualOutput); } - public static void executeAndPrint(Session session, String statement) { - String actualOutput = execute(session, statement); - System.out.println(actualOutput); - } - private static String execute(Session session, String statement) { LOGGER.info("Execute Statement: \"{}\"", statement); From 57b96ac7a0bbe44f0ea045babd854fefeaa5bf74 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Thu, 18 Jul 2024 22:38:29 +0800 Subject: [PATCH 086/138] fix test --- .../filesystem/FileSystemCapacityExpansionIT.java | 7 +++++-- .../expansion/redis/RedisCapacityExpansionIT.java | 6 ++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java index 5ea76c67bd..291e526d6a 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java @@ -40,6 +40,7 @@ protected void testInvalidDummyParams( LOGGER.info("filesystem skips test for wrong dummy engine params."); } + // filesystem中,所有dummy数据都识别为BINARY @Override protected void testShowColumnsInExpansion(boolean before) { String statement = "SHOW COLUMNS nt.wf03.*;"; @@ -99,6 +100,7 @@ protected void testShowColumnsInExpansion(boolean before) { SQLTestTools.executeAndCompare(session, statement, expected); } + // filesystem中,所有dummy数据都识别为BINARY @Override protected void testShowColumnsRemoveStorageEngine(boolean before) { String statement = "SHOW COLUMNS p1.*, p2.*, p3.*;"; @@ -112,7 +114,7 @@ protected void testShowColumnsRemoveStorageEngine(boolean before) { + "| p1.nt.wf03.wt01.status2| BINARY|\n" + "| p2.nt.wf03.wt01.status2| BINARY|\n" + "| p3.nt.wf03.wt01.status2| BINARY|\n" - + "|p3.nt.wf04.wt01.temperature| DOUBLE|\n" + + "|p3.nt.wf04.wt01.temperature| BINARY|\n" + "+---------------------------+--------+\n" + "Total line number = 4\n"; } else { // 移除schemaPrefix为p2及p3,dataPrefix为nt.wf03的数据源 @@ -122,13 +124,14 @@ protected void testShowColumnsRemoveStorageEngine(boolean before) { + "| Path|DataType|\n" + "+---------------------------+--------+\n" + "| p1.nt.wf03.wt01.status2| BINARY|\n" - + "|p3.nt.wf04.wt01.temperature| DOUBLE|\n" + + "|p3.nt.wf04.wt01.temperature| BINARY|\n" + "+---------------------------+--------+\n" + "Total line number = 2\n"; } SQLTestTools.executeAndCompare(session, statement, expected); } + // filesystem中,所有dummy数据都识别为BINARY @Override public void testShowColumns() { String statement = "SHOW COLUMNS mn.*;"; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisCapacityExpansionIT.java index 7166e030d7..11733ce81e 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisCapacityExpansionIT.java @@ -57,6 +57,7 @@ protected void testQuerySpecialHistoryData() { SQLTestTools.executeAndCompare(session, statement, expect); } + // redis中,所有dummy数据都识别为BINARY @Override protected void testShowColumnsInExpansion(boolean before) { String statement = "SHOW COLUMNS nt.wf03.*;"; @@ -116,6 +117,7 @@ protected void testShowColumnsInExpansion(boolean before) { SQLTestTools.executeAndCompare(session, statement, expected); } + // redis中,所有dummy数据都识别为BINARY @Override protected void testShowColumnsRemoveStorageEngine(boolean before) { String statement = "SHOW COLUMNS p1.*, p2.*, p3.*;"; @@ -129,7 +131,7 @@ protected void testShowColumnsRemoveStorageEngine(boolean before) { + "| p1.nt.wf03.wt01.status2| BINARY|\n" + "| p2.nt.wf03.wt01.status2| BINARY|\n" + "| p3.nt.wf03.wt01.status2| BINARY|\n" - + "|p3.nt.wf04.wt01.temperature| DOUBLE|\n" + + "|p3.nt.wf04.wt01.temperature| BINARY|\n" + "+---------------------------+--------+\n" + "Total line number = 4\n"; } else { // 移除schemaPrefix为p2及p3,dataPrefix为nt.wf03的数据源 @@ -139,7 +141,7 @@ protected void testShowColumnsRemoveStorageEngine(boolean before) { + "| Path|DataType|\n" + "+---------------------------+--------+\n" + "| p1.nt.wf03.wt01.status2| BINARY|\n" - + "|p3.nt.wf04.wt01.temperature| DOUBLE|\n" + + "|p3.nt.wf04.wt01.temperature| BINARY|\n" + "+---------------------------+--------+\n" + "Total line number = 2\n"; } From 042f7dc293c438f14150303383aa5bb50deffe36 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Thu, 18 Jul 2024 22:40:25 +0800 Subject: [PATCH 087/138] adjust getColumns --- .../execute/StoragePhysicalTaskExecutor.java | 22 +++++----- .../iginx/influxdb/InfluxDBStorage.java | 7 ++-- .../tsinghua/iginx/iotdb/IoTDBStorage.java | 42 +++++++++---------- .../iginx/mongodb/MongoDBStorage.java | 2 +- .../iginx/parquet/exec/LocalExecutor.java | 2 +- .../tsinghua/iginx/redis/RedisStorage.java | 4 +- .../iginx/relational/RelationalStorage.java | 6 +-- .../edu/tsinghua/iginx/utils/StringUtils.java | 3 -- 8 files changed, 40 insertions(+), 48 deletions(-) diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java index 795db3bd6a..b67c821d08 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java @@ -382,9 +382,6 @@ public TaskExecuteResult executeShowColumns(ShowColumns showColumns) { if (patternsCutSchemaPrefix.isEmpty()) { continue; } - if (patternsCutSchemaPrefix.contains("*")) { - patternsCutSchemaPrefix = Collections.emptySet(); - } List columnList = pair.k.getColumns(patternsCutSchemaPrefix, tagFilter); if (tagFilter != null) { @@ -441,16 +438,14 @@ public TaskExecuteResult executeShowColumns(ShowColumns showColumns) { } private static Set cutSchemaPrefix(String schemaPrefix, Set patterns) { - if (schemaPrefix == null) { - if (patterns.isEmpty()) { - return Collections.singleton("*"); - } else { - return patterns; - } - } + // show columns的patterns为空,查询所有列 if (patterns.isEmpty()) { return Collections.singleton("*"); } + // 该数据源没有schema prefix,直接匹配patterns + if (schemaPrefix == null) { + return patterns; + } Set patternsCutSchemaPrefix = new HashSet<>(); for (String pattern : patterns) { @@ -468,32 +463,35 @@ private static Set cutSchemaPrefix(String schemaPrefix, String pattern) String[] patternSplit = pattern.split("\\."); int minLen = Math.min(prefixSplit.length, patternSplit.length); int index = 0; + // 逐级匹配pattern和schemaPrefix while (index < minLen && prefixSplit[index].equals(patternSplit[index])) { index++; } + // pattern匹配结束,schemaPrefix还有剩余,则该storageEngine下没有该pattern if (index == patternSplit.length) { return Collections.emptySet(); } + // schemaPrefix匹配结束,pattern还有剩余,则把该pattern减去前缀schemaPrefix if (index == prefixSplit.length) { return Collections.singleton(joinWithDot(patternSplit, index)); } + // pattern和schemaPrefix不匹配 if (!patternSplit[index].equals("*")) { return Collections.emptySet(); } Set target = new HashSet<>(); - // 将pattern的'*'视为部分匹配该前缀,即把'*'下推到数据源 target.add(joinWithDot(patternSplit, index)); - if (index + 1 < patternSplit.length) { // 将pattern的'*'视为完全匹配该前缀,即不把'*'下推到数据源 String patternRemain = joinWithDot(patternSplit, index + 1); target.add(patternRemain); + // 将schemaPrefix的每一级分别匹配'*' for (int i = index + 1; i < prefixSplit.length; i++) { String prefixRemain = joinWithDot(prefixSplit, i); target.addAll(cutSchemaPrefix(prefixRemain, patternRemain)); diff --git a/dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java b/dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java index 5d2a6f4d06..22f374f743 100644 --- a/dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java +++ b/dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java @@ -272,10 +272,9 @@ public List getColumns(Set patterns, TagFilter tagFilter) { // List> patternPairs = new ArrayList<>(); - if (patterns == null - || patterns.size() == 0 - || patterns.contains("*") - || patterns.contains("*.*")) { + if (patterns == null || patterns.isEmpty()) { + tables = Collections.emptyList(); + } else if (patterns.contains("*") || patterns.contains("*.*")) { statement = String.format(SHOW_TIME_SERIES, bucket.getName()); tables = client.getQueryApi().query(statement, organization.getId()); } else { diff --git a/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java b/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java index 0215cb19b5..084a52a986 100644 --- a/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java +++ b/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java @@ -282,28 +282,26 @@ private void getColumns2StorageUnit( TagFilter tagFilter) throws PhysicalException { try { - Iterator iterator = patterns.iterator(); - do { - String pattern = iterator.hasNext() ? iterator.next() : null; - SessionDataSetWrapper dataSet; - LOGGER.debug("get time series: {}", pattern); - if (pattern != null) { - LOGGER.debug("do show timeseries: {}", pattern); - dataSet = sessionPool.executeQueryStatement(String.format(SHOW_TIMESERIES, pattern)); - getColumnsFromDataSet(columns, columns2StorageUnit, tagFilter, dataSet); - dataSet.close(); - - dataSet = - sessionPool.executeQueryStatement(String.format(SHOW_TIMESERIES_DUMMY, pattern)); - getColumnsFromDataSet(columns, columns2StorageUnit, tagFilter, dataSet); - dataSet.close(); - } else { - LOGGER.debug("do show all timeseries"); - dataSet = sessionPool.executeQueryStatement(SHOW_TIMESERIES_ALL); - getColumnsFromDataSet(columns, columns2StorageUnit, tagFilter, dataSet); - dataSet.close(); - } - } while (iterator.hasNext()); + if (patterns.isEmpty()) { + return; + } + SessionDataSetWrapper dataSet; + if (patterns.contains("*")) { + LOGGER.debug("do show all timeseries"); + dataSet = sessionPool.executeQueryStatement(SHOW_TIMESERIES_ALL); + getColumnsFromDataSet(columns, columns2StorageUnit, tagFilter, dataSet); + dataSet.close(); + return; + } + for (String pattern : patterns) { + LOGGER.debug("do show timeseries: {}", pattern); + dataSet = sessionPool.executeQueryStatement(String.format(SHOW_TIMESERIES, pattern)); + getColumnsFromDataSet(columns, columns2StorageUnit, tagFilter, dataSet); + dataSet.close(); + dataSet = sessionPool.executeQueryStatement(String.format(SHOW_TIMESERIES_DUMMY, pattern)); + getColumnsFromDataSet(columns, columns2StorageUnit, tagFilter, dataSet); + dataSet.close(); + } } catch (IoTDBConnectionException | StatementExecutionException e) { throw new IoTDBTaskExecuteFailureException("get time series failure: ", e); } diff --git a/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java b/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java index 0726e15e6d..30d373f5e8 100644 --- a/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java +++ b/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java @@ -327,7 +327,7 @@ private static long getDuplicateKey(WriteError error) { public List getColumns(Set patterns, TagFilter tagFilter) { List patternList = new ArrayList<>(patterns); if (patternList.isEmpty()) { - patternList.add("*"); + return Collections.emptyList(); } List columns = new ArrayList<>(); for (String dbName : getDatabaseNames(this.client)) { diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java index 9eacf439eb..cb42fa66f7 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java @@ -328,7 +328,7 @@ public List getColumnsOfStorageUnit( String storageUnit, Set patterns, TagFilter tagFilter) throws PhysicalException { List patternList = new ArrayList<>(patterns); if (patternList.isEmpty()) { - patternList.add("*"); + return Collections.emptyList(); } if (storageUnit.equals("*")) { List columns = new ArrayList<>(); diff --git a/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java b/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java index 8dc566d43f..cfe173a8a6 100644 --- a/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java +++ b/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java @@ -483,7 +483,7 @@ private void getIginxColumns(Consumer ret, Set patterns, TagFilt throws PhysicalException { List patternList = new ArrayList<>(patterns); if (patternList.isEmpty()) { - patternList.add("*"); + return; } List allPaths = determinePathList("*", patternList, tagFilter); try (Jedis jedis = getDataConnection()) { @@ -502,7 +502,7 @@ private void getIginxColumns(Consumer ret, Set patterns, TagFilt private void getDummyColumns(Consumer ret, Set patterns) { List patternList = new ArrayList<>(patterns); if (patternList.isEmpty()) { - patternList.add("*"); + return; } try (Jedis jedis = getDummyConnection()) { for (String pattern : patternList) { diff --git a/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java index 3e2e6eb452..0b90202288 100644 --- a/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java +++ b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java @@ -372,7 +372,7 @@ public List getColumns(Set patterns, TagFilter tagFilter) try { // dummy pattern list List patternList = new ArrayList<>(); - if (patterns == null || patterns.size() == 0) { + if (patterns.contains("*")) { patternList = new ArrayList<>(Collections.singletonList("*.*")); } String colPattern; @@ -389,7 +389,7 @@ public List getColumns(Set patterns, TagFilter tagFilter) && !databaseName.startsWith(DATABASE_PREFIX); if (isDummy) { // find pattern that match .* to avoid creating databases after. - if (patterns == null || patterns.size() == 0) { + if (patterns.contains("*")) { continue; } for (String p : patterns) { @@ -404,7 +404,7 @@ public List getColumns(Set patterns, TagFilter tagFilter) Map tableAndColPattern = new HashMap<>(); - if (patterns != null && patterns.size() != 0) { + if (!patterns.isEmpty()) { tableAndColPattern = splitAndMergeQueryPatterns(databaseName, new ArrayList<>(patterns)); } else { for (String table : getTables(databaseName, "%")) { diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java index b7d183f88b..15f6bf4c1a 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java @@ -117,9 +117,6 @@ public static String reformatPath(String path) { } public static boolean pathNotMatchPatterns(String path, Set patterns) { - if (patterns.isEmpty()) { - return false; - } for (String pattern : patterns) { if (match(path, pattern)) { return false; From 3b712a2e86faf0ee35b61fe67a42af3e8a2c6a35 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Thu, 18 Jul 2024 23:22:45 +0800 Subject: [PATCH 088/138] Revert "adjust getColumns" This reverts commit 042f7dc293c438f14150303383aa5bb50deffe36. --- .../execute/StoragePhysicalTaskExecutor.java | 22 +++++----- .../iginx/influxdb/InfluxDBStorage.java | 7 ++-- .../tsinghua/iginx/iotdb/IoTDBStorage.java | 42 ++++++++++--------- .../iginx/mongodb/MongoDBStorage.java | 2 +- .../iginx/parquet/exec/LocalExecutor.java | 2 +- .../tsinghua/iginx/redis/RedisStorage.java | 4 +- .../iginx/relational/RelationalStorage.java | 6 +-- .../edu/tsinghua/iginx/utils/StringUtils.java | 3 ++ 8 files changed, 48 insertions(+), 40 deletions(-) diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java index b67c821d08..795db3bd6a 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java @@ -382,6 +382,9 @@ public TaskExecuteResult executeShowColumns(ShowColumns showColumns) { if (patternsCutSchemaPrefix.isEmpty()) { continue; } + if (patternsCutSchemaPrefix.contains("*")) { + patternsCutSchemaPrefix = Collections.emptySet(); + } List columnList = pair.k.getColumns(patternsCutSchemaPrefix, tagFilter); if (tagFilter != null) { @@ -438,14 +441,16 @@ public TaskExecuteResult executeShowColumns(ShowColumns showColumns) { } private static Set cutSchemaPrefix(String schemaPrefix, Set patterns) { - // show columns的patterns为空,查询所有列 + if (schemaPrefix == null) { + if (patterns.isEmpty()) { + return Collections.singleton("*"); + } else { + return patterns; + } + } if (patterns.isEmpty()) { return Collections.singleton("*"); } - // 该数据源没有schema prefix,直接匹配patterns - if (schemaPrefix == null) { - return patterns; - } Set patternsCutSchemaPrefix = new HashSet<>(); for (String pattern : patterns) { @@ -463,35 +468,32 @@ private static Set cutSchemaPrefix(String schemaPrefix, String pattern) String[] patternSplit = pattern.split("\\."); int minLen = Math.min(prefixSplit.length, patternSplit.length); int index = 0; - // 逐级匹配pattern和schemaPrefix while (index < minLen && prefixSplit[index].equals(patternSplit[index])) { index++; } - // pattern匹配结束,schemaPrefix还有剩余,则该storageEngine下没有该pattern if (index == patternSplit.length) { return Collections.emptySet(); } - // schemaPrefix匹配结束,pattern还有剩余,则把该pattern减去前缀schemaPrefix if (index == prefixSplit.length) { return Collections.singleton(joinWithDot(patternSplit, index)); } - // pattern和schemaPrefix不匹配 if (!patternSplit[index].equals("*")) { return Collections.emptySet(); } Set target = new HashSet<>(); + // 将pattern的'*'视为部分匹配该前缀,即把'*'下推到数据源 target.add(joinWithDot(patternSplit, index)); + if (index + 1 < patternSplit.length) { // 将pattern的'*'视为完全匹配该前缀,即不把'*'下推到数据源 String patternRemain = joinWithDot(patternSplit, index + 1); target.add(patternRemain); - // 将schemaPrefix的每一级分别匹配'*' for (int i = index + 1; i < prefixSplit.length; i++) { String prefixRemain = joinWithDot(prefixSplit, i); target.addAll(cutSchemaPrefix(prefixRemain, patternRemain)); diff --git a/dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java b/dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java index 22f374f743..5d2a6f4d06 100644 --- a/dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java +++ b/dataSource/influxdb/src/main/java/cn/edu/tsinghua/iginx/influxdb/InfluxDBStorage.java @@ -272,9 +272,10 @@ public List getColumns(Set patterns, TagFilter tagFilter) { // List> patternPairs = new ArrayList<>(); - if (patterns == null || patterns.isEmpty()) { - tables = Collections.emptyList(); - } else if (patterns.contains("*") || patterns.contains("*.*")) { + if (patterns == null + || patterns.size() == 0 + || patterns.contains("*") + || patterns.contains("*.*")) { statement = String.format(SHOW_TIME_SERIES, bucket.getName()); tables = client.getQueryApi().query(statement, organization.getId()); } else { diff --git a/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java b/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java index 084a52a986..0215cb19b5 100644 --- a/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java +++ b/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java @@ -282,26 +282,28 @@ private void getColumns2StorageUnit( TagFilter tagFilter) throws PhysicalException { try { - if (patterns.isEmpty()) { - return; - } - SessionDataSetWrapper dataSet; - if (patterns.contains("*")) { - LOGGER.debug("do show all timeseries"); - dataSet = sessionPool.executeQueryStatement(SHOW_TIMESERIES_ALL); - getColumnsFromDataSet(columns, columns2StorageUnit, tagFilter, dataSet); - dataSet.close(); - return; - } - for (String pattern : patterns) { - LOGGER.debug("do show timeseries: {}", pattern); - dataSet = sessionPool.executeQueryStatement(String.format(SHOW_TIMESERIES, pattern)); - getColumnsFromDataSet(columns, columns2StorageUnit, tagFilter, dataSet); - dataSet.close(); - dataSet = sessionPool.executeQueryStatement(String.format(SHOW_TIMESERIES_DUMMY, pattern)); - getColumnsFromDataSet(columns, columns2StorageUnit, tagFilter, dataSet); - dataSet.close(); - } + Iterator iterator = patterns.iterator(); + do { + String pattern = iterator.hasNext() ? iterator.next() : null; + SessionDataSetWrapper dataSet; + LOGGER.debug("get time series: {}", pattern); + if (pattern != null) { + LOGGER.debug("do show timeseries: {}", pattern); + dataSet = sessionPool.executeQueryStatement(String.format(SHOW_TIMESERIES, pattern)); + getColumnsFromDataSet(columns, columns2StorageUnit, tagFilter, dataSet); + dataSet.close(); + + dataSet = + sessionPool.executeQueryStatement(String.format(SHOW_TIMESERIES_DUMMY, pattern)); + getColumnsFromDataSet(columns, columns2StorageUnit, tagFilter, dataSet); + dataSet.close(); + } else { + LOGGER.debug("do show all timeseries"); + dataSet = sessionPool.executeQueryStatement(SHOW_TIMESERIES_ALL); + getColumnsFromDataSet(columns, columns2StorageUnit, tagFilter, dataSet); + dataSet.close(); + } + } while (iterator.hasNext()); } catch (IoTDBConnectionException | StatementExecutionException e) { throw new IoTDBTaskExecuteFailureException("get time series failure: ", e); } diff --git a/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java b/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java index 30d373f5e8..0726e15e6d 100644 --- a/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java +++ b/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java @@ -327,7 +327,7 @@ private static long getDuplicateKey(WriteError error) { public List getColumns(Set patterns, TagFilter tagFilter) { List patternList = new ArrayList<>(patterns); if (patternList.isEmpty()) { - return Collections.emptyList(); + patternList.add("*"); } List columns = new ArrayList<>(); for (String dbName : getDatabaseNames(this.client)) { diff --git a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java index cb42fa66f7..9eacf439eb 100644 --- a/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java +++ b/dataSource/parquet/src/main/java/cn/edu/tsinghua/iginx/parquet/exec/LocalExecutor.java @@ -328,7 +328,7 @@ public List getColumnsOfStorageUnit( String storageUnit, Set patterns, TagFilter tagFilter) throws PhysicalException { List patternList = new ArrayList<>(patterns); if (patternList.isEmpty()) { - return Collections.emptyList(); + patternList.add("*"); } if (storageUnit.equals("*")) { List columns = new ArrayList<>(); diff --git a/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java b/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java index cfe173a8a6..8dc566d43f 100644 --- a/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java +++ b/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java @@ -483,7 +483,7 @@ private void getIginxColumns(Consumer ret, Set patterns, TagFilt throws PhysicalException { List patternList = new ArrayList<>(patterns); if (patternList.isEmpty()) { - return; + patternList.add("*"); } List allPaths = determinePathList("*", patternList, tagFilter); try (Jedis jedis = getDataConnection()) { @@ -502,7 +502,7 @@ private void getIginxColumns(Consumer ret, Set patterns, TagFilt private void getDummyColumns(Consumer ret, Set patterns) { List patternList = new ArrayList<>(patterns); if (patternList.isEmpty()) { - return; + patternList.add("*"); } try (Jedis jedis = getDummyConnection()) { for (String pattern : patternList) { diff --git a/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java index 0b90202288..3e2e6eb452 100644 --- a/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java +++ b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java @@ -372,7 +372,7 @@ public List getColumns(Set patterns, TagFilter tagFilter) try { // dummy pattern list List patternList = new ArrayList<>(); - if (patterns.contains("*")) { + if (patterns == null || patterns.size() == 0) { patternList = new ArrayList<>(Collections.singletonList("*.*")); } String colPattern; @@ -389,7 +389,7 @@ public List getColumns(Set patterns, TagFilter tagFilter) && !databaseName.startsWith(DATABASE_PREFIX); if (isDummy) { // find pattern that match .* to avoid creating databases after. - if (patterns.contains("*")) { + if (patterns == null || patterns.size() == 0) { continue; } for (String p : patterns) { @@ -404,7 +404,7 @@ public List getColumns(Set patterns, TagFilter tagFilter) Map tableAndColPattern = new HashMap<>(); - if (!patterns.isEmpty()) { + if (patterns != null && patterns.size() != 0) { tableAndColPattern = splitAndMergeQueryPatterns(databaseName, new ArrayList<>(patterns)); } else { for (String table : getTables(databaseName, "%")) { diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java index 15f6bf4c1a..b7d183f88b 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java @@ -117,6 +117,9 @@ public static String reformatPath(String path) { } public static boolean pathNotMatchPatterns(String path, Set patterns) { + if (patterns.isEmpty()) { + return false; + } for (String pattern : patterns) { if (match(path, pattern)) { return false; From 7c399b917114ac5c9b3fa5acd340e1de0993ca5f Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Thu, 18 Jul 2024 23:24:58 +0800 Subject: [PATCH 089/138] add unit test --- .../execute/StoragePhysicalTaskExecutor.java | 77 +----------------- .../tsinghua/iginx/iotdb/IoTDBStorage.java | 3 +- .../edu/tsinghua/iginx/utils/StringUtils.java | 78 +++++++++++++++++++ .../tsinghua/iginx/utils/StringUtilsTest.java | 24 ++++++ 4 files changed, 104 insertions(+), 78 deletions(-) diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java index 795db3bd6a..b191483a6c 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java @@ -378,7 +378,7 @@ public TaskExecuteResult executeShowColumns(ShowColumns showColumns) { : StringUtils.reformatPath(storage.getDataPrefix() + ".*"); // schemaPrefix是在IGinX中定义的,数据源的路径中没有该前缀,因此需要剪掉前缀是schemaPrefix的部分 - Set patternsCutSchemaPrefix = cutSchemaPrefix(schemaPrefix, patterns); + Set patternsCutSchemaPrefix = StringUtils.cutSchemaPrefix(schemaPrefix, patterns); if (patternsCutSchemaPrefix.isEmpty()) { continue; } @@ -440,81 +440,6 @@ public TaskExecuteResult executeShowColumns(ShowColumns showColumns) { } } - private static Set cutSchemaPrefix(String schemaPrefix, Set patterns) { - if (schemaPrefix == null) { - if (patterns.isEmpty()) { - return Collections.singleton("*"); - } else { - return patterns; - } - } - if (patterns.isEmpty()) { - return Collections.singleton("*"); - } - - Set patternsCutSchemaPrefix = new HashSet<>(); - for (String pattern : patterns) { - Set tmp = cutSchemaPrefix(schemaPrefix, pattern); - if (tmp.contains("*")) { - return Collections.singleton("*"); - } - patternsCutSchemaPrefix.addAll(tmp); - } - return patternsCutSchemaPrefix; - } - - private static Set cutSchemaPrefix(String schemaPrefix, String pattern) { - String[] prefixSplit = schemaPrefix.split("\\."); - String[] patternSplit = pattern.split("\\."); - int minLen = Math.min(prefixSplit.length, patternSplit.length); - int index = 0; - while (index < minLen && prefixSplit[index].equals(patternSplit[index])) { - index++; - } - - if (index == patternSplit.length) { - return Collections.emptySet(); - } - - if (index == prefixSplit.length) { - return Collections.singleton(joinWithDot(patternSplit, index)); - } - - if (!patternSplit[index].equals("*")) { - return Collections.emptySet(); - } - - Set target = new HashSet<>(); - - // 将pattern的'*'视为部分匹配该前缀,即把'*'下推到数据源 - target.add(joinWithDot(patternSplit, index)); - - if (index + 1 < patternSplit.length) { - // 将pattern的'*'视为完全匹配该前缀,即不把'*'下推到数据源 - String patternRemain = joinWithDot(patternSplit, index + 1); - target.add(patternRemain); - - for (int i = index + 1; i < prefixSplit.length; i++) { - String prefixRemain = joinWithDot(prefixSplit, i); - target.addAll(cutSchemaPrefix(prefixRemain, patternRemain)); - } - } - - return target; - } - - private static String joinWithDot(String[] strings, int begin) { - if (begin >= strings.length) { - return ""; - } - StringBuilder sb = new StringBuilder(); - for (int i = begin; i < strings.length; i++) { - sb.append(strings[i]).append("."); - } - sb.setLength(sb.length() - 1); - return sb.toString(); - } - public void commit(List tasks) { for (StoragePhysicalTask task : tasks) { if (replicaDispatcher == null) { diff --git a/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java b/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java index 0215cb19b5..22d54185ec 100644 --- a/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java +++ b/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java @@ -64,7 +64,6 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -918,7 +917,7 @@ private String getFilterString(Filter filter, String storageUnit) throws Physica if (filterStr.contains("*")) { List columns = new ArrayList<>(); Map columns2Fragment = new HashMap<>(); - getColumns2StorageUnit(columns, columns2Fragment, new HashSet<>(), null); + getColumns2StorageUnit(columns, columns2Fragment, Collections.singleton("*"), null); filterStr = FilterTransformer.toString( expandFilterWildcard(filter.copy(), columns, columns2Fragment, storageUnit)); diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java index b7d183f88b..228d095f7b 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java @@ -22,6 +22,8 @@ import java.time.DateTimeException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Set; @@ -200,4 +202,80 @@ public static Long tryParse2Key(String value) { } return res; } + + public static Set cutSchemaPrefix(String schemaPrefix, Set patterns) { + // show columns的patterns为空,查询所有列 + if (patterns.isEmpty()) { + return Collections.singleton("*"); + } + // 该数据源没有schema prefix,直接匹配patterns + if (schemaPrefix == null || schemaPrefix.isEmpty()) { + return patterns; + } + + Set patternsCutSchemaPrefix = new HashSet<>(); + for (String pattern : patterns) { + Set tmp = cutSchemaPrefix(schemaPrefix, pattern); + if (tmp.contains("*")) { + return Collections.singleton("*"); + } + patternsCutSchemaPrefix.addAll(tmp); + } + return patternsCutSchemaPrefix; + } + + private static Set cutSchemaPrefix(String schemaPrefix, String pattern) { + String[] prefixSplit = schemaPrefix.split("\\."); + String[] patternSplit = pattern.split("\\."); + int minLen = Math.min(prefixSplit.length, patternSplit.length); + int index = 0; + // 逐级匹配pattern和schemaPrefix + while (index < minLen && prefixSplit[index].equals(patternSplit[index])) { + index++; + } + + // pattern匹配结束,schemaPrefix还有剩余,则该storageEngine下没有该pattern + if (index == patternSplit.length) { + return Collections.emptySet(); + } + + // schemaPrefix匹配结束,pattern还有剩余,则把该pattern减去前缀schemaPrefix + if (index == prefixSplit.length) { + return Collections.singleton(joinWithDot(patternSplit, index)); + } + + // pattern和schemaPrefix不匹配 + if (!patternSplit[index].equals("*")) { + return Collections.emptySet(); + } + + Set target = new HashSet<>(); + // 将pattern的'*'视为部分匹配该前缀,即把'*'下推到数据源 + target.add(joinWithDot(patternSplit, index)); + if (index + 1 < patternSplit.length) { + // 将pattern的'*'视为完全匹配该前缀,即不把'*'下推到数据源 + String patternRemain = joinWithDot(patternSplit, index + 1); + target.add(patternRemain); + + // 将schemaPrefix的每一级分别匹配'*' + for (int i = index + 1; i < prefixSplit.length; i++) { + String prefixRemain = joinWithDot(prefixSplit, i); + target.addAll(cutSchemaPrefix(prefixRemain, patternRemain)); + } + } + + return target; + } + + private static String joinWithDot(String[] strings, int begin) { + if (begin >= strings.length) { + return ""; + } + StringBuilder sb = new StringBuilder(); + for (int i = begin; i < strings.length; i++) { + sb.append(strings[i]).append("."); + } + sb.setLength(sb.length() - 1); + return sb.toString(); + } } diff --git a/shared/src/test/java/cn/edu/tsinghua/iginx/utils/StringUtilsTest.java b/shared/src/test/java/cn/edu/tsinghua/iginx/utils/StringUtilsTest.java index ab7e707ae6..6202d31422 100644 --- a/shared/src/test/java/cn/edu/tsinghua/iginx/utils/StringUtilsTest.java +++ b/shared/src/test/java/cn/edu/tsinghua/iginx/utils/StringUtilsTest.java @@ -19,7 +19,12 @@ package cn.edu.tsinghua.iginx.utils; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; import org.junit.Before; import org.junit.Test; @@ -55,4 +60,23 @@ public void toRegexExpr() { assertEquals(".*\\Q.\\E.*\\Q.c\\E", StringUtils.toRegexExpr("**.**.c")); assertEquals(".*\\Q.\\E.*\\Q.\\E.*", StringUtils.toRegexExpr("**.**.**")); } + + @Test + public void cutSchemaPrefix() { + assertEquals(toSet("*"), StringUtils.cutSchemaPrefix(null, Collections.emptySet())); + assertEquals(toSet("*"), StringUtils.cutSchemaPrefix("a.b", Collections.emptySet())); + assertEquals(toSet("a.*", "b.*"), StringUtils.cutSchemaPrefix(null, toSet("a.*", "b.*"))); + assertEquals(toSet("*"), StringUtils.cutSchemaPrefix("a.b.c", toSet("a.*"))); + assertEquals(toSet("*"), StringUtils.cutSchemaPrefix("a.b.c", toSet("a.b.c.*"))); + assertEquals(Collections.emptySet(), StringUtils.cutSchemaPrefix("a.b.c", toSet("a.b.c"))); + assertEquals(Collections.emptySet(), StringUtils.cutSchemaPrefix("a.b.c", toSet("d.*"))); + assertEquals(Collections.emptySet(), StringUtils.cutSchemaPrefix("a.bb.c", toSet("a.b.*"))); + assertEquals(Collections.emptySet(), StringUtils.cutSchemaPrefix("a.b.c", toSet("a.bb.*"))); + assertEquals(toSet("*"), StringUtils.cutSchemaPrefix("a.b.c", toSet("*.b.*"))); + assertEquals(toSet("b.c", "*.b.c"), StringUtils.cutSchemaPrefix("a.b.c", toSet("*.b.c"))); + } + + private Set toSet(String... items) { + return new HashSet<>(Arrays.asList(items)); + } } From 379c5d26653f0ce12789c602f736c437f4a2f1b7 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Thu, 18 Jul 2024 23:26:33 +0800 Subject: [PATCH 090/138] fix --- .../src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java b/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java index 22d54185ec..beeaffa97c 100644 --- a/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java +++ b/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java @@ -917,7 +917,7 @@ private String getFilterString(Filter filter, String storageUnit) throws Physica if (filterStr.contains("*")) { List columns = new ArrayList<>(); Map columns2Fragment = new HashMap<>(); - getColumns2StorageUnit(columns, columns2Fragment, Collections.singleton("*"), null); + getColumns2StorageUnit(columns, columns2Fragment, new HashSet<>(), null); filterStr = FilterTransformer.toString( expandFilterWildcard(filter.copy(), columns, columns2Fragment, storageUnit)); From fa971246d6afb80971c676c48b45b69d50b62ae2 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Thu, 18 Jul 2024 23:37:01 +0800 Subject: [PATCH 091/138] format --- .../src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java | 1 + .../test/java/cn/edu/tsinghua/iginx/utils/StringUtilsTest.java | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java b/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java index beeaffa97c..0215cb19b5 100644 --- a/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java +++ b/dataSource/iotdb12/src/main/java/cn/edu/tsinghua/iginx/iotdb/IoTDBStorage.java @@ -64,6 +64,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; diff --git a/shared/src/test/java/cn/edu/tsinghua/iginx/utils/StringUtilsTest.java b/shared/src/test/java/cn/edu/tsinghua/iginx/utils/StringUtilsTest.java index 6202d31422..f5d0338cf0 100644 --- a/shared/src/test/java/cn/edu/tsinghua/iginx/utils/StringUtilsTest.java +++ b/shared/src/test/java/cn/edu/tsinghua/iginx/utils/StringUtilsTest.java @@ -19,7 +19,6 @@ package cn.edu.tsinghua.iginx.utils; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; import java.util.Arrays; import java.util.Collections; From 8c1cc2becd0700c8ee815c2a5ae69058a4d24968 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Fri, 19 Jul 2024 12:26:57 +0800 Subject: [PATCH 092/138] add debug log --- .../cn/edu/tsinghua/iginx/relational/RelationalStorage.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java index 3e2e6eb452..3778b30843 100644 --- a/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java +++ b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java @@ -135,6 +135,7 @@ private Connection getConnection(String databaseName) { HikariDataSource dataSource = connectionPoolMap.get(databaseName); if (dataSource != null) { try { + LOGGER.debug("Get connection for database {}", databaseName); return dataSource.getConnection(); } catch (SQLException e) { LOGGER.error("Cannot get connection for database {}", databaseName, e); @@ -157,6 +158,7 @@ private Connection getConnection(String databaseName) { HikariDataSource newDataSource = new HikariDataSource(config); connectionPoolMap.put(databaseName, newDataSource); + LOGGER.debug("Create connection for database {}", databaseName); return newDataSource.getConnection(); } catch (SQLException e) { LOGGER.error("Cannot get connection for database {}", databaseName, e); From aea60ba83dcb4a914adeeafb607e9babba04159a Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Fri, 19 Jul 2024 13:09:53 +0800 Subject: [PATCH 093/138] try to fix close connection --- .../cn/edu/tsinghua/iginx/relational/RelationalStorage.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java index 3778b30843..be73d3d1b1 100644 --- a/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java +++ b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java @@ -275,6 +275,7 @@ private List getDatabaseNames() throws SQLException { } rs.close(); conn.close(); + closeConnection(relationalMeta.getDefaultDatabaseName()); return databaseNames; } @@ -303,6 +304,7 @@ private List getTables(String databaseName, String tablePattern) { rs.close(); conn.close(); + closeConnection(databaseName); return tableNames; } catch (SQLException | RelationalTaskExecuteFailureException e) { LOGGER.error("unexpected error: ", e); @@ -331,6 +333,7 @@ private List getColumns( } rs.close(); conn.close(); + closeConnection(databaseName); return columnFields; } catch (SQLException | RelationalTaskExecuteFailureException e) { LOGGER.error("unexpected error: ", e); @@ -1282,6 +1285,7 @@ public TaskExecuteResult executeDelete(Delete delete, DataArea dataArea) { stmt.execute(statement); // 删除数据库 stmt.close(); defaultConn.close(); + closeConnection(relationalMeta.getDefaultDatabaseName()); return new TaskExecuteResult(null, null); } else { return new TaskExecuteResult( @@ -1363,6 +1367,7 @@ public TaskExecuteResult executeInsert(Insert insert, DataArea dataArea) { } try { conn.close(); + closeConnection(databaseName); } catch (SQLException ex) { LOGGER.error("encounter error when closing connection: {}", ex.getMessage()); } From b4bc9664efc8b6ac2acb0c54115687613f2bc711 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Fri, 19 Jul 2024 13:12:01 +0800 Subject: [PATCH 094/138] add log --- .../java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java | 1 + 1 file changed, 1 insertion(+) diff --git a/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java index be73d3d1b1..6742892cf2 100644 --- a/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java +++ b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java @@ -374,6 +374,7 @@ public List getColumns(Set patterns, TagFilter tagFilter) throws RelationalTaskExecuteFailureException { List columns = new ArrayList<>(); Map extraParams = meta.getExtraParams(); + LOGGER.debug("Get Columns with patterns: {}", patterns); try { // dummy pattern list List patternList = new ArrayList<>(); From bf88e1dc9ea405ac05009d1906846cf5bf64128d Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Fri, 19 Jul 2024 13:28:41 +0800 Subject: [PATCH 095/138] revert --- .../cn/edu/tsinghua/iginx/relational/RelationalStorage.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java index 6742892cf2..314d6d4cd5 100644 --- a/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java +++ b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java @@ -275,7 +275,6 @@ private List getDatabaseNames() throws SQLException { } rs.close(); conn.close(); - closeConnection(relationalMeta.getDefaultDatabaseName()); return databaseNames; } @@ -304,7 +303,6 @@ private List getTables(String databaseName, String tablePattern) { rs.close(); conn.close(); - closeConnection(databaseName); return tableNames; } catch (SQLException | RelationalTaskExecuteFailureException e) { LOGGER.error("unexpected error: ", e); @@ -333,7 +331,6 @@ private List getColumns( } rs.close(); conn.close(); - closeConnection(databaseName); return columnFields; } catch (SQLException | RelationalTaskExecuteFailureException e) { LOGGER.error("unexpected error: ", e); @@ -1286,7 +1283,6 @@ public TaskExecuteResult executeDelete(Delete delete, DataArea dataArea) { stmt.execute(statement); // 删除数据库 stmt.close(); defaultConn.close(); - closeConnection(relationalMeta.getDefaultDatabaseName()); return new TaskExecuteResult(null, null); } else { return new TaskExecuteResult( @@ -1368,7 +1364,6 @@ public TaskExecuteResult executeInsert(Insert insert, DataArea dataArea) { } try { conn.close(); - closeConnection(databaseName); } catch (SQLException ex) { LOGGER.error("encounter error when closing connection: {}", ex.getMessage()); } From 786df5b145863c5cb06fd0d897c22c8bcb313366 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Fri, 19 Jul 2024 14:05:03 +0800 Subject: [PATCH 096/138] test --- .github/actions/service/postgresql/action.yml | 1 + .../cn/edu/tsinghua/iginx/relational/RelationalStorage.java | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/actions/service/postgresql/action.yml b/.github/actions/service/postgresql/action.yml index 295d7f2f29..3d60b67be0 100644 --- a/.github/actions/service/postgresql/action.yml +++ b/.github/actions/service/postgresql/action.yml @@ -63,6 +63,7 @@ runs: echo "port = ${port}" >> "${PGCONF}" echo "unix_socket_directories = ''" >> "${PGCONF}" echo "fsync = off" >> "${PGCONF}" + echo "max_connections = 200" >> "${PGCONF}" pg_ctl start --pgdata="${PGDATA}" done diff --git a/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java index 314d6d4cd5..3e2e6eb452 100644 --- a/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java +++ b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java @@ -135,7 +135,6 @@ private Connection getConnection(String databaseName) { HikariDataSource dataSource = connectionPoolMap.get(databaseName); if (dataSource != null) { try { - LOGGER.debug("Get connection for database {}", databaseName); return dataSource.getConnection(); } catch (SQLException e) { LOGGER.error("Cannot get connection for database {}", databaseName, e); @@ -158,7 +157,6 @@ private Connection getConnection(String databaseName) { HikariDataSource newDataSource = new HikariDataSource(config); connectionPoolMap.put(databaseName, newDataSource); - LOGGER.debug("Create connection for database {}", databaseName); return newDataSource.getConnection(); } catch (SQLException e) { LOGGER.error("Cannot get connection for database {}", databaseName, e); @@ -371,7 +369,6 @@ public List getColumns(Set patterns, TagFilter tagFilter) throws RelationalTaskExecuteFailureException { List columns = new ArrayList<>(); Map extraParams = meta.getExtraParams(); - LOGGER.debug("Get Columns with patterns: {}", patterns); try { // dummy pattern list List patternList = new ArrayList<>(); From c3a3ae6b36deb0537d00617d2852127b32ffb6d3 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Fri, 19 Jul 2024 15:54:59 +0800 Subject: [PATCH 097/138] add test --- .../expansion/BaseCapacityExpansionIT.java | 205 ++++++++++-------- .../FileSystemCapacityExpansionIT.java | 29 +++ .../mongodb/MongoDBCapacityExpansionIT.java | 42 ++++ .../redis/RedisCapacityExpansionIT.java | 29 +++ 4 files changed, 219 insertions(+), 86 deletions(-) diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java index a137ed3192..ef39ddf879 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java @@ -476,92 +476,6 @@ private void queryAllNewData() { SQLTestTools.executeAndCompare(session, statement, expect); } - protected void testShowColumnsInExpansion(boolean before) { - String statement = "SHOW COLUMNS nt.wf03.*;"; - String expected = - "Columns:\n" - + "+--------------------+--------+\n" - + "| Path|DataType|\n" - + "+--------------------+--------+\n" - + "|nt.wf03.wt01.status2| LONG|\n" - + "+--------------------+--------+\n" - + "Total line number = 1\n"; - SQLTestTools.executeAndCompare(session, statement, expected); - - statement = "SHOW COLUMNS p1.*;"; - if (before) { - expected = - "Columns:\n" - + "+----+--------+\n" - + "|Path|DataType|\n" - + "+----+--------+\n" - + "+----+--------+\n" - + "Empty set.\n"; - } else { // 添加schemaPrefix为p1,dataPrefix为nt.wf03的数据源 - expected = - "Columns:\n" - + "+-----------------------+--------+\n" - + "| Path|DataType|\n" - + "+-----------------------+--------+\n" - + "|p1.nt.wf03.wt01.status2| LONG|\n" - + "+-----------------------+--------+\n" - + "Total line number = 1\n"; - } - SQLTestTools.executeAndCompare(session, statement, expected); - - statement = "SHOW COLUMNS *.wf03.wt01.*;"; - if (before) { - expected = - "Columns:\n" - + "+--------------------+--------+\n" - + "| Path|DataType|\n" - + "+--------------------+--------+\n" - + "|nt.wf03.wt01.status2| LONG|\n" - + "+--------------------+--------+\n" - + "Total line number = 1\n"; - } else { // 添加schemaPrefix为p1,dataPrefix为nt.wf03的数据源 - expected = - "Columns:\n" - + "+-----------------------+--------+\n" - + "| Path|DataType|\n" - + "+-----------------------+--------+\n" - + "| nt.wf03.wt01.status2| LONG|\n" - + "|p1.nt.wf03.wt01.status2| LONG|\n" - + "+-----------------------+--------+\n" - + "Total line number = 2\n"; - } - SQLTestTools.executeAndCompare(session, statement, expected); - } - - protected void testShowColumnsRemoveStorageEngine(boolean before) { - String statement = "SHOW COLUMNS p1.*, p2.*, p3.*;"; - String expected; - if (before) { - expected = - "Columns:\n" - + "+---------------------------+--------+\n" - + "| Path|DataType|\n" - + "+---------------------------+--------+\n" - + "| p1.nt.wf03.wt01.status2| LONG|\n" - + "| p2.nt.wf03.wt01.status2| LONG|\n" - + "| p3.nt.wf03.wt01.status2| LONG|\n" - + "|p3.nt.wf04.wt01.temperature| DOUBLE|\n" - + "+---------------------------+--------+\n" - + "Total line number = 4\n"; - } else { // schemaPrefix为p2及p3,dataPrefix为nt.wf03的数据源被移除 - expected = - "Columns:\n" - + "+---------------------------+--------+\n" - + "| Path|DataType|\n" - + "+---------------------------+--------+\n" - + "| p1.nt.wf03.wt01.status2| LONG|\n" - + "|p3.nt.wf04.wt01.temperature| DOUBLE|\n" - + "+---------------------------+--------+\n" - + "Total line number = 2\n"; - } - SQLTestTools.executeAndCompare(session, statement, expected); - } - private void testAddAndRemoveStorageEngineWithPrefix() { String dataPrefix1 = "nt.wf03"; String dataPrefix2 = "nt.wf04"; @@ -677,6 +591,125 @@ private void testAddAndRemoveStorageEngineWithPrefix() { testShowClusterInfo(2); } + protected void testShowColumnsInExpansion(boolean before) { + String statement = "SHOW COLUMNS nt.wf03.*;"; + String expected = + "Columns:\n" + + "+--------------------+--------+\n" + + "| Path|DataType|\n" + + "+--------------------+--------+\n" + + "|nt.wf03.wt01.status2| LONG|\n" + + "+--------------------+--------+\n" + + "Total line number = 1\n"; + SQLTestTools.executeAndCompare(session, statement, expected); + + statement = "SHOW COLUMNS;"; + if (before) { + expected = + "Columns:\n" + + "+--------------------------------------------------------------------------------------+--------+\n" + + "| Path|DataType|\n" + + "+--------------------------------------------------------------------------------------+--------+\n" + + "+ b.b.b| LONG|\n" + + "+ ln.wf02.status| BOOLEAN|\n" + + "+ ln.wf02.version| BINARY|\n" + + "+ nt.wf03.wt01.status2| LONG|\n" + + "+ nt.wf04.wt01.temperature| DOUBLE|\n" + + "|zzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzzzz| LONG|\n" + + "+--------------------------------------------------------------------------------------+--------+\n" + + "Total line number = 6\n"; + } else { // 添加schemaPrefix为p1,dataPrefix为nt.wf03的数据源 + expected = + "Columns:\n" + + "+--------------------------------------------------------------------------------------+--------+\n" + + "| Path|DataType|\n" + + "+--------------------------------------------------------------------------------------+--------+\n" + + "+ b.b.b| LONG|\n" + + "+ ln.wf02.status| BOOLEAN|\n" + + "+ ln.wf02.version| BINARY|\n" + + "+ nt.wf03.wt01.status2| LONG|\n" + + "+ nt.wf04.wt01.temperature| DOUBLE|\n" + + "+ p1.nt.wf03.wt01.status2| LONG|\n" + + "|zzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzzzz| LONG|\n" + + "+--------------------------------------------------------------------------------------+--------+\n" + + "Total line number = 7\n"; + } + SQLTestTools.executeAndCompare(session, statement, expected); + + statement = "SHOW COLUMNS p1.*;"; + if (before) { + expected = + "Columns:\n" + + "+----+--------+\n" + + "|Path|DataType|\n" + + "+----+--------+\n" + + "+----+--------+\n" + + "Empty set.\n"; + } else { // 添加schemaPrefix为p1,dataPrefix为nt.wf03的数据源 + expected = + "Columns:\n" + + "+-----------------------+--------+\n" + + "| Path|DataType|\n" + + "+-----------------------+--------+\n" + + "|p1.nt.wf03.wt01.status2| LONG|\n" + + "+-----------------------+--------+\n" + + "Total line number = 1\n"; + } + SQLTestTools.executeAndCompare(session, statement, expected); + + statement = "SHOW COLUMNS *.wf03.wt01.*;"; + if (before) { + expected = + "Columns:\n" + + "+--------------------+--------+\n" + + "| Path|DataType|\n" + + "+--------------------+--------+\n" + + "|nt.wf03.wt01.status2| LONG|\n" + + "+--------------------+--------+\n" + + "Total line number = 1\n"; + } else { // 添加schemaPrefix为p1,dataPrefix为nt.wf03的数据源 + expected = + "Columns:\n" + + "+-----------------------+--------+\n" + + "| Path|DataType|\n" + + "+-----------------------+--------+\n" + + "| nt.wf03.wt01.status2| LONG|\n" + + "|p1.nt.wf03.wt01.status2| LONG|\n" + + "+-----------------------+--------+\n" + + "Total line number = 2\n"; + } + SQLTestTools.executeAndCompare(session, statement, expected); + } + + protected void testShowColumnsRemoveStorageEngine(boolean before) { + String statement = "SHOW COLUMNS p1.*, p2.*, p3.*;"; + String expected; + if (before) { + expected = + "Columns:\n" + + "+---------------------------+--------+\n" + + "| Path|DataType|\n" + + "+---------------------------+--------+\n" + + "| p1.nt.wf03.wt01.status2| LONG|\n" + + "| p2.nt.wf03.wt01.status2| LONG|\n" + + "| p3.nt.wf03.wt01.status2| LONG|\n" + + "|p3.nt.wf04.wt01.temperature| DOUBLE|\n" + + "+---------------------------+--------+\n" + + "Total line number = 4\n"; + } else { // schemaPrefix为p2及p3,dataPrefix为nt.wf03的数据源被移除 + expected = + "Columns:\n" + + "+---------------------------+--------+\n" + + "| Path|DataType|\n" + + "+---------------------------+--------+\n" + + "| p1.nt.wf03.wt01.status2| LONG|\n" + + "|p3.nt.wf04.wt01.temperature| DOUBLE|\n" + + "+---------------------------+--------+\n" + + "Total line number = 2\n"; + } + SQLTestTools.executeAndCompare(session, statement, expected); + } + private void testShowClusterInfo(int expected) { try { ClusterInfo clusterInfo = session.getClusterInfo(); diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java index 291e526d6a..bd4855e9cf 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java @@ -54,6 +54,35 @@ protected void testShowColumnsInExpansion(boolean before) { + "Total line number = 1\n"; SQLTestTools.executeAndCompare(session, statement, expected); + statement = "SHOW COLUMNS;"; + if (before) { + expected = + "Columns:\n" + + "+------------------------+--------+\n" + + "| Path|DataType|\n" + + "+------------------------+--------+\n" + + "+ ln.wf02.status| BOOLEAN|\n" + + "+ ln.wf02.version| BINARY|\n" + + "+ nt.wf03.wt01.status2| LONG|\n" + + "+nt.wf04.wt01.temperature| DOUBLE|\n" + + "+------------------------+--------+\n" + + "Total line number = 4\n"; + } else { // 添加schemaPrefix为p1,dataPrefix为nt.wf03的数据源 + expected = + "Columns:\n" + + "+------------------------+--------+\n" + + "| Path|DataType|\n" + + "+------------------------+--------+\n" + + "+ ln.wf02.status| BOOLEAN|\n" + + "+ ln.wf02.version| BINARY|\n" + + "+ nt.wf03.wt01.status2| BINARY|\n" + + "+nt.wf04.wt01.temperature| BINARY|\n" + + "+ p1.nt.wf03.wt01.status2| BINARY|\n" + + "+------------------------+--------+\n" + + "Total line number = 5\n"; + } + SQLTestTools.executeAndCompare(session, statement, expected); + if (before) { statement = "SHOW COLUMNS p1.*;"; expected = diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java index 9fdf65a17d..bdd820430b 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java @@ -55,6 +55,48 @@ protected void testShowColumnsInExpansion(boolean before) { + "Total line number = 2\n"; SQLTestTools.executeAndCompare(session, statement, expected); + statement = "SHOW COLUMNS;"; + if (before) { + expected = + "Columns:\n" + + "+--------------------------------------------------------------------------------------+--------+\n" + + "| Path|DataType|\n" + + "+--------------------------------------------------------------------------------------+--------+\n" + + "+ b.b._id| INTEGER|\n" + + "+ b.b.b| LONG|\n" + + "+ ln.wf02.status| BOOLEAN|\n" + + "+ ln.wf02.version| BINARY|\n" + + "+ nt.wf03._id| INTEGER|\n" + + "+ nt.wf03.wt01.status2| LONG|\n" + + "+ nt.wf04._id| INTEGER|\n" + + "+ nt.wf04.wt01.temperature| DOUBLE|\n" + + "| zzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzz._id| INTEGER|\n" + + "|zzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzzzz| LONG|\n" + + "+--------------------------------------------------------------------------------------+--------+\n" + + "Total line number = 10\n"; + } else { // 添加schemaPrefix为p1,dataPrefix为nt.wf03的数据源 + expected = + "Columns:\n" + + "+--------------------------------------------------------------------------------------+--------+\n" + + "| Path|DataType|\n" + + "+--------------------------------------------------------------------------------------+--------+\n" + + "+ b.b._id| INTEGER|\n" + + "+ b.b.b| LONG|\n" + + "+ ln.wf02.status| BOOLEAN|\n" + + "+ ln.wf02.version| BINARY|\n" + + "+ nt.wf03._id| INTEGER|\n" + + "+ nt.wf03.wt01.status2| LONG|\n" + + "+ nt.wf04._id| INTEGER|\n" + + "+ nt.wf04.wt01.temperature| DOUBLE|\n" + + "+ p1.nt.wf03._id| INTEGER|\n" + + "+ p1.nt.wf03.wt01.status2| LONG|\n" + + "| zzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzz._id| INTEGER|\n" + + "|zzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzzzz| LONG|\n" + + "+--------------------------------------------------------------------------------------+--------+\n" + + "Total line number = 12\n"; + } + SQLTestTools.executeAndCompare(session, statement, expected); + if (before) { statement = "SHOW COLUMNS p1.*;"; expected = diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisCapacityExpansionIT.java index 11733ce81e..7b6a064238 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisCapacityExpansionIT.java @@ -71,6 +71,35 @@ protected void testShowColumnsInExpansion(boolean before) { + "Total line number = 1\n"; SQLTestTools.executeAndCompare(session, statement, expected); + statement = "SHOW COLUMNS;"; + if (before) { + expected = + "Columns:\n" + + "+------------------------+--------+\n" + + "| Path|DataType|\n" + + "+------------------------+--------+\n" + + "+ ln.wf02.status| BOOLEAN|\n" + + "+ ln.wf02.version| BINARY|\n" + + "+ nt.wf03.wt01.status2| LONG|\n" + + "+nt.wf04.wt01.temperature| DOUBLE|\n" + + "+------------------------+--------+\n" + + "Total line number = 4\n"; + } else { // 添加schemaPrefix为p1,dataPrefix为nt.wf03的数据源 + expected = + "Columns:\n" + + "+------------------------+--------+\n" + + "| Path|DataType|\n" + + "+------------------------+--------+\n" + + "+ ln.wf02.status| BOOLEAN|\n" + + "+ ln.wf02.version| BINARY|\n" + + "+ nt.wf03.wt01.status2| BINARY|\n" + + "+nt.wf04.wt01.temperature| BINARY|\n" + + "+ p1.nt.wf03.wt01.status2| BINARY|\n" + + "+------------------------+--------+\n" + + "Total line number = 5\n"; + } + SQLTestTools.executeAndCompare(session, statement, expected); + if (before) { statement = "SHOW COLUMNS p1.*;"; expected = From 868cd5aff2e4c28c83cda163d990faaa97689213 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Fri, 19 Jul 2024 16:35:57 +0800 Subject: [PATCH 098/138] test --- .../iginx/integration/expansion/BaseCapacityExpansionIT.java | 4 +++- .../expansion/filesystem/FileSystemCapacityExpansionIT.java | 4 +++- .../expansion/mongodb/MongoDBCapacityExpansionIT.java | 4 +++- .../expansion/redis/RedisCapacityExpansionIT.java | 4 +++- .../iginx/integration/expansion/utils/SQLTestTools.java | 5 +++++ 5 files changed, 17 insertions(+), 4 deletions(-) diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java index ef39ddf879..b3767be436 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java @@ -618,6 +618,7 @@ protected void testShowColumnsInExpansion(boolean before) { + "|zzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzzzz| LONG|\n" + "+--------------------------------------------------------------------------------------+--------+\n" + "Total line number = 6\n"; + SQLTestTools.executeAndPrint(session, statement); } else { // 添加schemaPrefix为p1,dataPrefix为nt.wf03的数据源 expected = "Columns:\n" @@ -633,8 +634,9 @@ protected void testShowColumnsInExpansion(boolean before) { + "|zzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzzzz| LONG|\n" + "+--------------------------------------------------------------------------------------+--------+\n" + "Total line number = 7\n"; + SQLTestTools.executeAndPrint(session, statement); } - SQLTestTools.executeAndCompare(session, statement, expected); + // SQLTestTools.executeAndCompare(session, statement, expected); statement = "SHOW COLUMNS p1.*;"; if (before) { diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java index bd4855e9cf..c47d02d069 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java @@ -67,6 +67,7 @@ protected void testShowColumnsInExpansion(boolean before) { + "+nt.wf04.wt01.temperature| DOUBLE|\n" + "+------------------------+--------+\n" + "Total line number = 4\n"; + SQLTestTools.executeAndPrint(session, statement); } else { // 添加schemaPrefix为p1,dataPrefix为nt.wf03的数据源 expected = "Columns:\n" @@ -80,8 +81,9 @@ protected void testShowColumnsInExpansion(boolean before) { + "+ p1.nt.wf03.wt01.status2| BINARY|\n" + "+------------------------+--------+\n" + "Total line number = 5\n"; + SQLTestTools.executeAndPrint(session, statement); } - SQLTestTools.executeAndCompare(session, statement, expected); + // SQLTestTools.executeAndCompare(session, statement, expected); if (before) { statement = "SHOW COLUMNS p1.*;"; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java index bdd820430b..8e8df19ffb 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java @@ -74,6 +74,7 @@ protected void testShowColumnsInExpansion(boolean before) { + "|zzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzzzz| LONG|\n" + "+--------------------------------------------------------------------------------------+--------+\n" + "Total line number = 10\n"; + SQLTestTools.executeAndPrint(session, statement); } else { // 添加schemaPrefix为p1,dataPrefix为nt.wf03的数据源 expected = "Columns:\n" @@ -94,8 +95,9 @@ protected void testShowColumnsInExpansion(boolean before) { + "|zzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzzzz| LONG|\n" + "+--------------------------------------------------------------------------------------+--------+\n" + "Total line number = 12\n"; + SQLTestTools.executeAndPrint(session, statement); } - SQLTestTools.executeAndCompare(session, statement, expected); + // SQLTestTools.executeAndCompare(session, statement, expected); if (before) { statement = "SHOW COLUMNS p1.*;"; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisCapacityExpansionIT.java index 7b6a064238..136fd4b243 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisCapacityExpansionIT.java @@ -84,6 +84,7 @@ protected void testShowColumnsInExpansion(boolean before) { + "+nt.wf04.wt01.temperature| DOUBLE|\n" + "+------------------------+--------+\n" + "Total line number = 4\n"; + SQLTestTools.executeAndPrint(session, statement); } else { // 添加schemaPrefix为p1,dataPrefix为nt.wf03的数据源 expected = "Columns:\n" @@ -97,8 +98,9 @@ protected void testShowColumnsInExpansion(boolean before) { + "+ p1.nt.wf03.wt01.status2| BINARY|\n" + "+------------------------+--------+\n" + "Total line number = 5\n"; + SQLTestTools.executeAndPrint(session, statement); } - SQLTestTools.executeAndCompare(session, statement, expected); + // SQLTestTools.executeAndCompare(session, statement, expected); if (before) { statement = "SHOW COLUMNS p1.*;"; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/utils/SQLTestTools.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/utils/SQLTestTools.java index c421de3683..1df5e79557 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/utils/SQLTestTools.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/utils/SQLTestTools.java @@ -42,6 +42,11 @@ public static void executeAndCompare(Session session, String statement, String e assertEquals(exceptOutput, actualOutput); } + public static void executeAndPrint(Session session, String statement) { + String actualOutput = execute(session, statement); + System.out.println(actualOutput); + } + private static String execute(Session session, String statement) { LOGGER.info("Execute Statement: \"{}\"", statement); From ee0ed2961ce67491f86160e4e64cbda015efe576 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Fri, 19 Jul 2024 17:39:18 +0800 Subject: [PATCH 099/138] fix test --- .../expansion/BaseCapacityExpansionIT.java | 26 +++++------ .../FileSystemCapacityExpansionIT.java | 22 ++++----- .../mongodb/MongoDBCapacityExpansionIT.java | 40 ++++++++-------- .../redis/RedisCapacityExpansionIT.java | 46 ++++++++++--------- .../expansion/utils/SQLTestTools.java | 5 -- 5 files changed, 65 insertions(+), 74 deletions(-) diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java index b3767be436..4b08c0e8ca 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java @@ -610,33 +610,31 @@ protected void testShowColumnsInExpansion(boolean before) { + "+--------------------------------------------------------------------------------------+--------+\n" + "| Path|DataType|\n" + "+--------------------------------------------------------------------------------------+--------+\n" - + "+ b.b.b| LONG|\n" - + "+ ln.wf02.status| BOOLEAN|\n" - + "+ ln.wf02.version| BINARY|\n" - + "+ nt.wf03.wt01.status2| LONG|\n" - + "+ nt.wf04.wt01.temperature| DOUBLE|\n" + + "| b.b.b| LONG|\n" + + "| ln.wf02.status| BOOLEAN|\n" + + "| ln.wf02.version| BINARY|\n" + + "| nt.wf03.wt01.status2| LONG|\n" + + "| nt.wf04.wt01.temperature| DOUBLE|\n" + "|zzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzzzz| LONG|\n" + "+--------------------------------------------------------------------------------------+--------+\n" + "Total line number = 6\n"; - SQLTestTools.executeAndPrint(session, statement); } else { // 添加schemaPrefix为p1,dataPrefix为nt.wf03的数据源 expected = "Columns:\n" + "+--------------------------------------------------------------------------------------+--------+\n" + "| Path|DataType|\n" + "+--------------------------------------------------------------------------------------+--------+\n" - + "+ b.b.b| LONG|\n" - + "+ ln.wf02.status| BOOLEAN|\n" - + "+ ln.wf02.version| BINARY|\n" - + "+ nt.wf03.wt01.status2| LONG|\n" - + "+ nt.wf04.wt01.temperature| DOUBLE|\n" - + "+ p1.nt.wf03.wt01.status2| LONG|\n" + + "| b.b.b| LONG|\n" + + "| ln.wf02.status| BOOLEAN|\n" + + "| ln.wf02.version| BINARY|\n" + + "| nt.wf03.wt01.status2| LONG|\n" + + "| nt.wf04.wt01.temperature| DOUBLE|\n" + + "| p1.nt.wf03.wt01.status2| LONG|\n" + "|zzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzzzz| LONG|\n" + "+--------------------------------------------------------------------------------------+--------+\n" + "Total line number = 7\n"; - SQLTestTools.executeAndPrint(session, statement); } - // SQLTestTools.executeAndCompare(session, statement, expected); + SQLTestTools.executeAndCompare(session, statement, expected); statement = "SHOW COLUMNS p1.*;"; if (before) { diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java index c47d02d069..40e511ef22 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java @@ -61,29 +61,27 @@ protected void testShowColumnsInExpansion(boolean before) { + "+------------------------+--------+\n" + "| Path|DataType|\n" + "+------------------------+--------+\n" - + "+ ln.wf02.status| BOOLEAN|\n" - + "+ ln.wf02.version| BINARY|\n" - + "+ nt.wf03.wt01.status2| LONG|\n" - + "+nt.wf04.wt01.temperature| DOUBLE|\n" + + "| ln.wf02.status| BOOLEAN|\n" + + "| ln.wf02.version| BINARY|\n" + + "| nt.wf03.wt01.status2| BINARY|\n" + + "|nt.wf04.wt01.temperature| BINARY|\n" + "+------------------------+--------+\n" + "Total line number = 4\n"; - SQLTestTools.executeAndPrint(session, statement); } else { // 添加schemaPrefix为p1,dataPrefix为nt.wf03的数据源 expected = "Columns:\n" + "+------------------------+--------+\n" + "| Path|DataType|\n" + "+------------------------+--------+\n" - + "+ ln.wf02.status| BOOLEAN|\n" - + "+ ln.wf02.version| BINARY|\n" - + "+ nt.wf03.wt01.status2| BINARY|\n" - + "+nt.wf04.wt01.temperature| BINARY|\n" - + "+ p1.nt.wf03.wt01.status2| BINARY|\n" + + "| ln.wf02.status| BOOLEAN|\n" + + "| ln.wf02.version| BINARY|\n" + + "| nt.wf03.wt01.status2| BINARY|\n" + + "|nt.wf04.wt01.temperature| BINARY|\n" + + "| p1.nt.wf03.wt01.status2| BINARY|\n" + "+------------------------+--------+\n" + "Total line number = 5\n"; - SQLTestTools.executeAndPrint(session, statement); } - // SQLTestTools.executeAndCompare(session, statement, expected); + SQLTestTools.executeAndCompare(session, statement, expected); if (before) { statement = "SHOW COLUMNS p1.*;"; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java index 8e8df19ffb..e835264e25 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java @@ -62,42 +62,40 @@ protected void testShowColumnsInExpansion(boolean before) { + "+--------------------------------------------------------------------------------------+--------+\n" + "| Path|DataType|\n" + "+--------------------------------------------------------------------------------------+--------+\n" - + "+ b.b._id| INTEGER|\n" - + "+ b.b.b| LONG|\n" - + "+ ln.wf02.status| BOOLEAN|\n" - + "+ ln.wf02.version| BINARY|\n" - + "+ nt.wf03._id| INTEGER|\n" - + "+ nt.wf03.wt01.status2| LONG|\n" - + "+ nt.wf04._id| INTEGER|\n" - + "+ nt.wf04.wt01.temperature| DOUBLE|\n" + + "| b.b._id| INTEGER|\n" + + "| b.b.b| LONG|\n" + + "| ln.wf02.status| BOOLEAN|\n" + + "| ln.wf02.version| BINARY|\n" + + "| nt.wf03._id| INTEGER|\n" + + "| nt.wf03.wt01.status2| LONG|\n" + + "| nt.wf04._id| INTEGER|\n" + + "| nt.wf04.wt01.temperature| DOUBLE|\n" + "| zzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzz._id| INTEGER|\n" + "|zzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzzzz| LONG|\n" + "+--------------------------------------------------------------------------------------+--------+\n" + "Total line number = 10\n"; - SQLTestTools.executeAndPrint(session, statement); } else { // 添加schemaPrefix为p1,dataPrefix为nt.wf03的数据源 expected = "Columns:\n" + "+--------------------------------------------------------------------------------------+--------+\n" + "| Path|DataType|\n" + "+--------------------------------------------------------------------------------------+--------+\n" - + "+ b.b._id| INTEGER|\n" - + "+ b.b.b| LONG|\n" - + "+ ln.wf02.status| BOOLEAN|\n" - + "+ ln.wf02.version| BINARY|\n" - + "+ nt.wf03._id| INTEGER|\n" - + "+ nt.wf03.wt01.status2| LONG|\n" - + "+ nt.wf04._id| INTEGER|\n" - + "+ nt.wf04.wt01.temperature| DOUBLE|\n" - + "+ p1.nt.wf03._id| INTEGER|\n" - + "+ p1.nt.wf03.wt01.status2| LONG|\n" + + "| b.b._id| INTEGER|\n" + + "| b.b.b| LONG|\n" + + "| ln.wf02.status| BOOLEAN|\n" + + "| ln.wf02.version| BINARY|\n" + + "| nt.wf03._id| INTEGER|\n" + + "| nt.wf03.wt01.status2| LONG|\n" + + "| nt.wf04._id| INTEGER|\n" + + "| nt.wf04.wt01.temperature| DOUBLE|\n" + + "| p1.nt.wf03._id| INTEGER|\n" + + "| p1.nt.wf03.wt01.status2| LONG|\n" + "| zzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzz._id| INTEGER|\n" + "|zzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzzzz| LONG|\n" + "+--------------------------------------------------------------------------------------+--------+\n" + "Total line number = 12\n"; - SQLTestTools.executeAndPrint(session, statement); } - // SQLTestTools.executeAndCompare(session, statement, expected); + SQLTestTools.executeAndCompare(session, statement, expected); if (before) { statement = "SHOW COLUMNS p1.*;"; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisCapacityExpansionIT.java index 136fd4b243..1fe88fc48a 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisCapacityExpansionIT.java @@ -75,32 +75,34 @@ protected void testShowColumnsInExpansion(boolean before) { if (before) { expected = "Columns:\n" - + "+------------------------+--------+\n" - + "| Path|DataType|\n" - + "+------------------------+--------+\n" - + "+ ln.wf02.status| BOOLEAN|\n" - + "+ ln.wf02.version| BINARY|\n" - + "+ nt.wf03.wt01.status2| LONG|\n" - + "+nt.wf04.wt01.temperature| DOUBLE|\n" - + "+------------------------+--------+\n" - + "Total line number = 4\n"; - SQLTestTools.executeAndPrint(session, statement); + + "+--------------------------------------------------------------------------------------+--------+\n" + + "| Path|DataType|\n" + + "+--------------------------------------------------------------------------------------+--------+\n" + + "| b.b.b| BINARY|\n" + + "| ln.wf02.status| BOOLEAN|\n" + + "| ln.wf02.version| BINARY|\n" + + "| nt.wf03.wt01.status2| BINARY|\n" + + "| nt.wf04.wt01.temperature| BINARY\n" + + "|zzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzzzz| BINARY|\n" + + "+--------------------------------------------------------------------------------------+--------+\n" + + "Total line number = 6\n"; } else { // 添加schemaPrefix为p1,dataPrefix为nt.wf03的数据源 expected = "Columns:\n" - + "+------------------------+--------+\n" - + "| Path|DataType|\n" - + "+------------------------+--------+\n" - + "+ ln.wf02.status| BOOLEAN|\n" - + "+ ln.wf02.version| BINARY|\n" - + "+ nt.wf03.wt01.status2| BINARY|\n" - + "+nt.wf04.wt01.temperature| BINARY|\n" - + "+ p1.nt.wf03.wt01.status2| BINARY|\n" - + "+------------------------+--------+\n" - + "Total line number = 5\n"; - SQLTestTools.executeAndPrint(session, statement); + + "+--------------------------------------------------------------------------------------+--------+\n" + + "| Path|DataType|\n" + + "+--------------------------------------------------------------------------------------+--------+\n" + + "| b.b.b| BINARY|\n" + + "| ln.wf02.status| BOOLEAN|\n" + + "| ln.wf02.version| BINARY|\n" + + "| nt.wf03.wt01.status2| BINARY|\n" + + "| nt.wf04.wt01.temperature| BINARY|\n" + + "| p1.nt.wf03.wt01.status2| BINARY|\n" + + "|zzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzzzz| BINARY|\n" + + "+--------------------------------------------------------------------------------------+--------+\n" + + "Total line number = 7\n"; } - // SQLTestTools.executeAndCompare(session, statement, expected); + SQLTestTools.executeAndCompare(session, statement, expected); if (before) { statement = "SHOW COLUMNS p1.*;"; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/utils/SQLTestTools.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/utils/SQLTestTools.java index 1df5e79557..c421de3683 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/utils/SQLTestTools.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/utils/SQLTestTools.java @@ -42,11 +42,6 @@ public static void executeAndCompare(Session session, String statement, String e assertEquals(exceptOutput, actualOutput); } - public static void executeAndPrint(Session session, String statement) { - String actualOutput = execute(session, statement); - System.out.println(actualOutput); - } - private static String execute(Session session, String statement) { LOGGER.info("Execute Statement: \"{}\"", statement); From 4ccd732a2c0b0f2c1b56f0f58b02bd41afdaa672 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Sat, 20 Jul 2024 05:52:24 +0800 Subject: [PATCH 100/138] test --- .github/workflows/standard-test-suite.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/standard-test-suite.yml b/.github/workflows/standard-test-suite.yml index e0fc21f331..0f841da109 100644 --- a/.github/workflows/standard-test-suite.yml +++ b/.github/workflows/standard-test-suite.yml @@ -32,7 +32,6 @@ jobs: db-ce: uses: ./.github/workflows/DB-CE.yml with: - os-matrix: '["ubuntu-latest"]' metadata-matrix: '["zookeeper"]' # remote-test: # uses: ./.github/workflows/remote-test.yml From e2a974748ea96e3ac2223a59dc663357893dcee7 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Sat, 20 Jul 2024 11:55:16 +0800 Subject: [PATCH 101/138] fix --- .../parquet/ParquetCapacityExpansionIT.java | 88 +++++++++++++++++++ .../redis/RedisCapacityExpansionIT.java | 2 +- 2 files changed, 89 insertions(+), 1 deletion(-) diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetCapacityExpansionIT.java index 60f3aa60ee..0e8ca7d21c 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetCapacityExpansionIT.java @@ -21,6 +21,7 @@ import static cn.edu.tsinghua.iginx.thrift.StorageEngineType.parquet; import cn.edu.tsinghua.iginx.integration.expansion.BaseCapacityExpansionIT; +import cn.edu.tsinghua.iginx.integration.expansion.utils.SQLTestTools; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -38,4 +39,91 @@ protected void testInvalidDummyParams( int port, boolean hasData, boolean isReadOnly, String dataPrefix, String schemaPrefix) { LOGGER.info("parquet skips test for wrong dummy engine params."); } + + @Override + protected void testShowColumnsInExpansion(boolean before) { + String statement = "SHOW COLUMNS nt.wf03.*;"; + String expected = + "Columns:\n" + + "+--------------------+--------+\n" + + "| Path|DataType|\n" + + "+--------------------+--------+\n" + + "|nt.wf03.wt01.status2| LONG|\n" + + "+--------------------+--------+\n" + + "Total line number = 1\n"; + SQLTestTools.executeAndCompare(session, statement, expected); + + statement = "SHOW COLUMNS;"; + if (before) { + expected = + "Columns:\n" + + "+------------------------+--------+\n" + + "| Path|DataType|\n" + + "+------------------------+--------+\n" + + "| ln.wf02.status| BOOLEAN|\n" + + "| ln.wf02.version| BINARY|\n" + + "| nt.wf03.wt01.status2| LONG|\n" + + "|nt.wf04.wt01.temperature| DOUBLE|\n" + + "+------------------------+--------+\n" + + "Total line number = 4\n"; + } else { // 添加schemaPrefix为p1,dataPrefix为nt.wf03的数据源 + expected = + "Columns:\n" + + "+------------------------+--------+\n" + + "| Path|DataType|\n" + + "+------------------------+--------+\n" + + "| ln.wf02.status| BOOLEAN|\n" + + "| ln.wf02.version| BINARY|\n" + + "| nt.wf03.wt01.status2| LONG|\n" + + "|nt.wf04.wt01.temperature| DOUBLE|\n" + + "| p1.nt.wf03.wt01.status2| LONG|\n" + + "+------------------------+--------+\n" + + "Total line number = 5\n"; + } + SQLTestTools.executeAndCompare(session, statement, expected); + + statement = "SHOW COLUMNS p1.*;"; + if (before) { + expected = + "Columns:\n" + + "+----+--------+\n" + + "|Path|DataType|\n" + + "+----+--------+\n" + + "+----+--------+\n" + + "Empty set.\n"; + } else { // 添加schemaPrefix为p1,dataPrefix为nt.wf03的数据源 + expected = + "Columns:\n" + + "+-----------------------+--------+\n" + + "| Path|DataType|\n" + + "+-----------------------+--------+\n" + + "|p1.nt.wf03.wt01.status2| LONG|\n" + + "+-----------------------+--------+\n" + + "Total line number = 1\n"; + } + SQLTestTools.executeAndCompare(session, statement, expected); + + statement = "SHOW COLUMNS *.wf03.wt01.*;"; + if (before) { + expected = + "Columns:\n" + + "+--------------------+--------+\n" + + "| Path|DataType|\n" + + "+--------------------+--------+\n" + + "|nt.wf03.wt01.status2| LONG|\n" + + "+--------------------+--------+\n" + + "Total line number = 1\n"; + } else { // 添加schemaPrefix为p1,dataPrefix为nt.wf03的数据源 + expected = + "Columns:\n" + + "+-----------------------+--------+\n" + + "| Path|DataType|\n" + + "+-----------------------+--------+\n" + + "| nt.wf03.wt01.status2| LONG|\n" + + "|p1.nt.wf03.wt01.status2| LONG|\n" + + "+-----------------------+--------+\n" + + "Total line number = 2\n"; + } + SQLTestTools.executeAndCompare(session, statement, expected); + } } diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisCapacityExpansionIT.java index 1fe88fc48a..cce701d58d 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisCapacityExpansionIT.java @@ -82,7 +82,7 @@ protected void testShowColumnsInExpansion(boolean before) { + "| ln.wf02.status| BOOLEAN|\n" + "| ln.wf02.version| BINARY|\n" + "| nt.wf03.wt01.status2| BINARY|\n" - + "| nt.wf04.wt01.temperature| BINARY\n" + + "| nt.wf04.wt01.temperature| BINARY|\n" + "|zzzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzz.zzzzzzzzzzzzzzzzzzzzzzzzzzzzz| BINARY|\n" + "+--------------------------------------------------------------------------------------+--------+\n" + "Total line number = 6\n"; From 0448186108d567a27958e1df9cd246262723e4bf Mon Sep 17 00:00:00 2001 From: An Qi Date: Sat, 20 Jul 2024 11:58:45 +0800 Subject: [PATCH 102/138] build: dedup maven configuration and deploy (#397) * build(dataSource): dedup maven configuration * build: remove duplicate properties and deploy --- antlr/pom.xml | 2 -- client/pom.xml | 2 -- dataSource/filesystem/pom.xml | 44 ----------------------------- dataSource/influxdb/pom.xml | 44 ----------------------------- dataSource/iotdb12/pom.xml | 44 ----------------------------- dataSource/mongodb/pom.xml | 44 ----------------------------- dataSource/parquet/pom.xml | 45 ------------------------------ dataSource/pom.xml | 38 +++++++++++++++++++++++-- dataSource/redis/pom.xml | 44 ----------------------------- dataSource/relational/pom.xml | 43 ---------------------------- dataSource/src/assembly/driver.xml | 32 --------------------- dependency/pom.xml | 4 +-- example/pom.xml | 2 -- jdbc/pom.xml | 5 ---- optimizer/pom.xml | 4 +-- pom.xml | 4 ++- session/pom.xml | 5 ---- shared/pom.xml | 5 ---- test/pom.xml | 2 -- thrift/pom.xml | 1 - 20 files changed, 40 insertions(+), 374 deletions(-) delete mode 100644 dataSource/src/assembly/driver.xml diff --git a/antlr/pom.xml b/antlr/pom.xml index aaab110a17..b376f3738f 100644 --- a/antlr/pom.xml +++ b/antlr/pom.xml @@ -32,8 +32,6 @@ IGinX Antlr - 8 - 8 true diff --git a/client/pom.xml b/client/pom.xml index d9dfbdea5b..b34ae71707 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -32,8 +32,6 @@ IGinX Client - 8 - 8 true diff --git a/dataSource/filesystem/pom.xml b/dataSource/filesystem/pom.xml index 771e9d141c..b864642567 100644 --- a/dataSource/filesystem/pom.xml +++ b/dataSource/filesystem/pom.xml @@ -31,59 +31,15 @@ filesystem IGinX FileSystem - - .. - filesystem - 8 - 8 - - org.apache.maven.plugins maven-assembly-plugin - - org.apache.maven.plugins - maven-dependency-plugin - 2.10 - - - copy-dependencies - - copy-dependencies - - package - - ../../core/target/iginx-core-${project.version}/driver/filesystem/ - provided - - - - org.apache.maven.plugins maven-antrun-plugin - 1.7 - - - copy-native-libraries - - run - - package - - - - - - - - - - - diff --git a/dataSource/influxdb/pom.xml b/dataSource/influxdb/pom.xml index 5e512561fc..4d598e043e 100644 --- a/dataSource/influxdb/pom.xml +++ b/dataSource/influxdb/pom.xml @@ -31,13 +31,6 @@ influxdb IGinX InfluxDB - - .. - influxdb - 8 - 8 - - com.influxdb @@ -51,46 +44,9 @@ org.apache.maven.plugins maven-assembly-plugin - - org.apache.maven.plugins - maven-dependency-plugin - 2.10 - - - copy-dependencies - - copy-dependencies - - package - - ../../core/target/iginx-core-${project.version}/driver/influxdb/ - provided - - - - org.apache.maven.plugins maven-antrun-plugin - 1.7 - - - copy-native-libraries - - run - - package - - - - - - - - - - - diff --git a/dataSource/iotdb12/pom.xml b/dataSource/iotdb12/pom.xml index ecf94a8b6f..d471263235 100644 --- a/dataSource/iotdb12/pom.xml +++ b/dataSource/iotdb12/pom.xml @@ -31,13 +31,6 @@ iotdb12 IGinX IoTDB12 - - .. - iotdb12 - 8 - 8 - - org.apache.iotdb @@ -80,46 +73,9 @@ org.apache.maven.plugins maven-assembly-plugin - - org.apache.maven.plugins - maven-dependency-plugin - 2.10 - - - copy-dependencies - - copy-dependencies - - package - - ../../core/target/iginx-core-${project.version}/driver/iotdb12/ - provided - - - - org.apache.maven.plugins maven-antrun-plugin - 1.7 - - - copy-native-libraries - - run - - package - - - - - - - - - - - diff --git a/dataSource/mongodb/pom.xml b/dataSource/mongodb/pom.xml index 09d0e20aba..ba3347602c 100644 --- a/dataSource/mongodb/pom.xml +++ b/dataSource/mongodb/pom.xml @@ -31,13 +31,6 @@ mongodb IGinX MongoDB - - .. - mongodb - 8 - 8 - - org.mongodb @@ -51,46 +44,9 @@ org.apache.maven.plugins maven-assembly-plugin - - org.apache.maven.plugins - maven-dependency-plugin - 2.10 - - - copy-dependencies - - copy-dependencies - - package - - ../../core/target/iginx-core-${project.version}/driver/mongodb/ - provided - - - - org.apache.maven.plugins maven-antrun-plugin - 1.7 - - - copy-native-libraries - - run - - package - - - - - - - - - - - diff --git a/dataSource/parquet/pom.xml b/dataSource/parquet/pom.xml index 16b440d9a0..8fdeeef642 100644 --- a/dataSource/parquet/pom.xml +++ b/dataSource/parquet/pom.xml @@ -30,13 +30,6 @@ parquet IGinX Parquet - - .. - parquet - 8 - 8 - - cn.edu.tsinghua.iginx @@ -85,47 +78,9 @@ org.apache.maven.plugins maven-assembly-plugin - - org.apache.maven.plugins - maven-dependency-plugin - 2.10 - - - copy-dependencies - - copy-dependencies - - package - - ../../core/target/iginx-core-${project.version}/driver/parquet/ - provided - junit,hamcrest-core - - - - org.apache.maven.plugins maven-antrun-plugin - 1.7 - - - copy-native-libraries - - run - - package - - - - - - - - - - - diff --git a/dataSource/pom.xml b/dataSource/pom.xml index 469850f2ce..d1d25c1b04 100644 --- a/dataSource/pom.xml +++ b/dataSource/pom.xml @@ -61,9 +61,20 @@ maven-assembly-plugin false - - ${driver.basedir}/src/assembly/driver.xml - + + + driver + + dir + + false + + + driver/${project.artifactId} + + + + @@ -74,6 +85,27 @@ + + org.apache.maven.plugins + maven-antrun-plugin + 1.7 + + + copy-driver-into-core + + run + + package + + + + + + + + + + diff --git a/dataSource/redis/pom.xml b/dataSource/redis/pom.xml index cacb7fd25e..7af0f58773 100644 --- a/dataSource/redis/pom.xml +++ b/dataSource/redis/pom.xml @@ -30,13 +30,6 @@ redis IGinX Redis - - .. - redis - 8 - 8 - - redis.clients @@ -56,46 +49,9 @@ org.apache.maven.plugins maven-assembly-plugin - - org.apache.maven.plugins - maven-dependency-plugin - 2.10 - - - copy-dependencies - - copy-dependencies - - package - - ../../core/target/iginx-core-${project.version}/driver/redis/ - provided - - - - org.apache.maven.plugins maven-antrun-plugin - 1.7 - - - copy-native-libraries - - run - - package - - - - - - - - - - - diff --git a/dataSource/relational/pom.xml b/dataSource/relational/pom.xml index 269cb2f509..21d4a6b6ec 100644 --- a/dataSource/relational/pom.xml +++ b/dataSource/relational/pom.xml @@ -31,12 +31,6 @@ relational IGinX relational - - .. - relational - 8 - 8 - org.postgresql @@ -67,46 +61,9 @@ org.apache.maven.plugins maven-assembly-plugin - - org.apache.maven.plugins - maven-dependency-plugin - 2.10 - - - copy-dependencies - - copy-dependencies - - package - - ../../core/target/iginx-core-${project.version}/driver/relational/ - provided - - - - org.apache.maven.plugins maven-antrun-plugin - 1.7 - - - copy-native-libraries - - run - - package - - - - - - - - - - - diff --git a/dataSource/src/assembly/driver.xml b/dataSource/src/assembly/driver.xml deleted file mode 100644 index cabcb955a3..0000000000 --- a/dataSource/src/assembly/driver.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - driver - - dir - - false - - - driver/${driver.name} - - - \ No newline at end of file diff --git a/dependency/pom.xml b/dependency/pom.xml index 9f887753a7..436305a6b2 100644 --- a/dependency/pom.xml +++ b/dependency/pom.xml @@ -32,9 +32,7 @@ IGinX Dependency - 8 - 8 - UTF-8 + true diff --git a/example/pom.xml b/example/pom.xml index 3640abf9da..a3342c7f33 100644 --- a/example/pom.xml +++ b/example/pom.xml @@ -32,8 +32,6 @@ IGinX Example - 8 - 8 true diff --git a/jdbc/pom.xml b/jdbc/pom.xml index 13709688ed..63b65b6269 100644 --- a/jdbc/pom.xml +++ b/jdbc/pom.xml @@ -30,11 +30,6 @@ iginx-jdbc IGinX JDBC - - 8 - 8 - - cn.edu.tsinghua diff --git a/optimizer/pom.xml b/optimizer/pom.xml index c14ac218b9..e604d642cf 100644 --- a/optimizer/pom.xml +++ b/optimizer/pom.xml @@ -31,9 +31,7 @@ IGinX Optimizer - 8 - 8 - UTF-8 + true diff --git a/pom.xml b/pom.xml index d820ddfe0e..5ce478eada 100644 --- a/pom.xml +++ b/pom.xml @@ -62,6 +62,8 @@ 0.8.6 ${project.basedir} + 8 + 8 UTF-8 UTF-8 0.8.0-SNAPSHOT @@ -338,7 +340,7 @@ org.apache.maven.plugins maven-assembly-plugin - 3.6.0 + 3.7.1 com.mycila diff --git a/session/pom.xml b/session/pom.xml index f560483863..34bac0393b 100644 --- a/session/pom.xml +++ b/session/pom.xml @@ -30,11 +30,6 @@ iginx-session IGinX Session - - 8 - 8 - - cn.edu.tsinghua diff --git a/shared/pom.xml b/shared/pom.xml index 241e1adc82..d8c589b5b3 100644 --- a/shared/pom.xml +++ b/shared/pom.xml @@ -30,11 +30,6 @@ iginx-shared IGinX Shared - - 8 - 8 - - org.apache.commons diff --git a/test/pom.xml b/test/pom.xml index ba885f0559..598fdb8aff 100644 --- a/test/pom.xml +++ b/test/pom.xml @@ -32,8 +32,6 @@ IGinX Test - 8 - 8 true diff --git a/thrift/pom.xml b/thrift/pom.xml index 613ee91931..9a440b3161 100644 --- a/thrift/pom.xml +++ b/thrift/pom.xml @@ -32,7 +32,6 @@ IGinX Thrift - UTF-8 0.16.0 From 28cf725aac1a96497664a86fca8c0178552a1606 Mon Sep 17 00:00:00 2001 From: An Qi Date: Sat, 20 Jul 2024 12:05:16 +0800 Subject: [PATCH 103/138] build: update netty and arrow version (#396) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit arrow 发布的新版本,IGinX跟随更新,舍弃原来使用的arrow 17.0-snapshot版本 --------- Co-authored-by: Yuqing Zhu --- core/pom.xml | 28 ------- dependency/pom.xml | 185 --------------------------------------------- pom.xml | 78 +++++++------------ 3 files changed, 29 insertions(+), 262 deletions(-) diff --git a/core/pom.xml b/core/pom.xml index 6b220e3345..b232c0c0d1 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -81,27 +81,14 @@ com.fasterxml.jackson.core jackson-core - 2.12.5 com.fasterxml.jackson.core jackson-annotations - 2.12.5 io.etcd jetcd-core - true - - - org.slf4j - slf4j-log4j12 - - - log4j - log4j - - io.moquette @@ -118,7 +105,6 @@ io.netty netty-all - 4.1.59.Final org.apache.zookeeper @@ -163,15 +149,6 @@ cn.hutool hutool-all - - - com.google.flatbuffers - flatbuffers-java - - - org.apache.arrow - arrow-format - org.apache.arrow arrow-vector @@ -185,11 +162,6 @@ arrow-memory-netty runtime - - org.apache.arrow - arrow-memory-netty-buffer-patch - runtime - org.apache.arrow arrow-algorithm diff --git a/dependency/pom.xml b/dependency/pom.xml index 436305a6b2..930901c80f 100644 --- a/dependency/pom.xml +++ b/dependency/pom.xml @@ -43,109 +43,6 @@ - - com.googlecode.maven-download-plugin - download-maven-plugin - 1.9.0 - - - get-arrow-java-root - - wget - - generate-sources - - https://github.com/IGinX-THU/IGinX-resources/raw/main/arrow-snapshot/arrow-java-root-17.0.0-20240709.071332-1.pom - target/remote-jars - arrow-java-root-17.0.0-SNAPSHOT.pom - - - - get-arrow-memory - - wget - - generate-sources - - https://github.com/IGinX-THU/IGinX-resources/raw/main/arrow-snapshot/arrow-memory-17.0.0-20240709.071332-1.pom - target/remote-jars - arrow-memory-17.0.0-SNAPSHOT.pom - - - - get-arrow-memory-core-snapshot - - wget - - generate-sources - - https://github.com/IGinX-THU/IGinX-resources/raw/main/arrow-snapshot/arrow-memory-core-17.0.0-20240709.071332-1.jar - target/remote-jars - arrow-memory-core-17.0.0-SNAPSHOT.jar - - - - get-arrow-memory-netty-snapshot - - wget - - generate-sources - - https://github.com/IGinX-THU/IGinX-resources/raw/main/arrow-snapshot/arrow-memory-netty-17.0.0-20240709.071332-1.jar - target/remote-jars - arrow-memory-netty-17.0.0-SNAPSHOT.jar - - - - get-arrow-memory-netty-buffer-patch - - wget - - generate-sources - - https://github.com/IGinX-THU/IGinX-resources/raw/main/arrow-snapshot/arrow-memory-netty-buffer-patch-17.0.0-20240709.071332-1.jar - target/remote-jars - arrow-memory-netty-buffer-patch-17.0.0-SNAPSHOT.jar - - - - get-arrow-format-snapshot - - wget - - generate-sources - - https://github.com/IGinX-THU/IGinX-resources/raw/main/arrow-snapshot/arrow-format-17.0.0-20240709.071332-1.jar - target/remote-jars - arrow-format-17.0.0-SNAPSHOT.jar - - - - get-arrow-vector-snapshot - - wget - - generate-sources - - https://github.com/IGinX-THU/IGinX-resources/raw/main/arrow-snapshot/arrow-vector-17.0.0-20240709.071332-1.jar - target/remote-jars - arrow-vector-17.0.0-SNAPSHOT.jar - - - - get-arrow-algorithm-snapshot - - wget - - generate-sources - - https://github.com/IGinX-THU/IGinX-resources/raw/main/arrow-snapshot/arrow-algorithm-17.0.0-20240709.071332-1.jar - target/remote-jars - arrow-algorithm-17.0.0-SNAPSHOT.jar - - - - org.apache.maven.plugins maven-install-plugin @@ -161,88 +58,6 @@ src/main/resources/pemja-0.5-SNAPSHOT.jar - - install-arrow-java-root - - install-file - - generate-sources - - target/remote-jars/arrow-java-root-17.0.0-SNAPSHOT.pom - target/remote-jars/arrow-java-root-17.0.0-SNAPSHOT.pom - - - - install-arrow-memory - - install-file - - generate-sources - - target/remote-jars/arrow-memory-17.0.0-SNAPSHOT.pom - target/remote-jars/arrow-memory-17.0.0-SNAPSHOT.pom - - - - install-arrow-memory-core-snapshot - - install-file - - generate-sources - - target/remote-jars/arrow-memory-core-17.0.0-SNAPSHOT.jar - - - - install-arrow-memory-netty-snapshot - - install-file - - generate-sources - - target/remote-jars/arrow-memory-netty-17.0.0-SNAPSHOT.jar - - - - install-arrow-memory-netty-buffer-patch - - install-file - - generate-sources - - target/remote-jars/arrow-memory-netty-buffer-patch-17.0.0-SNAPSHOT.jar - - - - install-arrow-format-snapshot - - install-file - - generate-sources - - target/remote-jars/arrow-format-17.0.0-SNAPSHOT.jar - - - - install-arrow-vector-snapshot - - install-file - - generate-sources - - target/remote-jars/arrow-vector-17.0.0-SNAPSHOT.jar - - - - install-arrow-algorithm-snapshot - - install-file - - generate-sources - - target/remote-jars/arrow-algorithm-17.0.0-SNAPSHOT.jar - - diff --git a/pom.xml b/pom.xml index 5ce478eada..de3cf9f36e 100644 --- a/pom.xml +++ b/pom.xml @@ -157,49 +157,23 @@ 2.2 - com.fasterxml.jackson.core - jackson-databind - 2.13.4.2 + com.fasterxml.jackson + jackson-bom + 2.17.2 + pom + import cn.hutool hutool-all 5.8.26 - - com.google.flatbuffers - flatbuffers-java - 23.5.26 - - - org.apache.arrow - arrow-format - 17.0.0-SNAPSHOT - - - org.apache.arrow - arrow-vector - 17.0.0-SNAPSHOT - - - org.apache.arrow - arrow-memory-core - 17.0.0-SNAPSHOT - - - org.apache.arrow - arrow-memory-netty - 17.0.0-SNAPSHOT - org.apache.arrow - arrow-memory-netty-buffer-patch - 17.0.0-SNAPSHOT - - - org.apache.arrow - arrow-algorithm - 17.0.0-SNAPSHOT + arrow-bom + 17.0.0 + pom + import org.apache.commons @@ -236,6 +210,13 @@ commons-email 1.6.0 + + io.netty + netty-bom + 4.1.110.Final + pom + import + org.apache.zookeeper zookeeper @@ -269,18 +250,15 @@ io.etcd jetcd-core - 0.5.7 - true - - - org.slf4j - slf4j-log4j12 - - - log4j - log4j - - + 0.5.11 + + + + io.grpc + grpc-bom + 1.57.2 + pom + import com.influxdb @@ -311,8 +289,10 @@ com.google.guava - guava - 33.2.0-jre + guava-bom + 33.2.1-jre + pom + import From 3c9c574477303806d522f81cdb100fd657e5ea9c Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Sat, 20 Jul 2024 12:17:48 +0800 Subject: [PATCH 104/138] feat(test): adjust TPC-H test (#399) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 待清理代码,用于下一PR 等下一PR处理 --- .github/actions/tpchSingleTest/action.yml | 79 +++ .github/workflows/tpc-h.yml | 153 ++--- .../iginx/integration/tool/ConfLoader.java | 10 + .../integration/tpch/TPCHDataGeneratorIT.java | 321 +++++++++++ .../integration/tpch/TPCHRegressionIT.java | 529 ------------------ .../tpch/TPCHRegressionMainIT.java | 117 ++++ .../integration/tpch/TPCHRegressionNewIT.java | 237 ++++++++ .../iginx/integration/tpch/TPCHUtils.java | 188 +++++++ test/src/test/resources/testConfig.properties | 1 + .../tpch/runtimeInfo/failedQueryIds.txt | 12 + .../tpch/runtimeInfo/iterationTimes.txt | 1 + .../tpch/runtimeInfo/newTimeCosts.txt | 22 + .../tpch/runtimeInfo/oldTimeCosts.txt | 22 + .../resources/tpch/runtimeInfo/status.txt | 1 + 14 files changed, 1095 insertions(+), 598 deletions(-) create mode 100644 .github/actions/tpchSingleTest/action.yml create mode 100644 test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHDataGeneratorIT.java delete mode 100644 test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHRegressionIT.java create mode 100644 test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHRegressionMainIT.java create mode 100644 test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHRegressionNewIT.java create mode 100644 test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHUtils.java create mode 100644 test/src/test/resources/tpch/runtimeInfo/failedQueryIds.txt create mode 100644 test/src/test/resources/tpch/runtimeInfo/iterationTimes.txt create mode 100644 test/src/test/resources/tpch/runtimeInfo/newTimeCosts.txt create mode 100644 test/src/test/resources/tpch/runtimeInfo/oldTimeCosts.txt create mode 100644 test/src/test/resources/tpch/runtimeInfo/status.txt diff --git a/.github/actions/tpchSingleTest/action.yml b/.github/actions/tpchSingleTest/action.yml new file mode 100644 index 0000000000..a8c8d74a1a --- /dev/null +++ b/.github/actions/tpchSingleTest/action.yml @@ -0,0 +1,79 @@ +name: "tpch-single-test" +description: "test tpc-h once in main branch and new branch" +inputs: + status: + description: "status of last test" + default: "unfinished" +outputs: + status: + description: "status of this test" + value: ${{ steps.get.outputs.status }} + +runs: + using: "composite" + steps: + - name: Start Old IGinX + if: inputs.status != 'ok' + uses: ./.github/actions/iginxRunner + # shell: bash + # run: | + # cd IGinX/core/target/iginx-core-${VERSION} + # pwd + # export IGINX_HOME=$PWD + # echo "IGinX home path: $IGINX_HOME" + # cd .. + # chmod +x iginx-core-${VERSION}/sbin/start_iginx.sh + # nohup iginx-core-${VERSION}/sbin/start_iginx.sh > ../../iginx-${VERSION}.log 2>&1 & + + - name: Run TPCH Test on Old IGinX + if: inputs.status != 'ok' + shell: bash + run: | + mvn test -q -Dtest=TPCHRegressionMainIT -DfailIfNoTests=false -P-format + # cp test/src/test/resources/tpch/runtimeInfo/failedQueryIds.txt IGinX/test/src/test/resources/tpch/runtimeInfo/ + # cp test/src/test/resources/tpch/runtimeInfo/iteratoionTimes.txt IGinX/test/src/test/resources/tpch/runtimeInfo/ + # mvn test -q -Dtest=TPCHRegressionMainIT -DfailIfNoTests=false -P-format + + - name: Show Old IGinX log + if: inputs.status != 'ok' + shell: bash + run: cat iginx-*.log + # run: cat IGinX/iginx-*.log + + - name: Stop Old IGinX + if: inputs.status != 'ok' + uses: ./.github/actions/iginxRunner + with: + version: ${VERSION} + if-stop: "true" + + - name: Start New IGinX + if: inputs.status != 'ok' + uses: ./.github/actions/iginxRunner + + - name: Run Regression Test on New IGinX + if: inputs.status != 'ok' + shell: bash + run: | + mvn test -q -Dtest=TPCHRegressionNewIT -DfailIfNoTests=false -P-format + # cp IGinX/test/src/test/resources/tpch/runtimeInfo/oldTimeCosts.txt test/src/test/resources/tpch/runtimeInfo/ + # mvn test -q -Dtest=TPCHRegressionNewIT -DfailIfNoTests=false -P-format + + - name: Show New IGinX log + if: inputs.status != 'ok' + shell: bash + run: cat iginx-*.log + + - name: Stop New IGinX + if: inputs.status != 'ok' + uses: ./.github/actions/iginxRunner + with: + version: ${VERSION} + if-stop: "true" + + - name: Get Test Result + id: get + shell: bash + run: | + STATUS=$(cat test/src/test/resources/tpch/runtimeInfo/status.txt) + echo "status=$STATUS" >> $GITHUB_OUTPUT diff --git a/.github/workflows/tpc-h.yml b/.github/workflows/tpc-h.yml index 7e1cd95982..eb0983aed0 100644 --- a/.github/workflows/tpc-h.yml +++ b/.github/workflows/tpc-h.yml @@ -89,99 +89,114 @@ jobs: with: DB-name: ${{ matrix.DB-name }} - - name: Get Old Version IGinX and Copy TPC-H Data - shell: bash - run: | - git clone https://github.com/IGinX-THU/IGinX.git - mkdir IGinX/tpc - cp -r tpc/* IGinX/tpc/ - ls -a 'IGinX/tpc/TPC-H V3.0.1/data' + # - name: Get Old Version IGinX + # shell: bash + # run: git clone https://github.com/IGinX-THU/IGinX.git + # + # - name: Rewrite DB Conf in Old IGinX + # uses: ./.github/actions/dbConfWriter + # with: + # DB-name: ${{ matrix.DB-name }} + # Root-Dir-Path: "IGinX" + # + # - name: Install Old IGinX with Maven + # shell: bash + # run: | + # cd IGinX + # mvn clean package -DskipTests -P-format -q + # + # - name: Change Old IGinX config + # uses: ./.github/actions/confWriter + # with: + # DB-name: ${{ matrix.DB-name }} + # Set-Filter-Fragment-OFF: "true" + # Metadata: ${{ matrix.metadata }} + # Root-Dir-Path: "IGinX" - - name: Rewrite DB Conf in Old IGinX - uses: ./.github/actions/dbConfWriter - with: - DB-name: ${{ matrix.DB-name }} - Root-Dir-Path: "IGinX" - - - name: Install Old IGinX with Maven + - name: Install New IGinX with Maven shell: bash run: | - cd IGinX mvn clean package -DskipTests -P-format -q - - name: Change Old IGinX config + - name: Change New IGinX config uses: ./.github/actions/confWriter with: DB-name: ${{ matrix.DB-name }} Set-Filter-Fragment-OFF: "true" Metadata: ${{ matrix.metadata }} - Root-Dir-Path: "IGinX" - - name: Start Old IGinX - if: always() - shell: bash - run: | - cd IGinX/core/target/iginx-core-${VERSION} - pwd - export IGINX_HOME=$PWD - echo "IGinX home path: $IGINX_HOME" - cd .. - chmod +x iginx-core-${VERSION}/sbin/start_iginx.sh - nohup iginx-core-${VERSION}/sbin/start_iginx.sh > ../../iginx-${VERSION}.log 2>&1 & - - - name: Run Regression Test on Old IGinX - if: always() + - name: Start New IGinX + uses: ./.github/actions/iginxRunner + + - name: Insert Data and Register UDF shell: bash - run: | - cd IGinX - mvn test -q -Dtest=TPCHRegressionIT -DfailIfNoTests=false -P-format + run: mvn test -q -Dtest=TPCHDataGeneratorIT -DfailIfNoTests=false -P-format - - name: Show Old IGinX log + - name: Stop New IGinX + uses: ./.github/actions/iginxRunner + with: + version: ${VERSION} + if-stop: "true" + + - name: Show New IGinX log if: always() shell: bash - run: | - cat IGinX/iginx-*.log + run: cat iginx-*.log - - name: Stop ZooKeeper - uses: ./.github/actions/zookeeperRunner + - name: Run 1st Regression Test + id: test1 + uses: ./.github/actions/tpchSingleTest + + - name: Run 2nd Regression Test + id: test2 + uses: ./.github/actions/tpchSingleTest with: - if-stop: "true" + status: ${{ steps.test1.outputs.status }} - - name: Stop Old IGinX - uses: ./.github/actions/iginxRunner + - name: Run 3rd Regression Test + id: test3 + uses: ./.github/actions/tpchSingleTest with: - version: ${VERSION} - if-stop: "true" + status: ${{ steps.test2.outputs.status }} - - name: Rerun ZooKeeper - uses: ./.github/actions/zookeeperRunner + - name: Run 4th Regression Test + id: test4 + uses: ./.github/actions/tpchSingleTest with: - if-rerun: "true" + status: ${{ steps.test3.outputs.status }} - - name: Install New IGinX with Maven - shell: bash - run: | - mvn clean package -DskipTests -P-format -q - cp IGinX/test/src/test/resources/tpch/oldTimeCosts.txt test/src/test/resources/tpch/ + - name: Run 5th Regression Test + id: test5 + uses: ./.github/actions/tpchSingleTest + with: + status: ${{ steps.test4.outputs.status }} - - name: Change New IGinX config - uses: ./.github/actions/confWriter + - name: Run 6th Regression Test + id: test6 + uses: ./.github/actions/tpchSingleTest with: - DB-name: ${{ matrix.DB-name }} - Set-Filter-Fragment-OFF: "true" - Metadata: ${{ matrix.metadata }} + status: ${{ steps.test5.outputs.status }} - - name: Start New IGinX - uses: ./.github/actions/iginxRunner + - name: Run 7th Regression Test + id: test7 + uses: ./.github/actions/tpchSingleTest + with: + status: ${{ steps.test6.outputs.status }} - - name: Run Regression Test on New IGinX - if: always() - shell: bash - run: | - mvn test -q -Dtest=TPCHRegressionIT -DfailIfNoTests=false -P-format + - name: Run 8th Regression Test + id: test8 + uses: ./.github/actions/tpchSingleTest + with: + status: ${{ steps.test7.outputs.status }} - - name: Show New IGinX log - if: always() - shell: bash - run: | - cat iginx-*.log + - name: Run 9th Regression Test + id: test9 + uses: ./.github/actions/tpchSingleTest + with: + status: ${{ steps.test8.outputs.status }} + + - name: Run 10th Regression Test + id: test10 + uses: ./.github/actions/tpchSingleTest + with: + status: ${{ steps.test9.outputs.status }} diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/ConfLoader.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/ConfLoader.java index 3c56aa2224..b0553a2f6e 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/ConfLoader.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tool/ConfLoader.java @@ -126,6 +126,16 @@ public String getDBCETestWay() { return getTestProperty(DBCE_TEST_WAY, DEFAULT_DBCE_TEST_WAY); } + public List getQueryIds() { + String input = properties.getProperty("query_ids"); + String[] split = input.split(","); + List list = new ArrayList<>(); + for (String s : split) { + list.add(Integer.parseInt(s)); + } + return list; + } + public int getMaxRepetitionsNum() { return Integer.parseInt(properties.getProperty("max_repetitions_num")); } diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHDataGeneratorIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHDataGeneratorIT.java new file mode 100644 index 0000000000..4ee261646d --- /dev/null +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHDataGeneratorIT.java @@ -0,0 +1,321 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package cn.edu.tsinghua.iginx.integration.tpch; + +import static cn.edu.tsinghua.iginx.integration.tpch.TPCHDataGeneratorIT.FieldType.DATE; +import static cn.edu.tsinghua.iginx.integration.tpch.TPCHDataGeneratorIT.FieldType.NUM; +import static cn.edu.tsinghua.iginx.integration.tpch.TPCHDataGeneratorIT.FieldType.STR; +import static org.junit.Assert.fail; + +import cn.edu.tsinghua.iginx.exception.SessionException; +import cn.edu.tsinghua.iginx.integration.controller.Controller; +import cn.edu.tsinghua.iginx.integration.tool.ConfLoader; +import cn.edu.tsinghua.iginx.session.Session; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.TimeZone; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TPCHDataGeneratorIT { + + private static final Logger LOGGER = LoggerFactory.getLogger(TPCHDataGeneratorIT.class); + + // host info + protected static String defaultTestHost = "127.0.0.1"; + protected static int defaultTestPort = 6888; + protected static String defaultTestUser = "root"; + protected static String defaultTestPass = "root"; + + // .tbl文件所在目录 + private static final String DATA_DIR = + System.getProperty("user.dir") + "/../tpc/TPC-H V3.0.1/data"; + + // udf文件所在目录 + private static final String UDF_DIR = "src/test/resources/tpch/udf/"; + + protected static Session session; + + List queryIds; + + enum FieldType { + NUM, + STR, + DATE + } + + public TPCHDataGeneratorIT() { + ConfLoader conf = new ConfLoader(Controller.CONFIG_FILE); + queryIds = conf.getQueryIds(); + } + + @BeforeClass + public static void setUp() throws SessionException { + session = new Session(defaultTestHost, defaultTestPort, defaultTestUser, defaultTestPass); + session.openSession(); + } + + @AfterClass + public static void close() throws SessionException { + session.closeSession(); + } + + @Before + public void prepare() { + List tableList = + Arrays.asList( + "region", "nation", "supplier", "part", "partsupp", "customer", "orders", "lineitem"); + + List> fieldsList = new ArrayList<>(); + List> typesList = new ArrayList<>(); + + // region表 + fieldsList.add(Arrays.asList("r_regionkey", "r_name", "r_comment")); + typesList.add(Arrays.asList(NUM, STR, STR)); + + // nation表 + fieldsList.add(Arrays.asList("n_nationkey", "n_name", "n_regionkey", "n_comment")); + typesList.add(Arrays.asList(NUM, STR, NUM, STR)); + + // supplier表 + fieldsList.add( + Arrays.asList( + "s_suppkey", + "s_name", + "s_address", + "s_nationkey", + "s_phone", + "s_acctbal", + "s_comment")); + typesList.add(Arrays.asList(NUM, STR, STR, NUM, STR, NUM, STR)); + + // part表 + fieldsList.add( + Arrays.asList( + "p_partkey", + "p_name", + "p_mfgr", + "p_brand", + "p_type", + "p_size", + "p_container", + "p_retailprice", + "p_comment")); + typesList.add(Arrays.asList(NUM, STR, STR, STR, STR, NUM, STR, NUM, STR)); + + // partsupp表 + fieldsList.add( + Arrays.asList("ps_partkey", "ps_suppkey", "ps_availqty", "ps_supplycost", "ps_comment")); + typesList.add(Arrays.asList(NUM, NUM, NUM, NUM, STR)); + + // customer表 + fieldsList.add( + Arrays.asList( + "c_custkey", + "c_name", + "c_address", + "c_nationkey", + "c_phone", + "c_acctbal", + "c_mktsegment", + "c_comment")); + typesList.add(Arrays.asList(NUM, STR, STR, NUM, STR, NUM, STR, STR)); + + // orders表 + fieldsList.add( + Arrays.asList( + "o_orderkey", + "o_custkey", + "o_orderstatus", + "o_totalprice", + "o_orderdate", + "o_orderpriority", + "o_clerk", + "o_shippriority", + "o_comment")); + typesList.add(Arrays.asList(NUM, NUM, STR, NUM, DATE, STR, STR, NUM, STR)); + + // lineitem表 + fieldsList.add( + Arrays.asList( + "l_orderkey", + "l_partkey", + "l_suppkey", + "l_linenumber", + "l_quantity", + "l_extendedprice", + "l_discount", + "l_tax", + "l_returnflag", + "l_linestatus", + "l_shipdate", + "l_commitdate", + "l_receiptdate", + "l_shipinstruct", + "l_shipmode", + "l_comment")); + typesList.add( + Arrays.asList( + NUM, NUM, NUM, NUM, NUM, NUM, NUM, NUM, STR, STR, DATE, DATE, DATE, STR, STR, STR)); + + // 插入数据 + for (int i = 0; i < 8; i++) { + insertTable(tableList.get(i), fieldsList.get(i), typesList.get(i)); + } + + List> UDFInfos = new ArrayList<>(); + UDFInfos.add(Arrays.asList("UDTF", "extractYear", "UDFExtractYear", "udtf_extract_year.py")); + // 注册UDF函数 + for (List UDFInfo : UDFInfos) { + registerUDF(UDFInfo); + } + } + + private void insertTable(String table, List fields, List types) { + StringBuilder builder = new StringBuilder("INSERT INTO "); + builder.append(table); + builder.append("(key, "); + for (String field : fields) { + builder.append(field); + builder.append(", "); + } + builder.setLength(builder.length() - 2); + builder.append(") VALUES "); + String insertPrefix = builder.toString(); + + long count = 0; + try (BufferedReader br = + new BufferedReader(new FileReader(String.format("%s/%s.tbl", DATA_DIR, table)))) { + StringBuilder sb = new StringBuilder(insertPrefix); + String line; + while ((line = br.readLine()) != null) { + String[] items = line.split("\\|"); + sb.append("("); + sb.append(count); // 插入自增key列 + count++; + sb.append(", "); + assert fields.size() == items.length; + for (int i = 0; i < items.length; i++) { + switch (types.get(i)) { + case NUM: + sb.append(items[i]); + sb.append(", "); + break; + case STR: // 字符串类型在外面需要包一层引号 + sb.append("\""); + sb.append(items[i]); + sb.append("\", "); + break; + case DATE: // 日期类型需要转为时间戳 + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); + long time = dateFormat.parse(items[i]).getTime(); + sb.append(time); + sb.append(", "); + break; + default: + break; + } + } + sb.setLength(sb.length() - 2); + sb.append("), "); + + // 每次最多插入10000条数据 + if (count % 10000 == 0) { + sb.setLength(sb.length() - 2); + sb.append(";"); + session.executeSql(sb.toString()); + sb = new StringBuilder(insertPrefix); + } + } + // 插入剩余数据 + if (sb.length() != insertPrefix.length()) { + sb.setLength(sb.length() - 2); + sb.append(";"); + session.executeSql(sb.toString()); + } + LOGGER.info("Insert {} records into table [{}].", count, table); + } catch (IOException | ParseException | SessionException e) { + LOGGER.error("Insert into table {} fail. Caused by:", table, e); + fail(); + } + } + + private void registerUDF(List UDFInfo) { + String SINGLE_UDF_REGISTER_SQL = "CREATE FUNCTION %s \"%s\" FROM \"%s\" IN \"%s\";"; + File udfFile = new File(UDF_DIR + UDFInfo.get(3)); + String register = + String.format( + SINGLE_UDF_REGISTER_SQL, + UDFInfo.get(0), + UDFInfo.get(1), + UDFInfo.get(2), + udfFile.getAbsolutePath()); + try { + LOGGER.info("Execute register UDF statement: {}", register); + session.executeRegisterTask(register, false); + } catch (SessionException e) { + LOGGER.error("Statement: \"{}\" execute fail. Caused by:", register, e); + fail(); + } + } + + // 插入TPC-H测试中的临时表 + @Test + public void insertTmpTable() { + for (int queryId : queryIds) { + String sqlString = null; + try { + sqlString = + TPCHUtils.readSqlFileAsString("src/test/resources/tpch/queries/q" + queryId + ".sql"); + } catch (IOException e) { + LOGGER.error("Fail to read sql file: q{}.sql. Caused by: ", queryId, e); + fail(); + } + String[] sqls = sqlString.split(";"); + if (sqls.length < 2) { + LOGGER.error("q{}.sql has no ';' in the end. Caused by: ", queryId); + fail(); + } else if (sqls.length == 2) { + // 只有一条查询语句,无需插入临时表 + continue; + } + // 处理插入临时表语句 + for (int i = 0; i < sqls.length - 2; i++) { + String sql = sqls[i] + ";"; + try { + session.executeSql(sql); + } catch (SessionException e) { + LOGGER.error("Statement: \"{}\" execute fail. Caused by:", sql, e); + fail(); + } + } + } + } +} diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHRegressionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHRegressionIT.java deleted file mode 100644 index 8b3bde7220..0000000000 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHRegressionIT.java +++ /dev/null @@ -1,529 +0,0 @@ -/* - * IGinX - the polystore system with high performance - * Copyright (C) Tsinghua University - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package cn.edu.tsinghua.iginx.integration.tpch; - -import static cn.edu.tsinghua.iginx.integration.controller.Controller.clearAllData; -import static cn.edu.tsinghua.iginx.integration.tpch.TPCHRegressionIT.FieldType.DATE; -import static cn.edu.tsinghua.iginx.integration.tpch.TPCHRegressionIT.FieldType.NUM; -import static cn.edu.tsinghua.iginx.integration.tpch.TPCHRegressionIT.FieldType.STR; -import static org.junit.Assert.fail; - -import cn.edu.tsinghua.iginx.exception.SessionException; -import cn.edu.tsinghua.iginx.integration.controller.Controller; -import cn.edu.tsinghua.iginx.integration.tool.ConfLoader; -import cn.edu.tsinghua.iginx.session.Session; -import cn.edu.tsinghua.iginx.session.SessionExecuteSqlResult; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Scanner; -import java.util.TimeZone; -import java.util.stream.Collectors; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class TPCHRegressionIT { - - private static final Logger LOGGER = LoggerFactory.getLogger(TPCHRegressionIT.class); - - // host info - protected static String defaultTestHost = "127.0.0.1"; - protected static int defaultTestPort = 6888; - protected static String defaultTestUser = "root"; - protected static String defaultTestPass = "root"; - - // .tbl文件所在目录 - private static final String dataDir = - System.getProperty("user.dir") + "/../tpc/TPC-H V3.0.1/data"; - - // udf文件所在目录 - private static final String udfDir = "src/test/resources/tpch/udf/"; - - // 最大重复测试次数 - private static int MAX_REPETITIONS_NUM; - - // 回归阈值 - private static double REGRESSION_THRESHOLD; - - protected static Session session; - - enum FieldType { - NUM, - STR, - DATE - } - - public TPCHRegressionIT() { - ConfLoader conf = new ConfLoader(Controller.CONFIG_FILE); - MAX_REPETITIONS_NUM = conf.getMaxRepetitionsNum(); - REGRESSION_THRESHOLD = conf.getRegressionThreshold(); - } - - @BeforeClass - public static void setUp() throws SessionException { - session = new Session(defaultTestHost, defaultTestPort, defaultTestUser, defaultTestPass); - session.openSession(); - } - - @AfterClass - public static void tearDown() throws SessionException { - clearAllData(session); - session.closeSession(); - } - - @Before - public void prepare() { - List tableList = - Arrays.asList( - "region", "nation", "supplier", "part", "partsupp", "customer", "orders", "lineitem"); - - List> fieldsList = new ArrayList<>(); - List> typesList = new ArrayList<>(); - - // region表 - fieldsList.add(Arrays.asList("r_regionkey", "r_name", "r_comment")); - typesList.add(Arrays.asList(NUM, STR, STR)); - - // nation表 - fieldsList.add(Arrays.asList("n_nationkey", "n_name", "n_regionkey", "n_comment")); - typesList.add(Arrays.asList(NUM, STR, NUM, STR)); - - // supplier表 - fieldsList.add( - Arrays.asList( - "s_suppkey", - "s_name", - "s_address", - "s_nationkey", - "s_phone", - "s_acctbal", - "s_comment")); - typesList.add(Arrays.asList(NUM, STR, STR, NUM, STR, NUM, STR)); - - // part表 - fieldsList.add( - Arrays.asList( - "p_partkey", - "p_name", - "p_mfgr", - "p_brand", - "p_type", - "p_size", - "p_container", - "p_retailprice", - "p_comment")); - typesList.add(Arrays.asList(NUM, STR, STR, STR, STR, NUM, STR, NUM, STR)); - - // partsupp表 - fieldsList.add( - Arrays.asList("ps_partkey", "ps_suppkey", "ps_availqty", "ps_supplycost", "ps_comment")); - typesList.add(Arrays.asList(NUM, NUM, NUM, NUM, STR)); - - // customer表 - fieldsList.add( - Arrays.asList( - "c_custkey", - "c_name", - "c_address", - "c_nationkey", - "c_phone", - "c_acctbal", - "c_mktsegment", - "c_comment")); - typesList.add(Arrays.asList(NUM, STR, STR, NUM, STR, NUM, STR, STR)); - - // orders表 - fieldsList.add( - Arrays.asList( - "o_orderkey", - "o_custkey", - "o_orderstatus", - "o_totalprice", - "o_orderdate", - "o_orderpriority", - "o_clerk", - "o_shippriority", - "o_comment")); - typesList.add(Arrays.asList(NUM, NUM, STR, NUM, DATE, STR, STR, NUM, STR)); - - // lineitem表 - fieldsList.add( - Arrays.asList( - "l_orderkey", - "l_partkey", - "l_suppkey", - "l_linenumber", - "l_quantity", - "l_extendedprice", - "l_discount", - "l_tax", - "l_returnflag", - "l_linestatus", - "l_shipdate", - "l_commitdate", - "l_receiptdate", - "l_shipinstruct", - "l_shipmode", - "l_comment")); - typesList.add( - Arrays.asList( - NUM, NUM, NUM, NUM, NUM, NUM, NUM, NUM, STR, STR, DATE, DATE, DATE, STR, STR, STR)); - - // 插入数据 - for (int i = 0; i < 8; i++) { - insertTable(tableList.get(i), fieldsList.get(i), typesList.get(i)); - } - - List> UDFInfos = new ArrayList<>(); - UDFInfos.add(Arrays.asList("UDTF", "extractYear", "UDFExtractYear", "udtf_extract_year.py")); - // 注册UDF函数 - for (List UDFInfo : UDFInfos) { - registerUDF(UDFInfo); - } - } - - private void insertTable(String table, List fields, List types) { - StringBuilder builder = new StringBuilder("INSERT INTO "); - builder.append(table); - builder.append("(key, "); - for (String field : fields) { - builder.append(field); - builder.append(", "); - } - builder.setLength(builder.length() - 2); - builder.append(") VALUES "); - String insertPrefix = builder.toString(); - - long count = 0; - try (BufferedReader br = - new BufferedReader(new FileReader(String.format("%s/%s.tbl", dataDir, table)))) { - StringBuilder sb = new StringBuilder(insertPrefix); - String line; - while ((line = br.readLine()) != null) { - String[] items = line.split("\\|"); - sb.append("("); - sb.append(count); // 插入自增key列 - count++; - sb.append(", "); - assert fields.size() == items.length; - for (int i = 0; i < items.length; i++) { - switch (types.get(i)) { - case NUM: - sb.append(items[i]); - sb.append(", "); - break; - case STR: // 字符串类型在外面需要包一层引号 - sb.append("\""); - sb.append(items[i]); - sb.append("\", "); - break; - case DATE: // 日期类型需要转为时间戳 - SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); - dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); - long time = dateFormat.parse(items[i]).getTime(); - sb.append(time); - sb.append(", "); - break; - default: - break; - } - } - sb.setLength(sb.length() - 2); - sb.append("), "); - - // 每次最多插入10000条数据 - if (count % 10000 == 0) { - sb.setLength(sb.length() - 2); - sb.append(";"); - session.executeSql(sb.toString()); - sb = new StringBuilder(insertPrefix); - } - } - // 插入剩余数据 - if (sb.length() != insertPrefix.length()) { - sb.setLength(sb.length() - 2); - sb.append(";"); - session.executeSql(sb.toString()); - } - LOGGER.info("Insert {} records into table [{}].", count, table); - } catch (IOException | ParseException | SessionException e) { - LOGGER.error("Insert into table {} fail. Caused by:", table, e); - fail(); - } - } - - private void registerUDF(List UDFInfo) { - String SINGLE_UDF_REGISTER_SQL = "CREATE FUNCTION %s \"%s\" FROM \"%s\" IN \"%s\";"; - File udfFile = new File(udfDir + UDFInfo.get(3)); - String register = - String.format( - SINGLE_UDF_REGISTER_SQL, - UDFInfo.get(0), - UDFInfo.get(1), - UDFInfo.get(2), - udfFile.getAbsolutePath()); - try { - LOGGER.info("Execute register UDF statement: {}", register); - session.executeRegisterTask(register, false); - } catch (SessionException e) { - LOGGER.error("Statement: \"{}\" execute fail. Caused by:", register, e); - fail(); - } - } - - @After - public void clearData() throws SessionException { - session.executeSql("CLEAR DATA;"); - } - - @Test - public void test() { - try { - // 获取当前JVM的Runtime实例 - Runtime runtime = Runtime.getRuntime(); - // 执行垃圾回收,尽量释放内存 - runtime.gc(); - // 获取执行语句前的内存使用情况 - long usedMemoryBefore = runtime.totalMemory() - runtime.freeMemory(); - long startTime; - // 13有问题 - List queryIds = Arrays.asList(1, 2, 3, 5, 6, 9, 10, 16, 17, 18, 19, 20); - for (int queryId : queryIds) { - // read from sql file - String sqlString = - readSqlFileAsString("src/test/resources/tpch/queries/q" + queryId + ".sql"); - // 开始 tpc-h 查询 - System.out.println("start tpc-h query " + queryId); - startTime = System.currentTimeMillis(); - // 执行查询语句, split by ; 最后一句为执行结果 - SessionExecuteSqlResult result = null; - String[] sqls = sqlString.split(";"); - for (String sql : sqls) { - if (sql.trim().isEmpty()) { - continue; - } - sql += ";"; - try { - result = session.executeSql(sql); - } catch (SessionException e) { - LOGGER.error("Statement: \"{}\" execute fail. Caused by:", sql, e); - fail(); - } - result.print(false, ""); - } - // 再次执行垃圾回收 - runtime.gc(); - // 获取执行语句后的内存使用情况 - long usedMemoryAfter = runtime.totalMemory() - runtime.freeMemory(); - // 计算内存使用的变化 - long memoryUsed = usedMemoryAfter - usedMemoryBefore; - // 输出内存使用情况 - System.out.println("Memory used by the statement: " + memoryUsed + " bytes"); - long timeCost = System.currentTimeMillis() - startTime; - System.out.println("end tpc-h query, time cost: " + timeCost + "ms"); - - // 验证 - List> values = result.getValues(); - List> answers = - csvReader("src/test/resources/tpch/sf0.1/q" + queryId + ".csv"); - if (values.size() != answers.size()) { - System.out.println("values.size() = " + values.size()); - System.out.println("answers.size() = " + answers.size()); - throw new RuntimeException("size not equal"); - } - for (int i = 0; i < values.size(); i++) { - for (int j = 0; j < values.get(i).size(); j++) { - if (result.getPaths().get(j).contains("address") - || result.getPaths().get(j).contains("comment") - || result.getPaths().get(j).contains("orderdate")) { - // TODO change unix time to date - continue; - } - // if only contains number and dot, then parse to double - if (values.get(i).get(j).toString().matches("-?[0-9]+.*[0-9]*")) { - double number = Double.parseDouble(values.get(i).get(j).toString()); - double answerNumber = Double.parseDouble(answers.get(i).get(j)); - if (answerNumber - number >= 1e-3 || number - answerNumber >= 1e-3) { - System.out.println("Number: " + number); - System.out.println("Answer number: " + answerNumber); - } - assert answerNumber - number < 1e-3 && number - answerNumber < 1e-3; - } else { - String resultString = - new String((byte[]) values.get(i).get(j), StandardCharsets.UTF_8); - String answerString = answers.get(i).get(j); - if (!resultString.equals(answerString)) { - System.out.println("Result string: " + resultString); - System.out.println("Answer string: " + answerString); - } - assert resultString.equals(answerString); - } - } - } - } - - String fileName = "src/test/resources/tpch/oldTimeCosts.txt"; - if (!Files.exists(Paths.get(fileName))) { // 文件不存在,即此次跑的是主分支代码,需要将查询时间写入文件 - List timeCosts = new ArrayList<>(); - for (int queryId : queryIds) { - // 开始 tpc-h 查询 - System.out.printf("start tpc-h query %d in main branch%n", queryId); - // read from sql file - String sqlString = - readSqlFileAsString("src/test/resources/tpch/queries/q" + queryId + ".sql"); - // 执行查询语句, split by ; 最后一句为执行结果 - String[] sqls = sqlString.split(";"); - - // 主分支上重复查询两次取平均值 - long sum = 0; - for (int i = 0; i < 2; i++) { - long timeCost = executeSQL(sqls[sqls.length - 2] + ";"); - sum += timeCost; - } - sum /= 2; - timeCosts.add(sum); - System.out.printf("end tpc-h query %d in main branch, time cost: %dms%n", queryId, sum); - } - writeToFile(timeCosts, fileName); - } else { // 文件存在,即此次跑的是新分支代码,需要读取文件进行比较 - List oldTimeCosts = readFromFile(fileName); - double multiplyPercentage = 1 + REGRESSION_THRESHOLD; - for (int i = 0; i < queryIds.size(); i++) { - double oldTimeCost = (double) oldTimeCosts.get(i); - double newTimeCost = 0; - List newTimeCosts = new ArrayList<>(); - boolean regressionDetected = true; - - while (newTimeCosts.size() < MAX_REPETITIONS_NUM) { - // 开始 tpc-h 查询 - System.out.printf("start tpc-h query %d in new branch%n", queryIds.get(i)); - // read from sql file - String sqlString = - readSqlFileAsString("src/test/resources/tpch/queries/q" + queryIds.get(i) + ".sql"); - // 执行查询语句, split by ; 最后一句为执行结果 - String[] sqls = sqlString.split(";"); - long timeCost = executeSQL(sqls[sqls.length - 2] + ";"); - System.out.printf( - "end tpc-h query %d in new branch, time cost: %dms%n", queryIds.get(i), timeCost); - newTimeCosts.add(timeCost); - newTimeCost = getMedian(newTimeCosts); - if (oldTimeCost * multiplyPercentage >= newTimeCost) { - regressionDetected = false; - break; - } - } - - // 重复10次后耗时仍超过阈值 - if (regressionDetected) { - System.out.printf( - "performance degradation of query %d exceeds %f%n", - queryIds.get(i), REGRESSION_THRESHOLD); - System.out.printf("old timing: %.3fms%n", oldTimeCost); - System.out.printf("new timing: %.3fms%n", newTimeCost); - LOGGER.error("TPC-H query {} regression test fail.", queryIds.get(i)); - fail(); - } - } - } - - } catch (IOException e) { - LOGGER.error("Test fail. Caused by:", e); - fail(); - } - } - - private static long executeSQL(String sql) { - long startTime = System.currentTimeMillis(); - try { - SessionExecuteSqlResult result = session.executeSql(sql); - } catch (SessionException e) { - LOGGER.error("Statement: \"{}\" execute fail. Caused by:", sql, e); - fail(); - } - return System.currentTimeMillis() - startTime; - } - - private static double getMedian(List array) { - Collections.sort(array); - int middle = array.size() / 2; - return array.size() % 2 == 0 - ? (array.get(middle - 1) + array.get(middle)) / 2.0 - : (double) array.get(middle); - } - - private static void writeToFile(List timeCosts, String fileName) throws IOException { - Path filePath = Paths.get(fileName); - List lines = timeCosts.stream().map(String::valueOf).collect(Collectors.toList()); - Files.write(filePath, lines); - } - - private static List readFromFile(String fileName) throws IOException { - Path filePath = Paths.get(fileName); - List lines = Files.readAllLines(filePath); - return lines.stream().map(Long::valueOf).collect(Collectors.toList()); - } - - private static List> csvReader(String filePath) { - List> data = new ArrayList<>(); - boolean skipHeader = true; - try (Scanner scanner = new Scanner(Paths.get(filePath))) { - while (scanner.hasNextLine()) { - String line = scanner.nextLine(); - if (skipHeader) { - skipHeader = false; - continue; - } - List row = Arrays.asList(line.split("\\|")); - data.add(row); - } - } catch (IOException e) { - LOGGER.error("Read file {} fail. Caused by:", filePath, e); - fail(); - } - System.out.println(data); - return data; - } - - private static String readSqlFileAsString(String filePath) throws IOException { - StringBuilder contentBuilder = new StringBuilder(); - try (BufferedReader br = new BufferedReader(new FileReader(filePath))) { - String line; - while ((line = br.readLine()) != null) { - contentBuilder.append(line).append("\n"); - } - } - return contentBuilder.toString(); - } -} diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHRegressionMainIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHRegressionMainIT.java new file mode 100644 index 0000000000..dca93d56a3 --- /dev/null +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHRegressionMainIT.java @@ -0,0 +1,117 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package cn.edu.tsinghua.iginx.integration.tpch; + +import cn.edu.tsinghua.iginx.exception.SessionException; +import cn.edu.tsinghua.iginx.integration.controller.Controller; +import cn.edu.tsinghua.iginx.integration.tool.ConfLoader; +import cn.edu.tsinghua.iginx.session.Session; +import java.util.ArrayList; +import java.util.List; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TPCHRegressionMainIT { + + private static final Logger LOGGER = LoggerFactory.getLogger(TPCHRegressionMainIT.class); + + // host info + protected static String defaultTestHost = "127.0.0.1"; + protected static int defaultTestPort = 6888; + protected static String defaultTestUser = "root"; + protected static String defaultTestPass = "root"; + + protected static Session session; + + static final String FAILED_QUERY_ID_PATH = + "src/test/resources/tpch/runtimeInfo/failedQueryIds.txt"; + + static final String ITERATION_TIMES_PATH = + "src/test/resources/tpch/runtimeInfo/iterationTimes.txt"; + + static final String MAIN_TIME_COSTS_PATH = "src/test/resources/tpch/runtimeInfo/oldTimeCosts.txt"; + + // 最大重复测试次数 + int MAX_REPETITIONS_NUM; + + List queryIds; + + // 当前查询次数 + int iterationTimes; + + // 是否需要验证正确性 + boolean needValidate; + + public TPCHRegressionMainIT() { + ConfLoader conf = new ConfLoader(Controller.CONFIG_FILE); + List lines = TPCHUtils.getLinesFromFile(ITERATION_TIMES_PATH); + iterationTimes = Integer.parseInt(lines.get(0)); + if (iterationTimes == 1) { + queryIds = conf.getQueryIds(); + } else { + lines = TPCHUtils.getLinesFromFile(FAILED_QUERY_ID_PATH); + queryIds = new ArrayList<>(); + for (String line : lines) { + queryIds.add(Integer.parseInt(line)); + } + } + // 第一次查询需要验证查询结果正确性 + needValidate = iterationTimes == 1; + MAX_REPETITIONS_NUM = conf.getMaxRepetitionsNum(); + } + + @BeforeClass + public static void setUp() throws SessionException { + session = new Session(defaultTestHost, defaultTestPort, defaultTestUser, defaultTestPass); + session.openSession(); + } + + @AfterClass + public static void tearDown() throws SessionException { + session.closeSession(); + } + + @Test + public void test() { + if (queryIds.isEmpty()) { + LOGGER.info("No query remain, skip test main branch."); + return; + } + LOGGER.info("QueryIds remain: {}", queryIds); + if (iterationTimes > MAX_REPETITIONS_NUM) { + LOGGER.error( + "Repeatedly executed query more than {} times, test failed.", MAX_REPETITIONS_NUM); + Assert.fail(); + } + + List> timeCosts = TPCHUtils.readTimeCostsFromFile(MAIN_TIME_COSTS_PATH); + for (int queryId : queryIds) { + long timeCost = TPCHUtils.executeTPCHQuery(session, queryId, needValidate); + timeCosts.get(queryId - 1).add(timeCost); + System.out.printf( + "Successfully execute TPC-H query %d in main branch in iteration %d, time cost: %dms%n", + queryId, iterationTimes, timeCost); + } + TPCHUtils.clearAndRewriteTimeCostsToFile(timeCosts, MAIN_TIME_COSTS_PATH); + } +} diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHRegressionNewIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHRegressionNewIT.java new file mode 100644 index 0000000000..a5c95dd82f --- /dev/null +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHRegressionNewIT.java @@ -0,0 +1,237 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package cn.edu.tsinghua.iginx.integration.tpch; + +import cn.edu.tsinghua.iginx.exception.SessionException; +import cn.edu.tsinghua.iginx.integration.controller.Controller; +import cn.edu.tsinghua.iginx.integration.tool.ConfLoader; +import cn.edu.tsinghua.iginx.session.Session; +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TPCHRegressionNewIT { + + private static final Logger LOGGER = LoggerFactory.getLogger(TPCHRegressionNewIT.class); + + // host info + protected static String defaultTestHost = "127.0.0.1"; + protected static int defaultTestPort = 6888; + protected static String defaultTestUser = "root"; + protected static String defaultTestPass = "root"; + + protected static Session session; + + static final String FAILED_QUERY_ID_PATH = + "src/test/resources/tpch/runtimeInfo/failedQueryIds.txt"; + + static final String ITERATION_TIMES_PATH = + "src/test/resources/tpch/runtimeInfo/iterationTimes.txt"; + + static final String MAIN_TIME_COSTS_PATH = "src/test/resources/tpch/runtimeInfo/oldTimeCosts.txt"; + + static final String NEW_TIME_COSTS_PATH = "src/test/resources/tpch/runtimeInfo/newTimeCosts.txt"; + + static final String STATUS_PATH = "src/test/resources/tpch/runtimeInfo/status.txt"; + + // 最大重复测试次数 + int MAX_REPETITIONS_NUM; + + // 回归阈值 + double REGRESSION_THRESHOLD; + + List queryIds; + + // 当前查询次数 + int iterationTimes; + + // 是否需要验证正确性 + boolean needValidate; + + public TPCHRegressionNewIT() { + ConfLoader conf = new ConfLoader(Controller.CONFIG_FILE); + List lines = TPCHUtils.getLinesFromFile(ITERATION_TIMES_PATH); + iterationTimes = Integer.parseInt(lines.get(0)); + if (iterationTimes == 1) { + queryIds = conf.getQueryIds(); + } else { + lines = TPCHUtils.getLinesFromFile(FAILED_QUERY_ID_PATH); + queryIds = new ArrayList<>(); + for (String line : lines) { + queryIds.add(Integer.parseInt(line)); + } + } + // 第一次查询需要验证查询结果正确性 + needValidate = iterationTimes == 1; + MAX_REPETITIONS_NUM = conf.getMaxRepetitionsNum(); + REGRESSION_THRESHOLD = conf.getRegressionThreshold(); + } + + @BeforeClass + public static void setUp() throws SessionException { + session = new Session(defaultTestHost, defaultTestPort, defaultTestUser, defaultTestPass); + session.openSession(); + } + + @AfterClass + public static void tearDown() throws SessionException { + session.closeSession(); + } + + @Test + public void test() { + if (queryIds.isEmpty()) { + LOGGER.info("No query remain, skip test new branch."); + return; + } + LOGGER.info("QueryIds remain: {}", queryIds); + if (iterationTimes > MAX_REPETITIONS_NUM) { + LOGGER.error( + "Repeatedly executed query more than {} times, test failed.", MAX_REPETITIONS_NUM); + Assert.fail(); + } + + List failedQueryIds = new ArrayList<>(); + List> oldTimeCosts = TPCHUtils.readTimeCostsFromFile(MAIN_TIME_COSTS_PATH); + List> newTimeCosts = TPCHUtils.readTimeCostsFromFile(NEW_TIME_COSTS_PATH); + double ratio = 1 + REGRESSION_THRESHOLD; + for (int queryId : queryIds) { + long timeCost = TPCHUtils.executeTPCHQuery(session, queryId, needValidate); + newTimeCosts.get(queryId - 1).add(timeCost); + System.out.printf( + "Successfully execute TPC-H query %d in new branch in iteration %d, time cost: %dms%n", + queryId, iterationTimes, timeCost); + + // 新旧分支查询次数不相同 + if (oldTimeCosts.get(queryId - 1).size() != newTimeCosts.get(queryId - 1).size()) { + LOGGER.error( + "Query {} run {} times in main branch, but {} times in new branch, please check.", + queryId, + oldTimeCosts.get(queryId - 1).size(), + newTimeCosts.get(queryId - 1).size()); + Assert.fail(); + } + + // 与主分支运行结果进行比较 + long oldTimeCostMedian = getMedian(oldTimeCosts.get(queryId - 1)); + long newTimeCostMedian = getMedian(newTimeCosts.get(queryId - 1)); + if (oldTimeCostMedian * ratio < newTimeCostMedian) { + if (iterationTimes >= MAX_REPETITIONS_NUM) { + LOGGER.error( + "Repeatedly executed query {} more than {} times, old time costs' median: {}ms, new time costs' median: {}ms, test failed.", + queryId, + MAX_REPETITIONS_NUM, + oldTimeCostMedian, + newTimeCostMedian); + Assert.fail(); + } + failedQueryIds.add(queryId); + continue; + } + LOGGER.info( + "Query {} passed after {} times' iterations, old time costs' median: {}ms, new time costs' median: {}ms.", + queryId, + iterationTimes, + oldTimeCostMedian, + newTimeCostMedian); + } + + if (failedQueryIds.isEmpty()) { + writeOKtoFile(); + } + + TPCHUtils.clearAndRewriteTimeCostsToFile(newTimeCosts, NEW_TIME_COSTS_PATH); + clearAndRewriteFailedQueryIdsToFile(failedQueryIds); + updateIterationTimes(); + } + + private long getMedian(List array) { + Collections.sort(array); + int middle = array.size() / 2; + return array.size() % 2 == 0 + ? (long) ((array.get(middle - 1) + array.get(middle)) / 2.0) + : array.get(middle); + } + + private void writeOKtoFile() { + try (FileWriter fileWriter = new FileWriter(STATUS_PATH); + BufferedWriter bufferedWriter = new BufferedWriter(fileWriter)) { + // 清空文件内容 + fileWriter.write(""); + fileWriter.flush(); + // 重新写入内容 + bufferedWriter.write("ok"); + } catch (IOException e) { + LOGGER.error("Write to file {} fail. Caused by:", STATUS_PATH, e); + Assert.fail(); + } + } + + private void clearAndRewriteFailedQueryIdsToFile(List failedQueryIds) { + Path path = Paths.get(FAILED_QUERY_ID_PATH); + if (!Files.exists(path)) { + try { + Files.createFile(path); + } catch (IOException e) { + LOGGER.error("Failed to create file {}. Caused by: ", FAILED_QUERY_ID_PATH, e); + Assert.fail(); + } + } + try (FileWriter fileWriter = new FileWriter(String.valueOf(path)); + BufferedWriter bufferedWriter = new BufferedWriter(fileWriter)) { + // 清空文件内容 + fileWriter.write(""); + fileWriter.flush(); + // 重新写入内容 + for (int failedQueryId : failedQueryIds) { + bufferedWriter.write(String.valueOf(failedQueryId)); + bufferedWriter.newLine(); + } + } catch (IOException e) { + LOGGER.error("Write to file {} fail. Caused by:", path.getFileName(), e); + Assert.fail(); + } + } + + private void updateIterationTimes() { + iterationTimes++; + try (FileWriter fileWriter = new FileWriter(ITERATION_TIMES_PATH); + BufferedWriter bufferedWriter = new BufferedWriter(fileWriter)) { + // 清空文件内容 + fileWriter.write(""); + fileWriter.flush(); + // 重新写入内容 + bufferedWriter.write(String.valueOf(iterationTimes)); + } catch (IOException e) { + LOGGER.error("Write to file {} fail. Caused by:", ITERATION_TIMES_PATH, e); + Assert.fail(); + } + } +} diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHUtils.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHUtils.java new file mode 100644 index 0000000000..d22b5a0e9a --- /dev/null +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHUtils.java @@ -0,0 +1,188 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package cn.edu.tsinghua.iginx.integration.tpch; + +import cn.edu.tsinghua.iginx.exception.SessionException; +import cn.edu.tsinghua.iginx.session.Session; +import cn.edu.tsinghua.iginx.session.SessionExecuteSqlResult; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Scanner; +import java.util.stream.Collectors; +import org.junit.Assert; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TPCHUtils { + + private static final Logger LOGGER = LoggerFactory.getLogger(TPCHUtils.class); + + public static String readSqlFileAsString(String filePath) throws IOException { + StringBuilder contentBuilder = new StringBuilder(); + try (BufferedReader br = new BufferedReader(new FileReader(filePath))) { + String line; + while ((line = br.readLine()) != null) { + contentBuilder.append(line).append("\n"); + } + } + return contentBuilder.toString(); + } + + public static List> readTimeCostsFromFile(String filename) { + List lines = getLinesFromFile(filename); + assert lines.size() == 22; + + // TPC-H一共有22条查询 + List> timeCosts = new ArrayList<>(22); + for (int i = 0; i < 22; i++) { + List tmp = new ArrayList<>(); + String[] lineArray = lines.get(i).split(","); + for (String str : lineArray) { + if (!str.isEmpty()) { + tmp.add(Long.parseLong(str)); + } + } + timeCosts.add(tmp); + } + return timeCosts; + } + + public static void clearAndRewriteTimeCostsToFile(List> timeCosts, String filename) { + try (FileWriter fileWriter = new FileWriter(filename); + BufferedWriter bufferedWriter = new BufferedWriter(fileWriter)) { + // 清空文件内容 + fileWriter.write(""); + fileWriter.flush(); + // 重新写入内容 + for (List timeCost : timeCosts) { + bufferedWriter.write( + timeCost.stream().map(String::valueOf).collect(Collectors.joining(","))); + bufferedWriter.newLine(); + } + } catch (IOException e) { + LOGGER.error("Write to file {} fail. Caused by:", filename, e); + Assert.fail(); + } + } + + public static List getLinesFromFile(String fileName) { + Path filePath = Paths.get(fileName); + List lines = null; + try { + lines = Files.readAllLines(filePath); + } catch (IOException e) { + LOGGER.error("Read file {} fail. Caused by:", filePath, e); + Assert.fail(); + } + return lines; + } + + public static long executeTPCHQuery(Session session, int queryId, boolean needValidate) { + String sqlString = null; + try { + sqlString = + TPCHUtils.readSqlFileAsString("src/test/resources/tpch/queries/q" + queryId + ".sql"); + } catch (IOException e) { + LOGGER.error("Fail to read sql file: q{}.sql. Caused by: ", queryId, e); + Assert.fail(); + } + String[] sqls = sqlString.split(";"); + String sql = sqls[sqls.length - 2] + ";"; + SessionExecuteSqlResult result = null; + long startTime = System.currentTimeMillis(); + try { + result = session.executeSql(sql); + } catch (SessionException e) { + LOGGER.error("Statement: \"{}\" execute fail. Caused by:", sql, e); + Assert.fail(); + } + long cost = System.currentTimeMillis() - startTime; + if (needValidate) { + validate(result, queryId); + } + return cost; + } + + private static void validate(SessionExecuteSqlResult result, int queryId) { + List> values = result.getValues(); + List> answers = csvReader("src/test/resources/tpch/sf0.1/q" + queryId + ".csv"); + if (values.size() != answers.size()) { + System.out.println("values.size() = " + values.size()); + System.out.println("answers.size() = " + answers.size()); + throw new RuntimeException("size not equal"); + } + for (int i = 0; i < values.size(); i++) { + for (int j = 0; j < values.get(i).size(); j++) { + if (result.getPaths().get(j).contains("address") + || result.getPaths().get(j).contains("comment") + || result.getPaths().get(j).contains("orderdate")) { + // TODO change unix time to date + continue; + } + // if only contains number and dot, then parse to double + if (values.get(i).get(j).toString().matches("-?[0-9]+.*[0-9]*")) { + double number = Double.parseDouble(values.get(i).get(j).toString()); + double answerNumber = Double.parseDouble(answers.get(i).get(j)); + if (answerNumber - number >= 1e-3 || number - answerNumber >= 1e-3) { + System.out.println("Number: " + number); + System.out.println("Answer number: " + answerNumber); + } + assert answerNumber - number < 1e-3 && number - answerNumber < 1e-3; + } else { + String resultString = new String((byte[]) values.get(i).get(j), StandardCharsets.UTF_8); + String answerString = answers.get(i).get(j); + if (!resultString.equals(answerString)) { + System.out.println("Result string: " + resultString); + System.out.println("Answer string: " + answerString); + } + assert resultString.equals(answerString); + } + } + } + } + + private static List> csvReader(String filePath) { + List> data = new ArrayList<>(); + boolean skipHeader = true; + try (Scanner scanner = new Scanner(Paths.get(filePath))) { + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); + if (skipHeader) { + skipHeader = false; + continue; + } + List row = Arrays.asList(line.split("\\|")); + data.add(row); + } + } catch (IOException e) { + LOGGER.error("Read file {} fail. Caused by:", filePath, e); + Assert.fail(); + } + return data; + } +} diff --git a/test/src/test/resources/testConfig.properties b/test/src/test/resources/testConfig.properties index 489bde4f2b..6d68075533 100644 --- a/test/src/test/resources/testConfig.properties +++ b/test/src/test/resources/testConfig.properties @@ -73,5 +73,6 @@ is_scaling=false DBCE_test_way=oriHasDataExpHasData # TPC-H test +query_ids=1,2,3,5,6,9,10,16,17,18,19,20 max_repetitions_num=10 regression_threshold=0.3 diff --git a/test/src/test/resources/tpch/runtimeInfo/failedQueryIds.txt b/test/src/test/resources/tpch/runtimeInfo/failedQueryIds.txt new file mode 100644 index 0000000000..00eb5f812a --- /dev/null +++ b/test/src/test/resources/tpch/runtimeInfo/failedQueryIds.txt @@ -0,0 +1,12 @@ +1 +2 +3 +5 +6 +9 +10 +16 +17 +18 +19 +20 \ No newline at end of file diff --git a/test/src/test/resources/tpch/runtimeInfo/iterationTimes.txt b/test/src/test/resources/tpch/runtimeInfo/iterationTimes.txt new file mode 100644 index 0000000000..56a6051ca2 --- /dev/null +++ b/test/src/test/resources/tpch/runtimeInfo/iterationTimes.txt @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/test/src/test/resources/tpch/runtimeInfo/newTimeCosts.txt b/test/src/test/resources/tpch/runtimeInfo/newTimeCosts.txt new file mode 100644 index 0000000000..901c11fe8f --- /dev/null +++ b/test/src/test/resources/tpch/runtimeInfo/newTimeCosts.txt @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/src/test/resources/tpch/runtimeInfo/oldTimeCosts.txt b/test/src/test/resources/tpch/runtimeInfo/oldTimeCosts.txt new file mode 100644 index 0000000000..901c11fe8f --- /dev/null +++ b/test/src/test/resources/tpch/runtimeInfo/oldTimeCosts.txt @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/src/test/resources/tpch/runtimeInfo/status.txt b/test/src/test/resources/tpch/runtimeInfo/status.txt new file mode 100644 index 0000000000..c852a940ea --- /dev/null +++ b/test/src/test/resources/tpch/runtimeInfo/status.txt @@ -0,0 +1 @@ +unfinished \ No newline at end of file From 2378e8b3f8cc5d6e0d3c95dada1791487ea7e1fc Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Sun, 21 Jul 2024 20:37:14 +0800 Subject: [PATCH 105/138] fix --- .../integration/expansion/redis/RedisHistoryDataGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisHistoryDataGenerator.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisHistoryDataGenerator.java index 5e9cbcb02f..b80dc2fdd9 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisHistoryDataGenerator.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisHistoryDataGenerator.java @@ -83,7 +83,7 @@ public void writeSpecialHistoryData() { @Override public void clearHistoryDataForGivenPort(int port) { Jedis jedis = new Jedis(LOCAL_IP, port); - jedis.flushDB(); + jedis.flushAll(); jedis.close(); LOGGER.info("clear data on 127.0.0.1:{} success!", port); } From c63034e5c30343ed7794f1d3d9aa076950a4f262 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Sun, 21 Jul 2024 21:44:28 +0800 Subject: [PATCH 106/138] open other test --- .github/workflows/standard-test-suite.yml | 66 +++++++++++------------ 1 file changed, 32 insertions(+), 34 deletions(-) diff --git a/.github/workflows/standard-test-suite.yml b/.github/workflows/standard-test-suite.yml index 0f841da109..67e41e0f75 100644 --- a/.github/workflows/standard-test-suite.yml +++ b/.github/workflows/standard-test-suite.yml @@ -1,46 +1,44 @@ name: Standard Test Suite -#on: -# pull_request: # when a PR is opened or reopened -# types: [opened, reopened] -# branches: -# - main - -on: [pull_request] +on: + pull_request: # when a PR is opened or reopened + types: [opened, reopened] + branches: + - main concurrency: group: "${{ github.workflow }}-${{ github.ref }}" cancel-in-progress: true jobs: - # unit-test: - # uses: ./.github/workflows/unit-test.yml - # unit-mds: - # uses: ./.github/workflows/unit-mds.yml - # case-regression: - # uses: ./.github/workflows/case-regression.yml - # with: - # metadata-matrix: '["zookeeper"]' - # standalone-test: - # uses: ./.github/workflows/standalone-test.yml - # with: - # metadata-matrix: '["zookeeper"]' - # standalone-test-pushdown: - # uses: ./.github/workflows/standalone-test-pushdown.yml - # with: - # metadata-matrix: '["zookeeper"]' + unit-test: + uses: ./.github/workflows/unit-test.yml + unit-mds: + uses: ./.github/workflows/unit-mds.yml + case-regression: + uses: ./.github/workflows/case-regression.yml + with: + metadata-matrix: '["zookeeper"]' + standalone-test: + uses: ./.github/workflows/standalone-test.yml + with: + metadata-matrix: '["zookeeper"]' + standalone-test-pushdown: + uses: ./.github/workflows/standalone-test-pushdown.yml + with: + metadata-matrix: '["zookeeper"]' db-ce: uses: ./.github/workflows/DB-CE.yml with: metadata-matrix: '["zookeeper"]' -# remote-test: -# uses: ./.github/workflows/remote-test.yml -# with: -# metadata-matrix: '["zookeeper"]' -# assemebly-test: -# uses: ./.github/workflows/assembly-test.yml -# tpc-h-regression-test: -# uses: ./.github/workflows/tpc-h.yml -# with: -# os-matrix: '["ubuntu-latest"]' -# metadata-matrix: '["zookeeper"]' + remote-test: + uses: ./.github/workflows/remote-test.yml + with: + metadata-matrix: '["zookeeper"]' + assemebly-test: + uses: ./.github/workflows/assembly-test.yml + tpc-h-regression-test: + uses: ./.github/workflows/tpc-h.yml + with: + os-matrix: '["ubuntu-latest"]' + metadata-matrix: '["zookeeper"]' From 6a0530f3697e353171cecdafe776985d64fb87b7 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Mon, 22 Jul 2024 09:50:20 +0800 Subject: [PATCH 107/138] feat(test): tpc-h test (new comp to main) (#400) --- .github/actions/dbConfWriter/action.yml | 4 +- .github/actions/dbRunner/action.yml | 10 ++- .github/actions/tpchDataWriter/action.yml | 28 +++++++++ .github/actions/tpchSingleTest/action.yml | 35 +++++------ .github/scripts/tpch/download_tpch_data.sh | 4 +- .github/workflows/tpc-h.yml | 62 +++++++------------ .../integration/tpch/TPCHDataGeneratorIT.java | 21 +++++-- .../tpch/TPCHRegressionMainIT.java | 2 +- .../integration/tpch/TPCHRegressionNewIT.java | 10 +-- .../test/resources/tpch/thu_cloud_download.py | 0 10 files changed, 104 insertions(+), 72 deletions(-) create mode 100644 .github/actions/tpchDataWriter/action.yml rename thu_cloud_download.py => test/src/test/resources/tpch/thu_cloud_download.py (100%) diff --git a/.github/actions/dbConfWriter/action.yml b/.github/actions/dbConfWriter/action.yml index eb73d32788..98a20de36a 100644 --- a/.github/actions/dbConfWriter/action.yml +++ b/.github/actions/dbConfWriter/action.yml @@ -59,7 +59,7 @@ runs: uses: ./.github/actions/edit with: paths: ${{ inputs.Root-Dir-Path }}/conf/config.properties - statements: s#dir=/path/to/your/parquet#dir=test/iginx_mn#g + statements: s#dir=/path/to/your/parquet#dir=${GITHUB_WORKSPACE}/test/iginx_mn#g - if: inputs.DB-name == 'Parquet' name: Modify IGinX Config @@ -101,7 +101,7 @@ runs: uses: ./.github/actions/edit with: paths: ${{ inputs.Root-Dir-Path }}/conf/config.properties - statements: s#dir=/path/to/your/filesystem#dir=test/iginx_mn#g + statements: s#dir=/path/to/your/filesystem#dir=${GITHUB_WORKSPACE}/test/iginx_mn#g - if: inputs.DB-name == 'FileSystem' name: Modify IGinX Config diff --git a/.github/actions/dbRunner/action.yml b/.github/actions/dbRunner/action.yml index 2a57acb4c7..b9993ace68 100644 --- a/.github/actions/dbRunner/action.yml +++ b/.github/actions/dbRunner/action.yml @@ -82,7 +82,10 @@ runs: shell: bash run: | cp -f "${GITHUB_WORKSPACE}/conf/config.properties" "${GITHUB_WORKSPACE}/conf/config.properties.bak" - if [[ "$RUNNER_OS" == "Linux" || "$RUNNER_OS" == "Windows" ]]; then + if [[ "$RUNNER_OS" == "Linux" ]]; then + chmod +x "${GITHUB_WORKSPACE}/.github/scripts/dataSources/parquet_linux_windows.sh" + "${GITHUB_WORKSPACE}/.github/scripts/dataSources/parquet_linux_windows.sh" 6667 6888 test/mn ${GITHUB_WORKSPACE}/test/iginx_mn false false conf/config.properties + elif [[ "$RUNNER_OS" == "Windows" ]]; then chmod +x "${GITHUB_WORKSPACE}/.github/scripts/dataSources/parquet_linux_windows.sh" "${GITHUB_WORKSPACE}/.github/scripts/dataSources/parquet_linux_windows.sh" 6667 6888 test/mn test/iginx_mn false false conf/config.properties elif [ "$RUNNER_OS" == "macOS" ]; then @@ -118,7 +121,10 @@ runs: shell: bash run: | cp -f "${GITHUB_WORKSPACE}/conf/config.properties" "${GITHUB_WORKSPACE}/conf/config.properties.bak" - if [[ "$RUNNER_OS" == "Linux" || "$RUNNER_OS" == "Windows" ]]; then + if [[ "$RUNNER_OS" == "Linux" ]]; then + chmod +x "${GITHUB_WORKSPACE}/.github/scripts/dataSources/filesystem_linux_windows.sh" + "${GITHUB_WORKSPACE}/.github/scripts/dataSources/filesystem_linux_windows.sh" 6667 6888 test/mn ${GITHUB_WORKSPACE}/test/iginx_mn false false conf/config.properties + elif [[ "$RUNNER_OS" == "Windows" ]]; then chmod +x "${GITHUB_WORKSPACE}/.github/scripts/dataSources/filesystem_linux_windows.sh" "${GITHUB_WORKSPACE}/.github/scripts/dataSources/filesystem_linux_windows.sh" 6667 6888 test/mn test/iginx_mn false false conf/config.properties elif [ "$RUNNER_OS" == "macOS" ]; then diff --git a/.github/actions/tpchDataWriter/action.yml b/.github/actions/tpchDataWriter/action.yml new file mode 100644 index 0000000000..6f40bdd56b --- /dev/null +++ b/.github/actions/tpchDataWriter/action.yml @@ -0,0 +1,28 @@ +name: "tpch-data-writer" +description: "insert data before test tpc-h" +inputs: + DB-name: + description: "DB name" + required: false + default: IoTDB12 + +runs: + using: "composite" # Mandatory parameter + steps: + - name: Start New IGinX + uses: ./.github/actions/iginxRunner + + - name: Insert Data and Register UDF + shell: bash + run: mvn test -q -Dtest=TPCHDataGeneratorIT -DfailIfNoTests=false -P-format + + - name: Show New IGinX log + if: always() + shell: bash + run: cat iginx-*.log + + - name: Stop New IGinX + uses: ./.github/actions/iginxRunner + with: + version: ${VERSION} + if-stop: "true" diff --git a/.github/actions/tpchSingleTest/action.yml b/.github/actions/tpchSingleTest/action.yml index a8c8d74a1a..4577cfcc7b 100644 --- a/.github/actions/tpchSingleTest/action.yml +++ b/.github/actions/tpchSingleTest/action.yml @@ -14,31 +14,29 @@ runs: steps: - name: Start Old IGinX if: inputs.status != 'ok' - uses: ./.github/actions/iginxRunner - # shell: bash - # run: | - # cd IGinX/core/target/iginx-core-${VERSION} - # pwd - # export IGINX_HOME=$PWD - # echo "IGinX home path: $IGINX_HOME" - # cd .. - # chmod +x iginx-core-${VERSION}/sbin/start_iginx.sh - # nohup iginx-core-${VERSION}/sbin/start_iginx.sh > ../../iginx-${VERSION}.log 2>&1 & + shell: bash + run: | + cd IGinX/core/target/iginx-core-${VERSION} + pwd + export IGINX_HOME=$PWD + echo "IGinX home path: $IGINX_HOME" + cd .. + chmod +x iginx-core-${VERSION}/sbin/start_iginx.sh + nohup iginx-core-${VERSION}/sbin/start_iginx.sh > ../../iginx-${VERSION}.log 2>&1 & - name: Run TPCH Test on Old IGinX if: inputs.status != 'ok' shell: bash run: | + cp -f test/src/test/resources/tpch/runtimeInfo/failedQueryIds.txt IGinX/test/src/test/resources/tpch/runtimeInfo/failedQueryIds.txt + cp -f test/src/test/resources/tpch/runtimeInfo/iterationTimes.txt IGinX/test/src/test/resources/tpch/runtimeInfo/iterationTimes.txt + cd IGinX mvn test -q -Dtest=TPCHRegressionMainIT -DfailIfNoTests=false -P-format - # cp test/src/test/resources/tpch/runtimeInfo/failedQueryIds.txt IGinX/test/src/test/resources/tpch/runtimeInfo/ - # cp test/src/test/resources/tpch/runtimeInfo/iteratoionTimes.txt IGinX/test/src/test/resources/tpch/runtimeInfo/ - # mvn test -q -Dtest=TPCHRegressionMainIT -DfailIfNoTests=false -P-format - name: Show Old IGinX log - if: inputs.status != 'ok' + if: always() shell: bash - run: cat iginx-*.log - # run: cat IGinX/iginx-*.log + run: cat IGinX/iginx-*.log - name: Stop Old IGinX if: inputs.status != 'ok' @@ -55,12 +53,11 @@ runs: if: inputs.status != 'ok' shell: bash run: | + cp -f IGinX/test/src/test/resources/tpch/runtimeInfo/oldTimeCosts.txt test/src/test/resources/tpch/runtimeInfo/oldTimeCosts.txt mvn test -q -Dtest=TPCHRegressionNewIT -DfailIfNoTests=false -P-format - # cp IGinX/test/src/test/resources/tpch/runtimeInfo/oldTimeCosts.txt test/src/test/resources/tpch/runtimeInfo/ - # mvn test -q -Dtest=TPCHRegressionNewIT -DfailIfNoTests=false -P-format - name: Show New IGinX log - if: inputs.status != 'ok' + if: always() shell: bash run: cat iginx-*.log diff --git a/.github/scripts/tpch/download_tpch_data.sh b/.github/scripts/tpch/download_tpch_data.sh index f5aeecad85..e6707b1c84 100644 --- a/.github/scripts/tpch/download_tpch_data.sh +++ b/.github/scripts/tpch/download_tpch_data.sh @@ -19,11 +19,11 @@ if [ "$RUNNER_OS" = "Windows" ]; then - python thu_cloud_download.py \ + python test/src/test/resources/tpch/thu_cloud_download.py \ -l https://cloud.tsinghua.edu.cn/d/740c158819bc4759a36e/ \ -s "." else - python3 thu_cloud_download.py \ + python3 test/src/test/resources/tpch/thu_cloud_download.py \ -l https://cloud.tsinghua.edu.cn/d/740c158819bc4759a36e/ \ -s "." fi diff --git a/.github/workflows/tpc-h.yml b/.github/workflows/tpc-h.yml index eb0983aed0..2622175de3 100644 --- a/.github/workflows/tpc-h.yml +++ b/.github/workflows/tpc-h.yml @@ -89,59 +89,45 @@ jobs: with: DB-name: ${{ matrix.DB-name }} - # - name: Get Old Version IGinX - # shell: bash - # run: git clone https://github.com/IGinX-THU/IGinX.git - # - # - name: Rewrite DB Conf in Old IGinX - # uses: ./.github/actions/dbConfWriter - # with: - # DB-name: ${{ matrix.DB-name }} - # Root-Dir-Path: "IGinX" - # - # - name: Install Old IGinX with Maven - # shell: bash - # run: | - # cd IGinX - # mvn clean package -DskipTests -P-format -q - # - # - name: Change Old IGinX config - # uses: ./.github/actions/confWriter - # with: - # DB-name: ${{ matrix.DB-name }} - # Set-Filter-Fragment-OFF: "true" - # Metadata: ${{ matrix.metadata }} - # Root-Dir-Path: "IGinX" + - name: Get Old Version IGinX + shell: bash + run: git clone https://github.com/IGinX-THU/IGinX.git - - name: Install New IGinX with Maven + - name: Rewrite DB Conf in Old IGinX + uses: ./.github/actions/dbConfWriter + with: + DB-name: ${{ matrix.DB-name }} + Root-Dir-Path: "IGinX" + + - name: Install Old IGinX with Maven shell: bash run: | + cd IGinX mvn clean package -DskipTests -P-format -q - - name: Change New IGinX config + - name: Change Old IGinX Config uses: ./.github/actions/confWriter with: DB-name: ${{ matrix.DB-name }} Set-Filter-Fragment-OFF: "true" Metadata: ${{ matrix.metadata }} + Root-Dir-Path: "IGinX" - - name: Start New IGinX - uses: ./.github/actions/iginxRunner - - - name: Insert Data and Register UDF + - name: Install New IGinX with Maven shell: bash - run: mvn test -q -Dtest=TPCHDataGeneratorIT -DfailIfNoTests=false -P-format + run: mvn clean package -DskipTests -P-format -q - - name: Stop New IGinX - uses: ./.github/actions/iginxRunner + - name: Change New IGinX Config + uses: ./.github/actions/confWriter with: - version: ${VERSION} - if-stop: "true" + DB-name: ${{ matrix.DB-name }} + Set-Filter-Fragment-OFF: "true" + Metadata: ${{ matrix.metadata }} - - name: Show New IGinX log - if: always() - shell: bash - run: cat iginx-*.log + - name: Insert Data into DB + uses: ./.github/actions/tpchDataWriter + with: + DB-name: ${{ matrix.DB-name }} - name: Run 1st Regression Test id: test1 diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHDataGeneratorIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHDataGeneratorIT.java index 4ee261646d..1472236bde 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHDataGeneratorIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHDataGeneratorIT.java @@ -54,11 +54,14 @@ public class TPCHDataGeneratorIT { protected static String defaultTestPass = "root"; // .tbl文件所在目录 - private static final String DATA_DIR = - System.getProperty("user.dir") + "/../tpc/TPC-H V3.0.1/data"; + static final String DATA_DIR = System.getProperty("user.dir") + "/../tpc/TPC-H V3.0.1/data"; // udf文件所在目录 - private static final String UDF_DIR = "src/test/resources/tpch/udf/"; + static final String UDF_DIR = "src/test/resources/tpch/udf/"; + + static final String SHOW_FUNCTION = "SHOW FUNCTIONS;"; + + static final String SINGLE_UDF_REGISTER_SQL = "CREATE FUNCTION %s \"%s\" FROM \"%s\" IN \"%s\";"; protected static Session session; @@ -268,7 +271,17 @@ private void insertTable(String table, List fields, List type } private void registerUDF(List UDFInfo) { - String SINGLE_UDF_REGISTER_SQL = "CREATE FUNCTION %s \"%s\" FROM \"%s\" IN \"%s\";"; + String result = ""; + try { + result = session.executeSql(SHOW_FUNCTION).getResultInString(false, ""); + } catch (SessionException e) { + LOGGER.error("Statement: \"{}\" execute fail. Caused by:", SHOW_FUNCTION, e); + fail(); + } + // UDF已注册 + if (result.contains(UDFInfo.get(1))) { + return; + } File udfFile = new File(UDF_DIR + UDFInfo.get(3)); String register = String.format( diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHRegressionMainIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHRegressionMainIT.java index dca93d56a3..57b695368c 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHRegressionMainIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHRegressionMainIT.java @@ -92,7 +92,7 @@ public static void tearDown() throws SessionException { } @Test - public void test() { + public void testMainBranch() { if (queryIds.isEmpty()) { LOGGER.info("No query remain, skip test main branch."); return; diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHRegressionNewIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHRegressionNewIT.java index a5c95dd82f..9c2bc79f13 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHRegressionNewIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/tpch/TPCHRegressionNewIT.java @@ -106,7 +106,7 @@ public static void tearDown() throws SessionException { } @Test - public void test() { + public void testNewBranch() { if (queryIds.isEmpty()) { LOGGER.info("No query remain, skip test new branch."); return; @@ -125,9 +125,11 @@ public void test() { for (int queryId : queryIds) { long timeCost = TPCHUtils.executeTPCHQuery(session, queryId, needValidate); newTimeCosts.get(queryId - 1).add(timeCost); - System.out.printf( - "Successfully execute TPC-H query %d in new branch in iteration %d, time cost: %dms%n", - queryId, iterationTimes, timeCost); + LOGGER.info( + "Successfully execute TPC-H query {} in new branch in iteration {}, time cost: {}ms", + queryId, + iterationTimes, + timeCost); // 新旧分支查询次数不相同 if (oldTimeCosts.get(queryId - 1).size() != newTimeCosts.get(queryId - 1).size()) { diff --git a/thu_cloud_download.py b/test/src/test/resources/tpch/thu_cloud_download.py similarity index 100% rename from thu_cloud_download.py rename to test/src/test/resources/tpch/thu_cloud_download.py From b0da6814c93a29a3ca45e6bc6f6053421a89e9a8 Mon Sep 17 00:00:00 2001 From: ZM <12236590+shinyano@users.noreply.github.com> Date: Mon, 22 Jul 2024 09:57:57 +0800 Subject: [PATCH 108/138] feat(core): allow scheduling transform jobs (#366) Allow user to schedule their defined transform jobs with advanced options. Users can now specify the exact time for execution or set up recurring schedules. Usage: Add this line to the end of YAML file that defines your transform job. schedule: "" Formats The can be in one of the following four formats: Recurring Execution: every 3 second/minute/hour/day/month/year: Executes every 3 seconds/minutes/hours/days/months/years. every 3 minute starts '2024-07-19 12:00:00' ends '2024-07-20 12:00:00': From 2024-07-19 12:00:00 to 2024-07-20 12:00:00, execute job every 3 minutes. every 3 minute ends '23:59:59': From now to 23:59:59 same day, execute job every 3 minutes. every 3 minute starts '13:00:00': From 13:00:00 today, execute job every 3 minutes forever. every mon,wed: Executes every Monday and Wednesday. Delayed Execution: after 3 second/minute/hour/day/month/year: Executes once after 3 seconds/minutes/hours/days/months/years. Specific Time Execution: at '2024-07-19 12:00:00': Executes once at the specified time. at '12:00:00': Executes once at the specified time today. Cron Format: A cron-formatted string. Cron string reference: Quartz cron trigger tutorials --- conf/config.properties | 5 +- core/pom.xml | 10 + .../tsinghua/iginx/transform/api/Runner.java | 5 +- .../tsinghua/iginx/transform/api/Writer.java | 3 + .../iginx/transform/data/ArrowWriter.java | 3 + .../transform/data/CollectionWriter.java | 5 + .../iginx/transform/data/Exporter.java | 3 + .../transform/data/FileAppendWriter.java | 5 + .../iginx/transform/data/IginXWriter.java | 3 + .../iginx/transform/data/LogWriter.java | 5 + .../iginx/transform/data/PemjaWriter.java | 3 + .../transform/exec/BatchStageRunner.java | 9 + .../iginx/transform/exec/JobRunner.java | 73 ++-- .../iginx/transform/exec/ScheduledJob.java | 71 ++++ .../transform/exec/StreamStageRunner.java | 10 + .../transform/exec/TransformJobManager.java | 56 ++- .../tsinghua/iginx/transform/pojo/Job.java | 27 +- .../pojo/JobScheduleTriggerMaker.java | 395 ++++++++++++++++++ .../pojo/TransformJobFinishListener.java | 70 ++++ .../tsinghua/iginx/transform/TriggerTest.java | 354 ++++++++++++++++ .../edu/tsinghua/iginx/session/Session.java | 10 + .../edu/tsinghua/iginx/utils/JobFromYAML.java | 9 + .../edu/tsinghua/iginx/utils/YAMLReader.java | 2 + .../integration/func/udf/TransformIT.java | 188 ++++++++- .../transform/TransformScheduledAfter10s.yaml | 9 + .../TransformScheduledAt10sFromNow.yaml | 9 + .../transform/TransformScheduledCron.yaml | 9 + .../transform/TransformScheduledEvery10s.yaml | 9 + thrift/src/main/proto/rpc.thrift | 2 + 29 files changed, 1301 insertions(+), 61 deletions(-) create mode 100644 core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/ScheduledJob.java create mode 100644 core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/JobScheduleTriggerMaker.java create mode 100644 core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/TransformJobFinishListener.java create mode 100644 core/src/test/java/cn/edu/tsinghua/iginx/transform/TriggerTest.java create mode 100644 test/src/test/resources/transform/TransformScheduledAfter10s.yaml create mode 100644 test/src/test/resources/transform/TransformScheduledAt10sFromNow.yaml create mode 100644 test/src/test/resources/transform/TransformScheduledCron.yaml create mode 100644 test/src/test/resources/transform/TransformScheduledEvery10s.yaml diff --git a/conf/config.properties b/conf/config.properties index f56d4ba3ec..fc45be4f78 100644 --- a/conf/config.properties +++ b/conf/config.properties @@ -220,7 +220,10 @@ asyncRestThreadPool=100 ########################## ### Python配置 ########################## -# python脚本启动命令,建议使用"which python"查询出的绝对路径,如下所示 +# python脚本启动命令 +# 在Windows上需将python3改为python +# pythonCMD=python +# 在unix上,建议使用"which python"查询出的绝对路径,如下所示 #pythonCMD=/Library/Frameworks/Python.framework/Versions/3.7/bin/python3 pythonCMD=python3 diff --git a/core/pom.xml b/core/pom.xml index b232c0c0d1..aa6fc845be 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -203,6 +203,16 @@ 1.6.15 test + + org.quartz-scheduler + quartz + 2.3.2 + + + org.quartz-scheduler + quartz-jobs + 2.3.2 + diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/api/Runner.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/api/Runner.java index c7097610ee..2d8a0a617d 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/api/Runner.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/api/Runner.java @@ -19,12 +19,15 @@ package cn.edu.tsinghua.iginx.transform.api; import cn.edu.tsinghua.iginx.transform.exception.TransformException; +import org.quartz.SchedulerException; public interface Runner { - void start() throws TransformException; + void start() throws TransformException, SchedulerException; void run() throws TransformException; void close() throws TransformException; + + boolean scheduled(); } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/api/Writer.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/api/Writer.java index d9e12a244e..82ae54a2fe 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/api/Writer.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/api/Writer.java @@ -24,4 +24,7 @@ public interface Writer { void writeBatch(BatchData batchData) throws WriteBatchException; + + // reset state for next scheduled run + void reset(); } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/ArrowWriter.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/ArrowWriter.java index 1714c6d88f..05eb2c596a 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/ArrowWriter.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/ArrowWriter.java @@ -86,4 +86,7 @@ public void writeBatch(BatchData batchData) throws WriteBatchException { throw new WriteBatchException("ArrowWriter fail to write batch", e); } } + + @Override + public void reset() {} } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/CollectionWriter.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/CollectionWriter.java index 1dde14fd81..cfdacf5dbf 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/CollectionWriter.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/CollectionWriter.java @@ -37,4 +37,9 @@ public void write(BatchData batchData) { public BatchData getCollectedData() { return collectedData; } + + @Override + public void reset() { + collectedData = null; + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/Exporter.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/Exporter.java index 7408118e30..52ca86a676 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/Exporter.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/Exporter.java @@ -23,4 +23,7 @@ public interface Exporter { Mutex getMutex(); + + // reset state for next scheduled run + void reset(); } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/FileAppendWriter.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/FileAppendWriter.java index 8f9eea77eb..110a992f9d 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/FileAppendWriter.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/FileAppendWriter.java @@ -111,4 +111,9 @@ private void writeFile(String fileName, String content) { LOGGER.error("unexpected error: ", e); } } + + @Override + public void reset() { + hasWriteHeader = false; + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/IginXWriter.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/IginXWriter.java index c81108f4c9..f83fbec8a8 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/IginXWriter.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/IginXWriter.java @@ -95,4 +95,7 @@ private String reformatPath(String path) { path = path.replaceAll("[}]", "]"); return path; } + + @Override + public void reset() {} } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/LogWriter.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/LogWriter.java index 8049aed459..0520bd2526 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/LogWriter.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/LogWriter.java @@ -50,4 +50,9 @@ public void write(BatchData batchData) { LOGGER.info(row.toCSVTypeString()); }); } + + @Override + public void reset() { + hasWriteHeader = false; + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/PemjaWriter.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/PemjaWriter.java index e7536d444f..311da56331 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/PemjaWriter.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/data/PemjaWriter.java @@ -34,4 +34,7 @@ public PemjaWriter(PemjaWorker worker) { public void writeBatch(BatchData batchData) throws WriteBatchException { worker.process(batchData); } + + @Override + public void reset() {} } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/BatchStageRunner.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/BatchStageRunner.java index d186a2faad..6cab1ff374 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/BatchStageRunner.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/BatchStageRunner.java @@ -75,8 +75,17 @@ public void run() throws WriteBatchException { // wait for py work finish writing. mutex.lock(); + + mutex.unlock(); + writer.reset(); } @Override public void close() {} + + // schedule config would be set at higher level + @Override + public boolean scheduled() { + return false; + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/JobRunner.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/JobRunner.java index aa388b269f..bea851de4b 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/JobRunner.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/JobRunner.java @@ -22,13 +22,17 @@ import cn.edu.tsinghua.iginx.thrift.JobState; import cn.edu.tsinghua.iginx.transform.api.Runner; import cn.edu.tsinghua.iginx.transform.api.Stage; -import cn.edu.tsinghua.iginx.transform.exception.TransformException; import cn.edu.tsinghua.iginx.transform.exception.UnknownDataFlowException; import cn.edu.tsinghua.iginx.transform.pojo.BatchStage; import cn.edu.tsinghua.iginx.transform.pojo.Job; import cn.edu.tsinghua.iginx.transform.pojo.StreamStage; +import cn.edu.tsinghua.iginx.transform.pojo.TransformJobFinishListener; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import org.quartz.*; +import org.quartz.impl.StdSchedulerFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -39,13 +43,15 @@ public class JobRunner implements Runner { private final List runnerList; + private Scheduler scheduler; + public JobRunner(Job job) { this.job = job; this.runnerList = new ArrayList<>(); } @Override - public void start() throws UnknownDataFlowException { + public void start() throws UnknownDataFlowException, SchedulerException { for (Stage stage : job.getStageList()) { DataFlowType dataFlowType = stage.getStageType(); switch (dataFlowType) { @@ -60,41 +66,54 @@ public void start() throws UnknownDataFlowException { throw new UnknownDataFlowException(dataFlowType); } } + scheduler = StdSchedulerFactory.getDefaultScheduler(); + + JobDetail jobDetail = JobBuilder.newJob(ScheduledJob.class).build(); + + jobDetail.getJobDataMap().put("runnerList", runnerList); + jobDetail.getJobDataMap().put("job", job); + + Trigger trigger = job.getTrigger(); + LOGGER.info( + "Trigger details: StartTime={}, EndTime={}, NextFireTime={}", + trigger.getStartTime(), + trigger.getEndTime(), + trigger.getNextFireTime()); + + scheduler.scheduleJob(jobDetail, trigger); } @Override public void run() { - job.setState(JobState.JOB_RUNNING); - try { - for (Runner runner : runnerList) { - runner.start(); - runner.run(); - runner.close(); - } - // we don't need this.close() because all children runners are closed. - if (job.getActive().compareAndSet(true, false)) { - job.setState(JobState.JOB_FINISHED); - job.setException(null); - } - } catch (TransformException e) { - LOGGER.error("Fail to run transform job id={}, because", job.getJobId(), e); - if (job.getActive().compareAndSet(true, false)) { - job.setState(JobState.JOB_FAILING); - job.setException(e); - close(); - job.setState(JobState.JOB_FAILED); - } - } + // idle: waiting for scheduler to fire jobs + job.setState(JobState.JOB_IDLE); + ExecutorService executor = Executors.newSingleThreadExecutor(); + executor.submit( + // 新起一个线程 + () -> { + try { + scheduler.getListenerManager().addTriggerListener(new TransformJobFinishListener()); + LOGGER.info("Starting scheduler..."); + scheduler.start(); // 启动调度器 + LOGGER.info("Scheduler started"); + } catch (SchedulerException e) { + LOGGER.error("Failed to start scheduler", e); + job.setState(JobState.JOB_FAILED); + } + }); } @Override public void close() { try { - for (Runner runner : runnerList) { - runner.close(); - } - } catch (TransformException e) { + scheduler.shutdown(); + } catch (SchedulerException e) { LOGGER.error("Fail to close Transform job runner id={}, because", job.getJobId(), e); } } + + @Override + public boolean scheduled() { + return job.isScheduled(); + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/ScheduledJob.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/ScheduledJob.java new file mode 100644 index 0000000000..f6cae81aab --- /dev/null +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/ScheduledJob.java @@ -0,0 +1,71 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package cn.edu.tsinghua.iginx.transform.exec; + +import cn.edu.tsinghua.iginx.thrift.JobState; +import cn.edu.tsinghua.iginx.transform.api.Runner; +import cn.edu.tsinghua.iginx.transform.exception.TransformException; +import cn.edu.tsinghua.iginx.transform.pojo.Job; +import java.util.List; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.quartz.SchedulerException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ScheduledJob implements org.quartz.Job { + private static final Logger LOGGER = LoggerFactory.getLogger(ScheduledJob.class); + + @Override + public void execute(JobExecutionContext context) throws JobExecutionException { + Job job = (Job) context.getMergedJobDataMap().get("job"); + List runnerList = (List) context.getMergedJobDataMap().get("runnerList"); + + job.setState(JobState.JOB_RUNNING); + job.getActive().compareAndSet(false, true); + try { + for (Runner runner : runnerList) { + runner.start(); + runner.run(); + runner.close(); + } + if (job.getActive().compareAndSet(true, false)) { + // wait for next execution + job.setState(JobState.JOB_IDLE); + job.setException(null); + } + // if a trigger has finished all execution, TransformJobFinishListener will handle work left. + } catch (TransformException | SchedulerException e) { + job.setState(JobState.JOB_FAILING); + job.setException(e); + try { + for (Runner runner : runnerList) { + runner.close(); + } + } catch (TransformException closeException) { + LOGGER.error("can't close job: {}", job.getJobId()); + } + JobExecutionException e2 = new JobExecutionException(e); + // Quartz will automatically unschedule + // all triggers associated with this job + // so that it does not run again + e2.setUnscheduleAllTriggers(true); + throw e2; + } + } +} diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/StreamStageRunner.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/StreamStageRunner.java index d10f301699..b47eeb3bfe 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/StreamStageRunner.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/StreamStageRunner.java @@ -121,6 +121,10 @@ public void run() throws WriteBatchException { // wait for last batch finished. mutex.lock(); + + // unlock for further scheduled runs + mutex.unlock(); + writer.reset(); } @Override @@ -129,4 +133,10 @@ public void close() { reader.close(); } } + + // schedule config would be set at higher level + @Override + public boolean scheduled() { + return false; + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/TransformJobManager.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/TransformJobManager.java index 64ec4051f2..6a5402a570 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/TransformJobManager.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/exec/TransformJobManager.java @@ -25,6 +25,7 @@ import cn.edu.tsinghua.iginx.thrift.JobState; import cn.edu.tsinghua.iginx.thrift.TaskType; import cn.edu.tsinghua.iginx.transform.api.Checker; +import cn.edu.tsinghua.iginx.transform.exception.TransformException; import cn.edu.tsinghua.iginx.transform.pojo.Job; import cn.edu.tsinghua.iginx.transform.pojo.PythonTask; import cn.edu.tsinghua.iginx.transform.pojo.Task; @@ -107,20 +108,15 @@ private void process(Job job) throws Exception { runner.start(); jobRunnerMap.put(job.getJobId(), runner); runner.run(); - jobRunnerMap.remove(job.getJobId()); // since we will retry, we can't do this in finally } catch (Exception e) { LOGGER.error("Fail to process transform job id={}, because", job.getJobId(), e); throw e; - } finally { - // TODO: is it legal to retry after runner.close()??? - // TODO: - // we don't need to close runner for FINISHED or FAILED jobs - // can we move runner.close() into catch clause? - runner.close(); } // TODO: should we set end time and log time cost for failed jobs? - job.setEndTime(System.currentTimeMillis()); - LOGGER.info("Job id={} cost {} ms.", job.getJobId(), job.getEndTime() - job.getStartTime()); + if (!runner.scheduled()) { + job.setEndTime(System.currentTimeMillis()); + LOGGER.info("Job id={} cost {} ms.", job.getJobId(), job.getEndTime() - job.getStartTime()); + } } public boolean cancel(long jobId) { @@ -147,22 +143,40 @@ public boolean cancel(long jobId) { switch (job.getState()) { // won't be null case JOB_RUNNING: case JOB_CREATED: - break; // continue execution + // atomic guard + if (!job.getActive().compareAndSet(true, false)) { + return false; + } + case JOB_IDLE: + // reorder as Normal run: [set-ING,] close, set-ED, remove[, set end time, log time cost]. + job.setState(JobState.JOB_CLOSING); + runner.close(); + job.setState(JobState.JOB_CLOSED); + jobRunnerMap.remove(jobId); + job.setEndTime(System.currentTimeMillis()); + LOGGER.info("Job id={} cost {} ms.", job.getJobId(), job.getEndTime() - job.getStartTime()); + return true; default: return false; } - // atomic guard - if (!job.getActive().compareAndSet(true, false)) { - return false; + } + + public void removeFinishedScheduleJob(long jobID) throws TransformException { + Job job = jobMap.get(jobID); + if (job == null) { + throw new TransformException("No job with id: " + jobID + " exists."); + } + JobRunner runner = jobRunnerMap.get(jobID); + if (runner == null) { + throw new TransformException("No job runner with id: " + jobID + " exists."); + } + if (job.getState() == JobState.JOB_FINISHED) { + jobRunnerMap.remove(jobID); + runner.close(); + return; } - // reorder as Normal run: [set-ING,] close, set-ED, remove[, set end time, log time cost]. - job.setState(JobState.JOB_CLOSING); - runner.close(); - job.setState(JobState.JOB_CLOSED); - jobRunnerMap.remove(jobId); - job.setEndTime(System.currentTimeMillis()); - LOGGER.info("Job id={} cost {} ms.", job.getJobId(), job.getEndTime() - job.getStartTime()); - return true; + throw new TransformException( + "Job with id: " + jobID + "did not finish correctly. Current state: " + job.getState()); } public JobState queryJobState(long jobId) { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/Job.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/Job.java index 8a42a0bf1f..877dc9e1e3 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/Job.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/Job.java @@ -27,6 +27,8 @@ import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import lombok.Data; +import org.quartz.Trigger; +import org.quartz.TriggerBuilder; @Data public class Job { @@ -48,11 +50,15 @@ public class Job { private final List taskList; private final List stageList; + private boolean scheduled = false; + private String scheduleStr = null; + private final Trigger trigger; + public Job(long id, CommitTransformJobReq req) { jobId = id; sessionId = req.getSessionId(); state = JobState.JOB_CREATED; - active = new AtomicBoolean(true); + active = new AtomicBoolean(false); exportType = req.getExportType(); if (exportType.equals(ExportType.File)) { @@ -97,13 +103,21 @@ public Job(long id, CommitTransformJobReq req) { stage = new StreamStage(sessionId, stage, new ArrayList<>(stageTasks), writer); stageList.add(stage); } + if (req.isSetSchedule()) { + trigger = JobScheduleTriggerMaker.getTrigger(req.getSchedule()); + scheduled = true; + scheduleStr = req.getSchedule(); + } else { + // no schedule information provided. job will be fired instantly + trigger = TriggerBuilder.newTrigger().startNow().build(); + } } public Job(long id, long sessionId, JobFromYAML jobFromYAML) { this.jobId = id; this.sessionId = sessionId; this.state = JobState.JOB_CREATED; - active = new AtomicBoolean(true); + active = new AtomicBoolean(false); String exportType = jobFromYAML.getExportType().toLowerCase().trim(); if (exportType.equals("file")) { @@ -151,6 +165,14 @@ public Job(long id, long sessionId, JobFromYAML jobFromYAML) { stage = new StreamStage(sessionId, stage, new ArrayList<>(stageTasks), writer); stageList.add(stage); } + + if (jobFromYAML.getSchedule() != null && !jobFromYAML.getSchedule().isEmpty()) { + trigger = JobScheduleTriggerMaker.getTrigger(jobFromYAML.getSchedule()); + scheduled = true; + scheduleStr = jobFromYAML.getSchedule(); + } else { + trigger = TriggerBuilder.newTrigger().startNow().build(); + } } @Override @@ -176,6 +198,7 @@ public String toString() { + taskList + ", stageList=" + stageList + + (scheduleStr != null ? ", schedule string=" + scheduleStr : "") + '}'; } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/JobScheduleTriggerMaker.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/JobScheduleTriggerMaker.java new file mode 100644 index 0000000000..cd56a39e9e --- /dev/null +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/JobScheduleTriggerMaker.java @@ -0,0 +1,395 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package cn.edu.tsinghua.iginx.transform.pojo; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.validation.constraints.NotNull; +import org.quartz.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class JobScheduleTriggerMaker { + + private static final Logger LOGGER = LoggerFactory.getLogger(JobScheduleTriggerMaker.class); + private static final SimpleDateFormat DATE_TIME_FORMAT = + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss"); + private static final String weekdayRegex = + "(mon|tue|wed|thu|fri|sat|sun|monday|tuesday|wednesday|thursday|friday|saturday|sunday)"; + + private static final Pattern everyPattern = + Pattern.compile( + "(?i)^every\\s+(\\d+)\\s+(second|minute|hour|day|month|year)(?:\\s+starts\\s+'([^']+)')?(?:\\s+ends\\s+'([^']+)')?$"); + + private static final Pattern everyWeekdayPattern = + Pattern.compile(String.format("(?i)^every ((?:%s,?)+)$", weekdayRegex)); + + private static final Pattern afterPattern = + Pattern.compile("(?i)^after\\s+(\\d+)\\s+(second|minute|hour|day|month|year)$"); + + private static final Pattern atPattern = + Pattern.compile("(?i)^at\\s+'((?:\\d{4}-\\d{2}-\\d{2}\\s+)?\\d{2}:\\d{2}:\\d{2})'$"); + + private static String errMsg; + + private static Date now; + + private enum INTERVAL_ENUM { + SECOND, + MINUTE, + HOUR, + DAY, + MONTH, + YEAR; + + public static INTERVAL_ENUM matcher(String unit) { + unit = unit.trim().toLowerCase(); + switch (unit) { + case "second": + return SECOND; + case "minute": + return MINUTE; + case "hour": + return HOUR; + case "day": + return DAY; + case "month": + return MONTH; + case "year": + return YEAR; + default: + return null; + } + } + } + + /** + * 根据调度字符串生成 Quartz Trigger。调度字符串大致可分为以下四种: 1. every 3 second/minute/hour/day/month/year + * 每隔3秒/分/小时/天/月/年执行一次,可以添加开始时间和结束时间,两个时间必须用单引号包围,例如: every 10 minute starts '2024-02-03 12:00:00' + * ends '2024-02-04 12:00:00' 2. after 3 second/minute/hour/day/month/year 在3秒/分/小时/天/月/年后执行一次; 3. + * at (yyyy-MM-dd)? HH:mm:ss 在指定时间执行 4. (* * * * * *) cron格式的字符串 + * + * @param jobSchedule 调度字符串,控制任务执行的时间 + * @return 返回在指定时间触发的Quartz触发器 + */ + public static Trigger getTrigger(@NotNull String jobSchedule) { + // corn in quartz is not case-sensitive + jobSchedule = jobSchedule.trim().toLowerCase(); + now = new Date(); + if (jobSchedule.isEmpty()) { + throw new IllegalArgumentException("Job schedule indicator string is empty."); + } + if (jobSchedule.startsWith("every")) { + if (jobSchedule.matches(String.valueOf(everyWeekdayPattern))) { + return everyWeeklyTrigger(jobSchedule); + } + return everyTrigger(jobSchedule); + } else if (jobSchedule.startsWith("after")) { + return afterTrigger(jobSchedule); + } else if (jobSchedule.startsWith("at")) { + return atTrigger(jobSchedule); + } else if (jobSchedule.matches("\\(.*\\)")) { + return cronTrigger(jobSchedule); + } + + throw new IllegalArgumentException("Invalid time format: " + jobSchedule); + } + + private static Trigger everyTrigger(String jobSchedule) { + Matcher nomalEverymatcher = everyPattern.matcher(jobSchedule); + TriggerBuilder triggerBuilder = TriggerBuilder.newTrigger(); + + if (nomalEverymatcher.matches()) { + int intervalValue = Integer.parseInt(nomalEverymatcher.group(1)); + INTERVAL_ENUM intervalUnit = INTERVAL_ENUM.matcher(nomalEverymatcher.group(2)); + if (intervalUnit == null) { + LOGGER.error( + "Error parsing interval unit {}. Available: second, minute, hour, day.", + nomalEverymatcher.group(2)); + throw new IllegalArgumentException( + "Error parsing interval unit " + + nomalEverymatcher.group(2) + + ". Available: second, minute, hour, day."); + } + String starts = nomalEverymatcher.group(3); + String ends = nomalEverymatcher.group(4); + + switch (intervalUnit) { + case SECOND: + triggerBuilder.withSchedule( + SimpleScheduleBuilder.simpleSchedule() + .withIntervalInSeconds(intervalValue) + .repeatForever()); + break; + case MINUTE: + triggerBuilder.withSchedule( + SimpleScheduleBuilder.simpleSchedule() + .withIntervalInMinutes(intervalValue) + .repeatForever()); + break; + case HOUR: + triggerBuilder.withSchedule( + SimpleScheduleBuilder.simpleSchedule() + .withIntervalInHours(intervalValue) + .repeatForever()); + break; + case DAY: + triggerBuilder.withSchedule( + SimpleScheduleBuilder.simpleSchedule() + .withIntervalInHours(intervalValue * 24) + .repeatForever()); + break; + case MONTH: + triggerBuilder.withSchedule( + CalendarIntervalScheduleBuilder.calendarIntervalSchedule() + .withIntervalInMonths(intervalValue)); + break; + case YEAR: + triggerBuilder.withSchedule( + CalendarIntervalScheduleBuilder.calendarIntervalSchedule() + .withIntervalInYears(intervalValue)); + break; + } + + Date startDate = null, endDate = null; + + if (starts != null) { + try { + startDate = parseDate(starts); + if (startDate.before(now)) { + errMsg = String.format("Start Time %s is before current time.", starts); + LOGGER.error(errMsg); + throw new IllegalArgumentException(errMsg); + } + triggerBuilder.startAt(startDate); + } catch (ParseException e) { + errMsg = String.format("Error parsing start time %s. Please refer to manual.", starts); + LOGGER.error(errMsg, e); + throw new IllegalArgumentException(errMsg); + } + } else { + triggerBuilder.startAt(now); + } + + if (ends != null) { + try { + endDate = parseDate(ends); + if (startDate != null && endDate.before(startDate)) { + errMsg = String.format("End Time %s is before start time %s.", ends, starts); + LOGGER.error(errMsg); + throw new IllegalArgumentException(errMsg); + } + if (endDate.before(now)) { + errMsg = String.format("End Time %s is before current time.", ends); + LOGGER.error(errMsg); + throw new IllegalArgumentException(errMsg); + } + triggerBuilder.endAt(endDate); + } catch (ParseException e) { + errMsg = String.format("Error parsing end time %s. Please refer to manual.", ends); + LOGGER.error(errMsg); + throw new IllegalArgumentException(errMsg); + } + } + } else { + errMsg = + String.format("Error parsing schedule string %s. Please refer to manual.", jobSchedule); + LOGGER.error(errMsg); + throw new IllegalArgumentException(errMsg); + } + return triggerBuilder.build(); + } + + private static Trigger everyWeeklyTrigger(String jobSchedule) { + Matcher matcher = everyWeekdayPattern.matcher(jobSchedule); + if (matcher.matches()) { + String daysString = matcher.group(1); + String[] daysArray = daysString.split(","); + Set daysOfWeek = new HashSet<>(); + + for (String day : daysArray) { + day = day.trim().toLowerCase(Locale.ROOT); + switch (day) { + case "mon": + case "monday": + daysOfWeek.add(DateBuilder.MONDAY); + break; + case "tue": + case "tuesday": + daysOfWeek.add(DateBuilder.TUESDAY); + break; + case "wed": + case "wednesday": + daysOfWeek.add(DateBuilder.WEDNESDAY); + break; + case "thu": + case "thursday": + daysOfWeek.add(DateBuilder.THURSDAY); + break; + case "fri": + case "friday": + daysOfWeek.add(DateBuilder.FRIDAY); + break; + case "sat": + case "saturday": + daysOfWeek.add(DateBuilder.SATURDAY); + break; + case "sun": + case "sunday": + daysOfWeek.add(DateBuilder.SUNDAY); + break; + default: + throw new IllegalArgumentException("Invalid day of the week: " + day); + } + } + return TriggerBuilder.newTrigger() + .withSchedule( + DailyTimeIntervalScheduleBuilder.dailyTimeIntervalSchedule() + .onDaysOfTheWeek(daysOfWeek.toArray(new Integer[0]))) + .build(); + } + throw new IllegalArgumentException("Invalid weekly format: " + jobSchedule); + } + + private static Trigger afterTrigger(String jobSchedule) { + Matcher afterMatcher = afterPattern.matcher(jobSchedule); + TriggerBuilder triggerBuilder = TriggerBuilder.newTrigger(); + + if (afterMatcher.matches()) { + int intervalValue = Integer.parseInt(afterMatcher.group(1)); + INTERVAL_ENUM intervalUnit = INTERVAL_ENUM.matcher(afterMatcher.group(2)); + if (intervalUnit == null) { + LOGGER.error( + "Error parsing interval unit {}. Available: second, minute, hour, day.", + afterMatcher.group(2)); + throw new IllegalArgumentException( + "Error parsing interval unit " + + afterMatcher.group(2) + + ". Available: second, minute, hour, day."); + } + + switch (intervalUnit) { + case SECOND: + triggerBuilder.startAt( + DateBuilder.futureDate(intervalValue, DateBuilder.IntervalUnit.SECOND)); + break; + case MINUTE: + triggerBuilder.startAt( + DateBuilder.futureDate(intervalValue, DateBuilder.IntervalUnit.MINUTE)); + break; + case HOUR: + triggerBuilder.startAt( + DateBuilder.futureDate(intervalValue, DateBuilder.IntervalUnit.HOUR)); + break; + case DAY: + triggerBuilder.startAt( + DateBuilder.futureDate(intervalValue, DateBuilder.IntervalUnit.DAY)); + break; + case MONTH: + triggerBuilder.startAt( + DateBuilder.futureDate(intervalValue, DateBuilder.IntervalUnit.MONTH)); + break; + case YEAR: + triggerBuilder.startAt( + DateBuilder.futureDate(intervalValue, DateBuilder.IntervalUnit.YEAR)); + break; + } + } else { + LOGGER.error("Error parsing schedule string {}. Please refer to manual.", jobSchedule); + throw new IllegalArgumentException( + "Error parsing schedule string " + jobSchedule + ". Please refer to manual."); + } + return triggerBuilder.build(); + } + + private static Trigger atTrigger(String jobSchedule) { + Matcher atMatcher = atPattern.matcher(jobSchedule); + + if (atMatcher.matches()) { + String atTime = atMatcher.group(1); + try { + Date atDate = parseDate(atTime); + if (atDate.before(now)) { + errMsg = + String.format("Trying to trigger a job at %s which is before current time", atTime); + LOGGER.error(errMsg); + throw new IllegalArgumentException(errMsg); + } + return TriggerBuilder.newTrigger() + .startAt(atDate) + .withSchedule( + SimpleScheduleBuilder.simpleSchedule() + .withMisfireHandlingInstructionFireNow() + .withRepeatCount(0)) + .build(); + } catch (ParseException e) { + errMsg = String.format("Error parsing time %s. Please refer to manual.", atTime); + LOGGER.error(errMsg); + throw new IllegalArgumentException(errMsg); + } + } else { + LOGGER.error("Error parsing schedule string {}. Please refer to manual.", jobSchedule); + throw new IllegalArgumentException( + "Error parsing schedule string " + jobSchedule + ". Please refer to manual."); + } + } + + private static Trigger cronTrigger(String jobSchedule) { + String cronExpression = jobSchedule.substring(1, jobSchedule.length() - 1); + if (cronExpression.isEmpty()) { + errMsg = "Cron string is empty. Please provide a valid corn expression."; + LOGGER.error(errMsg); + throw new IllegalArgumentException(errMsg); + } + if (!CronExpression.isValidExpression(cronExpression)) { + errMsg = + String.format( + "Cron string (%s) is not valid. Please provide a valid cron expression.", + cronExpression); + LOGGER.error(errMsg); + throw new IllegalArgumentException(errMsg); + } + return TriggerBuilder.newTrigger() + .withSchedule(CronScheduleBuilder.cronSchedule(cronExpression)) + .build(); + } + + /** + * 解析日期“HH:mm:ss”格式或者"yyyy-MM-dd HH:mm:ss"格式 + * + * @param dateString 日期字符串 + * @return 解析得到的Date类型变量 + * @throws ParseException + */ + private static Date parseDate(String dateString) throws ParseException { + if (dateString == null || dateString.isEmpty()) { + return null; + } + if (dateString.length() == 8) { // 'HH:mm:ss' format + // Set the date part to the current date + String today = new SimpleDateFormat("yyyy-MM-dd").format(now); + dateString = today + " " + dateString; + } + // 'yyyy-MM-dd HH:mm:ss' format + return DATE_TIME_FORMAT.parse(dateString); + } +} diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/TransformJobFinishListener.java b/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/TransformJobFinishListener.java new file mode 100644 index 0000000000..fda033d779 --- /dev/null +++ b/core/src/main/java/cn/edu/tsinghua/iginx/transform/pojo/TransformJobFinishListener.java @@ -0,0 +1,70 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package cn.edu.tsinghua.iginx.transform.pojo; + +import cn.edu.tsinghua.iginx.thrift.JobState; +import cn.edu.tsinghua.iginx.transform.exception.TransformException; +import cn.edu.tsinghua.iginx.transform.exec.TransformJobManager; +import org.quartz.JobExecutionContext; +import org.quartz.Trigger; +import org.quartz.listeners.TriggerListenerSupport; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TransformJobFinishListener extends TriggerListenerSupport { + + private static final Logger LOGGER = LoggerFactory.getLogger(TransformJobFinishListener.class); + + @Override + public String getName() { + return "JobFinishListener"; + } + + @Override + public void triggerFired(Trigger trigger, JobExecutionContext context) { + // 触发器被触发时的操作 + LOGGER.info( + "Trigger fired: {}, job:{}", + trigger.getKey(), + ((Job) context.getMergedJobDataMap().get("job")).getJobId()); + } + + @Override + public void triggerMisfired(Trigger trigger) { + // 触发器错过触发时的操作 + LOGGER.warn("Trigger misfired: {}", trigger.getKey()); + } + + @Override + public void triggerComplete( + Trigger trigger, + JobExecutionContext context, + Trigger.CompletedExecutionInstruction triggerInstructionCode) { + if (trigger.getNextFireTime() == null) { + // 触发器的所有执行结束 + Job job = (Job) context.getMergedJobDataMap().get("job"); + job.setState(JobState.JOB_FINISHED); + LOGGER.info("Job {} has completed all executions.", job.getJobId()); + try { + TransformJobManager.getInstance().removeFinishedScheduleJob(job.getJobId()); + } catch (TransformException e) { + throw new RuntimeException(e); + } + } + } +} diff --git a/core/src/test/java/cn/edu/tsinghua/iginx/transform/TriggerTest.java b/core/src/test/java/cn/edu/tsinghua/iginx/transform/TriggerTest.java new file mode 100644 index 0000000000..c008dc85c5 --- /dev/null +++ b/core/src/test/java/cn/edu/tsinghua/iginx/transform/TriggerTest.java @@ -0,0 +1,354 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package cn.edu.tsinghua.iginx.transform; + +import static org.junit.Assert.*; + +import cn.edu.tsinghua.iginx.transform.pojo.JobScheduleTriggerMaker; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.concurrent.TimeUnit; +import org.junit.Test; +import org.quartz.CronTrigger; +import org.quartz.DateBuilder; +import org.quartz.Trigger; +import org.quartz.impl.triggers.CalendarIntervalTriggerImpl; +import org.quartz.impl.triggers.SimpleTriggerImpl; + +public class TriggerTest { + + private static final SimpleDateFormat DATE_TIME_FORMAT = + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss"); + + private Trigger make(String schedule) { + return JobScheduleTriggerMaker.getTrigger(schedule); + } + + @Test + public void testEveryTrigger() { + String schedule = "every 3 second"; + Trigger trigger = make(schedule); + assertNotNull(trigger); + assertTrue(trigger instanceof SimpleTriggerImpl); + assertEquals(3000L, ((SimpleTriggerImpl) trigger).getRepeatInterval()); + + // minute + schedule = "every 10 minute"; + trigger = make(schedule); + assertNotNull(trigger); + assertTrue(trigger instanceof SimpleTriggerImpl); + assertEquals(600000L, ((SimpleTriggerImpl) trigger).getRepeatInterval()); + + // hour + schedule = "every 2 hour"; + trigger = make(schedule); + assertNotNull(trigger); + assertTrue(trigger instanceof SimpleTriggerImpl); + assertEquals(7200000L, ((SimpleTriggerImpl) trigger).getRepeatInterval()); + + // day + schedule = "every 1 day"; + trigger = make(schedule); + assertNotNull(trigger); + assertTrue(trigger instanceof SimpleTriggerImpl); + assertEquals(86400000L, ((SimpleTriggerImpl) trigger).getRepeatInterval()); + + // month + schedule = "every 1 month"; + trigger = make(schedule); + assertNotNull(trigger); + assertTrue(trigger instanceof CalendarIntervalTriggerImpl); + assertEquals(1, ((CalendarIntervalTriggerImpl) trigger).getRepeatInterval()); + assertEquals( + DateBuilder.IntervalUnit.MONTH, + ((CalendarIntervalTriggerImpl) trigger).getRepeatIntervalUnit()); + + // year + schedule = "every 1 year"; + trigger = make(schedule); + assertNotNull(trigger); + assertTrue(trigger instanceof CalendarIntervalTriggerImpl); + assertEquals(1, ((CalendarIntervalTriggerImpl) trigger).getRepeatInterval()); + assertEquals( + DateBuilder.IntervalUnit.YEAR, + ((CalendarIntervalTriggerImpl) trigger).getRepeatIntervalUnit()); + } + + @Test + public void testEveryTriggerWithDateTimeBounds() throws ParseException { + String schedule = "every 10 minute starts '2099-02-03 12:00:00' ends '2099-02-04 12:00:00'"; + Date expectedStartTime = DATE_TIME_FORMAT.parse("2099-02-03 12:00:00"); + Date expectedEndTime = DATE_TIME_FORMAT.parse("2099-02-04 12:00:00"); + + Trigger trigger = make(schedule); + assertNotNull(trigger); + assertTrue(trigger instanceof SimpleTriggerImpl); + assertEquals(600000L, ((SimpleTriggerImpl) trigger).getRepeatInterval()); + assertEquals(expectedStartTime, trigger.getStartTime()); + assertEquals(expectedEndTime, trigger.getEndTime()); + } + + @Test + public void testEveryTriggerWithTimeBounds() throws ParseException, InterruptedException { + String schedule = "every 5 second starts '23:59:53' ends '23:59:59'"; + + Calendar now = Calendar.getInstance(); + String today = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); + + // wait till next day if startTime-3s is before current time, -3s to make sure we have enough + // time + // +5 to make sure it's next day + if (now.after(DATE_TIME_FORMAT.parse(today + " " + "23:59:50"))) { + long toNextDay = 24 * 60 * 60 * 1000 - now.getTimeInMillis() + 5; + TimeUnit.MILLISECONDS.sleep(toNextDay); + } + today = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); + Date expectedStartTime = DATE_TIME_FORMAT.parse(today + " " + "23:59:53"); + Date expectedEndTime = DATE_TIME_FORMAT.parse(today + " " + "23:59:59"); + + Trigger trigger = make(schedule); + assertNotNull(trigger); + assertTrue(trigger instanceof SimpleTriggerImpl); + assertEquals(5000L, ((SimpleTriggerImpl) trigger).getRepeatInterval()); + assertEquals(expectedStartTime, trigger.getStartTime()); + assertEquals(expectedEndTime, trigger.getEndTime()); + } + + @Test + public void testEveryTriggerWithStartDateTimeBound() throws ParseException, InterruptedException { + // with date + String schedule = "every 10 minute starts '2099-02-03 12:00:00'"; + Date expectedStartTime = DATE_TIME_FORMAT.parse("2099-02-03 12:00:00"); + + Trigger trigger = make(schedule); + assertNotNull(trigger); + assertTrue(trigger instanceof SimpleTriggerImpl); + assertEquals(600000L, ((SimpleTriggerImpl) trigger).getRepeatInterval()); + assertEquals(expectedStartTime, trigger.getStartTime()); + assertNull(trigger.getEndTime()); + + // no date, may need to wait till next day + schedule = "every 5 second starts '23:59:58'"; + Calendar now = Calendar.getInstance(); + String today = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); + if (now.after(DATE_TIME_FORMAT.parse(today + " 23:59:55"))) { + long toNextDay = 24 * 60 * 60 * 1000 - now.getTimeInMillis() + 5; + TimeUnit.MILLISECONDS.sleep(toNextDay); + } + today = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); + expectedStartTime = DATE_TIME_FORMAT.parse(today + " " + "23:59:58"); + + trigger = make(schedule); + assertNotNull(trigger); + assertTrue(trigger instanceof SimpleTriggerImpl); + assertEquals(5000L, ((SimpleTriggerImpl) trigger).getRepeatInterval()); + assertEquals(expectedStartTime, trigger.getStartTime()); + assertNull(trigger.getEndTime()); + } + + @Test + public void testEveryTriggerWithEndDateTimeBound() throws ParseException, InterruptedException { + // with date + String schedule = "every 10 minute ends '2099-02-03 12:00:00'"; + Date expectedEndTime = DATE_TIME_FORMAT.parse("2099-02-03 12:00:00"); + + Trigger trigger = make(schedule); + assertNotNull(trigger); + assertTrue(trigger instanceof SimpleTriggerImpl); + assertEquals(600000L, ((SimpleTriggerImpl) trigger).getRepeatInterval()); + assertEquals(expectedEndTime, trigger.getEndTime()); + + long currentTime = System.currentTimeMillis(); + long triggerStartTime = trigger.getStartTime().getTime(); + + // Allow a tolerance of 1000 milliseconds, 500 would fail + long tolerance = 1000L; + + assertTrue( + "The trigger start time is not within the expected tolerance range.", + Math.abs(triggerStartTime - currentTime) <= tolerance); + + // no date, may need to wait till next day + schedule = "every 5 second ends '23:59:57'"; + Calendar now = Calendar.getInstance(); + String today = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); + if (now.after(DATE_TIME_FORMAT.parse(today + " 23:59:57"))) { + long toNextDay = 24 * 60 * 60 * 1000 - now.getTimeInMillis() + 5; + TimeUnit.MILLISECONDS.sleep(toNextDay); + } + today = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); + expectedEndTime = DATE_TIME_FORMAT.parse(today + " " + "23:59:57"); + + trigger = make(schedule); + assertNotNull(trigger); + assertTrue(trigger instanceof SimpleTriggerImpl); + assertEquals(5000L, ((SimpleTriggerImpl) trigger).getRepeatInterval()); + assertEquals(expectedEndTime, trigger.getEndTime()); + + currentTime = System.currentTimeMillis(); + triggerStartTime = trigger.getStartTime().getTime(); + + assertTrue( + "The trigger start time is not within the expected tolerance range.", + Math.abs(triggerStartTime - currentTime) <= tolerance); + } + + @Test + public void testAfterTrigger() { + // second + String schedule = "after 3 second"; + long currentTime = System.currentTimeMillis(); + Trigger trigger = make(schedule); + assertNotNull(trigger); + assertTrue(trigger instanceof SimpleTriggerImpl); + long triggerStartTime = trigger.getStartTime().getTime(); + long expectedStartTime = currentTime + 3000L; + + // Allow a tolerance of 1000 milliseconds + long tolerance = 1000L; + assertTrue( + "The trigger start time is not within the expected tolerance range.", + Math.abs(triggerStartTime - expectedStartTime) <= tolerance); + + // minute + schedule = "after 3 minute"; + currentTime = System.currentTimeMillis(); + trigger = make(schedule); + assertNotNull(trigger); + assertTrue(trigger instanceof SimpleTriggerImpl); + triggerStartTime = trigger.getStartTime().getTime(); + expectedStartTime = currentTime + 3 * 60 * 1000L; + assertTrue( + "The trigger start time is not within the expected tolerance range.", + Math.abs(triggerStartTime - expectedStartTime) <= tolerance); + + // hour + schedule = "after 3 hour"; + currentTime = System.currentTimeMillis(); + trigger = make(schedule); + assertNotNull(trigger); + assertTrue(trigger instanceof SimpleTriggerImpl); + triggerStartTime = trigger.getStartTime().getTime(); + expectedStartTime = currentTime + 3 * 60 * 60 * 1000L; + assertTrue( + "The trigger start time is not within the expected tolerance range.", + Math.abs(triggerStartTime - expectedStartTime) <= tolerance); + + // day + schedule = "after 3 day"; + currentTime = System.currentTimeMillis(); + trigger = make(schedule); + assertNotNull(trigger); + assertTrue(trigger instanceof SimpleTriggerImpl); + triggerStartTime = trigger.getStartTime().getTime(); + expectedStartTime = currentTime + 3 * 60 * 60 * 24 * 1000L; + assertTrue( + "The trigger start time is not within the expected tolerance range.", + Math.abs(triggerStartTime - expectedStartTime) <= tolerance); + + // month + schedule = "after 3 month"; + currentTime = System.currentTimeMillis(); + trigger = make(schedule); + assertNotNull(trigger); + assertTrue(trigger instanceof SimpleTriggerImpl); + + // Calculate the expected start time by adding 3 months to the current time + Calendar expectedStartCalendar = Calendar.getInstance(); + expectedStartCalendar.setTimeInMillis(currentTime); + int currentHour = expectedStartCalendar.get(Calendar.HOUR_OF_DAY); + int currentMinute = expectedStartCalendar.get(Calendar.MINUTE); + int currentSecond = expectedStartCalendar.get(Calendar.SECOND); + expectedStartCalendar.add(Calendar.MONTH, 3); + expectedStartCalendar.set(Calendar.HOUR_OF_DAY, currentHour); + expectedStartCalendar.set(Calendar.MINUTE, currentMinute); + expectedStartCalendar.set(Calendar.SECOND, currentSecond); + expectedStartTime = expectedStartCalendar.getTimeInMillis(); + triggerStartTime = trigger.getStartTime().getTime(); + assertTrue( + "The trigger start time is not within the expected tolerance range.", + Math.abs(triggerStartTime - expectedStartTime) <= tolerance); + + // year + schedule = "after 3 year"; + currentTime = System.currentTimeMillis(); + trigger = make(schedule); + assertNotNull(trigger); + assertTrue(trigger instanceof SimpleTriggerImpl); + + // Calculate the expected start time by adding 3 years to the current time + expectedStartCalendar = Calendar.getInstance(); + expectedStartCalendar.setTimeInMillis(currentTime); + currentHour = expectedStartCalendar.get(Calendar.HOUR_OF_DAY); + currentMinute = expectedStartCalendar.get(Calendar.MINUTE); + currentSecond = expectedStartCalendar.get(Calendar.SECOND); + expectedStartCalendar.add(Calendar.YEAR, 3); + expectedStartCalendar.set(Calendar.HOUR_OF_DAY, currentHour); + expectedStartCalendar.set(Calendar.MINUTE, currentMinute); + expectedStartCalendar.set(Calendar.SECOND, currentSecond); + expectedStartTime = expectedStartCalendar.getTimeInMillis(); + triggerStartTime = trigger.getStartTime().getTime(); + assertTrue( + "The trigger start time is not within the expected tolerance range.", + Math.abs(triggerStartTime - expectedStartTime) <= tolerance); + } + + @Test + public void testAtTrigger() throws ParseException, InterruptedException { + // with date + String schedule = "at '2099-12-31 23:59:59'"; + Trigger trigger = make(schedule); + Date atDate = DATE_TIME_FORMAT.parse("2099-12-31 23:59:59"); + assertNotNull(trigger); + assertTrue(trigger instanceof SimpleTriggerImpl); + assertEquals(atDate, trigger.getStartTime()); + + // no date, may need to wait till next day + schedule = "at '23:59:57'"; + Calendar now = Calendar.getInstance(); + String today = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); + if (now.after(DATE_TIME_FORMAT.parse(today + " 23:59:57"))) { + long toNextDay = 24 * 60 * 60 * 1000 - now.getTimeInMillis() + 5; + TimeUnit.MILLISECONDS.sleep(toNextDay); + } + today = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); + atDate = DATE_TIME_FORMAT.parse(today + " " + "23:59:57"); + trigger = make(schedule); + assertNotNull(trigger); + assertTrue(trigger instanceof SimpleTriggerImpl); + assertEquals(atDate, trigger.getStartTime()); + } + + @Test + public void testCronTrigger() { + String schedule = "(0 0/5 14,18 * * ?)"; + Trigger trigger = make(schedule); + assertNotNull(trigger); + assertTrue(trigger instanceof CronTrigger); + assertEquals("0 0/5 14,18 * * ?", ((CronTrigger) trigger).getCronExpression()); + } + + @Test + public void testInvalidSchedule() { + String schedule = "invalid schedule"; + assertThrows(IllegalArgumentException.class, () -> make(schedule)); + } +} diff --git a/session/src/main/java/cn/edu/tsinghua/iginx/session/Session.java b/session/src/main/java/cn/edu/tsinghua/iginx/session/Session.java index 9190d6a0cb..b2f94cde63 100644 --- a/session/src/main/java/cn/edu/tsinghua/iginx/session/Session.java +++ b/session/src/main/java/cn/edu/tsinghua/iginx/session/Session.java @@ -1121,11 +1121,21 @@ void closeQuery(long queryId) throws SessionException { public long commitTransformJob( List taskInfoList, ExportType exportType, String fileName) throws SessionException { + return commitTransformJob(taskInfoList, exportType, fileName, null); + } + + public long commitTransformJob( + List taskInfoList, ExportType exportType, String fileName, String schedule) + throws SessionException { CommitTransformJobReq req = new CommitTransformJobReq(sessionId, taskInfoList, exportType); if (fileName != null) { req.setFileName(fileName); } + if (schedule != null) { + req.setSchedule(schedule); + } + Reference ref = new Reference<>(); executeWithCheck(() -> (ref.resp = client.commitTransformJob(req)).status); return ref.resp.getJobId(); diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/JobFromYAML.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/JobFromYAML.java index e6b1de01ce..a2eda0e13b 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/JobFromYAML.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/JobFromYAML.java @@ -25,6 +25,7 @@ public class JobFromYAML { private List taskList; private String exportFile; private String exportType; + private String schedule; public JobFromYAML() {} @@ -51,4 +52,12 @@ public String getExportType() { public void setExportType(String exportType) { this.exportType = exportType; } + + public String getSchedule() { + return schedule; + } + + public void setSchedule(String schedule) { + this.schedule = schedule; + } } diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/YAMLReader.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/YAMLReader.java index a75b2066e0..bb3cb761a9 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/YAMLReader.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/YAMLReader.java @@ -59,10 +59,12 @@ public String normalize(String conf) { String exportType = "(?i)exportType"; String exportFile = "(?i)exportFile"; String exportNameList = "(?i)exportNameList"; + String schedule = "(?i)schedule"; conf = conf.replaceAll(exportType, "exportType"); conf = conf.replaceAll(exportFile, "exportFile"); conf = conf.replaceAll(exportNameList, "exportNameList"); + conf = conf.replaceAll(schedule, "schedule"); return conf; } diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/udf/TransformIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/udf/TransformIT.java index 0e524e84e8..083819ad75 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/udf/TransformIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/udf/TransformIT.java @@ -19,6 +19,7 @@ import static cn.edu.tsinghua.iginx.integration.controller.Controller.SUPPORT_KEY; import static cn.edu.tsinghua.iginx.integration.controller.Controller.clearAllData; +import static cn.edu.tsinghua.iginx.utils.FileUtils.appendFile; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; @@ -36,21 +37,16 @@ import cn.edu.tsinghua.iginx.utils.RpcUtils; import cn.edu.tsinghua.iginx.utils.YAMLReader; import cn.edu.tsinghua.iginx.utils.YAMLWriter; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; +import java.io.*; import java.nio.file.Files; import java.nio.file.Paths; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.lang3.RandomStringUtils; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -215,6 +211,22 @@ private void verifyJobState(long jobId) throws SessionException, InterruptedExce assertTrue(finishedJobIds.contains(jobId)); } + private void cancelJob(long jobID) { + try { + JobState jobState; + session.cancelTransformJob(jobID); + jobState = session.queryTransformJobStatus(jobID); + LOGGER.info("After cancellation, job {} state is {}", jobID, jobState.toString()); + assertEquals(JobState.JOB_CLOSED, jobState); + + List closedJobIds = session.showEligibleJob(JobState.JOB_CLOSED); + assertTrue(closedJobIds.contains(jobID)); + } catch (SessionException e) { + LOGGER.error("Failed to cancel job: {}", jobID, e); + fail(); + } + } + @Test public void exportFileWithoutPermissionTest() { LOGGER.info("exportFileWithoutPermissionTest"); @@ -272,6 +284,145 @@ public void commitSingleSqlStatementByYamlTest() { } } + @Test + public void commitScheduledYamlTestAfter10s() { + LOGGER.info("commitScheduledYamlTest(after 10s)"); + String outputFileName = OUTPUT_DIR_PREFIX + File.separator + "export_file_after_10_s.txt"; + try { + String yamlFileName = OUTPUT_DIR_PREFIX + File.separator + "TransformScheduledAfter10s.yaml"; + SessionExecuteSqlResult result = + session.executeSql(String.format(COMMIT_SQL_FORMATTER, yamlFileName)); + + Thread.sleep(3000L); // sleep 3s to delay insertion + String insertSQL = "insert into scheduleData(key, %s) values(1, 2);"; + // add col0 + session.executeSql(String.format(insertSQL, "col0")); + + long jobId = result.getJobId(); + verifyJobState(jobId); + // job will finish after 10 seconds + + // check whether new column is in job result + fileResultContains(outputFileName, "col0"); + } catch (SessionException | InterruptedException e) { + LOGGER.error("Transform: execute fail. Caused by:", e); + fail(); + } finally { + try { + assertTrue(Files.deleteIfExists(Paths.get(outputFileName))); + } catch (IOException e) { + LOGGER.error("Fail to delete result file: {}", outputFileName, e); + fail(); + } + } + } + + @Test + public void commitScheduledYamlTestEvery10sAndCancel() { + LOGGER.info("commitScheduledYamlTest(every 10s) and cancel"); + String outputFileName = OUTPUT_DIR_PREFIX + File.separator + "export_file_every_10_s.txt"; + try { + String insertSQL = "insert into scheduleData(key, %s) values(1, 2);"; + String yamlFileName = OUTPUT_DIR_PREFIX + File.separator + "TransformScheduledEvery10s.yaml"; + // add col0 + session.executeSql(String.format(insertSQL, "col0")); + SessionExecuteSqlResult result = + session.executeSql(String.format(COMMIT_SQL_FORMATTER, yamlFileName)); + long jobId = result.getJobId(); + try { + + Thread.sleep(3000L); // sleep 3s to make sure first try is triggered. + LOGGER.info("Verifying 0th try..."); + fileResultContains(outputFileName, "col0"); + + // add col1, col2 and verify res are changed + for (int i = 1; i < 3; i++) { + session.executeSql(String.format(insertSQL, "col" + i)); + Thread.sleep(10000L); // sleep 10s to make sure next try is triggered. + LOGGER.info("Verifying " + i + "th try..."); + fileResultContains(outputFileName, "col" + i); + } + } finally { + cancelJob(jobId); + assertTrue(Files.deleteIfExists(Paths.get(outputFileName))); + } + } catch (SessionException | InterruptedException e) { + LOGGER.error("Transform: execute fail. Caused by:", e); + fail(); + } catch (IOException e) { + LOGGER.error("Fail to delete result file: {}", outputFileName, e); + fail(); + } + } + + @Ignore // this test takes too much time(> 1 minute) because the smallest time unit in cron is + // minute. This test has been tested locally before committed + @Test + public void commitScheduledYamlTestByCronAndCancel() { + LOGGER.info("commitScheduledYamlTest(every 1 minute by cron) and cancel"); + String outputFileName = + OUTPUT_DIR_PREFIX + File.separator + "export_file_every_1_minute_cron.txt"; + try { + String insertSQL = "insert into scheduleData(key, %s) values(1, 2);"; + String yamlFileName = OUTPUT_DIR_PREFIX + File.separator + "TransformScheduledCron.yaml"; + SessionExecuteSqlResult result = + session.executeSql(String.format(COMMIT_SQL_FORMATTER, yamlFileName)); + long jobId = result.getJobId(); + try { + // add col0 + session.executeSql(String.format(insertSQL, "col0")); + Thread.sleep(62000L); // sleep 62s to make sure next try is triggered. + LOGGER.info("Verifying 0th try..."); + fileResultContains(outputFileName, "col0"); + } finally { + cancelJob(jobId); + assertTrue(Files.deleteIfExists(Paths.get(outputFileName))); + } + } catch (SessionException | InterruptedException e) { + LOGGER.error("Transform: execute fail. Caused by:", e); + fail(); + } catch (IOException e) { + LOGGER.error("Fail to delete result file: {}", outputFileName, e); + fail(); + } + } + + @Ignore // the time system on github action is somehow bugged, thus it cannot be tested in action + // It has passed local test + @Test + public void commitScheduledYamlTestAt10sFromNow() { + LOGGER.info("commitScheduledYamlTest(at 10s from now)"); + String outputFileName = OUTPUT_DIR_PREFIX + File.separator + "export_file_at_10_s.txt"; + try { + String insertSQL = "insert into scheduleData(key, %s) values(1, 2);"; + String yamlFileName = + OUTPUT_DIR_PREFIX + File.separator + "TransformScheduledAt10sFromNow.yaml"; + + LocalDateTime tenSecondsLater = LocalDateTime.now().plusSeconds(10); + String formattedDateTime = + tenSecondsLater.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + appendFile(new File(yamlFileName), "\nschedule: \"at '" + formattedDateTime + "'\""); + + SessionExecuteSqlResult result = + session.executeSql(String.format(COMMIT_SQL_FORMATTER, yamlFileName)); + long jobId = result.getJobId(); + Thread.sleep(2000L); // add new data after 2s, before job is triggered. + // add col0 + session.executeSql(String.format(insertSQL, "col0")); + + Thread.sleep(8000L); // verify result after 10s + fileResultContains(outputFileName, "col0"); + + verifyJobState(jobId); + } catch (SessionException | InterruptedException e) { + LOGGER.error("Transform: execute fail. Caused by:", e); + fail(); + } catch (IOException e) { + LOGGER.error("Fail to add schedule line in yaml", e); + fail(); + } + } + @Test public void commitMultipleSqlStatementsTest() { LOGGER.info("commitMultipleSqlStatementsTest"); @@ -738,4 +889,23 @@ public void cancelJobTest() { fail(); } } + + // file contains + private void fileResultContains(String filename, String content) { + boolean contains = false; + try (BufferedReader reader = new BufferedReader(new FileReader(filename))) { + String line = reader.readLine(); + while (line != null) { + if (line.contains(content)) { + contains = true; + break; + } + line = reader.readLine(); + } + } catch (IOException e) { + LOGGER.error("Verify file export result failed.", e); + fail(); + } + assertTrue(contains); + } } diff --git a/test/src/test/resources/transform/TransformScheduledAfter10s.yaml b/test/src/test/resources/transform/TransformScheduledAfter10s.yaml new file mode 100644 index 0000000000..bcbb9817b7 --- /dev/null +++ b/test/src/test/resources/transform/TransformScheduledAfter10s.yaml @@ -0,0 +1,9 @@ +--- +taskList: +- taskType: "iginx" + timeout: 10000000 + sqlList: + - "show columns;" +schedule: "after 10 second" +exportType: "file" +exportFile: "test/src/test/resources/transform/export_file_after_10_s.txt" \ No newline at end of file diff --git a/test/src/test/resources/transform/TransformScheduledAt10sFromNow.yaml b/test/src/test/resources/transform/TransformScheduledAt10sFromNow.yaml new file mode 100644 index 0000000000..9fd046e3cc --- /dev/null +++ b/test/src/test/resources/transform/TransformScheduledAt10sFromNow.yaml @@ -0,0 +1,9 @@ +--- +taskList: + - taskType: "iginx" + timeout: 10000000 + sqlList: + - "show columns;" +exportType: "file" +exportFile: "test/src/test/resources/transform/export_file_at_10_s.txt" + diff --git a/test/src/test/resources/transform/TransformScheduledCron.yaml b/test/src/test/resources/transform/TransformScheduledCron.yaml new file mode 100644 index 0000000000..bea1e3b76f --- /dev/null +++ b/test/src/test/resources/transform/TransformScheduledCron.yaml @@ -0,0 +1,9 @@ +--- +taskList: + - taskType: "iginx" + timeout: 10000000 + sqlList: + - "show columns;" +schedule: "(0 0/1 * 1/1 * ? *)" +exportType: "file" +exportFile: "test/src/test/resources/transform/export_file_every_1_minute_cron.txt" \ No newline at end of file diff --git a/test/src/test/resources/transform/TransformScheduledEvery10s.yaml b/test/src/test/resources/transform/TransformScheduledEvery10s.yaml new file mode 100644 index 0000000000..c49048520f --- /dev/null +++ b/test/src/test/resources/transform/TransformScheduledEvery10s.yaml @@ -0,0 +1,9 @@ +--- +taskList: + - taskType: "iginx" + timeout: 10000000 + sqlList: + - "show columns;" +schedule: "every 10 second" +exportType: "file" +exportFile: "test/src/test/resources/transform/export_file_every_10_s.txt" \ No newline at end of file diff --git a/thrift/src/main/proto/rpc.thrift b/thrift/src/main/proto/rpc.thrift index 7223d28930..b0429d071b 100644 --- a/thrift/src/main/proto/rpc.thrift +++ b/thrift/src/main/proto/rpc.thrift @@ -115,6 +115,7 @@ enum JobState { JOB_UNKNOWN, JOB_FINISHED, JOB_CREATED, + JOB_IDLE, JOB_RUNNING, JOB_FAILING, JOB_FAILED, @@ -548,6 +549,7 @@ struct CommitTransformJobReq { 2: required list taskList 3: required ExportType exportType 4: optional string fileName + 5: optional string schedule } struct CommitTransformJobResp { From 6ab0f6d494fb8e9702ace9eb606eacb547fb3dba Mon Sep 17 00:00:00 2001 From: An Qi Date: Mon, 22 Jul 2024 09:59:42 +0800 Subject: [PATCH 109/138] docs: fix iotdb download link (#401) * docs: fix iotdb download link * docs: fix iotdb download link * docs: fix iotdb download link --------- Co-authored-by: Yuqing Zhu --- docs/quickStarts/IGinXBySource-EnglishVersion.md | 6 +++--- docs/quickStarts/IGinXBySource.md | 6 +++--- docs/quickStarts/IGinXCluster-EnglishVersion.md | 6 +++--- docs/quickStarts/IGinXCluster.md | 6 +++--- docs/quickStarts/IGinXManual-EnglishVersion.md | 8 ++++---- docs/quickStarts/IGinXManual.md | 8 ++++---- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/docs/quickStarts/IGinXBySource-EnglishVersion.md b/docs/quickStarts/IGinXBySource-EnglishVersion.md index 4c5e96bd6a..f653df1eea 100644 --- a/docs/quickStarts/IGinXBySource-EnglishVersion.md +++ b/docs/quickStarts/IGinXBySource-EnglishVersion.md @@ -157,8 +157,8 @@ The specific installation method is as follows: ```shell $ cd ~ -$ wget https://mirrors.bfsu.edu.cn/apache/iotdb/0.12.0/apache-iotdb-0.12.0-server-bin.zip -$ unzip apache-iotdb-0.12.0-server-bin.zip +$ wget https://github.com/IGinX-THU/IGinX-resources/raw/main/resources/apache-iotdb-0.12.6-server-bin.zip +$ unzip apache-iotdb-0.12.6-server-bin.zip ``` ### IGinX Installation @@ -217,7 +217,7 @@ First of all, you need to launch IoTDB. ```shell $ cd ~ -$ cd apache-iotdb-0.12.0-server-bin/ +$ cd apache-iotdb-0.12.6-server-bin/ $ ./sbin/start-server.sh ``` diff --git a/docs/quickStarts/IGinXBySource.md b/docs/quickStarts/IGinXBySource.md index 816437b558..5cfaaa4adc 100644 --- a/docs/quickStarts/IGinXBySource.md +++ b/docs/quickStarts/IGinXBySource.md @@ -161,8 +161,8 @@ IoTDB 是 Apache 推出的时序数据库,具体安装方式如下: ```shell $ cd ~ -$ wget https://mirrors.bfsu.edu.cn/apache/iotdb/0.12.0/apache-iotdb-0.12.0-server-bin.zip -$ unzip apache-iotdb-0.12.0-server-bin.zip +$ wget https://github.com/IGinX-THU/IGinX-resources/raw/main/resources/apache-iotdb-0.12.6-server-bin.zip +$ unzip apache-iotdb-0.12.6-server-bin.zip ``` ### IGinX 安装 @@ -217,7 +217,7 @@ $ mvn clean install -Dmaven.test.skip=true ```shell $ cd ~ -$ cd apache-iotdb-0.12.0-server-bin/ +$ cd apache-iotdb-0.12.6-server-bin/ $ ./sbin/start-server.sh ``` diff --git a/docs/quickStarts/IGinXCluster-EnglishVersion.md b/docs/quickStarts/IGinXCluster-EnglishVersion.md index c7770b6440..116f844e97 100644 --- a/docs/quickStarts/IGinXCluster-EnglishVersion.md +++ b/docs/quickStarts/IGinXCluster-EnglishVersion.md @@ -91,8 +91,8 @@ The specific installation method is as follows: ```shell $ cd ~ -$ wget https://mirrors.bfsu.edu.cn/apache/iotdb/0.12.0/apache-iotdb-0.12.0-server-bin.zip -$ unzip apache-iotdb-0.12.0-server-bin.zip +$ wget https://github.com/IGinX-THU/IGinX-resources/raw/main/resources/apache-iotdb-0.12.6-server-bin.zip +$ unzip apache-iotdb-0.12.6-server-bin.zip ``` ### IGinX Installation @@ -117,7 +117,7 @@ Start the first instance: ```shell $ cd ~ -$ cd apache-iotdb-0.12.0-server-bin/ +$ cd apache-iotdb-0.12.6-server-bin/ $ ./sbin/start-server.sh # start instance one 127.0.0.1:6667 ``` diff --git a/docs/quickStarts/IGinXCluster.md b/docs/quickStarts/IGinXCluster.md index e1ec7879cb..a210e88d95 100644 --- a/docs/quickStarts/IGinXCluster.md +++ b/docs/quickStarts/IGinXCluster.md @@ -88,8 +88,8 @@ IoTDB 是 Apache 推出的时序数据库,具体安装方式如下: ```shell $ cd ~ -$ wget https://mirrors.bfsu.edu.cn/apache/iotdb/0.12.0/apache-iotdb-0.12.0-server-bin.zip -$ unzip apache-iotdb-0.12.0-server-bin.zip +$ wget https://github.com/IGinX-THU/IGinX-resources/raw/main/resources/apache-iotdb-0.12.6-server-bin.zip +$ unzip apache-iotdb-0.12.6-server-bin.zip ``` ### IGinX 安装 @@ -121,7 +121,7 @@ rpc_port=6667 ```shell $ cd ~ -$ cd apache-iotdb-0.12.0-server-bin/ +$ cd apache-iotdb-0.12.6-server-bin/ $ ./sbin/start-server.sh # 启动实例一 127.0.0.1: 6667 ``` diff --git a/docs/quickStarts/IGinXManual-EnglishVersion.md b/docs/quickStarts/IGinXManual-EnglishVersion.md index e4490a22ea..5854c78b74 100644 --- a/docs/quickStarts/IGinXManual-EnglishVersion.md +++ b/docs/quickStarts/IGinXManual-EnglishVersion.md @@ -136,8 +136,8 @@ The specific installation method is as follows: ```shell $ cd ~ -$ wget https://mirrors.bfsu.edu.cn/apache/iotdb/0.12.0/apache-iotdb-0.12.0-server-bin.zip -$ unzip apache-iotdb-0.12.0-server-bin.zip +$ wget https://github.com/IGinX-THU/IGinX-resources/raw/main/resources/apache-iotdb-0.12.6-server-bin.zip +$ unzip apache-iotdb-0.12.6-server-bin.zip ``` ### Download the binary executables @@ -173,7 +173,7 @@ First of all, you need to launch IoTDB. ```shell $ cd ~ -$ cd apache-iotdb-0.12.0-server-bin/ +$ cd apache-iotdb-0.12.6-server-bin/ $ ./sbin/start-server.sh ``` @@ -241,7 +241,7 @@ Here is an example of starting two instances with ports 6667 and 7667, respectiv ```shell $ cd ~ -$ cd apache-iotdb-0.12.0-server-bin/ +$ cd apache-iotdb-0.12.6-server-bin/ $ ./sbin/start-server.sh # 启动实例一 127.0.0.1: 6667 ``` diff --git a/docs/quickStarts/IGinXManual.md b/docs/quickStarts/IGinXManual.md index 489730983c..c07aee8f6c 100644 --- a/docs/quickStarts/IGinXManual.md +++ b/docs/quickStarts/IGinXManual.md @@ -133,8 +133,8 @@ IoTDB 是 Apache 推出的时序数据库,具体安装方式如下: ```shell $ cd ~ -$ wget https://mirrors.bfsu.edu.cn/apache/iotdb/0.12.0/apache-iotdb-0.12.0-server-bin.zip -$ unzip apache-iotdb-0.12.0-server-bin.zip +$ wget https://github.com/IGinX-THU/IGinX-resources/raw/main/resources/apache-iotdb-0.12.6-server-bin.zip +$ unzip apache-iotdb-0.12.6-server-bin.zip ``` ### 下载二进制可执行文件 @@ -171,7 +171,7 @@ $ mvn clean install -Dmaven.test.skip=true ```shell $ cd ~ -$ cd apache-iotdb-0.12.0-server-bin/ +$ cd apache-iotdb-0.12.6-server-bin/ $ ./sbin/start-server.sh ``` @@ -239,7 +239,7 @@ IGinX 元数据存储管理现在有 ZooKeeper 存储、写本地文件两种方 ```shell $ cd ~ -$ cd apache-iotdb-0.12.0-server-bin/ +$ cd apache-iotdb-0.12.6-server-bin/ $ ./sbin/start-server.sh # 启动实例一 127.0.0.1: 6667 ``` From 0b59cfabf4da11ff2c948b4a2c3c854203b29321 Mon Sep 17 00:00:00 2001 From: Yuqing Zhu Date: Mon, 22 Jul 2024 16:32:20 +0800 Subject: [PATCH 110/138] chore: update docs to match versions (#404) * update versions in doc --- .../IGinXBySource-EnglishVersion.md | 12 +++++----- docs/quickStarts/IGinXBySource.md | 12 +++++----- .../IGinXCluster-EnglishVersion.md | 14 +++++------ docs/quickStarts/IGinXCluster.md | 18 +++++++------- .../IGinXInOneShot-EnglishVersion.md | 18 +++++++------- docs/quickStarts/IGinXInOneShot.md | 18 +++++++------- .../quickStarts/IGinXManual-EnglishVersion.md | 24 +++++++++---------- docs/quickStarts/IGinXManual.md | 24 +++++++++---------- .../IGinXBySource-EnglishVersion.md | 12 +++++----- docs/quickStarts_Parquet/IGinXBySource.md | 12 +++++----- .../IGinXCluster-EnglishVersion.md | 18 +++++++------- docs/quickStarts_Parquet/IGinXCluster.md | 18 +++++++------- .../IGinXInOneShot-EnglishVersion.md | 18 +++++++------- docs/quickStarts_Parquet/IGinXInOneShot.md | 18 +++++++------- 14 files changed, 118 insertions(+), 118 deletions(-) diff --git a/docs/quickStarts/IGinXBySource-EnglishVersion.md b/docs/quickStarts/IGinXBySource-EnglishVersion.md index f653df1eea..0591557544 100644 --- a/docs/quickStarts/IGinXBySource-EnglishVersion.md +++ b/docs/quickStarts/IGinXBySource-EnglishVersion.md @@ -424,17 +424,17 @@ Below is a short tutorial on how to use it. ### RPC Interface -Since the IGinX 0.5.1 version has not been released to the Maven central repository, if you want to use it, you need to manually install it to the local Maven repository. +Since the IGinX jars have not been released to the Maven central repository, if you want to use it, you need to manually install it to the local Maven repository. The specific installation method is as follows: ```shell -# download iginx 0.4 release version source code package -$ wget https://github.com/IGinX-THU/IGinX/archive/refs/tags/release/v0.5.1.tar.gz +# download the newest IGinX release version source code package +$ wget https://github.com/IGinX-THU/IGinX/archive/refs/tags/v0.7.0.zip # Unzip the source package -$ tar -zxvf v0.5.1.tar.gz +$ tar -zxvf v0.7.0.tar.gz # go to the main project's directory -$ cd IGinX-rc-v0.5.1 +$ cd IGinX-rc-v0.7.0 # Install to local Maven repository $ mvn clean install -DskipTests ``` @@ -445,7 +445,7 @@ Specifically, when using it, you only need to introduce the following dependenci cn.edu.tsinghua iginx-core - 0.8.0-SNAPSHOT + 0.7.0 ``` diff --git a/docs/quickStarts/IGinXBySource.md b/docs/quickStarts/IGinXBySource.md index 5cfaaa4adc..396389bb03 100644 --- a/docs/quickStarts/IGinXBySource.md +++ b/docs/quickStarts/IGinXBySource.md @@ -421,15 +421,15 @@ RPC 接口最常见的用法。 下面是一个简短的使用教程。 -由于目前 IGinX 0.5.1 版本还未发布到 maven 中央仓库,因此如需使用的话,需要手动安装到本地的 maven 仓库。具体安装方式如下: +由于目前 IGinX的jar包还未发布到 maven 中央仓库,因此如需使用的话,需要手动安装到本地的 maven 仓库。具体安装方式如下: ```shell -# 下载 IGinX 0.5.1 release 版本源码包 -$ wget https://github.com/IGinX-THU/IGinX/archive/refs/tags/release/v0.5.1.tar.gz +# 下载 IGinX 最新release 版本源码包 +$ wget https://github.com/IGinX-THU/IGinX/archive/refs/tags/v0.7.0.zip # 解压源码包 -$ tar -zxvf v0.5.1.tar.gz +$ tar -zxvf v0.7.0.tar.gz # 进入项目主目录 -$ cd IGinX-rc-v0.5.1 +$ cd IGinX-rc-v0.7.0 # 安装到本地 maven 仓库 $ mvn clean install -DskipTests ``` @@ -440,7 +440,7 @@ $ mvn clean install -DskipTests cn.edu.tsinghua iginx-core - 0.8.0-SNAPSHOT + 0.7.0 ``` diff --git a/docs/quickStarts/IGinXCluster-EnglishVersion.md b/docs/quickStarts/IGinXCluster-EnglishVersion.md index 116f844e97..6980407747 100644 --- a/docs/quickStarts/IGinXCluster-EnglishVersion.md +++ b/docs/quickStarts/IGinXCluster-EnglishVersion.md @@ -97,7 +97,7 @@ $ unzip apache-iotdb-0.12.6-server-bin.zip ### IGinX Installation -Go directly to the [IGinX project](https://github.com/IGinX-THU/IGinX) and download the [IGinX project release package](https://github.com/IGinX-THU/IGinX/releases/download/release%2Fv0.5.1/IGinX-release-v0.5.1-bin.tar.gz). That's it. +Go directly to the [IGinX project](https://github.com/IGinX-THU/IGinX) and download the [IGinX project release package](https://github.com/IGinX-THU/IGinX/releases/download/v0.7.0/IGinX-Server-0.7.0.tar.gz). That's it. ## Launch @@ -337,15 +337,15 @@ In addition to the RESTful interface, IGinX also provides RPC data access interf Below is a short tutorial on how to use it. -Since the IGinX 0.5.1 version has not been released to the maven central repository, if you want to use it, you need to manually install it to the local maven repository. The specific installation method is as follows: +Since the IGinX jars have not been released to the maven central repository, if you want to use it, you need to manually install it to the local maven repository. The specific installation method is as follows: ```shell -# Download IGinX 0.5.1 version source package -$ wget https://github.com/IGinX-THU/IGinX/archive/refs/tags/release/v0.5.1.tar.gz +# Download the newest IGinX version source package +$ wget https://github.com/IGinX-THU/IGinX/archive/refs/tags/v0.7.0.tar.gz # Unzip the source package -$ tar -zxvf v0.5.1.tar.gz +$ tar -zxvf v0.7.0.tar.gz # Enter the project's main directory -$ cd IGinX-release-v0.5.1 +$ cd IGinX-release-v0.7.0 # Install to local maven repository $ mvn clean install -DskipTests ``` @@ -356,7 +356,7 @@ Only when you are using it, you need to introduce the following dependencies in cn.edu.tsinghua iginx-core - 0.8.0-SNAPSHOT + 0.7.0 ``` diff --git a/docs/quickStarts/IGinXCluster.md b/docs/quickStarts/IGinXCluster.md index a210e88d95..d73bd2d20c 100644 --- a/docs/quickStarts/IGinXCluster.md +++ b/docs/quickStarts/IGinXCluster.md @@ -94,13 +94,13 @@ $ unzip apache-iotdb-0.12.6-server-bin.zip ### IGinX 安装 -直接访问 [IGinX 项目](https://github.com/IGinX-THU/IGinX)下载 [IGinX 项目发布包](https://github.com/IGinX-THU/IGinX/releases/download/release%2Fv0.5.1/IGinX-release-v0.5.1-bin.tar.gz) +直接访问 [IGinX 项目](https://github.com/IGinX-THU/IGinX)下载 [IGinX 项目发布包](https://github.com/IGinX-THU/IGinX/releases/download/v0.7.0/IGinX-Server-0.7.0.tar.gz) 即可。 ```shell $ cd ~ -$ wget https://github.com/IGinX-THU/IGinX/releases/download/release%2Fv0.5.1/IGinX-release-v0.5.1-bin.tar.gz -$ tar -zxvf IGinX-release-v0.5.1-bin.tar.gz +$ wget https://github.com/IGinX-THU/IGinX/releases/download/v0.7.0/IGinX-Server-0.7.0.tar.gz +$ tar -zxvf IGinX-Server-0.7.0.tar.gz ``` ## 启动 @@ -344,15 +344,15 @@ RPC 接口最常见的用法。 下面是一个简短的使用教程。 -由于目前 IGinX 0.5.1 版本还未发布到 maven 中央仓库,因此如需使用的话,需要手动安装到本地的 maven 仓库。具体安装方式如下: +由于目前 IGinX jar包还未发布到 maven 中央仓库,因此如需使用的话,需要手动安装到本地的 maven 仓库。具体安装方式如下: ```shell -# 下载 IGinX 0.5.1 release 版本源码包 -$ wget https://github.com/IGinX-THU/IGinX/archive/refs/tags/release/v0.5.1.tar.gz +# 下载 IGinX 最新release 版本源码包 +$ wget https://github.com/IGinX-THU/IGinX/archive/refs/tags/v0.7.0.tar.gz # 解压源码包 -$ tar -zxvf v0.5.1.tar.gz +$ tar -zxvf v0.7.0.tar.gz # 进入项目主目录 -$ cd IginX-release-v0.5.1 +$ cd IginX-release-v0.7.0 # 安装到本地 maven 仓库 $ mvn clean install -DskipTests ``` @@ -363,7 +363,7 @@ $ mvn clean install -DskipTests cn.edu.tsinghua iginx-core - 0.8.0-SNAPSHOT + 0.7.0 ``` diff --git a/docs/quickStarts/IGinXInOneShot-EnglishVersion.md b/docs/quickStarts/IGinXInOneShot-EnglishVersion.md index 24a59cc8f0..ec4c4784e4 100644 --- a/docs/quickStarts/IGinXInOneShot-EnglishVersion.md +++ b/docs/quickStarts/IGinXInOneShot-EnglishVersion.md @@ -55,15 +55,15 @@ IGinX is the main part of the system, and the installation package can be downlo ```shell $ cd ~ -$ wget https://github.com/IGinX-THU/IGinX/releases/download/release%2Fv0.5.1/IGinX-FastDeploy-v0.5.1-bin.tar.gz -$ tar -xzvf IGinX-FastDeploy-v0.5.1-bin.tar.gz +$ wget https://github.com/IGinX-THU/IGinX/releases/download/v0.7.0/IGinX-FastDeploy-0.7.0.tar.gz +$ tar -xzvf IGinX-FastDeploy-0.7.0.tar.gz ``` ## Launch ```shell $ cd ~ -$ cd IGinX-FastDeploy-v0.5.0-bin +$ cd IGinX-FastDeploy-0.7.0 $ chmod +x ./runIginxOn1Host.sh $ ./runIginxOn1Host.sh ``` @@ -251,17 +251,17 @@ Below is a short tutorial on how to use it. ### RPC Interface -Since the IGinX 0.5.1 version has not been released to the Maven central repository, if you want to use it, you need to manually install it to the local Maven repository. +Since the IGinX jars have not been released to the Maven central repository, if you want to use it, you need to manually install it to the local Maven repository. The specific installation method is as follows: ```shell -# download iginx 0.4 release version source code package -$ wget https://github.com/IGinX-THU/IGinX/archive/refs/tags/release/v0.5.1.tar.gz +# download the newest IGinX release version source code package +$ wget https://github.com/IGinX-THU/IGinX/archive/refs/tags/v0.7.0.tar.gz # Unzip the source package -$ tar -zxvf v0.5.1.tar.gz +$ tar -zxvf v0.7.0.tar.gz # go to the main project's directory -$ cd IGinX-release-v0.5.1 +$ cd IGinX-release-v0.7.0 # Install to local Maven repository $ mvn clean install -DskipTests ``` @@ -272,7 +272,7 @@ Specifically, when using it, you only need to introduce the following dependenci cn.edu.tsinghua iginx-core - 0.8.0-SNAPSHOT + 0.7.0 ``` diff --git a/docs/quickStarts/IGinXInOneShot.md b/docs/quickStarts/IGinXInOneShot.md index 92bb9e7c10..91b1a4424b 100644 --- a/docs/quickStarts/IGinXInOneShot.md +++ b/docs/quickStarts/IGinXInOneShot.md @@ -54,15 +54,15 @@ IGinX 为系统的主体部分,通过一键启动安装包 ```shell $ cd ~ -$ wget https://github.com/IGinX-THU/IGinX/releases/download/release%2Fv0.5.1/IGinX-FastDeploy-v0.5.1-bin.tar.gz -$ tar -xzvf IGinX-FastDeploy-v0.5.1-bin.tar.gz +$ wget https://github.com/IGinX-THU/IGinX/releases/download/v0.7.0/IGinX-FastDeploy-0.7.0.tar.gz +$ tar -xzvf IGinX-FastDeploy-v0.7.0-bin.tar.gz ``` ## 启动 ```shell $ cd ~ -$ cd IGinX-FastDeploy-v0.5.0-bin +$ cd IGinX-FastDeploy-0.7.0 $ chmod +x ./runIginxOn1Host.sh $ ./runIginxOn1Host.sh ``` @@ -247,15 +247,15 @@ RPC 接口最常见的用法。 下面是一个简短的使用教程。 -由于目前 IGinX 0.5.1 版本还未发布到 maven 中央仓库,因此如需使用的话,需要手动安装到本地的 maven 仓库。具体安装方式如下: +由于目前 IGinX jar包还未发布到 maven 中央仓库,因此如需使用的话,需要手动安装到本地的 maven 仓库。具体安装方式如下: ```shell -# 下载 IGinX 0.5.1 release 版本源码包 -$ wget https://github.com/IGinX-THU/IGinX/archive/refs/tags/release/v0.5.1.tar.gz +# 下载 IGinX 最新release 版本源码包 +$ wget https://github.com/IGinX-THU/IGinX/archive/refs/tags/v0.7.0.zip # 解压源码包 -$ tar -zxvf v0.5.1.tar.gz +$ tar -zxvf v0.7.0.tar.gz # 进入项目主目录 -$ cd IGinX-release-v0.5.1 +$ cd IGinX-release-v0.7.0 # 安装到本地 maven 仓库 $ mvn clean install -DskipTests ``` @@ -266,7 +266,7 @@ $ mvn clean install -DskipTests cn.edu.tsinghua iginx-core - 0.8.0-SNAPSHOT + 0.7.0 ``` diff --git a/docs/quickStarts/IGinXManual-EnglishVersion.md b/docs/quickStarts/IGinXManual-EnglishVersion.md index 5854c78b74..d742838af2 100644 --- a/docs/quickStarts/IGinXManual-EnglishVersion.md +++ b/docs/quickStarts/IGinXManual-EnglishVersion.md @@ -142,12 +142,12 @@ $ unzip apache-iotdb-0.12.6-server-bin.zip ### Download the binary executables -Go directly to the [IGinX project](https://github.com/IGinX-THU/IGinX) and download the [IGinX project release package](https://github.com/IGinX-THU/IGinX/releases/download/release%2Fv0.5.1/IGinX-release-v0.5.1-bin.tar.gz). +Go directly to the [IGinX project](https://github.com/IGinX-THU/IGinX) and download the [IGinX project release package](https://github.com/IGinX-THU/IGinX/releases/download/v0.7.0/IGinX-Server-0.7.0.tar.gz). ```shell $ cd ~ -$ wget https://github.com/IGinX-THU/IGinX/releases/download/release%2Fv0.5.1/IGinX-release-v0.5.1-bin.tar.gz -$ tar -xzvf IGinX-release-v0.5.1-bin.tar.gz +$ wget https://github.com/IGinX-THU/IGinX/releases/download/v0.7.0/IGinX-Server-0.7.0.tar.gz +$ tar -xzvf IGinX-Server-0.7.0.tar.gz ``` ### Compilation with source code @@ -191,7 +191,7 @@ The following display of words means the IoTDB installation was successful: #### Launch ZooKeeper -If you are taking a 0.2.0 binary installation package, or if you designate Zookeeper as the metadata management storage backend in the configuration file, you need to launch ZooKeeper. Otherwise, **skip this step entirely**. +If you are taking a binary installation package, or if you designate Zookeeper as the metadata management storage backend in the configuration file, you need to launch ZooKeeper. Otherwise, **skip this step entirely**. ```shell $ cd ~ @@ -213,7 +213,7 @@ Using the release package to launch ```shell $ cd ~ -$ cd IGinX-release-v0.5.1-bin +$ cd IGinX-Server-0.7.0 $ chmod +x startIginX.sh # enable permissions for startup scripts $ ./startIginX.sh ``` @@ -484,15 +484,15 @@ In addition to the RESTful interface, IGinX also provides RPC data access interf Below is a short tutorial on how to use it. -Since the IGinX 0.5.1 version has not been released to the maven central repository, if you want to use it, you need to manually install it to the local maven repository. The specific installation method is as follows: +Since the IGinX jars have not been released to the maven central repository, if you want to use it, you need to manually install it to the local maven repository. The specific installation method is as follows: ```shell -# Download iginx 0.2 rc version source package -$ wget https://github.com/IGinX-THU/IGinX/archive/refs/tags/release/v0.5.1.tar.gz +# Download the newest IGinX version source package +$ wget https://github.com/IGinX-THU/IGinX/archive/refs/tags/v0.7.0.tar.gz # Unzip the source package -$ tar -zxvf v0.5.1.tar.gz +$ tar -zxvf v0.7.0.tar.gz # Enter the project main directory -$ cd IGinX-rc-v0.5.1 +$ cd IGinX-v0.7.0 # Install to local maven repository $ mvn clean install -DskipTests ``` @@ -503,7 +503,7 @@ Only when you are using it, you need to introduce the following dependencies in cn.edu.tsinghua iginx-core - 0.8.0-SNAPSHOT + 0.7.0 ``` @@ -639,7 +639,7 @@ For the full version of the code, please refer to: https://github.com/IGinX-THU/ cn.edu.tsinghua iginx-session - 0.5.1 + 0.7.0 diff --git a/docs/quickStarts/IGinXManual.md b/docs/quickStarts/IGinXManual.md index c07aee8f6c..0ed5859982 100644 --- a/docs/quickStarts/IGinXManual.md +++ b/docs/quickStarts/IGinXManual.md @@ -139,13 +139,13 @@ $ unzip apache-iotdb-0.12.6-server-bin.zip ### 下载二进制可执行文件 -直接访问 [IGinX 项目](https://github.com/IGinX-THU/IGinX)下载 [IGinX 项目发布包](https://github.com/IGinX-THU/IGinX/releases/download/release%2Fv0.5.1/IGinX-release-v0.5.1-bin.tar.gz) +直接访问 [IGinX 项目](https://github.com/IGinX-THU/IGinX)下载 [IGinX 项目发布包](https://github.com/IGinX-THU/IGinX/releases/download/v0.7.0/IGinX-Server-0.7.0.tar.gz) 即可 ```shell $ cd ~ -$ wget https://github.com/IGinX-THU/IGinX/releases/download/release%2Fv0.5.1/IGinX-release-v0.5.1-bin.tar.gz -$ tar -zxvf IGinX-release-v0.5.1-bin.tar.gz +$ wget https://github.com/IGinX-THU/IGinX/releases/download/v0.7.0/IGinX-Server-0.7.0.tar.gz +$ tar -zxvf IGinX-Server-0.7.0.tar.gz ``` ### 使用源码编译 @@ -189,7 +189,7 @@ $ ./sbin/start-server.sh #### 启动 ZooKeeper -如果您采取的是 0.5.1 的二进制安装包,或者在配置文件中指定 ZooKeeper 为元数据管理存储后端,需要启动ZooKeeper。否则,**直接跳过此步骤** +如果您采取的是IGinX的快速部署安装包,或者在配置文件中指定 ZooKeeper 为元数据管理存储后端,需要启动ZooKeeper。否则,**直接跳过此步骤** ```shell $ cd ~ @@ -211,7 +211,7 @@ Starting zookeeper ... STARTED ```shell $ cd ~ -$ cd IGinX-release-v0.5.1-bin +$ cd IGinX-Server-0.7.0 $ chmod +x startIginX.sh # 为启动脚本添加启动权限 $ ./startIginX.sh ``` @@ -485,15 +485,15 @@ RPC 接口最常见的用法。 下面是一个简短的使用教程。 -由于目前 IGinX 0.5.1 版本还未发布到 maven 中央仓库,因此如需使用的话,需要手动安装到本地的 maven 仓库。具体安装方式如下: +由于目前 IGinX jar包还未发布到 maven 中央仓库,因此如需使用的话,需要手动安装到本地的 maven 仓库。具体安装方式如下: ```shell -# 下载 IGinX 0.5.1 release 版本源码包 -$ wget https://github.com/IGinX-THU/IGinX/archive/refs/tags/release/v0.5.1.tar.gz +# 下载 IGinX 最新release 版本源码包 +$ wget https://github.com/IGinX-THU/IGinX/archive/refs/tags/v0.7.0.tar.gz # 解压源码包 -$ tar -zxvf v0.5.1.tar.gz +$ tar -zxvf v0.7.0.tar.gz # 进入项目主目录 -$ cd IGinX-release-v0.5.1 +$ cd IGinX-release-v0.7.0 # 安装到本地 maven 仓库 $ mvn clean install -DskipTests ``` @@ -504,7 +504,7 @@ $ mvn clean install -DskipTests cn.edu.tsinghua iginx-core - 0.8.0-SNAPSHOT + 0.7.0 ``` @@ -641,7 +641,7 @@ session.closeSession(); cn.edu.tsinghua iginx-session - 0.5.1 + 0.7.0 diff --git a/docs/quickStarts_Parquet/IGinXBySource-EnglishVersion.md b/docs/quickStarts_Parquet/IGinXBySource-EnglishVersion.md index bfdeaf3c8b..bd1dcd0c3a 100644 --- a/docs/quickStarts_Parquet/IGinXBySource-EnglishVersion.md +++ b/docs/quickStarts_Parquet/IGinXBySource-EnglishVersion.md @@ -396,17 +396,17 @@ Below is a short tutorial on how to use it. ### RPC Interface -Since the IGinX 0.5.1 version has not been released to the Maven central repository, if you want to use it, you need to manually install it to the local Maven repository. +Since the IGinX jars have not been released to the Maven central repository, if you want to use it, you need to manually install it to the local Maven repository. The specific installation method is as follows: ```shell -# download iginx 0.4 release version source code package -$ wget https://github.com/IGinX-THU/IGinX/archive/refs/tags/release/v0.5.1.tar.gz +# download the newest iginx release version source code package +$ wget https://github.com/IGinX-THU/IGinX/releases/download/v0.7.0/IGinX-FastDeploy-0.7.0.tar.gz # Unzip the source package -$ tar -zxvf v0.5.1.tar.gz +$ tar -zxvf v0.7.0.tar.gz # go to the main project's directory -$ cd IGinX-rc-v0.5.1 +$ cd IGinX-rc-v0.7.0 # Install to local Maven repository $ mvn clean install -DskipTests ``` @@ -417,7 +417,7 @@ Specifically, when using it, you only need to introduce the following dependenci cn.edu.tsinghua iginx-core - 0.8.0-SNAPSHOT + 0.7.0 ``` diff --git a/docs/quickStarts_Parquet/IGinXBySource.md b/docs/quickStarts_Parquet/IGinXBySource.md index 52a04f64e4..f7fc887b6f 100644 --- a/docs/quickStarts_Parquet/IGinXBySource.md +++ b/docs/quickStarts_Parquet/IGinXBySource.md @@ -395,15 +395,15 @@ RPC 接口最常见的用法。 下面是一个简短的使用教程。 -由于目前 IGinX 0.5.1 版本还未发布到 maven 中央仓库,因此如需使用的话,需要手动安装到本地的 maven 仓库。具体安装方式如下: +由于目前 IGinX jar包还未发布到 maven 中央仓库,因此如需使用的话,需要手动安装到本地的 maven 仓库。具体安装方式如下: ```shell -# 下载 IGinX 0.5.1 release 版本源码包 -$ wget https://github.com/IGinX-THU/IGinX/archive/refs/tags/release/v0.5.1.tar.gz +# 下载 IGinX 最新release 版本源码包 +$ wget https://github.com/IGinX-THU/IGinX/archive/refs/tags/v0.7.0.tar.gz # 解压源码包 -$ tar -zxvf v0.5.1.tar.gz +$ tar -zxvf v0.7.0.tar.gz # 进入项目主目录 -$ cd IGinX-rc-v0.5.1 +$ cd IGinX-rc-v0.7.0 # 安装到本地 maven 仓库 $ mvn clean install -DskipTests ``` @@ -414,7 +414,7 @@ $ mvn clean install -DskipTests cn.edu.tsinghua iginx-core - 0.8.0-SNAPSHOT + 0.7.0 ``` diff --git a/docs/quickStarts_Parquet/IGinXCluster-EnglishVersion.md b/docs/quickStarts_Parquet/IGinXCluster-EnglishVersion.md index 8a23a80467..9aa22cded6 100644 --- a/docs/quickStarts_Parquet/IGinXCluster-EnglishVersion.md +++ b/docs/quickStarts_Parquet/IGinXCluster-EnglishVersion.md @@ -85,12 +85,12 @@ dataDir=data ### IGinX Installation -Go directly to the [IGinX project](https://github.com/IGinX-THU/IGinX) and download the [IGinX project release package](https://github.com/IGinX-THU/IGinX/releases/download/release%2Fv0.5.1/IGinX-release-v0.5.1-bin.tar.gz). That's it. +Go directly to the [IGinX project](https://github.com/IGinX-THU/IGinX) and download the [IGinX project release package](https://github.com/IGinX-THU/IGinX/releases/download/v0.7.0/IGinX-Server-0.7.0.tar.gz). That's it. ```shell $ cd ~ -$ wget https://github.com/IGinX-THU/IGinX/releases/download/release%2Fv0.5.1/IGinX-release-v0.5.1-bin.tar.gz -$ tar -zxvf IGinX-release-v0.5.1-bin.tar.gz +$ wget https://github.com/IGinX-THU/IGinX/releases/download/v0.7.0/IGinX-Server-0.7.0.tar.gz +$ tar -zxvf IGinX-Server-0.7.0.tar.gz ``` ## Launch @@ -303,15 +303,15 @@ In addition to the RESTful interface, IGinX also provides RPC data access interf Below is a short tutorial on how to use it. -Since the IGinX 0.5.1 version has not been released to the maven central repository, if you want to use it, you need to manually install it to the local maven repository. The specific installation method is as follows: +Since the IGinX jars have not been released to the maven central repository, if you want to use it, you need to manually install it to the local maven repository. The specific installation method is as follows: ```shell -# Download IGinX 0.5.1 version source package -$ wget https://github.com/IGinX-THU/IGinX/archive/refs/tags/release/v0.5.1.tar.gz +# Download the newest IGinX version source package +$ wget https://github.com/IGinX-THU/IGinX/archive/refs/tags/v0.7.0.tar.gz # Unzip the source package -$ tar -zxvf v0.5.1.tar.gz +$ tar -zxvf v0.7.0.tar.gz # Enter the project's main directory -$ cd IGinX-release-v0.5.1 +$ cd IGinX-release-v0.7.0 # Install to local maven repository $ mvn clean install -DskipTests ``` @@ -322,7 +322,7 @@ Only when you are using it, you need to introduce the following dependencies in cn.edu.tsinghua iginx-core - 0.8.0-SNAPSHOT + 0.7.0 ``` diff --git a/docs/quickStarts_Parquet/IGinXCluster.md b/docs/quickStarts_Parquet/IGinXCluster.md index 8f464cdc63..1fbdc61e04 100644 --- a/docs/quickStarts_Parquet/IGinXCluster.md +++ b/docs/quickStarts_Parquet/IGinXCluster.md @@ -84,13 +84,13 @@ dataDir=data ### IGinX 安装 -直接访问 [IGinX 项目](https://github.com/IGinX-THU/IGinX)下载 [IGinX 项目发布包](https://github.com/IGinX-THU/IGinX/releases/download/release%2Fv0.5.1/IGinX-release-v0.5.1-bin.tar.gz) +直接访问 [IGinX 项目](https://github.com/IGinX-THU/IGinX)下载 [IGinX 项目发布包](https://github.com/IGinX-THU/IGinX/releases/download/v0.7.0/IGinX-Server-0.7.0.tar.gz) 即可。 ```shell $ cd ~ -$ wget https://github.com/IGinX-THU/IGinX/releases/download/release%2Fv0.5.1/IGinX-release-v0.5.1-bin.tar.gz -$ tar -zxvf IGinX-release-v0.5.1-bin.tar.gz +$ wget https://github.com/IGinX-THU/IGinX/releases/download/v0.7.0/IGinX-Server-0.7.0.tar.gz +$ tar -zxvf IGinX-Server-0.7.0.tar.gz ``` ## 启动 @@ -306,15 +306,15 @@ RPC 接口最常见的用法。 下面是一个简短的使用教程。 -由于目前 IGinX 0.5.1 版本还未发布到 maven 中央仓库,因此如需使用的话,需要手动安装到本地的 maven 仓库。具体安装方式如下: +由于目前 IGinX jar包还未发布到 maven 中央仓库,因此如需使用的话,需要手动安装到本地的 maven 仓库。具体安装方式如下: ```shell -# 下载 IGinX 0.5.1 release 版本源码包 -$ wget https://github.com/IGinX-THU/IGinX/archive/refs/tags/release/v0.5.1.tar.gz +# 下载 IGinX 最新release 版本源码包 +$ wget https://github.com/IGinX-THU/IGinX/archive/refs/tags/v0.7.0.tar.gz # 解压源码包 -$ tar -zxvf v0.5.1.tar.gz +$ tar -zxvf v0.7.0.tar.gz # 进入项目主目录 -$ cd IginX-release-v0.5.1 +$ cd IginX-release-v0.7.0 # 安装到本地 maven 仓库 $ mvn clean install -DskipTests ``` @@ -325,7 +325,7 @@ $ mvn clean install -DskipTests cn.edu.tsinghua iginx-core - 0.8.0-SNAPSHOT + 0.7.0 ``` diff --git a/docs/quickStarts_Parquet/IGinXInOneShot-EnglishVersion.md b/docs/quickStarts_Parquet/IGinXInOneShot-EnglishVersion.md index 87a857a7ac..e027d9d501 100644 --- a/docs/quickStarts_Parquet/IGinXInOneShot-EnglishVersion.md +++ b/docs/quickStarts_Parquet/IGinXInOneShot-EnglishVersion.md @@ -55,15 +55,15 @@ IGinX is the main part of the system, and the installation package can be downlo ```shell $ cd ~ -$ wget https://github.com/IGinX-THU/IGinX/releases/download/release%2Fv0.5.1/IGinX-FastDeploy-v0.5.1-bin.tar.gz -$ tar -xzvf IGinX-FastDeploy-v0.5.1-bin.tar.gz +$ wget https://github.com/IGinX-THU/IGinX/releases/download/v0.7.0/IGinX-FastDeploy-0.7.0.tar.gz +$ tar -xzvf IGinX-FastDeploy-0.7.0.tar.gz ``` ## Launch ```shell $ cd ~ -$ cd IGinX-FastDeploy-v0.5.0-bin +$ cd IGinX-FastDeploy-0.7.0 $ chmod +x ./runIginxOn1Host.sh $ ./runIginxOn1Host.sh ``` @@ -233,17 +233,17 @@ Below is a short tutorial on how to use it. ### RPC Interface -Since the IGinX 0.5.1 version has not been released to the Maven central repository, if you want to use it, you need to manually install it to the local Maven repository. +Since the IGinX jars have not been released to the Maven central repository, if you want to use it, you need to manually install it to the local Maven repository. The specific installation method is as follows: ```shell -# download iginx 0.4 release version source code package -$ wget https://github.com/IGinX-THU/IGinX/archive/refs/tags/release/v0.5.1.tar.gz +# download the newest iginx release version source code package +$ wget https://github.com/IGinX-THU/IGinX/archive/refs/tags/v0.7.0.tar.gz # Unzip the source package -$ tar -zxvf v0.5.1.tar.gz +$ tar -zxvf v0.7.0.tar.gz # go to the main project's directory -$ cd IGinX-release-v0.5.1 +$ cd IGinX-release-v0.7.0 # Install to local Maven repository $ mvn clean install -DskipTests ``` @@ -254,7 +254,7 @@ Specifically, when using it, you only need to introduce the following dependenci cn.edu.tsinghua iginx-core - 0.8.0-SNAPSHOT + 0.7.0 ``` diff --git a/docs/quickStarts_Parquet/IGinXInOneShot.md b/docs/quickStarts_Parquet/IGinXInOneShot.md index 9fb95c5988..8549270990 100644 --- a/docs/quickStarts_Parquet/IGinXInOneShot.md +++ b/docs/quickStarts_Parquet/IGinXInOneShot.md @@ -54,15 +54,15 @@ IGinX 为系统的主体部分,通过一键启动安装包 ```shell $ cd ~ -$ wget https://github.com/IGinX-THU/IGinX/releases/download/release%2Fv0.5.1/IGinX-FastDeploy-v0.5.1-bin.tar.gz -$ tar -xzvf IGinX-FastDeploy-v0.5.1-bin.tar.gz +$ wget https://github.com/IGinX-THU/IGinX/releases/download/v0.7.0/IGinX-FastDeploy-0.7.0.tar.gz +$ tar -xzvf IGinX-FastDeploy-0.7.0.tar.gz ``` ## 启动 ```shell $ cd ~ -$ cd IGinX-FastDeploy-v0.5.0-bin +$ cd IGinX-FastDeploy-0.7.0 $ chmod +x ./runIginxOn1Host.sh $ ./runIginxOn1Host.sh ``` @@ -228,15 +228,15 @@ RPC 接口最常见的用法。 下面是一个简短的使用教程。 -由于目前 IGinX 0.5.1 版本还未发布到 maven 中央仓库,因此如需使用的话,需要手动安装到本地的 maven 仓库。具体安装方式如下: +由于目前 IGinX jar包还未发布到 maven 中央仓库,因此如需使用的话,需要手动安装到本地的 maven 仓库。具体安装方式如下: ```shell -# 下载 IGinX 0.5.1 release 版本源码包 -$ wget https://github.com/IGinX-THU/IGinX/archive/refs/tags/release/v0.5.1.tar.gz +# 下载 IGinX 最新release 版本源码包 +$ wget https://github.com/IGinX-THU/IGinX/archive/refs/tags/v0.7.0.tar.gz # 解压源码包 -$ tar -zxvf v0.5.1.tar.gz +$ tar -zxvf v0.7.0.tar.gz # 进入项目主目录 -$ cd IGinX-release-v0.5.1 +$ cd IGinX-release-v0.7.0 # 安装到本地 maven 仓库 $ mvn clean install -DskipTests ``` @@ -247,7 +247,7 @@ $ mvn clean install -DskipTests cn.edu.tsinghua iginx-core - 0.8.0-SNAPSHOT + 0.7.0 ``` From 0a3513a3ab7d3a29e4e66bfd10f303bd62a62969 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Tue, 23 Jul 2024 15:57:41 +0800 Subject: [PATCH 111/138] try to fix --- .github/actions/service/postgresql/action.yml | 1 - .github/workflows/standard-test-suite.yml | 35 +++++-------------- .../iginx/relational/RelationalStorage.java | 4 ++- 3 files changed, 11 insertions(+), 29 deletions(-) diff --git a/.github/actions/service/postgresql/action.yml b/.github/actions/service/postgresql/action.yml index 3d60b67be0..295d7f2f29 100644 --- a/.github/actions/service/postgresql/action.yml +++ b/.github/actions/service/postgresql/action.yml @@ -63,7 +63,6 @@ runs: echo "port = ${port}" >> "${PGCONF}" echo "unix_socket_directories = ''" >> "${PGCONF}" echo "fsync = off" >> "${PGCONF}" - echo "max_connections = 200" >> "${PGCONF}" pg_ctl start --pgdata="${PGDATA}" done diff --git a/.github/workflows/standard-test-suite.yml b/.github/workflows/standard-test-suite.yml index 67e41e0f75..582c5cfaa3 100644 --- a/.github/workflows/standard-test-suite.yml +++ b/.github/workflows/standard-test-suite.yml @@ -1,44 +1,25 @@ name: Standard Test Suite -on: - pull_request: # when a PR is opened or reopened - types: [opened, reopened] - branches: - - main +#on: +# pull_request: # when a PR is opened or reopened +# types: [opened, reopened] +# branches: +# - main + +on: [pull_request] concurrency: group: "${{ github.workflow }}-${{ github.ref }}" cancel-in-progress: true jobs: - unit-test: - uses: ./.github/workflows/unit-test.yml - unit-mds: - uses: ./.github/workflows/unit-mds.yml - case-regression: - uses: ./.github/workflows/case-regression.yml - with: - metadata-matrix: '["zookeeper"]' standalone-test: uses: ./.github/workflows/standalone-test.yml with: - metadata-matrix: '["zookeeper"]' - standalone-test-pushdown: - uses: ./.github/workflows/standalone-test-pushdown.yml - with: + os-matrix: '["ubuntu-latest"]' metadata-matrix: '["zookeeper"]' db-ce: uses: ./.github/workflows/DB-CE.yml - with: - metadata-matrix: '["zookeeper"]' - remote-test: - uses: ./.github/workflows/remote-test.yml - with: - metadata-matrix: '["zookeeper"]' - assemebly-test: - uses: ./.github/workflows/assembly-test.yml - tpc-h-regression-test: - uses: ./.github/workflows/tpc-h.yml with: os-matrix: '["ubuntu-latest"]' metadata-matrix: '["zookeeper"]' diff --git a/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java index 3e2e6eb452..71540885c9 100644 --- a/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java +++ b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java @@ -262,7 +262,8 @@ private boolean testConnection() { private List getDatabaseNames() throws SQLException { List databaseNames = new ArrayList<>(); Connection conn = getConnection(relationalMeta.getDefaultDatabaseName()); - ResultSet rs = conn.createStatement().executeQuery(relationalMeta.getDatabaseQuerySql()); + Statement statement = conn.createStatement(); + ResultSet rs = statement.executeQuery(relationalMeta.getDatabaseQuerySql()); while (rs.next()) { String databaseName = rs.getString("DATNAME"); if (relationalMeta.getSystemDatabaseName().contains(databaseName) @@ -272,6 +273,7 @@ private List getDatabaseNames() throws SQLException { databaseNames.add(databaseName); } rs.close(); + statement.close(); conn.close(); return databaseNames; } From 7c77b9c8fc5c1bfb73a15266784d8844d00e7fee Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Tue, 23 Jul 2024 16:50:57 +0800 Subject: [PATCH 112/138] open other tests --- .github/actions/service/postgresql/action.yml | 1 + .github/workflows/standard-test-suite.yml | 35 ++++++++++++++----- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/.github/actions/service/postgresql/action.yml b/.github/actions/service/postgresql/action.yml index 295d7f2f29..3d60b67be0 100644 --- a/.github/actions/service/postgresql/action.yml +++ b/.github/actions/service/postgresql/action.yml @@ -63,6 +63,7 @@ runs: echo "port = ${port}" >> "${PGCONF}" echo "unix_socket_directories = ''" >> "${PGCONF}" echo "fsync = off" >> "${PGCONF}" + echo "max_connections = 200" >> "${PGCONF}" pg_ctl start --pgdata="${PGDATA}" done diff --git a/.github/workflows/standard-test-suite.yml b/.github/workflows/standard-test-suite.yml index 582c5cfaa3..67e41e0f75 100644 --- a/.github/workflows/standard-test-suite.yml +++ b/.github/workflows/standard-test-suite.yml @@ -1,25 +1,44 @@ name: Standard Test Suite -#on: -# pull_request: # when a PR is opened or reopened -# types: [opened, reopened] -# branches: -# - main - -on: [pull_request] +on: + pull_request: # when a PR is opened or reopened + types: [opened, reopened] + branches: + - main concurrency: group: "${{ github.workflow }}-${{ github.ref }}" cancel-in-progress: true jobs: + unit-test: + uses: ./.github/workflows/unit-test.yml + unit-mds: + uses: ./.github/workflows/unit-mds.yml + case-regression: + uses: ./.github/workflows/case-regression.yml + with: + metadata-matrix: '["zookeeper"]' standalone-test: uses: ./.github/workflows/standalone-test.yml with: - os-matrix: '["ubuntu-latest"]' + metadata-matrix: '["zookeeper"]' + standalone-test-pushdown: + uses: ./.github/workflows/standalone-test-pushdown.yml + with: metadata-matrix: '["zookeeper"]' db-ce: uses: ./.github/workflows/DB-CE.yml + with: + metadata-matrix: '["zookeeper"]' + remote-test: + uses: ./.github/workflows/remote-test.yml + with: + metadata-matrix: '["zookeeper"]' + assemebly-test: + uses: ./.github/workflows/assembly-test.yml + tpc-h-regression-test: + uses: ./.github/workflows/tpc-h.yml with: os-matrix: '["ubuntu-latest"]' metadata-matrix: '["zookeeper"]' From acaf3794a477bd1969fff8921af3fa94ffe22711 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Wed, 24 Jul 2024 09:55:08 +0800 Subject: [PATCH 113/138] test --- .github/actions/service/postgresql/action.yml | 1 - .github/workflows/standard-test-suite.yml | 54 ++++++++++--------- .../iginx/relational/RelationalStorage.java | 2 + 3 files changed, 30 insertions(+), 27 deletions(-) diff --git a/.github/actions/service/postgresql/action.yml b/.github/actions/service/postgresql/action.yml index 3d60b67be0..295d7f2f29 100644 --- a/.github/actions/service/postgresql/action.yml +++ b/.github/actions/service/postgresql/action.yml @@ -63,7 +63,6 @@ runs: echo "port = ${port}" >> "${PGCONF}" echo "unix_socket_directories = ''" >> "${PGCONF}" echo "fsync = off" >> "${PGCONF}" - echo "max_connections = 200" >> "${PGCONF}" pg_ctl start --pgdata="${PGDATA}" done diff --git a/.github/workflows/standard-test-suite.yml b/.github/workflows/standard-test-suite.yml index 67e41e0f75..51e12aab7d 100644 --- a/.github/workflows/standard-test-suite.yml +++ b/.github/workflows/standard-test-suite.yml @@ -11,34 +11,36 @@ concurrency: cancel-in-progress: true jobs: - unit-test: - uses: ./.github/workflows/unit-test.yml - unit-mds: - uses: ./.github/workflows/unit-mds.yml - case-regression: - uses: ./.github/workflows/case-regression.yml - with: - metadata-matrix: '["zookeeper"]' - standalone-test: - uses: ./.github/workflows/standalone-test.yml - with: - metadata-matrix: '["zookeeper"]' - standalone-test-pushdown: - uses: ./.github/workflows/standalone-test-pushdown.yml - with: - metadata-matrix: '["zookeeper"]' + # unit-test: + # uses: ./.github/workflows/unit-test.yml + # unit-mds: + # uses: ./.github/workflows/unit-mds.yml + # case-regression: + # uses: ./.github/workflows/case-regression.yml + # with: + # metadata-matrix: '["zookeeper"]' + # standalone-test: + # uses: ./.github/workflows/standalone-test.yml + # with: + # metadata-matrix: '["zookeeper"]' + # standalone-test-pushdown: + # uses: ./.github/workflows/standalone-test-pushdown.yml + # with: + # metadata-matrix: '["zookeeper"]' db-ce: uses: ./.github/workflows/DB-CE.yml - with: - metadata-matrix: '["zookeeper"]' - remote-test: - uses: ./.github/workflows/remote-test.yml - with: - metadata-matrix: '["zookeeper"]' - assemebly-test: - uses: ./.github/workflows/assembly-test.yml - tpc-h-regression-test: - uses: ./.github/workflows/tpc-h.yml with: os-matrix: '["ubuntu-latest"]' metadata-matrix: '["zookeeper"]' + db-matrix: '["PostgreSQL"]' +# remote-test: +# uses: ./.github/workflows/remote-test.yml +# with: +# metadata-matrix: '["zookeeper"]' +# assemebly-test: +# uses: ./.github/workflows/assembly-test.yml +# tpc-h-regression-test: +# uses: ./.github/workflows/tpc-h.yml +# with: +# os-matrix: '["ubuntu-latest"]' +# metadata-matrix: '["zookeeper"]' diff --git a/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java index 71540885c9..31e16ee8da 100644 --- a/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java +++ b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java @@ -303,6 +303,7 @@ private List getTables(String databaseName, String tablePattern) { rs.close(); conn.close(); + closeConnection(databaseName); return tableNames; } catch (SQLException | RelationalTaskExecuteFailureException e) { LOGGER.error("unexpected error: ", e); @@ -331,6 +332,7 @@ private List getColumns( } rs.close(); conn.close(); + closeConnection(databaseName); return columnFields; } catch (SQLException | RelationalTaskExecuteFailureException e) { LOGGER.error("unexpected error: ", e); From 20b0beb66bbceb7130253112b67dcac772987e5c Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Wed, 24 Jul 2024 10:04:11 +0800 Subject: [PATCH 114/138] debug --- .../java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java | 1 + 1 file changed, 1 insertion(+) diff --git a/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java index 31e16ee8da..02c5c3a7fd 100644 --- a/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java +++ b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java @@ -1063,6 +1063,7 @@ private TaskExecuteResult executeProjectDummyWithFilter(Project project, Filter Map tableNameToColumnNames = splitEntry.getValue(); String databaseName = splitEntry.getKey(); conn = getConnection(databaseName); + LOGGER.info("datasource: {}", connectionPoolMap.keySet()); if (conn == null) { continue; } From 001afbde3f57089bbf1eb67ee3c75a3cb6928632 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Wed, 24 Jul 2024 10:09:51 +0800 Subject: [PATCH 115/138] debug --- .../cn/edu/tsinghua/iginx/relational/RelationalStorage.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java index 02c5c3a7fd..73d19b2cec 100644 --- a/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java +++ b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java @@ -169,6 +169,8 @@ private void closeConnection(String databaseName) { if (dataSource != null) { dataSource.close(); connectionPoolMap.remove(databaseName); + LOGGER.info("close datasource: {}", databaseName); + LOGGER.info("connectionPoolMap remain: {}", connectionPoolMap.keySet()); } } @@ -1062,6 +1064,7 @@ private TaskExecuteResult executeProjectDummyWithFilter(Project project, Filter for (Map.Entry> splitEntry : splitResults.entrySet()) { Map tableNameToColumnNames = splitEntry.getValue(); String databaseName = splitEntry.getKey(); + LOGGER.info("datasource: {}", connectionPoolMap.keySet()); conn = getConnection(databaseName); LOGGER.info("datasource: {}", connectionPoolMap.keySet()); if (conn == null) { From aebbdbcc17170188865c6124d4f567d29853d457 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Wed, 24 Jul 2024 10:16:01 +0800 Subject: [PATCH 116/138] debug --- .../java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java | 1 - 1 file changed, 1 deletion(-) diff --git a/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java index 73d19b2cec..cacb4cac59 100644 --- a/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java +++ b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java @@ -334,7 +334,6 @@ private List getColumns( } rs.close(); conn.close(); - closeConnection(databaseName); return columnFields; } catch (SQLException | RelationalTaskExecuteFailureException e) { LOGGER.error("unexpected error: ", e); From fd8af162b8d83b98e59da6b8b11b3fb019e36f62 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Wed, 24 Jul 2024 10:33:24 +0800 Subject: [PATCH 117/138] revert --- .github/actions/service/postgresql/action.yml | 1 + .github/workflows/standard-test-suite.yml | 54 +++++++++---------- .../iginx/relational/RelationalStorage.java | 5 -- 3 files changed, 27 insertions(+), 33 deletions(-) diff --git a/.github/actions/service/postgresql/action.yml b/.github/actions/service/postgresql/action.yml index 295d7f2f29..3d60b67be0 100644 --- a/.github/actions/service/postgresql/action.yml +++ b/.github/actions/service/postgresql/action.yml @@ -63,6 +63,7 @@ runs: echo "port = ${port}" >> "${PGCONF}" echo "unix_socket_directories = ''" >> "${PGCONF}" echo "fsync = off" >> "${PGCONF}" + echo "max_connections = 200" >> "${PGCONF}" pg_ctl start --pgdata="${PGDATA}" done diff --git a/.github/workflows/standard-test-suite.yml b/.github/workflows/standard-test-suite.yml index 51e12aab7d..67e41e0f75 100644 --- a/.github/workflows/standard-test-suite.yml +++ b/.github/workflows/standard-test-suite.yml @@ -11,36 +11,34 @@ concurrency: cancel-in-progress: true jobs: - # unit-test: - # uses: ./.github/workflows/unit-test.yml - # unit-mds: - # uses: ./.github/workflows/unit-mds.yml - # case-regression: - # uses: ./.github/workflows/case-regression.yml - # with: - # metadata-matrix: '["zookeeper"]' - # standalone-test: - # uses: ./.github/workflows/standalone-test.yml - # with: - # metadata-matrix: '["zookeeper"]' - # standalone-test-pushdown: - # uses: ./.github/workflows/standalone-test-pushdown.yml - # with: - # metadata-matrix: '["zookeeper"]' + unit-test: + uses: ./.github/workflows/unit-test.yml + unit-mds: + uses: ./.github/workflows/unit-mds.yml + case-regression: + uses: ./.github/workflows/case-regression.yml + with: + metadata-matrix: '["zookeeper"]' + standalone-test: + uses: ./.github/workflows/standalone-test.yml + with: + metadata-matrix: '["zookeeper"]' + standalone-test-pushdown: + uses: ./.github/workflows/standalone-test-pushdown.yml + with: + metadata-matrix: '["zookeeper"]' db-ce: uses: ./.github/workflows/DB-CE.yml + with: + metadata-matrix: '["zookeeper"]' + remote-test: + uses: ./.github/workflows/remote-test.yml + with: + metadata-matrix: '["zookeeper"]' + assemebly-test: + uses: ./.github/workflows/assembly-test.yml + tpc-h-regression-test: + uses: ./.github/workflows/tpc-h.yml with: os-matrix: '["ubuntu-latest"]' metadata-matrix: '["zookeeper"]' - db-matrix: '["PostgreSQL"]' -# remote-test: -# uses: ./.github/workflows/remote-test.yml -# with: -# metadata-matrix: '["zookeeper"]' -# assemebly-test: -# uses: ./.github/workflows/assembly-test.yml -# tpc-h-regression-test: -# uses: ./.github/workflows/tpc-h.yml -# with: -# os-matrix: '["ubuntu-latest"]' -# metadata-matrix: '["zookeeper"]' diff --git a/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java index cacb4cac59..71540885c9 100644 --- a/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java +++ b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java @@ -169,8 +169,6 @@ private void closeConnection(String databaseName) { if (dataSource != null) { dataSource.close(); connectionPoolMap.remove(databaseName); - LOGGER.info("close datasource: {}", databaseName); - LOGGER.info("connectionPoolMap remain: {}", connectionPoolMap.keySet()); } } @@ -305,7 +303,6 @@ private List getTables(String databaseName, String tablePattern) { rs.close(); conn.close(); - closeConnection(databaseName); return tableNames; } catch (SQLException | RelationalTaskExecuteFailureException e) { LOGGER.error("unexpected error: ", e); @@ -1063,9 +1060,7 @@ private TaskExecuteResult executeProjectDummyWithFilter(Project project, Filter for (Map.Entry> splitEntry : splitResults.entrySet()) { Map tableNameToColumnNames = splitEntry.getValue(); String databaseName = splitEntry.getKey(); - LOGGER.info("datasource: {}", connectionPoolMap.keySet()); conn = getConnection(databaseName); - LOGGER.info("datasource: {}", connectionPoolMap.keySet()); if (conn == null) { continue; } From 94669fa982ac98d665635116fbbce3e4e68d3ae7 Mon Sep 17 00:00:00 2001 From: An Qi Date: Wed, 24 Jul 2024 13:56:19 +0800 Subject: [PATCH 118/138] feat(redis,mongodb): allow to authenticate (#402) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 配置方法 Mongodb 使用 uri 对连接参数进行详细配置,包括鉴权机制,相关语法参见 Mongodb 文档 Redis 使用 username 和 password 两个参数配置用户名和参数,若不设置该选项,则不使用鉴权。 --- conf/config.properties | 2 +- .../tsinghua/iginx/mongodb/MongoDBStorage.java | 17 +++++++++-------- .../edu/tsinghua/iginx/redis/RedisStorage.java | 14 +++++++++++--- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/conf/config.properties b/conf/config.properties index fc45be4f78..3659ff0fd8 100644 --- a/conf/config.properties +++ b/conf/config.properties @@ -39,7 +39,7 @@ storageEngineList=127.0.0.1#6667#iotdb12#username=root#password=root#sessionPool #storageEngineList=127.0.0.1#5432#relational#engine=postgresql#username=postgres#password=postgres#has_data=false #storageEngineList=127.0.0.1#3306#relational#engine=mysql#username=root#password=mysql#has_data=false#meta_properties_path=your-meta-properties-path #storageEngineList=127.0.0.1#6667#parquet#dir=/path/to/your/parquet#dummy_dir=/path/to/your/data#iginx_port=6888#has_data=false#is_read_only=false#thrift_timeout=30000#thrift_pool_max_size=100#thrift_pool_min_evictable_idle_time_millis=600000#write.buffer.size=104857600#write.batch.size=1048576#compact.permits=16#cache.capacity=1073741824#parquet.block.size=134217728#parquet.page.size=8192#parquet.compression=SNAPPY -#storageEngineList=127.0.0.1#27017#mongodb#has_data=false#schema.sample.size=1000#dummy.sample.size=0 +#storageEngineList=127.0.0.1#27017#mongodb#uri="mongodb://127.0.0.1:27017/?maxPoolSize=200&maxIdleTimeMS=60000&waitQueueTimeoutMS=50000"#has_data=false#schema.sample.size=1000#dummy.sample.size=0 #storageEngineList=127.0.0.1#6667#filesystem#dir=/path/to/your/filesystem#dummy_dir=/path/to/your/data#iginx_port=6888#chunk_size_in_bytes=1048576#memory_pool_size=100#has_data=false#is_read_only=false#thrift_timeout=5000#thrift_pool_max_size=100#thrift_pool_min_evictable_idle_time_millis=600000 #storageEngineList=127.0.0.1#6379#redis#has_data=false#is_read_only=false#timeout=10000#data_db=1#dummy_db=0 diff --git a/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java b/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java index e55c72de5b..5824ecaf3a 100644 --- a/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java +++ b/dataSource/mongodb/src/main/java/cn/edu/tsinghua/iginx/mongodb/MongoDBStorage.java @@ -54,10 +54,7 @@ import cn.edu.tsinghua.iginx.thrift.DataType; import cn.edu.tsinghua.iginx.thrift.StorageEngineType; import cn.edu.tsinghua.iginx.utils.Pair; -import com.mongodb.MongoBulkWriteException; -import com.mongodb.MongoClientSettings; -import com.mongodb.ServerAddress; -import com.mongodb.WriteError; +import com.mongodb.*; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; import com.mongodb.client.MongoCollection; @@ -82,6 +79,7 @@ public class MongoDBStorage implements IStorage { private static final int SESSION_POOL_MAX_SIZE = 200; public static final String VALUE_FIELD = "v"; public static final String[] SYSTEM_DBS = new String[] {"admin", "config", "local"}; + public static final String CONNECTION_STRING = "uri"; public static final String SCHEMA_SAMPLE_SIZE = "schema.sample.size"; public static final String QUERY_SAMPLE_SIZE = "dummy.sample.size"; public static final String SCHEMA_SAMPLE_SIZE_DEFAULT = "1000"; @@ -97,6 +95,10 @@ public MongoDBStorage(StorageEngineMeta meta) throws StorageInitializationExcept throw new StorageInitializationException("unexpected database: " + meta.getStorageEngine()); } + String defaultConnection = String.format("mongodb://%s:%d", meta.getIp(), meta.getPort()); + String connectionString = + meta.getExtraParams().getOrDefault(CONNECTION_STRING, defaultConnection); + String sampleSize = meta.getExtraParams().getOrDefault(SCHEMA_SAMPLE_SIZE, SCHEMA_SAMPLE_SIZE_DEFAULT); this.schemaSampleSize = Integer.parseInt(sampleSize); @@ -106,7 +108,7 @@ public MongoDBStorage(StorageEngineMeta meta) throws StorageInitializationExcept this.querySampleSize = Integer.parseInt(querySampleSize); try { - this.client = connect(meta.getIp(), meta.getPort()); + this.client = connect(connectionString); } catch (Exception e) { String message = "fail to connect " + meta.getIp() + ":" + meta.getPort(); LOGGER.error(message, e); @@ -114,17 +116,16 @@ public MongoDBStorage(StorageEngineMeta meta) throws StorageInitializationExcept } } - private MongoClient connect(String ip, int port) { - ServerAddress address = new ServerAddress(ip, port); + private MongoClient connect(String connectionString) { MongoClientSettings settings = MongoClientSettings.builder() - .applyToClusterSettings(builder -> builder.hosts(Collections.singletonList(address))) .applyToConnectionPoolSettings( builder -> builder .maxWaitTime(MAX_WAIT_TIME, TimeUnit.SECONDS) .maxSize(SESSION_POOL_MAX_SIZE) .maxConnectionIdleTime(60, TimeUnit.SECONDS)) + .applyConnectionString(new ConnectionString(connectionString)) .build(); return MongoClients.create(settings); diff --git a/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java b/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java index b0928cd656..85754b328d 100644 --- a/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java +++ b/dataSource/redis/src/main/java/cn/edu/tsinghua/iginx/redis/RedisStorage.java @@ -78,9 +78,13 @@ public class RedisStorage implements IStorage { private static final String TIMEOUT = "timeout"; + private static final String USERNAME = "username"; + + private static final String PASSWORD = "password"; + private static final String DATA_DB = "data_db"; - private static final String DATA_PASSWORD = "dummy_db"; + private static final String DUMMY_DB = "dummy_db"; private static final int DEFAULT_TIMEOUT = 10000; @@ -103,11 +107,15 @@ public RedisStorage(StorageEngineMeta meta) throws StorageInitializationExceptio Map extraParams = meta.getExtraParams(); int timeout = Integer.parseInt(extraParams.getOrDefault(TIMEOUT, String.valueOf(DEFAULT_TIMEOUT))); - this.jedisPool = new JedisPool(new JedisPoolConfig(), meta.getIp(), meta.getPort(), timeout); + String username = extraParams.get(USERNAME); + String password = extraParams.get(PASSWORD); + this.jedisPool = + new JedisPool( + new JedisPoolConfig(), meta.getIp(), meta.getPort(), timeout, username, password); this.dataDb = Integer.parseInt(extraParams.getOrDefault(DATA_DB, String.valueOf(DEFAULT_DATA_DB))); this.dummyDb = - Integer.parseInt(extraParams.getOrDefault(DATA_PASSWORD, String.valueOf(DEFAULT_DUMMY_DB))); + Integer.parseInt(extraParams.getOrDefault(DUMMY_DB, String.valueOf(DEFAULT_DUMMY_DB))); this.dataPrefix = meta.getDataPrefix(); if (dataDb == dummyDb) { throw new StorageInitializationException("data db and dummy db should not be the same"); From 32077acdaca3d48343eba149efe01a744dd4faef Mon Sep 17 00:00:00 2001 From: SolomonAnn Date: Fri, 26 Jul 2024 11:01:13 +0800 Subject: [PATCH 119/138] Update StoragePhysicalTaskExecutor.java --- .../physical/storage/execute/StoragePhysicalTaskExecutor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java index b191483a6c..5fc35be652 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java @@ -371,7 +371,7 @@ public TaskExecuteResult executeShowColumns(ShowColumns showColumns) { TagFilter tagFilter = showColumns.getTagFilter(); String schemaPrefix = storage.getSchemaPrefix(); - // 不下推dataPrefix的原因:iotdb中,非dummy的数据库中如果有原始数据,会在show columns时被查询到并造成误解 + // 不下推dataPrefix的原因:非dummy的数据库中如果有原始数据,会在show columns时被查询到并造成误解 String dataPrefixRegex = storage.getDataPrefix() == null ? null From 97b56b0dba71c86c28ec0893f01339d2f43ab2e7 Mon Sep 17 00:00:00 2001 From: ZM <12236590+shinyano@users.noreply.github.com> Date: Fri, 26 Jul 2024 16:40:46 +0800 Subject: [PATCH 120/138] fix relational dummy project (#406) What's wrong? [Relational storage engine] Querying non-existing path prefix in dummy relational engine would cause exception, because the engine tries to connect to a database that does not exist. Fix Query infomation about databases before making connection. --- .../edu/tsinghua/iginx/relational/RelationalStorage.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java index bf26cf354b..ba123c716d 100644 --- a/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java +++ b/dataSource/relational/src/main/java/cn/edu/tsinghua/iginx/relational/RelationalStorage.java @@ -59,6 +59,7 @@ import cn.edu.tsinghua.iginx.utils.StringUtils; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; +import com.zaxxer.hikari.pool.HikariPool; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.sql.*; @@ -128,7 +129,7 @@ private Connection getConnection(String databaseName) { HikariDataSource newDataSource = new HikariDataSource(config); connectionPoolMap.put(databaseName, newDataSource); return newDataSource.getConnection(); - } catch (SQLException e) { + } catch (SQLException | HikariPool.PoolInitializationException e) { LOGGER.error("Cannot get connection for database {}", databaseName, e); return null; } @@ -1436,6 +1437,7 @@ private String reformatForJDBC(String path) { private Map> splitAndMergeHistoryQueryPatterns(List patterns) throws SQLException { // > + List databases = getDatabaseNames(); Map> splitResults = new HashMap<>(); String databaseName; String tableName; @@ -1499,6 +1501,9 @@ private Map> splitAndMergeHistoryQueryPatterns(List< } } } else { + if (!databases.contains(databaseName)) { + continue; + } List columnFieldList = getColumns(databaseName, tableName, columnNames); Map tableNameToColumnNames = new HashMap<>(); for (ColumnField columnField : columnFieldList) { From a73131355ba33ad3f4ac67266053d16337d2943d Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Fri, 26 Jul 2024 16:56:42 +0800 Subject: [PATCH 121/138] feat(core): rename duplicate same columns (#405) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 支持对同一列多次重命名 --- .../logical/generator/QueryGenerator.java | 16 +-- .../engine/logical/utils/OperatorUtils.java | 23 ++-- .../iginx/engine/logical/utils/PathUtils.java | 20 ++-- .../naive/NaiveOperatorMemoryExecutor.java | 6 +- .../execute/stream/RenameLazyStream.java | 5 +- .../iginx/engine/shared/data/read/Header.java | 102 +++++++++++------- .../engine/shared/expr/BaseExpression.java | 2 +- .../engine/shared/expr/BinaryExpression.java | 2 +- .../engine/shared/expr/BracketExpression.java | 2 +- .../shared/expr/ConstantExpression.java | 2 +- .../shared/expr/MultipleExpression.java | 2 +- .../engine/shared/expr/UnaryExpression.java | 2 +- .../iginx/engine/shared/operator/Rename.java | 36 +++---- .../sql/statement/frompart/CteFromPart.java | 10 +- .../sql/statement/frompart/FromPart.java | 4 +- .../sql/statement/frompart/PathFromPart.java | 9 +- .../frompart/ShowColumnsFromPart.java | 13 ++- .../statement/frompart/SubQueryFromPart.java | 6 +- .../select/BinarySelectStatement.java | 6 +- .../select/CommonTableExpression.java | 14 +-- .../sql/statement/select/SelectStatement.java | 4 +- .../select/UnarySelectStatement.java | 53 ++++++--- .../optimizer/FilterPushDownOptimizer.java | 18 ++-- .../optimizer/rules/ColumnPruningRule.java | 11 +- .../rules/FilterPushDownRenameRule.java | 10 +- .../rules/FunctionDistinctEliminateRule.java | 5 +- .../RowTransformConstantFoldingRule.java | 10 +- .../integration/func/sql/SQLSessionIT.java | 21 +++- .../iginx/integration/func/tag/TagIT.java | 12 +++ 29 files changed, 241 insertions(+), 185 deletions(-) diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/generator/QueryGenerator.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/generator/QueryGenerator.java index 439500ab9e..87576c0dbf 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/generator/QueryGenerator.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/generator/QueryGenerator.java @@ -113,7 +113,7 @@ protected Operator generateRoot(Statement statement) { .forEach( cte -> { Operator root = generateRoot(cte.getStatement()); - root = new Rename(new OperatorSource(root), cte.getAliasMap()); + root = new Rename(new OperatorSource(root), cte.getAliasList()); cte.setRoot(root); }); return generateRoot(selectStatement); @@ -382,7 +382,7 @@ private Operator initFromPart(UnarySelectStatement selectStatement) { throw new RuntimeException("Unknown FromPart type: " + fromPart.getType()); } if (fromPart.hasAlias()) { - root = new Rename(new OperatorSource(root), fromPart.getAliasMap()); + root = new Rename(new OperatorSource(root), fromPart.getAliasList()); } return root; } @@ -437,7 +437,7 @@ private Operator initFilterAndMergeFragmentsWithJoin(UnarySelectStatement select throw new RuntimeException("Unknown FromPart type: " + fromPart.getType()); } if (fromPart.hasAlias()) { - root = new Rename(new OperatorSource(root), fromPart.getAliasMap()); + root = new Rename(new OperatorSource(root), fromPart.getAliasList()); } joinList.add(root); }); @@ -797,16 +797,16 @@ private static Operator buildReorder(UnarySelectStatement selectStatement, Opera } /** - * 如果SelectStatement有AliasMap, 在root之上构建一个Rename操作符 + * 如果SelectStatement有AliasList, 在root之上构建一个Rename操作符 * * @param selectStatement Select上下文 * @param root 当前根节点 - * @return 添加了Rename操作符的根节点;如果没有AliasMap,返回原根节点 + * @return 添加了Rename操作符的根节点;如果没有AliasList,返回原根节点 */ private static Operator buildRename(UnarySelectStatement selectStatement, Operator root) { - Map aliasMap = selectStatement.getSelectAliasMap(); - if (!aliasMap.isEmpty()) { - root = new Rename(new OperatorSource(root), aliasMap); + List> aliasList = selectStatement.getSelectAliasList(); + if (!aliasList.isEmpty()) { + root = new Rename(new OperatorSource(root), aliasList); } return root; } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/utils/OperatorUtils.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/utils/OperatorUtils.java index efe872e189..76000d76ff 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/utils/OperatorUtils.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/logical/utils/OperatorUtils.java @@ -42,11 +42,11 @@ import cn.edu.tsinghua.iginx.engine.shared.source.OperatorSource; import cn.edu.tsinghua.iginx.engine.shared.source.Source; import cn.edu.tsinghua.iginx.engine.shared.source.SourceType; +import cn.edu.tsinghua.iginx.utils.Pair; import cn.edu.tsinghua.iginx.utils.StringUtils; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Map; import java.util.stream.Collectors; public class OperatorUtils { @@ -334,7 +334,7 @@ private static Operator pushDownApply(Operator root, List correlatedVari root = new Rename( new OperatorSource(pushDownApply(apply, correlatedVariables)), - rename.getAliasMap(), + rename.getAliasList(), ignorePatterns); break; case CrossJoin: @@ -605,8 +605,8 @@ public static List getPatternFromOperatorChildren( Operator visitedOperator = visitedOperators.get(i); if (visitedOperator.getType() == OperatorType.Rename) { Rename rename = (Rename) visitedOperator; - Map aliasMap = rename.getAliasMap(); - patterns = renamePattern(aliasMap, patterns); + List> aliasList = rename.getAliasList(); + patterns = renamePattern(aliasList, patterns); } } return patterns; @@ -648,17 +648,18 @@ private static boolean isPatternMatched(String patternA, String patternB) { /** * 正向重命名模式列表中的pattern,将key中的pattern替换为value中的pattern * - * @param aliasMap 重命名规则, key为旧模式,value为新模式 + * @param aliasList 重命名规则, key为旧模式,value为新模式 * @param patterns 要重命名的模式列表 * @return */ - private static List renamePattern(Map aliasMap, List patterns) { + private static List renamePattern( + List> aliasList, List patterns) { List renamedPatterns = new ArrayList<>(); for (String pattern : patterns) { boolean matched = false; - for (Map.Entry entry : aliasMap.entrySet()) { - String oldPattern = entry.getKey().replace("*", "(.*)"); - String newPattern = entry.getValue().replace("*", "$1"); + for (Pair pair : aliasList) { + String oldPattern = pair.k.replace("*", "(.*)"); + String newPattern = pair.v.replace("*", "$1"); if (pattern.matches(oldPattern)) { if (newPattern.contains("$1") && !oldPattern.contains("*")) { newPattern = newPattern.replace("$1", "*"); @@ -668,12 +669,12 @@ private static List renamePattern(Map aliasMap, List recoverRenamedPatterns( - Map aliasMap, List patterns) { + List> aliasList, List patterns) { return patterns.stream() - .map(pattern -> recoverRenamedPattern(aliasMap, pattern)) + .map(pattern -> recoverRenamedPattern(aliasList, pattern)) .collect(Collectors.toList()); } - public static String recoverRenamedPattern(Map aliasMap, String pattern) { - for (Map.Entry entry : aliasMap.entrySet()) { - String oldPattern = entry.getKey().replace("*", "$1"); // 通配符转换为正则的捕获组 - String newPattern = entry.getValue().replace("*", "(.*)"); // 使用反向引用保留原始匹配的部分 + public static String recoverRenamedPattern(List> aliasList, String pattern) { + for (Pair pair : aliasList) { + String oldPattern = pair.k.replace("*", "$1"); // 通配符转换为正则的捕获组 + String newPattern = pair.v.replace("*", "(.*)"); // 使用反向引用保留原始匹配的部分 if (pattern.matches(newPattern)) { // 如果旧模式中有通配符,但是新模式中没有,我们需要将新模式中的捕获组替换为通配符 if (oldPattern.contains("$1") && !newPattern.contains("*")) { @@ -85,9 +85,9 @@ public static String recoverRenamedPattern(Map aliasMap, String } return pattern.replaceAll(newPattern, oldPattern); } else if (newPattern.equals(pattern)) { - return entry.getKey(); + return pair.k; } else if (pattern.contains(".*") && newPattern.matches(StringUtils.reformatPath(pattern))) { - return entry.getKey(); + return pair.k; } } return pattern; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/naive/NaiveOperatorMemoryExecutor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/naive/NaiveOperatorMemoryExecutor.java index fca427c618..6993594cce 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/naive/NaiveOperatorMemoryExecutor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/naive/NaiveOperatorMemoryExecutor.java @@ -474,10 +474,8 @@ private RowStream executeMappingTransform(MappingTransform mappingTransform, Tab private RowStream executeRename(Rename rename, Table table) { Header header = table.getHeader(); - Map aliasMap = rename.getAliasMap(); - - List ignorePatterns = rename.getIgnorePatterns(); - Header newHeader = header.renamedHeader(aliasMap, ignorePatterns); + List> aliasList = rename.getAliasList(); + Header newHeader = header.renamedHeader(aliasList, rename.getIgnorePatterns()); List rows = new ArrayList<>(); table diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/RenameLazyStream.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/RenameLazyStream.java index 568a119f96..eddb89df0a 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/RenameLazyStream.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/memory/execute/stream/RenameLazyStream.java @@ -23,7 +23,6 @@ import cn.edu.tsinghua.iginx.engine.shared.data.read.Row; import cn.edu.tsinghua.iginx.engine.shared.data.read.RowStream; import cn.edu.tsinghua.iginx.engine.shared.operator.Rename; -import java.util.Map; public class RenameLazyStream extends UnaryLazyStream { @@ -40,9 +39,7 @@ public RenameLazyStream(Rename rename, RowStream stream) { public Header getHeader() throws PhysicalException { if (header == null) { Header header = stream.getHeader(); - Map aliasMap = rename.getAliasMap(); - - this.header = header.renamedHeader(aliasMap, rename.getIgnorePatterns()); + this.header = header.renamedHeader(rename.getAliasList(), rename.getIgnorePatterns()); } return header; } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/Header.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/Header.java index e224a26fbb..44a07a114f 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/Header.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/data/read/Header.java @@ -127,52 +127,72 @@ public boolean equals(Object o) { && Objects.equals(indexMap, header.indexMap); } - public Header renamedHeader(Map aliasMap, List ignorePatterns) { + public Header renamedHeader(List> aliasList, List ignorePatterns) { List newFields = new ArrayList<>(); - fields.forEach( - field -> { - // 如果列名在ignorePatterns中,对该列不执行rename - for (String ignorePattern : ignorePatterns) { - if (StringUtils.match(field.getName(), ignorePattern)) { - newFields.add(field); - return; - } + int size = getFieldSize(); + for (int i = 0; i < size; i++) { + Field field = fields.get(i); + // 如果列名在ignorePatterns中,对该列不执行rename + boolean ignore = false; + for (String ignorePattern : ignorePatterns) { + if (StringUtils.match(field.getName(), ignorePattern)) { + newFields.add(field); + ignore = true; + break; + } + } + if (ignore) { + continue; + } + String alias = ""; + for (Pair pair : aliasList) { + String oldPattern = pair.k; + String newPattern = pair.v; + if (oldPattern.equals("*") && newPattern.endsWith(".*")) { + String newPrefix = newPattern.substring(0, newPattern.length() - 1); + alias = newPrefix + field.getName(); + } else if (oldPattern.endsWith(".*") && newPattern.endsWith(".*")) { + String oldPrefix = oldPattern.substring(0, oldPattern.length() - 1); + String newPrefix = newPattern.substring(0, newPattern.length() - 1); + if (field.getName().startsWith(oldPrefix)) { + alias = field.getName().replaceFirst(oldPrefix, newPrefix); } - String alias = ""; - for (String oldPattern : aliasMap.keySet()) { - String newPattern = aliasMap.get(oldPattern); - if (oldPattern.equals("*") && newPattern.endsWith(".*")) { - String newPrefix = newPattern.substring(0, newPattern.length() - 1); - alias = newPrefix + field.getName(); - } else if (oldPattern.endsWith(".*") && newPattern.endsWith(".*")) { - String oldPrefix = oldPattern.substring(0, oldPattern.length() - 1); - String newPrefix = newPattern.substring(0, newPattern.length() - 1); - if (field.getName().startsWith(oldPrefix)) { - alias = field.getName().replaceFirst(oldPrefix, newPrefix); - } - break; - } else if (oldPattern.equals(field.getFullName())) { - alias = newPattern; - break; + break; + } else if (oldPattern.equals(field.getName())) { + alias = newPattern; + Set> tagSet = new HashSet<>(); + Field nextField = i < size - 1 ? fields.get(i + 1) : null; + tagSet.add(field.getTags()); + // 处理同一列但不同tag的情况 + while (nextField != null + && oldPattern.equals(nextField.getName()) + && !tagSet.contains(nextField.getTags())) { + newFields.add(new Field(alias, field.getType(), field.getTags())); + field = nextField; + i++; + nextField = i < size - 1 ? fields.get(i + 1) : null; + tagSet.add(field.getTags()); + } + aliasList.remove(pair); + break; + } else { + if (StringUtils.match(field.getName(), oldPattern)) { + if (newPattern.endsWith("." + oldPattern)) { + String prefix = newPattern.substring(0, newPattern.length() - oldPattern.length()); + alias = prefix + field.getName(); } else { - if (StringUtils.match(field.getName(), oldPattern)) { - if (newPattern.endsWith("." + oldPattern)) { - String prefix = - newPattern.substring(0, newPattern.length() - oldPattern.length()); - alias = prefix + field.getName(); - } else { - alias = newPattern; - } - break; - } + alias = newPattern; } + break; } - if (alias.isEmpty()) { - newFields.add(field); - } else { - newFields.add(new Field(alias, field.getType(), field.getTags())); - } - }); + } + } + if (alias.isEmpty()) { + newFields.add(field); + } else { + newFields.add(new Field(alias, field.getType(), field.getTags())); + } + } return new Header(getKey(), newFields); } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/BaseExpression.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/BaseExpression.java index 4d7240f2da..852af9629d 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/BaseExpression.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/BaseExpression.java @@ -52,7 +52,7 @@ public ExpressionType getType() { @Override public boolean hasAlias() { - return alias != null && !alias.equals(""); + return alias != null && !alias.isEmpty(); } @Override diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/BinaryExpression.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/BinaryExpression.java index 9b5dc92226..6a6d8009b0 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/BinaryExpression.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/BinaryExpression.java @@ -77,7 +77,7 @@ public ExpressionType getType() { @Override public boolean hasAlias() { - return alias != null && !alias.equals(""); + return alias != null && !alias.isEmpty(); } @Override diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/BracketExpression.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/BracketExpression.java index 4ee402ef12..9695abea76 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/BracketExpression.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/BracketExpression.java @@ -52,7 +52,7 @@ public ExpressionType getType() { @Override public boolean hasAlias() { - return alias != null && !alias.equals(""); + return alias != null && !alias.isEmpty(); } @Override diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/ConstantExpression.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/ConstantExpression.java index 4377c4ec78..86015e072a 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/ConstantExpression.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/ConstantExpression.java @@ -52,7 +52,7 @@ public ExpressionType getType() { @Override public boolean hasAlias() { - return alias != null && !alias.equals(""); + return alias != null && !alias.isEmpty(); } @Override diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/MultipleExpression.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/MultipleExpression.java index 2df31649bf..8f73f354f4 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/MultipleExpression.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/MultipleExpression.java @@ -92,7 +92,7 @@ public ExpressionType getType() { @Override public boolean hasAlias() { - return alias != null && !alias.equals(""); + return alias != null && !alias.isEmpty(); } @Override diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/UnaryExpression.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/UnaryExpression.java index e3ad98fb39..de051e6478 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/UnaryExpression.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/expr/UnaryExpression.java @@ -58,7 +58,7 @@ public ExpressionType getType() { @Override public boolean hasAlias() { - return alias != null && !alias.equals(""); + return alias != null && !alias.isEmpty(); } @Override diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Rename.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Rename.java index 0539de7378..5a26576916 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Rename.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/shared/operator/Rename.java @@ -20,32 +20,31 @@ import cn.edu.tsinghua.iginx.engine.shared.operator.type.OperatorType; import cn.edu.tsinghua.iginx.engine.shared.source.Source; +import cn.edu.tsinghua.iginx.utils.Pair; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; public class Rename extends AbstractUnaryOperator { - private final Map aliasMap; + private final List> aliasList; private final List ignorePatterns; // 不进行重命名的列 - public Rename(Source source, Map aliasMap) { - this(source, aliasMap, new ArrayList<>()); + public Rename(Source source, List> aliasList) { + this(source, aliasList, new ArrayList<>()); } - public Rename(Source source, Map aliasMap, List ignorePatterns) { + public Rename(Source source, List> aliasList, List ignorePatterns) { super(OperatorType.Rename, source); - if (aliasMap == null) { - throw new IllegalArgumentException("aliasMap shouldn't be null"); + if (aliasList == null) { + throw new IllegalArgumentException("aliasList shouldn't be null"); } - this.aliasMap = aliasMap; + this.aliasList = aliasList; this.ignorePatterns = ignorePatterns; } - public Map getAliasMap() { - return aliasMap; + public List> getAliasList() { + return aliasList; } public List getIgnorePatterns() { @@ -54,24 +53,23 @@ public List getIgnorePatterns() { @Override public Operator copy() { - return new Rename(getSource().copy(), new HashMap<>(aliasMap)); + return new Rename(getSource().copy(), new ArrayList<>(aliasList)); } @Override public UnaryOperator copyWithSource(Source source) { - return new Rename(source, new HashMap<>(aliasMap)); + return new Rename(source, new ArrayList<>(aliasList)); } @Override public String getInfo() { StringBuilder builder = new StringBuilder(); - builder.append("AliasMap: "); - aliasMap.forEach( - (k, v) -> builder.append("(").append(k).append(", ").append(v).append(")").append(",")); + builder.append("AliasList: "); + aliasList.forEach( + p -> builder.append("(").append(p.k).append(", ").append(p.v).append(")").append(",")); builder.deleteCharAt(builder.length() - 1); if (!ignorePatterns.isEmpty()) { - builder.append(", IgnorePatterns: "); - builder.append(ignorePatterns); + builder.append(", IgnorePatterns: ").append(ignorePatterns); } return builder.toString(); } @@ -85,6 +83,6 @@ public boolean equals(Object object) { return false; } Rename rename = (Rename) object; - return aliasMap.equals(rename.aliasMap) && ignorePatterns.equals(rename.ignorePatterns); + return aliasList.equals(rename.aliasList) && ignorePatterns.equals(rename.ignorePatterns); } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/CteFromPart.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/CteFromPart.java index 1b63e0126a..75840a9e5a 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/CteFromPart.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/CteFromPart.java @@ -24,11 +24,10 @@ import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; import cn.edu.tsinghua.iginx.sql.statement.frompart.join.JoinCondition; import cn.edu.tsinghua.iginx.sql.statement.select.CommonTableExpression; +import cn.edu.tsinghua.iginx.utils.Pair; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; public class CteFromPart implements FromPart { @@ -60,10 +59,9 @@ public boolean hasAlias() { } @Override - public Map getAliasMap() { - Map aliasMap = new HashMap<>(); - aliasMap.put(cte.getName() + ALL_PATH_SUFFIX, alias + ALL_PATH_SUFFIX); - return aliasMap; + public List> getAliasList() { + return Collections.singletonList( + new Pair<>(cte.getName() + ALL_PATH_SUFFIX, alias + ALL_PATH_SUFFIX)); } @Override diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/FromPart.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/FromPart.java index a7a66ebf47..4cbb2d5bc5 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/FromPart.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/FromPart.java @@ -19,14 +19,14 @@ package cn.edu.tsinghua.iginx.sql.statement.frompart; import cn.edu.tsinghua.iginx.sql.statement.frompart.join.JoinCondition; +import cn.edu.tsinghua.iginx.utils.Pair; import java.util.List; -import java.util.Map; public interface FromPart { FromPartType getType(); - Map getAliasMap(); + List> getAliasList(); boolean hasAlias(); diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/PathFromPart.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/PathFromPart.java index 5f2dd9360e..5a808ae6eb 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/PathFromPart.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/PathFromPart.java @@ -22,10 +22,9 @@ import cn.edu.tsinghua.iginx.engine.shared.Constants; import cn.edu.tsinghua.iginx.sql.statement.frompart.join.JoinCondition; +import cn.edu.tsinghua.iginx.utils.Pair; import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; public class PathFromPart implements FromPart { @@ -53,10 +52,8 @@ public FromPartType getType() { } @Override - public Map getAliasMap() { - Map aliasMap = new HashMap<>(); - aliasMap.put(path + ALL_PATH_SUFFIX, alias + ALL_PATH_SUFFIX); - return aliasMap; + public List> getAliasList() { + return Collections.singletonList(new Pair<>(path + ALL_PATH_SUFFIX, alias + ALL_PATH_SUFFIX)); } @Override diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/ShowColumnsFromPart.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/ShowColumnsFromPart.java index 8c18b32d48..2a8b66d6a4 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/ShowColumnsFromPart.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/ShowColumnsFromPart.java @@ -21,12 +21,11 @@ import cn.edu.tsinghua.iginx.engine.shared.Constants; import cn.edu.tsinghua.iginx.sql.statement.ShowColumnsStatement; import cn.edu.tsinghua.iginx.sql.statement.frompart.join.JoinCondition; +import cn.edu.tsinghua.iginx.utils.Pair; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; public class ShowColumnsFromPart implements FromPart { @@ -48,11 +47,11 @@ public ShowColumnsStatement getShowColumnsStatement() { } @Override - public Map getAliasMap() { - Map aliasMap = new HashMap<>(); - aliasMap.put("path", alias + ".path"); - aliasMap.put("type", alias + ".type"); - return aliasMap; + public List> getAliasList() { + List> aliasList = new ArrayList<>(2); + aliasList.add(new Pair<>("path", alias + ".path")); + aliasList.add(new Pair<>("type", alias + ".type")); + return aliasList; } @Override diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/SubQueryFromPart.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/SubQueryFromPart.java index ed45058b51..e3e75433d7 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/SubQueryFromPart.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/frompart/SubQueryFromPart.java @@ -23,8 +23,8 @@ import cn.edu.tsinghua.iginx.sql.statement.select.BinarySelectStatement; import cn.edu.tsinghua.iginx.sql.statement.select.SelectStatement; import cn.edu.tsinghua.iginx.sql.statement.select.UnarySelectStatement; +import cn.edu.tsinghua.iginx.utils.Pair; import java.util.List; -import java.util.Map; public class SubQueryFromPart implements FromPart { @@ -60,8 +60,8 @@ public FromPartType getType() { } @Override - public Map getAliasMap() { - return subQuery.getSubQueryAliasMap(alias); + public List> getAliasList() { + return subQuery.getSubQueryAliasList(alias); } @Override diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/BinarySelectStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/BinarySelectStatement.java index aec06e51b8..b7dbe5b082 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/BinarySelectStatement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/BinarySelectStatement.java @@ -20,10 +20,10 @@ import cn.edu.tsinghua.iginx.engine.shared.expr.Expression; import cn.edu.tsinghua.iginx.engine.shared.operator.type.OperatorType; +import cn.edu.tsinghua.iginx.utils.Pair; import java.util.ArrayList; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Set; public class BinarySelectStatement extends SelectStatement { @@ -93,7 +93,7 @@ public void initFreeVariables() { } @Override - public Map getSubQueryAliasMap(String alias) { - return leftQuery.getSubQueryAliasMap(alias); + public List> getSubQueryAliasList(String alias) { + return leftQuery.getSubQueryAliasList(alias); } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/CommonTableExpression.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/CommonTableExpression.java index 52a1438823..e08925a4d6 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/CommonTableExpression.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/CommonTableExpression.java @@ -21,10 +21,10 @@ import cn.edu.tsinghua.iginx.engine.shared.expr.Expression; import cn.edu.tsinghua.iginx.engine.shared.operator.Operator; import cn.edu.tsinghua.iginx.sql.SQLConstant; +import cn.edu.tsinghua.iginx.utils.Pair; +import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; public class CommonTableExpression { @@ -66,18 +66,18 @@ public void setRoot(Operator root) { this.root = root; } - public Map getAliasMap() { + public List> getAliasList() { if (columns.isEmpty()) { - return statement.getSubQueryAliasMap(name); + return statement.getSubQueryAliasList(name); } else { - Map aliasMap = new HashMap<>(); + List> aliasList = new ArrayList<>(columns.size()); for (int i = 0; i < columns.size(); i++) { Expression expression = statement.getExpressions().get(i); String originName = expression.hasAlias() ? expression.getAlias() : expression.getColumnName(); - aliasMap.put(originName, name + SQLConstant.DOT + columns.get(i)); + aliasList.add(new Pair<>(originName, name + SQLConstant.DOT + columns.get(i))); } - return aliasMap; + return aliasList; } } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/SelectStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/SelectStatement.java index 10a9eba5c8..2c3e4ce3c3 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/SelectStatement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/SelectStatement.java @@ -23,10 +23,10 @@ import cn.edu.tsinghua.iginx.sql.statement.StatementType; import cn.edu.tsinghua.iginx.sql.statement.select.subclause.LimitClause; import cn.edu.tsinghua.iginx.sql.statement.select.subclause.OrderByClause; +import cn.edu.tsinghua.iginx.utils.Pair; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Map; import java.util.Set; public abstract class SelectStatement extends DataStatement { @@ -135,7 +135,7 @@ public void addFreeVariable(String freeVariable) { public abstract void initFreeVariables(); - public abstract Map getSubQueryAliasMap(String alias); + public abstract List> getSubQueryAliasList(String alias); public enum SelectStatementType { UNARY, diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/UnarySelectStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/UnarySelectStatement.java index 32dedde8c1..4e2821435f 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/UnarySelectStatement.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/select/UnarySelectStatement.java @@ -38,8 +38,18 @@ import cn.edu.tsinghua.iginx.sql.statement.frompart.SubQueryFromPart; import cn.edu.tsinghua.iginx.sql.statement.select.subclause.*; import cn.edu.tsinghua.iginx.thrift.AggregateType; +import cn.edu.tsinghua.iginx.utils.Pair; import cn.edu.tsinghua.iginx.utils.StringUtils; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; public class UnarySelectStatement extends SelectStatement { @@ -425,48 +435,57 @@ public void setQueryType(QueryType queryType) { @Override public List getExpressions() { - List expressions = new ArrayList<>(); - expressions.addAll(selectClause.getExpressions()); - return expressions; + return new ArrayList<>(selectClause.getExpressions()); } public void addSelectClauseExpression(Expression expression) { selectClause.addExpression(expression); } - public Map getSelectAliasMap() { - Map aliasMap = new HashMap<>(); + public List> getSelectAliasList() { + List> aliasList = new ArrayList<>(); + AtomicBoolean hasAlias = new AtomicBoolean(false); getExpressions() .forEach( expression -> { if (expression.hasAlias()) { - aliasMap.put(expression.getColumnName(), expression.getAlias()); + aliasList.add(new Pair<>(expression.getColumnName(), expression.getAlias())); + hasAlias.set(true); + } else { + aliasList.add(new Pair<>(expression.getColumnName(), expression.getColumnName())); } }); - return aliasMap; + return hasAlias.get() ? aliasList : Collections.emptyList(); } @Override - public Map getSubQueryAliasMap(String alias) { - Map aliasMap = new HashMap<>(); + public List> getSubQueryAliasList(String alias) { + List> aliasList = new ArrayList<>(); getExpressions() .forEach( expression -> { if (expression.hasAlias()) { - aliasMap.put(expression.getAlias(), alias + DOT + expression.getAlias()); + aliasList.add( + new Pair<>(expression.getAlias(), alias + DOT + expression.getAlias())); } else { if (expression.getType().equals(Expression.ExpressionType.Binary) || expression.getType().equals(Expression.ExpressionType.Unary)) { - aliasMap.put( - expression.getColumnName(), - alias + DOT + L_PARENTHESES + expression.getColumnName() + R_PARENTHESES); + aliasList.add( + new Pair<>( + expression.getColumnName(), + alias + + DOT + + L_PARENTHESES + + expression.getColumnName() + + R_PARENTHESES)); } else { - aliasMap.put( - expression.getColumnName(), alias + DOT + expression.getColumnName()); + aliasList.add( + new Pair<>( + expression.getColumnName(), alias + DOT + expression.getColumnName())); } } }); - return aliasMap; + return aliasList; } public boolean needRowTransform() { diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/FilterPushDownOptimizer.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/FilterPushDownOptimizer.java index 73aed98b46..a87823fc87 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/FilterPushDownOptimizer.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/FilterPushDownOptimizer.java @@ -108,7 +108,7 @@ private void pushDown(Select selectOperator) { getRenameOperator(selectOperator, project, renameList); Filter unrenamedFilter = filter.copy(); for (Operator rename : renameList) { - unrenamedFilter = replacePathByRenameMap(unrenamedFilter, ((Rename) rename).getAliasMap()); + unrenamedFilter = replacePathByRenameMap(unrenamedFilter, ((Rename) rename).getAliasList()); } // the same meta just call once. @@ -264,7 +264,7 @@ private boolean getRenameOperator( return isCorrectRoad; } - private Filter replacePathByRenameMap(Filter filter, Map renameMap) { + private Filter replacePathByRenameMap(Filter filter, List> renameMap) { switch (filter.getType()) { case Or: List orChildren = ((OrFilter) filter).getChildren(); @@ -282,8 +282,8 @@ private Filter replacePathByRenameMap(Filter filter, Map renameM break; case Value: String path = ((ValueFilter) filter).getPath(); - for (Map.Entry entry : renameMap.entrySet()) { - path = replacePathByRenameEntry(path, entry); + for (Pair pair : renameMap) { + path = replacePathByRenameEntry(path, pair); } return new ValueFilter( path, ((ValueFilter) filter).getOp(), ((ValueFilter) filter).getValue()); @@ -291,8 +291,8 @@ private Filter replacePathByRenameMap(Filter filter, Map renameM String pathA = ((PathFilter) filter).getPathA(); String pathB = ((PathFilter) filter).getPathB(); - for (Map.Entry entry : renameMap.entrySet()) { - pathA = replacePathByRenameEntry(pathA, entry); + for (Pair pair : renameMap) { + pathA = replacePathByRenameEntry(pathA, pair); } return new PathFilter(pathA, ((PathFilter) filter).getOp(), pathB); @@ -302,9 +302,9 @@ private Filter replacePathByRenameMap(Filter filter, Map renameM return filter; } - private String replacePathByRenameEntry(String path, Map.Entry entry) { - String nameBeforeRename = entry.getKey(); - String nameAfterRename = entry.getValue(); + private String replacePathByRenameEntry(String path, Pair pair) { + String nameBeforeRename = pair.k; + String nameAfterRename = pair.v; if (path.equals(nameAfterRename)) { return nameBeforeRename; } diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/ColumnPruningRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/ColumnPruningRule.java index 5583f00048..5497103508 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/ColumnPruningRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/ColumnPruningRule.java @@ -18,8 +18,6 @@ package cn.edu.tsinghua.iginx.logical.optimizer.rules; -import static cn.edu.tsinghua.iginx.engine.logical.utils.PathUtils.*; - import cn.edu.tsinghua.iginx.engine.logical.utils.OperatorUtils; import cn.edu.tsinghua.iginx.engine.logical.utils.PathUtils; import cn.edu.tsinghua.iginx.engine.physical.memory.execute.utils.ExprUtils; @@ -42,6 +40,7 @@ import cn.edu.tsinghua.iginx.utils.StringUtils; import com.google.auto.service.AutoService; import java.util.*; +import java.util.regex.Pattern; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -117,9 +116,9 @@ private void collectColumns( } } else if (operator.getType() == OperatorType.Rename) { Rename rename = (Rename) operator; - Map aliasMap = rename.getAliasMap(); + List> aliasList = rename.getAliasList(); columns = - new HashSet<>(PathUtils.recoverRenamedPatterns(aliasMap, new ArrayList<>(columns))); + new HashSet<>(PathUtils.recoverRenamedPatterns(aliasList, new ArrayList<>(columns))); } else if (operator.getType() == OperatorType.GroupBy) { GroupBy groupBy = (GroupBy) operator; @@ -335,13 +334,13 @@ private void collectColumns( new ArrayList<>()); for (String column : columns) { for (String leftPattern : leftPatterns) { - if (OperatorUtils.covers(leftPattern, column)) { + if (Pattern.matches(StringUtils.reformatPath(leftPattern), column)) { leftColumns.add(column); break; } } for (String rightPattern : rightPatterns) { - if (OperatorUtils.covers(rightPattern, column)) { + if (Pattern.matches(StringUtils.reformatPath(rightPattern), column)) { rightColumns.add(column); break; } diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownRenameRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownRenameRule.java index 2d43357910..52a8849129 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownRenameRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FilterPushDownRenameRule.java @@ -25,8 +25,9 @@ import cn.edu.tsinghua.iginx.engine.shared.operator.filter.*; import cn.edu.tsinghua.iginx.engine.shared.source.OperatorSource; import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; +import cn.edu.tsinghua.iginx.utils.Pair; import com.google.auto.service.AutoService; -import java.util.Map; +import java.util.List; @AutoService(Rule.class) public class FilterPushDownRenameRule extends Rule { @@ -50,13 +51,13 @@ public boolean matches(RuleCall call) { public void onMatch(RuleCall call) { Select select = (Select) call.getMatchedRoot(); Rename rename = (Rename) ((OperatorSource) select.getSource()).getOperator(); - select.setFilter(replacePathByRenameMap(select.getFilter(), rename.getAliasMap())); + select.setFilter(replacePathByRenameMap(select.getFilter(), rename.getAliasList())); select.setSource(rename.getSource()); rename.setSource(new OperatorSource(select)); call.transformTo(rename); } - private Filter replacePathByRenameMap(Filter filter, Map renameMap) { + private Filter replacePathByRenameMap(Filter filter, List> renameMap) { Filter newFilter = filter.copy(); newFilter.accept( new FilterVisitor() { @@ -96,7 +97,8 @@ public void visit(ExprFilter filter) { return newFilter; } - private void replaceExpressionByRenameMap(Expression expression, Map renameMap) { + private void replaceExpressionByRenameMap( + Expression expression, List> renameMap) { expression.accept( new ExpressionVisitor() { @Override diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FunctionDistinctEliminateRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FunctionDistinctEliminateRule.java index 2a58bdd611..a5de437d5d 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FunctionDistinctEliminateRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/FunctionDistinctEliminateRule.java @@ -25,6 +25,7 @@ import cn.edu.tsinghua.iginx.engine.shared.operator.type.OperatorType; import cn.edu.tsinghua.iginx.engine.shared.source.OperatorSource; import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; +import cn.edu.tsinghua.iginx.utils.Pair; import com.google.auto.service.AutoService; import java.util.*; @@ -67,13 +68,13 @@ public boolean matches(RuleCall call) { public void onMatch(RuleCall call) { AbstractUnaryOperator unaryOperator = (AbstractUnaryOperator) call.getMatchedRoot(); List functionCallList = getFunctionCallList(unaryOperator); - Map renameMap = new HashMap<>(); + List> renameMap = new ArrayList<>(); // 将函数中的distinct去掉 for (FunctionCall functionCall : functionCallList) { String oldName = functionCall.getFunctionStr(); functionCall.getParams().setDistinct(false); - renameMap.put(functionCall.getFunctionStr(), oldName); + renameMap.add(new Pair<>(functionCall.getFunctionStr(), oldName)); } // 添加一个rename节点,将不带distinct的函数结果重命名为原来的函数名,否则显示与用户输入的SQL不一致 diff --git a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/RowTransformConstantFoldingRule.java b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/RowTransformConstantFoldingRule.java index 5ffca61e34..06018b972e 100644 --- a/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/RowTransformConstantFoldingRule.java +++ b/optimizer/src/main/java/cn/edu/tsinghua/iginx/logical/optimizer/rules/RowTransformConstantFoldingRule.java @@ -25,10 +25,10 @@ import cn.edu.tsinghua.iginx.engine.shared.operator.RowTransform; import cn.edu.tsinghua.iginx.engine.shared.source.OperatorSource; import cn.edu.tsinghua.iginx.logical.optimizer.core.RuleCall; +import cn.edu.tsinghua.iginx.utils.Pair; import com.google.auto.service.AutoService; -import java.util.HashMap; +import java.util.ArrayList; import java.util.List; -import java.util.Map; @AutoService(Rule.class) public class RowTransformConstantFoldingRule extends Rule { @@ -63,7 +63,7 @@ public boolean matches(RuleCall call) { public void onMatch(RuleCall call) { RowTransform rowTransform = (RowTransform) call.getMatchedRoot(); List functionCallList = rowTransform.getFunctionCallList(); - Map aliasMap = new HashMap<>(); + List> aliasList = new ArrayList<>(); for (FunctionCall functionCall : functionCallList) { Expression expr = functionCall.getParams().getExpr(); @@ -74,13 +74,13 @@ public void onMatch(RuleCall call) { Expression foldedExpression = ExprUtils.foldExpression(flattenedExpression); functionCall.getParams().setExpr(foldedExpression); String newName = foldedExpression.getColumnName(); - aliasMap.put(newName, oldName); + aliasList.add(new Pair<>(newName, oldName)); } } } // 改完之后要在上面加一层Rename,因为常量折叠改变了表达式输出的列名,但是我们依然要用原列名 - Rename rename = new Rename(new OperatorSource(rowTransform), aliasMap); + Rename rename = new Rename(new OperatorSource(rowTransform), aliasList); call.transformTo(rename); } } diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/sql/SQLSessionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/sql/SQLSessionIT.java index efb83e338f..fbf0ef62a6 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/sql/SQLSessionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/sql/SQLSessionIT.java @@ -3242,6 +3242,21 @@ public void testAlias() { + "+----+-------------------------------+--------------------------+\n" + "Total line number = 10\n"; executor.executeAndCompare(statement, expected); + + // duplicate columns + statement = "SELECT s1 AS a, s1, s1 AS s1, s2 AS c, s2 FROM us.d1 WHERE s1 > 50 AND s1 < 55;"; + expected = + "ResultSets:\n" + + "+---+--+--------+--+--+--------+\n" + + "|key| a|us.d1.s1|s1| c|us.d1.s2|\n" + + "+---+--+--------+--+--+--------+\n" + + "| 51|51| 51|51|52| 52|\n" + + "| 52|52| 52|52|53| 53|\n" + + "| 53|53| 53|53|54| 54|\n" + + "| 54|54| 54|54|55| 55|\n" + + "+---+--+--------+--+--+--------+\n" + + "Total line number = 4\n"; + executor.executeAndCompare(statement, expected); } @Test @@ -6874,7 +6889,7 @@ public void testFilterFragmentOptimizer() { + "|Reorder | Reorder| Order: avg(bb)|\n" + "| +--GroupBy | GroupBy|GroupByCols: aa, FuncList(Name, FuncType): (avg, System), MappingType: SetMapping isDistinct: false|\n" + "| +--Select | Select| Filter: key > 2|\n" - + "| +--Rename | Rename| AliasMap: (us.d2.a, aa),(us.d2.b, bb)|\n" + + "| +--Rename | Rename| AliasList: (us.d2.a, aa),(us.d2.b, bb)|\n" + "| +--Reorder | Reorder| Order: us.d2.a,us.d2.b|\n" + "| +--Project | Project| Patterns: us.d2.a,us.d2.b|\n" + "| +--PathUnion| PathUnion| |\n" @@ -6900,7 +6915,7 @@ public void testFilterFragmentOptimizer() { + "|Reorder | Reorder| Order: count(*)|\n" + "| +--Downsample | Downsample| Precision: 20, SlideDistance: 20, TimeRange: [1000, 1100), FuncList(Name, FunctionType): (count, System), MappingType: SetMapping|\n" + "| +--Select | Select| Filter: (key >= 1000 && key < 1100)|\n" - + "| +--Rename | Rename| AliasMap: (avg(us.d1.s1), avg_s1),(sum(us.d1.s2), sum_s2)|\n" + + "| +--Rename | Rename| AliasList: (avg(us.d1.s1), avg_s1),(sum(us.d1.s2), sum_s2)|\n" + "| +--Reorder | Reorder| Order: avg(us.d1.s1),sum(us.d1.s2)|\n" + "| +--Downsample | Downsample|Precision: 10, SlideDistance: 10, TimeRange: [1000, 1100), FuncList(Name, FunctionType): (avg, System), (sum, System), MappingType: SetMapping|\n" + "| +--Select | Select| Filter: (key >= 1000 && key < 1100)|\n" @@ -6959,7 +6974,7 @@ public void testFilterFragmentOptimizer() { + "|Reorder | Reorder| Order: count(*)|\n" + "| +--Downsample | Downsample| Precision: 20, SlideDistance: 20, TimeRange: [1000, 1100), FuncList(Name, FunctionType): (count, System), MappingType: SetMapping|\n" + "| +--Select | Select| Filter: (key >= 1000 && key < 1100)|\n" - + "| +--Rename | Rename| AliasMap: (avg(us.d1.s1), avg_s1),(sum(us.d1.s2), sum_s2)|\n" + + "| +--Rename | Rename| AliasList: (avg(us.d1.s1), avg_s1),(sum(us.d1.s2), sum_s2)|\n" + "| +--Reorder | Reorder| Order: avg(us.d1.s1),sum(us.d1.s2)|\n" + "| +--Downsample | Downsample|Precision: 10, SlideDistance: 10, TimeRange: [1000, 1100), FuncList(Name, FunctionType): (avg, System), (sum, System), MappingType: SetMapping|\n" + "| +--Select | Select| Filter: (key >= 1000 && key < 1100)|\n" diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/tag/TagIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/tag/TagIT.java index 87737b1270..7457b0dbfa 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/tag/TagIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/func/tag/TagIT.java @@ -1341,6 +1341,18 @@ public void testAlias() { + "Total line number = 2\n"; executeAndCompare(statement, expected); + statement = "SELECT s AS ts, s AS ss FROM ah.hr02;"; + expected = + "ResultSets:\n" + + "+---+----+---------+----+---------+\n" + + "|key| ts|ts{t1=v1}| ss|ss{t1=v1}|\n" + + "+---+----+---------+----+---------+\n" + + "|100|true| null|true| null|\n" + + "|400|null| false|null| false|\n" + + "+---+----+---------+----+---------+\n" + + "Total line number = 2\n"; + executeAndCompare(statement, expected); + statement = "SELECT s FROM ah.hr02 AS result_set;"; expected = "ResultSets:\n" From 23e369696f6f419082d03aa2124795314b1930d3 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Sun, 28 Jul 2024 10:36:00 +0800 Subject: [PATCH 122/138] feat(filesystem): push down patterns and tagFilter --- .../filesystem/exec/FileSystemManager.java | 38 +++++++++++++++++-- .../iginx/filesystem/exec/LocalExecutor.java | 25 ++++-------- 2 files changed, 42 insertions(+), 21 deletions(-) diff --git a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java index da9f0c9f4f..ccd2bfd8af 100644 --- a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java +++ b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java @@ -34,6 +34,7 @@ import cn.edu.tsinghua.iginx.filesystem.tools.MemoryPool; import cn.edu.tsinghua.iginx.thrift.DataType; import cn.edu.tsinghua.iginx.utils.Pair; +import cn.edu.tsinghua.iginx.utils.StringUtils; import java.io.File; import java.io.IOException; import java.nio.file.*; @@ -391,7 +392,19 @@ public FileVisitResult postVisitDirectory(Path dir, IOException exc) { .collect(Collectors.toList()); } - public List getAllFiles(File dir, boolean containsEmptyDir) { + public List getTargetFiles( + String root, + String storageUnit, + Set patterns, + TagFilter tagFilter, + boolean isDummy, + boolean containsEmptyDir) { + File dir; + if (isDummy) { + dir = new File(root); + } else { + dir = new File(FilePathUtils.toIginxPath(root, storageUnit, null)); + } dir = FilePathUtils.normalize(dir, FileAccessType.READ); List res = new ArrayList<>(); @@ -409,8 +422,27 @@ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) } @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { - res.add(file.toFile()); + public FileVisitResult visitFile(Path filePath, BasicFileAttributes attrs) { + File file = filePath.toFile(); + FileMeta meta = getFileMeta(file); + String columnPath = + FilePathUtils.convertAbsolutePathToPath( + root, file.getAbsolutePath(), storageUnit); + if (meta == null) { + throw new RuntimeException( + String.format( + "encounter error when getting columns of storage unit because file meta %s is null", + file.getAbsolutePath())); + } + // get columns by pattern + if (StringUtils.pathNotMatchPatterns(columnPath, patterns)) { + return FileVisitResult.CONTINUE; + } + // get columns by tag filter + if (tagFilter != null && !TagKVUtils.match(meta.getTags(), tagFilter)) { + return FileVisitResult.CONTINUE; + } + res.add(file); return FileVisitResult.CONTINUE; } diff --git a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java index f643026166..cf48d480f9 100644 --- a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java +++ b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java @@ -25,7 +25,6 @@ import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; import cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream.EmptyRowStream; import cn.edu.tsinghua.iginx.engine.physical.storage.domain.Column; -import cn.edu.tsinghua.iginx.engine.physical.storage.utils.TagKVUtils; import cn.edu.tsinghua.iginx.engine.physical.task.TaskExecuteResult; import cn.edu.tsinghua.iginx.engine.shared.KeyRange; import cn.edu.tsinghua.iginx.engine.shared.data.read.RowStream; @@ -48,7 +47,6 @@ import cn.edu.tsinghua.iginx.metadata.entity.KeyInterval; import cn.edu.tsinghua.iginx.thrift.DataType; import cn.edu.tsinghua.iginx.utils.Pair; -import cn.edu.tsinghua.iginx.utils.StringUtils; import java.io.File; import java.io.IOException; import java.util.ArrayList; @@ -334,36 +332,27 @@ public List getColumnsOfStorageUnit( String storageUnit, Set patterns, TagFilter tagFilter) throws PhysicalException { List columns = new ArrayList<>(); if (root != null) { - File directory = new File(FilePathUtils.toIginxPath(root, storageUnit, null)); - for (File file : fileSystemManager.getAllFiles(directory, false)) { + for (File file : + fileSystemManager.getTargetFiles(root, storageUnit, patterns, tagFilter, false, false)) { FileMeta meta = fileSystemManager.getFileMeta(file); - String columnPath = - FilePathUtils.convertAbsolutePathToPath(root, file.getAbsolutePath(), storageUnit); if (meta == null) { throw new PhysicalException( String.format( "encounter error when getting columns of storage unit because file meta %s is null", file.getAbsolutePath())); } - // get columns by pattern - if (StringUtils.pathNotMatchPatterns(columnPath, patterns)) { - continue; - } - // get columns by tag filter - if (tagFilter != null && !TagKVUtils.match(meta.getTags(), tagFilter)) { - continue; - } + String columnPath = + FilePathUtils.convertAbsolutePathToPath(root, file.getAbsolutePath(), storageUnit); columns.add(new Column(columnPath, meta.getDataType(), meta.getTags(), false)); } } // get columns from dummy storage unit if (hasData && dummyRoot != null && tagFilter == null) { - for (File file : fileSystemManager.getAllFiles(new File(realDummyRoot), true)) { + for (File file : + fileSystemManager.getTargetFiles( + realDummyRoot, storageUnit, patterns, null, true, true)) { String dummyPath = FilePathUtils.convertAbsolutePathToPath(dummyRoot, file.getAbsolutePath(), storageUnit); - if (StringUtils.pathNotMatchPatterns(dummyPath, patterns)) { - continue; - } columns.add(new Column(dummyPath, DataType.BINARY, null, true)); } } From 18826a05b07d05d1f06e2da5403e5fa4419c844f Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Sun, 28 Jul 2024 11:06:23 +0800 Subject: [PATCH 123/138] fix --- .../tsinghua/iginx/filesystem/exec/FileSystemManager.java | 8 +------- .../edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java | 6 ++++-- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java index ccd2bfd8af..dca42cde60 100644 --- a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java +++ b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java @@ -393,18 +393,12 @@ public FileVisitResult postVisitDirectory(Path dir, IOException exc) { } public List getTargetFiles( + File dir, String root, String storageUnit, Set patterns, TagFilter tagFilter, - boolean isDummy, boolean containsEmptyDir) { - File dir; - if (isDummy) { - dir = new File(root); - } else { - dir = new File(FilePathUtils.toIginxPath(root, storageUnit, null)); - } dir = FilePathUtils.normalize(dir, FileAccessType.READ); List res = new ArrayList<>(); diff --git a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java index cf48d480f9..8ed46c4a3f 100644 --- a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java +++ b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java @@ -332,8 +332,10 @@ public List getColumnsOfStorageUnit( String storageUnit, Set patterns, TagFilter tagFilter) throws PhysicalException { List columns = new ArrayList<>(); if (root != null) { + File directory = new File(FilePathUtils.toIginxPath(root, storageUnit, null)); for (File file : - fileSystemManager.getTargetFiles(root, storageUnit, patterns, tagFilter, false, false)) { + fileSystemManager.getTargetFiles( + directory, root, storageUnit, patterns, tagFilter, false)) { FileMeta meta = fileSystemManager.getFileMeta(file); if (meta == null) { throw new PhysicalException( @@ -350,7 +352,7 @@ public List getColumnsOfStorageUnit( if (hasData && dummyRoot != null && tagFilter == null) { for (File file : fileSystemManager.getTargetFiles( - realDummyRoot, storageUnit, patterns, null, true, true)) { + new File(realDummyRoot), dummyRoot, storageUnit, patterns, null, true)) { String dummyPath = FilePathUtils.convertAbsolutePathToPath(dummyRoot, file.getAbsolutePath(), storageUnit); columns.add(new Column(dummyPath, DataType.BINARY, null, true)); From 7832a82a4dafe4ec0023a1fc54cf64d07268e40e Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Mon, 5 Aug 2024 09:38:01 +0800 Subject: [PATCH 124/138] fix has_data --- .../physical/storage/execute/StoragePhysicalTaskExecutor.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java index 5fc35be652..4d90eebc6a 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java @@ -361,6 +361,9 @@ public TaskExecuteResult executeShowColumns(ShowColumns showColumns) { TreeSet columnSetAfterFilter = new TreeSet<>(Comparator.comparing(Column::getPhysicalPath)); for (StorageEngineMeta storage : storageList) { + if (!storage.isHasData()) { + continue; + } long id = storage.getId(); Pair pair = storageManager.getStorage(id); if (pair == null) { From 1fa2c8e99e00a4902ab940aaa24b3b852a5fb999 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Mon, 5 Aug 2024 09:59:48 +0800 Subject: [PATCH 125/138] Revert "fix has_data" This reverts commit 7832a82a4dafe4ec0023a1fc54cf64d07268e40e. --- .../physical/storage/execute/StoragePhysicalTaskExecutor.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java index 4d90eebc6a..5fc35be652 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java @@ -361,9 +361,6 @@ public TaskExecuteResult executeShowColumns(ShowColumns showColumns) { TreeSet columnSetAfterFilter = new TreeSet<>(Comparator.comparing(Column::getPhysicalPath)); for (StorageEngineMeta storage : storageList) { - if (!storage.isHasData()) { - continue; - } long id = storage.getId(); Pair pair = storageManager.getStorage(id); if (pair == null) { From d805bb2ea447d91cdcfe27da5de43d71ec313d3c Mon Sep 17 00:00:00 2001 From: ZM <12236590+shinyano@users.noreply.github.com> Date: Tue, 6 Aug 2024 11:42:10 +0800 Subject: [PATCH 126/138] feat(core): allow changing db params(only apply for dummy & read-only) (#398) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit User can alter the params of read-only dummy storage engine. The HAS_DATA & IS_READ_ONLY attributes cannot be modified. SQL ALTER STORAGEENGINE WITH PARAMS "(:,?)+"; example: alter storageengine 2 with params "dummy_dir:test/new_data"; ——简化实现,后续随节点移除、容错能力的增强,需要相应调整实现 同时,按需相应调整测试脚本目录结构 --- .github/actions/dbRunner/action.yml | 60 ++++++------ .../{ => startup}/filesystem_linux_windows.sh | 0 .../{ => startup}/filesystem_macos.sh | 0 .../dataSources/{ => startup}/influxdb.sh | 1 + .../{ => startup}/influxdb_macos.sh | 1 + .../{ => startup}/influxdb_windows.sh | 12 +-- .../dataSources/{ => startup}/iotdb12.sh | 1 + .../{ => startup}/iotdb12_macos.sh | 1 + .../{ => startup}/iotdb12_windows.sh | 1 + .../{ => startup}/mix_iotdb12_influxdb.sh | 8 +- .../mix_iotdb12_influxdb_macos.sh | 8 +- .../mix_iotdb12_influxdb_windows.sh | 8 +- .../{ => startup}/parquet_linux_windows.sh | 0 .../{ => startup}/parquet_macos.sh | 0 .../scripts/dataSources/update/influxdb.sh | 37 ++++++++ .../dataSources/update/influxdb_macos.sh | 37 ++++++++ .../dataSources/update/influxdb_windows.sh | 38 ++++++++ .github/scripts/dataSources/update/iotdb.sh | 26 ++++++ .../scripts/dataSources/update/iotdb_macos.sh | 26 ++++++ .../dataSources/update/iotdb_windows.sh | 26 ++++++ .github/scripts/dataSources/update/mysql.sh | 31 +++++++ .../scripts/dataSources/update/mysql_macos.sh | 31 +++++++ .../dataSources/update/mysql_windows.sh | 31 +++++++ .../scripts/dataSources/update/postgresql.sh | 27 ++++++ .../dataSources/update/postgresql_macos.sh | 27 ++++++ .../dataSources/update/postgresql_windows.sh | 27 ++++++ .../antlr4/cn/edu/tsinghua/iginx/sql/Sql.g4 | 11 +++ .../cn/edu/tsinghua/iginx/IginxWorker.java | 65 +++++++++---- .../cn/edu/tsinghua/iginx/conf/Constants.java | 7 ++ .../iginx/engine/StatementBuilder.java | 1 + .../physical/storage/StorageManager.java | 29 ++++++ .../execute/StoragePhysicalTaskExecutor.java | 12 +++ .../iginx/metadata/DefaultMetaManager.java | 5 +- .../metadata/entity/StorageEngineMeta.java | 31 +++++++ .../storage/etcd/ETCDMetaStorage.java | 2 +- .../metadata/utils/StorageEngineUtils.java | 7 +- .../tsinghua/iginx/sql/IginXSqlVisitor.java | 7 ++ .../sql/statement/AlterEngineStatement.java | 50 ++++++++++ .../iginx/sql/statement/StatementType.java | 1 + .../expansion/BaseCapacityExpansionIT.java | 93 ++++++++++++++++--- .../FileSystemCapacityExpansionIT.java | 7 ++ .../influxdb/InfluxDBCapacityExpansionIT.java | 28 ++++++ .../iotdb/IoTDB12CapacityExpansionIT.java | 28 ++++++ .../mongodb/MongoDBCapacityExpansionIT.java | 7 ++ .../mysql/MySQLCapacityExpansionIT.java | 31 +++++++ .../parquet/ParquetCapacityExpansionIT.java | 7 ++ .../PostgreSQLCapacityExpansionIT.java | 30 ++++++ .../redis/RedisCapacityExpansionIT.java | 7 ++ thrift/src/main/proto/rpc.thrift | 9 ++ 49 files changed, 851 insertions(+), 89 deletions(-) rename .github/scripts/dataSources/{ => startup}/filesystem_linux_windows.sh (100%) rename .github/scripts/dataSources/{ => startup}/filesystem_macos.sh (100%) rename .github/scripts/dataSources/{ => startup}/influxdb.sh (97%) rename .github/scripts/dataSources/{ => startup}/influxdb_macos.sh (97%) rename .github/scripts/dataSources/{ => startup}/influxdb_windows.sh (92%) rename .github/scripts/dataSources/{ => startup}/iotdb12.sh (96%) rename .github/scripts/dataSources/{ => startup}/iotdb12_macos.sh (96%) rename .github/scripts/dataSources/{ => startup}/iotdb12_windows.sh (97%) rename .github/scripts/dataSources/{ => startup}/mix_iotdb12_influxdb.sh (81%) rename .github/scripts/dataSources/{ => startup}/mix_iotdb12_influxdb_macos.sh (80%) rename .github/scripts/dataSources/{ => startup}/mix_iotdb12_influxdb_windows.sh (79%) rename .github/scripts/dataSources/{ => startup}/parquet_linux_windows.sh (100%) rename .github/scripts/dataSources/{ => startup}/parquet_macos.sh (100%) create mode 100644 .github/scripts/dataSources/update/influxdb.sh create mode 100644 .github/scripts/dataSources/update/influxdb_macos.sh create mode 100644 .github/scripts/dataSources/update/influxdb_windows.sh create mode 100644 .github/scripts/dataSources/update/iotdb.sh create mode 100644 .github/scripts/dataSources/update/iotdb_macos.sh create mode 100644 .github/scripts/dataSources/update/iotdb_windows.sh create mode 100644 .github/scripts/dataSources/update/mysql.sh create mode 100644 .github/scripts/dataSources/update/mysql_macos.sh create mode 100644 .github/scripts/dataSources/update/mysql_windows.sh create mode 100644 .github/scripts/dataSources/update/postgresql.sh create mode 100644 .github/scripts/dataSources/update/postgresql_macos.sh create mode 100644 .github/scripts/dataSources/update/postgresql_windows.sh create mode 100644 core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/AlterEngineStatement.java diff --git a/.github/actions/dbRunner/action.yml b/.github/actions/dbRunner/action.yml index b9993ace68..6c6b7d2fc1 100644 --- a/.github/actions/dbRunner/action.yml +++ b/.github/actions/dbRunner/action.yml @@ -24,14 +24,14 @@ runs: shell: bash run: | if [ "$RUNNER_OS" == "Linux" ]; then - chmod +x "${GITHUB_WORKSPACE}/.github/scripts/dataSources/influxdb.sh" - "${GITHUB_WORKSPACE}/.github/scripts/dataSources/influxdb.sh" 8088 8087 + chmod +x "${GITHUB_WORKSPACE}/.github/scripts/dataSources/startup/influxdb.sh" + "${GITHUB_WORKSPACE}/.github/scripts/dataSources/startup/influxdb.sh" 8088 8087 elif [ "$RUNNER_OS" == "Windows" ]; then - chmod +x "${GITHUB_WORKSPACE}/.github/scripts/dataSources/influxdb_windows.sh" - "${GITHUB_WORKSPACE}/.github/scripts/dataSources/influxdb_windows.sh" 8088 8087 + chmod +x "${GITHUB_WORKSPACE}/.github/scripts/dataSources/startup/influxdb_windows.sh" + "${GITHUB_WORKSPACE}/.github/scripts/dataSources/startup/influxdb_windows.sh" 8088 8087 elif [ "$RUNNER_OS" == "macOS" ]; then - chmod +x "${GITHUB_WORKSPACE}/.github/scripts/dataSources/influxdb_macos.sh" - "${GITHUB_WORKSPACE}/.github/scripts/dataSources/influxdb_macos.sh" 8088 8087 + chmod +x "${GITHUB_WORKSPACE}/.github/scripts/dataSources/startup/influxdb_macos.sh" + "${GITHUB_WORKSPACE}/.github/scripts/dataSources/startup/influxdb_macos.sh" 8088 8087 else echo "$RUNNER_OS is not supported" exit 1 @@ -46,14 +46,14 @@ runs: shell: bash run: | if [ "$RUNNER_OS" == "Linux" ]; then - chmod +x "${GITHUB_WORKSPACE}/.github/scripts/dataSources/iotdb12.sh" - "${GITHUB_WORKSPACE}/.github/scripts/dataSources/iotdb12.sh" 6667 6668 6669 + chmod +x "${GITHUB_WORKSPACE}/.github/scripts/dataSources/startup/iotdb12.sh" + "${GITHUB_WORKSPACE}/.github/scripts/dataSources/startup/iotdb12.sh" 6667 6668 6669 elif [ "$RUNNER_OS" == "Windows" ]; then - chmod +x "${GITHUB_WORKSPACE}/.github/scripts/dataSources/iotdb12_windows.sh" - "${GITHUB_WORKSPACE}/.github/scripts/dataSources/iotdb12_windows.sh" 6667 6668 6669 + chmod +x "${GITHUB_WORKSPACE}/.github/scripts/dataSources/startup/iotdb12_windows.sh" + "${GITHUB_WORKSPACE}/.github/scripts/dataSources/startup/iotdb12_windows.sh" 6667 6668 6669 elif [ "$RUNNER_OS" == "macOS" ]; then - chmod +x "${GITHUB_WORKSPACE}/.github/scripts/dataSources/iotdb12_macos.sh" - "${GITHUB_WORKSPACE}/.github/scripts/dataSources/iotdb12_macos.sh" 6667 6668 6669 + chmod +x "${GITHUB_WORKSPACE}/.github/scripts/dataSources/startup/iotdb12_macos.sh" + "${GITHUB_WORKSPACE}/.github/scripts/dataSources/startup/iotdb12_macos.sh" 6667 6668 6669 else echo "$RUNNER_OS is not supported" exit 1 @@ -64,14 +64,14 @@ runs: shell: bash run: | if [ "$RUNNER_OS" == "Linux" ]; then - chmod +x "${GITHUB_WORKSPACE}/.github/scripts/dataSources/mix_iotdb12_influxdb.sh" - "${GITHUB_WORKSPACE}/.github/scripts/dataSources/mix_iotdb12_influxdb.sh" + chmod +x "${GITHUB_WORKSPACE}/.github/scripts/dataSources/startup/mix_iotdb12_influxdb.sh" + "${GITHUB_WORKSPACE}/.github/scripts/dataSources/startup/mix_iotdb12_influxdb.sh" elif [ "$RUNNER_OS" == "Windows" ]; then - chmod +x "${GITHUB_WORKSPACE}/.github/scripts/dataSources/mix_iotdb12_influxdb_windows.sh" - "${GITHUB_WORKSPACE}/.github/scripts/dataSources/mix_iotdb12_influxdb_windows.sh" + chmod +x "${GITHUB_WORKSPACE}/.github/scripts/dataSources/startup/mix_iotdb12_influxdb_windows.sh" + "${GITHUB_WORKSPACE}/.github/scripts/dataSources/startup/mix_iotdb12_influxdb_windows.sh" elif [ "$RUNNER_OS" == "macOS" ]; then - chmod +x "${GITHUB_WORKSPACE}/.github/scripts/dataSources/mix_iotdb12_influxdb_macos.sh" - "${GITHUB_WORKSPACE}/.github/scripts/dataSources/mix_iotdb12_influxdb_macos.sh" + chmod +x "${GITHUB_WORKSPACE}/.github/scripts/dataSources/startup/mix_iotdb12_influxdb_macos.sh" + "${GITHUB_WORKSPACE}/.github/scripts/dataSources/startup/mix_iotdb12_influxdb_macos.sh" else echo "$RUNNER_OS is not supported" exit 1 @@ -83,14 +83,14 @@ runs: run: | cp -f "${GITHUB_WORKSPACE}/conf/config.properties" "${GITHUB_WORKSPACE}/conf/config.properties.bak" if [[ "$RUNNER_OS" == "Linux" ]]; then - chmod +x "${GITHUB_WORKSPACE}/.github/scripts/dataSources/parquet_linux_windows.sh" - "${GITHUB_WORKSPACE}/.github/scripts/dataSources/parquet_linux_windows.sh" 6667 6888 test/mn ${GITHUB_WORKSPACE}/test/iginx_mn false false conf/config.properties + chmod +x "${GITHUB_WORKSPACE}/.github/scripts/dataSources/startup/parquet_linux_windows.sh" + "${GITHUB_WORKSPACE}/.github/scripts/dataSources/startup/parquet_linux_windows.sh" 6667 6888 test/mn ${GITHUB_WORKSPACE}/test/iginx_mn false false conf/config.properties elif [[ "$RUNNER_OS" == "Windows" ]]; then - chmod +x "${GITHUB_WORKSPACE}/.github/scripts/dataSources/parquet_linux_windows.sh" - "${GITHUB_WORKSPACE}/.github/scripts/dataSources/parquet_linux_windows.sh" 6667 6888 test/mn test/iginx_mn false false conf/config.properties + chmod +x "${GITHUB_WORKSPACE}/.github/scripts/dataSources/startup/parquet_linux_windows.sh" + "${GITHUB_WORKSPACE}/.github/scripts/dataSources/startup/parquet_linux_windows.sh" 6667 6888 test/mn test/iginx_mn false false conf/config.properties elif [ "$RUNNER_OS" == "macOS" ]; then - chmod +x "${GITHUB_WORKSPACE}/.github/scripts/dataSources/parquet_macos.sh" - "${GITHUB_WORKSPACE}/.github/scripts/dataSources/parquet_macos.sh" 6667 6888 test/mn test/iginx_mn false false conf/config.properties + chmod +x "${GITHUB_WORKSPACE}/.github/scripts/dataSources/startup/parquet_macos.sh" + "${GITHUB_WORKSPACE}/.github/scripts/dataSources/startup/parquet_macos.sh" 6667 6888 test/mn test/iginx_mn false false conf/config.properties else echo "$RUNNER_OS is not supported" exit 1 @@ -122,14 +122,14 @@ runs: run: | cp -f "${GITHUB_WORKSPACE}/conf/config.properties" "${GITHUB_WORKSPACE}/conf/config.properties.bak" if [[ "$RUNNER_OS" == "Linux" ]]; then - chmod +x "${GITHUB_WORKSPACE}/.github/scripts/dataSources/filesystem_linux_windows.sh" - "${GITHUB_WORKSPACE}/.github/scripts/dataSources/filesystem_linux_windows.sh" 6667 6888 test/mn ${GITHUB_WORKSPACE}/test/iginx_mn false false conf/config.properties + chmod +x "${GITHUB_WORKSPACE}/.github/scripts/dataSources/startup/filesystem_linux_windows.sh" + "${GITHUB_WORKSPACE}/.github/scripts/dataSources/startup/filesystem_linux_windows.sh" 6667 6888 test/mn ${GITHUB_WORKSPACE}/test/iginx_mn false false conf/config.properties elif [[ "$RUNNER_OS" == "Windows" ]]; then - chmod +x "${GITHUB_WORKSPACE}/.github/scripts/dataSources/filesystem_linux_windows.sh" - "${GITHUB_WORKSPACE}/.github/scripts/dataSources/filesystem_linux_windows.sh" 6667 6888 test/mn test/iginx_mn false false conf/config.properties + chmod +x "${GITHUB_WORKSPACE}/.github/scripts/dataSources/startup/filesystem_linux_windows.sh" + "${GITHUB_WORKSPACE}/.github/scripts/dataSources/startup/filesystem_linux_windows.sh" 6667 6888 test/mn test/iginx_mn false false conf/config.properties elif [ "$RUNNER_OS" == "macOS" ]; then - chmod +x "${GITHUB_WORKSPACE}/.github/scripts/dataSources/filesystem_macos.sh" - "${GITHUB_WORKSPACE}/.github/scripts/dataSources/filesystem_macos.sh" 6667 6888 test/mn test/iginx_mn false false conf/config.properties + chmod +x "${GITHUB_WORKSPACE}/.github/scripts/dataSources/startup/filesystem_macos.sh" + "${GITHUB_WORKSPACE}/.github/scripts/dataSources/startup/filesystem_macos.sh" 6667 6888 test/mn test/iginx_mn false false conf/config.properties else echo "$RUNNER_OS is not supported" exit 1 diff --git a/.github/scripts/dataSources/filesystem_linux_windows.sh b/.github/scripts/dataSources/startup/filesystem_linux_windows.sh similarity index 100% rename from .github/scripts/dataSources/filesystem_linux_windows.sh rename to .github/scripts/dataSources/startup/filesystem_linux_windows.sh diff --git a/.github/scripts/dataSources/filesystem_macos.sh b/.github/scripts/dataSources/startup/filesystem_macos.sh similarity index 100% rename from .github/scripts/dataSources/filesystem_macos.sh rename to .github/scripts/dataSources/startup/filesystem_macos.sh diff --git a/.github/scripts/dataSources/influxdb.sh b/.github/scripts/dataSources/startup/influxdb.sh similarity index 97% rename from .github/scripts/dataSources/influxdb.sh rename to .github/scripts/dataSources/startup/influxdb.sh index 879629574d..3d051b8259 100644 --- a/.github/scripts/dataSources/influxdb.sh +++ b/.github/scripts/dataSources/startup/influxdb.sh @@ -40,6 +40,7 @@ sed -i "s/#storageEngineList=127.0.0.1#8086/storageEngineList=127.0.0.1#8086/g" for port in "$@" do + # target path is also used in update/ script sh -c "sudo cp -r influxdb2-2.0.7-linux-amd64/ influxdb2-2.0.7-linux-amd64-$port/" sudo sh -c "cd influxdb2-2.0.7-linux-amd64-$port/; nohup ./influxd run --bolt-path=~/.influxdbv2/influxd.bolt --engine-path=~/.influxdbv2/engine --http-bind-address=:$port --query-memory-bytes=20971520 &" diff --git a/.github/scripts/dataSources/influxdb_macos.sh b/.github/scripts/dataSources/startup/influxdb_macos.sh similarity index 97% rename from .github/scripts/dataSources/influxdb_macos.sh rename to .github/scripts/dataSources/startup/influxdb_macos.sh index 513562c313..a4774b06f4 100644 --- a/.github/scripts/dataSources/influxdb_macos.sh +++ b/.github/scripts/dataSources/startup/influxdb_macos.sh @@ -40,6 +40,7 @@ sed -i "" "s/#storageEngineList=127.0.0.1#8086/storageEngineList=127.0.0.1#8086/ for port in "$@" do + # target path is also used in update/ script sh -c "sudo cp -r influxdb2-2.0.7-darwin-amd64/ influxdb2-2.0.7-darwin-amd64-$port/" sudo sh -c "cd influxdb2-2.0.7-darwin-amd64-$port/; nohup ./influxd run --bolt-path=~/.influxdbv2/influxd.bolt --engine-path=~/.influxdbv2/engine --http-bind-address=:$port --query-memory-bytes=20971520 &" diff --git a/.github/scripts/dataSources/influxdb_windows.sh b/.github/scripts/dataSources/startup/influxdb_windows.sh similarity index 92% rename from .github/scripts/dataSources/influxdb_windows.sh rename to .github/scripts/dataSources/startup/influxdb_windows.sh index ac5669b550..7346abbe3a 100644 --- a/.github/scripts/dataSources/influxdb_windows.sh +++ b/.github/scripts/dataSources/startup/influxdb_windows.sh @@ -48,6 +48,7 @@ sed -i "s/#storageEngineList=127.0.0.1#8086/storageEngineList=127.0.0.1#8086/g" for port in "$@" do + # target path is also used in update/ script sh -c "cp -r influxdb2-2.0.7-windows-amd64/ influxdb2-2.0.7-windows-amd64-$port/" pathPrefix="influxdb2-2.0.7-windows-amd64-$port" @@ -57,15 +58,4 @@ do redirect="-RedirectStandardOutput '$pathPrefix/logs/db.log' -RedirectStandardError '$pathPrefix/logs/db-error.log'" powershell -command "Start-Process -FilePath 'influxdb2-2.0.7-windows-amd64-$port/influxd' $arguments -NoNewWindow $redirect" - - sh -c "sleep 10" - - sh -c "cat $pathPrefix/logs/db.log" - - echo "===========================================" - - sh -c "cat $pathPrefix/logs/db-error.log" - - echo "===========================================" - done diff --git a/.github/scripts/dataSources/iotdb12.sh b/.github/scripts/dataSources/startup/iotdb12.sh similarity index 96% rename from .github/scripts/dataSources/iotdb12.sh rename to .github/scripts/dataSources/startup/iotdb12.sh index 28d806af7f..00bad8eedb 100644 --- a/.github/scripts/dataSources/iotdb12.sh +++ b/.github/scripts/dataSources/startup/iotdb12.sh @@ -32,6 +32,7 @@ sh -c "sudo sed -i 's/^# compaction_strategy=.*$/compaction_strategy=NO_COMPACTI for port in "$@" do + # target path is also used in update/ script sh -c "sudo cp -r apache-iotdb-0.12.6-server-bin/ apache-iotdb-0.12.6-server-bin-$port" sh -c "sudo sed -i 's/# wal_buffer_size=16777216/wal_buffer_size=167772160/g' apache-iotdb-0.12.6-server-bin-$port/conf/iotdb-engine.properties" diff --git a/.github/scripts/dataSources/iotdb12_macos.sh b/.github/scripts/dataSources/startup/iotdb12_macos.sh similarity index 96% rename from .github/scripts/dataSources/iotdb12_macos.sh rename to .github/scripts/dataSources/startup/iotdb12_macos.sh index 021ae8cf35..05a4f5383f 100644 --- a/.github/scripts/dataSources/iotdb12_macos.sh +++ b/.github/scripts/dataSources/startup/iotdb12_macos.sh @@ -32,6 +32,7 @@ sh -c "sudo sed -i '' 's/#storageEngineList=127.0.0.1#6667#iotdb12/storageEngine for port in "$@" do + # target path is also used in update/ script sh -c "sudo cp -r apache-iotdb-0.12.6-server-bin/ apache-iotdb-0.12.6-server-bin-$port" sh -c "sudo sed -i '' 's/# wal_buffer_size=16777216/wal_buffer_size=167772160/' apache-iotdb-0.12.6-server-bin-$port/conf/iotdb-engine.properties" diff --git a/.github/scripts/dataSources/iotdb12_windows.sh b/.github/scripts/dataSources/startup/iotdb12_windows.sh similarity index 97% rename from .github/scripts/dataSources/iotdb12_windows.sh rename to .github/scripts/dataSources/startup/iotdb12_windows.sh index 82bddb7ffd..c6f35b16f9 100644 --- a/.github/scripts/dataSources/iotdb12_windows.sh +++ b/.github/scripts/dataSources/startup/iotdb12_windows.sh @@ -34,6 +34,7 @@ sh -c "sed -i 's/#storageEngineList=127.0.0.1#6667#iotdb12/storageEngineList=127 for port in "$@" do + # target path is also used in update/ script sh -c "cp -r apache-iotdb-0.12.6-server-bin/ apache-iotdb-0.12.6-server-bin-$port" sh -c "sed -i 's/6667/$port/g' apache-iotdb-0.12.6-server-bin-$port/conf/iotdb-engine.properties" diff --git a/.github/scripts/dataSources/mix_iotdb12_influxdb.sh b/.github/scripts/dataSources/startup/mix_iotdb12_influxdb.sh similarity index 81% rename from .github/scripts/dataSources/mix_iotdb12_influxdb.sh rename to .github/scripts/dataSources/startup/mix_iotdb12_influxdb.sh index 9a608a8589..38eb4c17dd 100644 --- a/.github/scripts/dataSources/mix_iotdb12_influxdb.sh +++ b/.github/scripts/dataSources/startup/mix_iotdb12_influxdb.sh @@ -20,13 +20,13 @@ set -e -sh -c "chmod +x .github/scripts/dataSources/iotdb12.sh" +sh -c "chmod +x .github/scripts/dataSources/startup/iotdb12.sh" -sh -c "chmod +x .github/scripts/dataSources/influxdb.sh" +sh -c "chmod +x .github/scripts/dataSources/startup/influxdb.sh" -sh -c ".github/scripts/dataSources/iotdb12.sh 6667" +sh -c ".github/scripts/dataSources/startup/iotdb12.sh 6667" -sh -c ".github/scripts/dataSources/influxdb.sh" +sh -c ".github/scripts/dataSources/startup/influxdb.sh" set -i "s/storageEngineList/#storageEngineList/g" conf/config.properties diff --git a/.github/scripts/dataSources/mix_iotdb12_influxdb_macos.sh b/.github/scripts/dataSources/startup/mix_iotdb12_influxdb_macos.sh similarity index 80% rename from .github/scripts/dataSources/mix_iotdb12_influxdb_macos.sh rename to .github/scripts/dataSources/startup/mix_iotdb12_influxdb_macos.sh index 936b956be4..e06e0c46d5 100644 --- a/.github/scripts/dataSources/mix_iotdb12_influxdb_macos.sh +++ b/.github/scripts/dataSources/startup/mix_iotdb12_influxdb_macos.sh @@ -20,13 +20,13 @@ set -e -sh -c "chmod +x .github/scripts/dataSources/iotdb12_macos.sh" +sh -c "chmod +x .github/scripts/dataSources/startup/iotdb12_macos.sh" -sh -c "chmod +x .github/scripts/dataSources/influxdb_macos.sh" +sh -c "chmod +x .github/scripts/dataSources/startup/influxdb_macos.sh" -sh -c ".github/scripts/dataSources/iotdb12_macos.sh 6667" +sh -c ".github/scripts/dataSources/startup/iotdb12_macos.sh 6667" -sh -c ".github/scripts/dataSources/influxdb_macos.sh" +sh -c ".github/scripts/dataSources/startup/influxdb_macos.sh" set -i "s/storageEngineList/#storageEngineList/g" conf/config.properties diff --git a/.github/scripts/dataSources/mix_iotdb12_influxdb_windows.sh b/.github/scripts/dataSources/startup/mix_iotdb12_influxdb_windows.sh similarity index 79% rename from .github/scripts/dataSources/mix_iotdb12_influxdb_windows.sh rename to .github/scripts/dataSources/startup/mix_iotdb12_influxdb_windows.sh index 857e3907bd..f1fd1c6e6c 100644 --- a/.github/scripts/dataSources/mix_iotdb12_influxdb_windows.sh +++ b/.github/scripts/dataSources/startup/mix_iotdb12_influxdb_windows.sh @@ -20,13 +20,13 @@ set -e -sh -c "chmod +x .github/scripts/dataSources/iotdb12_windows.sh" +sh -c "chmod +x .github/scripts/dataSources/startup/iotdb12_windows.sh" -sh -c "chmod +x .github/scripts/dataSources/influxdb_windows.sh" +sh -c "chmod +x .github/scripts/dataSources/startup/influxdb_windows.sh" -sh -c ".github/scripts/dataSources/iotdb12_windows.sh 6667" +sh -c ".github/scripts/dataSources/startup/iotdb12_windows.sh 6667" -sh -c ".github/scripts/dataSources/influxdb_windows.sh" +sh -c ".github/scripts/dataSources/startup/influxdb_windows.sh" sed -i "s/storageEngineList/#storageEngineList/g" conf/config.properties diff --git a/.github/scripts/dataSources/parquet_linux_windows.sh b/.github/scripts/dataSources/startup/parquet_linux_windows.sh similarity index 100% rename from .github/scripts/dataSources/parquet_linux_windows.sh rename to .github/scripts/dataSources/startup/parquet_linux_windows.sh diff --git a/.github/scripts/dataSources/parquet_macos.sh b/.github/scripts/dataSources/startup/parquet_macos.sh similarity index 100% rename from .github/scripts/dataSources/parquet_macos.sh rename to .github/scripts/dataSources/startup/parquet_macos.sh diff --git a/.github/scripts/dataSources/update/influxdb.sh b/.github/scripts/dataSources/update/influxdb.sh new file mode 100644 index 0000000000..df5737b298 --- /dev/null +++ b/.github/scripts/dataSources/update/influxdb.sh @@ -0,0 +1,37 @@ +#!/bin/sh +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +# usage:.sh + +set -e + +cd influxdb2-2.0.7-linux-amd64/ + +# 所有org的信息 +output=$(influx org list) + +echo $output + +# 只有一个组织,所以直接匹配 +id=$(echo "$output" | grep -Eo '^[a-z0-9]{16}') + +# 验证 +echo "Extracted ID: $id" + +sh -c "./influx org update --host http://localhost:$1 -t testToken -i $id -n $2" diff --git a/.github/scripts/dataSources/update/influxdb_macos.sh b/.github/scripts/dataSources/update/influxdb_macos.sh new file mode 100644 index 0000000000..8daa987745 --- /dev/null +++ b/.github/scripts/dataSources/update/influxdb_macos.sh @@ -0,0 +1,37 @@ +#!/bin/sh +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +# usage:.sh + +set -e + +cd influxdb2-2.0.7-darwin-amd64/ + +# 所有org的信息 +output=$(influx org list) + +echo $output + +# 只有一个组织,所以直接匹配 +id=$(echo "$output" | grep -Eo '^[a-z0-9]{16}') + +# 验证 +echo "Extracted ID: $id" + +sh -c "./influx org update --host http://localhost:$1 -t testToken -i $id -n $2" diff --git a/.github/scripts/dataSources/update/influxdb_windows.sh b/.github/scripts/dataSources/update/influxdb_windows.sh new file mode 100644 index 0000000000..160a36c4f2 --- /dev/null +++ b/.github/scripts/dataSources/update/influxdb_windows.sh @@ -0,0 +1,38 @@ +#!/bin/sh +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + + +# usage:.sh + +set -e + +cd influxdb2-2.0.7-windows-amd64/ + +# 所有org的信息 +output=$(influx org list) + +echo $output + +# 只有一个组织,所以直接匹配 +id=$(echo "$output" | grep -Eo '^[a-z0-9]{16}') + +# 验证 +echo "Extracted ID: $id" + +sh -c "./influx org --host http://localhost:$1 -t testToken update -i $id -n $2" diff --git a/.github/scripts/dataSources/update/iotdb.sh b/.github/scripts/dataSources/update/iotdb.sh new file mode 100644 index 0000000000..d4ccd6d608 --- /dev/null +++ b/.github/scripts/dataSources/update/iotdb.sh @@ -0,0 +1,26 @@ +#!/bin/sh +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + + +# usage:.sh + +set -e + +cd apache-iotdb-0.12.6-server-bin-$1/ +sh -c "sbin/start-cli.sh -h 127.0.0.1 -p $1 -u root -pw $2 -e 'ALTER USER root SET PASSWORD \"$3\";'" \ No newline at end of file diff --git a/.github/scripts/dataSources/update/iotdb_macos.sh b/.github/scripts/dataSources/update/iotdb_macos.sh new file mode 100644 index 0000000000..d4ccd6d608 --- /dev/null +++ b/.github/scripts/dataSources/update/iotdb_macos.sh @@ -0,0 +1,26 @@ +#!/bin/sh +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + + +# usage:.sh + +set -e + +cd apache-iotdb-0.12.6-server-bin-$1/ +sh -c "sbin/start-cli.sh -h 127.0.0.1 -p $1 -u root -pw $2 -e 'ALTER USER root SET PASSWORD \"$3\";'" \ No newline at end of file diff --git a/.github/scripts/dataSources/update/iotdb_windows.sh b/.github/scripts/dataSources/update/iotdb_windows.sh new file mode 100644 index 0000000000..a60e18c78a --- /dev/null +++ b/.github/scripts/dataSources/update/iotdb_windows.sh @@ -0,0 +1,26 @@ +#!/bin/sh +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + + +# usage:.sh + +set -e + +cd apache-iotdb-0.12.6-server-bin-$1/ +sh -c "sbin/start-cli.bat -h 127.0.0.1 -p $1 -u root -pw $2 -e 'ALTER USER root SET PASSWORD \"$3\";'" \ No newline at end of file diff --git a/.github/scripts/dataSources/update/mysql.sh b/.github/scripts/dataSources/update/mysql.sh new file mode 100644 index 0000000000..e5fb32035a --- /dev/null +++ b/.github/scripts/dataSources/update/mysql.sh @@ -0,0 +1,31 @@ +#!/bin/sh +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + + +# usage:.sh :set/unset + +set -e + +if [ $2 = "set" ]; then + # set password when there was none + mysql -h 127.0.0.1 --port=$1 -u root -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '$3'; flush privileges;" +else + # remove password + mysql -h 127.0.0.1 --port=$1 -u root -p$3 -e "ALTER USER 'root'@'localhost' IDENTIFIED BY ''; flush privileges;" +fi diff --git a/.github/scripts/dataSources/update/mysql_macos.sh b/.github/scripts/dataSources/update/mysql_macos.sh new file mode 100644 index 0000000000..e5fb32035a --- /dev/null +++ b/.github/scripts/dataSources/update/mysql_macos.sh @@ -0,0 +1,31 @@ +#!/bin/sh +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + + +# usage:.sh :set/unset + +set -e + +if [ $2 = "set" ]; then + # set password when there was none + mysql -h 127.0.0.1 --port=$1 -u root -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '$3'; flush privileges;" +else + # remove password + mysql -h 127.0.0.1 --port=$1 -u root -p$3 -e "ALTER USER 'root'@'localhost' IDENTIFIED BY ''; flush privileges;" +fi diff --git a/.github/scripts/dataSources/update/mysql_windows.sh b/.github/scripts/dataSources/update/mysql_windows.sh new file mode 100644 index 0000000000..e5fb32035a --- /dev/null +++ b/.github/scripts/dataSources/update/mysql_windows.sh @@ -0,0 +1,31 @@ +#!/bin/sh +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + + +# usage:.sh :set/unset + +set -e + +if [ $2 = "set" ]; then + # set password when there was none + mysql -h 127.0.0.1 --port=$1 -u root -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '$3'; flush privileges;" +else + # remove password + mysql -h 127.0.0.1 --port=$1 -u root -p$3 -e "ALTER USER 'root'@'localhost' IDENTIFIED BY ''; flush privileges;" +fi diff --git a/.github/scripts/dataSources/update/postgresql.sh b/.github/scripts/dataSources/update/postgresql.sh new file mode 100644 index 0000000000..d32940c16c --- /dev/null +++ b/.github/scripts/dataSources/update/postgresql.sh @@ -0,0 +1,27 @@ +#!/bin/sh +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + + +# usage:.sh + +set -e + +export PGPASSWORD=$2 + +psql -h 127.0.0.1 -U postgres -p $1 -c"ALTER USER postgres WITH PASSWORD '$3';" \ No newline at end of file diff --git a/.github/scripts/dataSources/update/postgresql_macos.sh b/.github/scripts/dataSources/update/postgresql_macos.sh new file mode 100644 index 0000000000..d32940c16c --- /dev/null +++ b/.github/scripts/dataSources/update/postgresql_macos.sh @@ -0,0 +1,27 @@ +#!/bin/sh +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + + +# usage:.sh + +set -e + +export PGPASSWORD=$2 + +psql -h 127.0.0.1 -U postgres -p $1 -c"ALTER USER postgres WITH PASSWORD '$3';" \ No newline at end of file diff --git a/.github/scripts/dataSources/update/postgresql_windows.sh b/.github/scripts/dataSources/update/postgresql_windows.sh new file mode 100644 index 0000000000..9525bcc34d --- /dev/null +++ b/.github/scripts/dataSources/update/postgresql_windows.sh @@ -0,0 +1,27 @@ +#!/bin/sh +# +# IGinX - the polystore system with high performance +# Copyright (C) Tsinghua University +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + + +# usage:.sh + +set -e + +export PGPASSWORD=$2 + +psql -h 127.0.0.1 -Upostgres -p$1 -c"ALTER USER postgres WITH PASSWORD '$3';" \ No newline at end of file diff --git a/antlr/src/main/antlr4/cn/edu/tsinghua/iginx/sql/Sql.g4 b/antlr/src/main/antlr4/cn/edu/tsinghua/iginx/sql/Sql.g4 index 59fde95dc1..23b146c76f 100644 --- a/antlr/src/main/antlr4/cn/edu/tsinghua/iginx/sql/Sql.g4 +++ b/antlr/src/main/antlr4/cn/edu/tsinghua/iginx/sql/Sql.g4 @@ -32,6 +32,7 @@ statement | SHOW COLUMNS showColumnsOptions # showColumnsStatement | SHOW REPLICA NUMBER # showReplicationStatement | ADD STORAGEENGINE storageEngineSpec # addStorageEngineStatement + | ALTER STORAGEENGINE engineId = INT WITH PARAMS params = stringLiteral # alterEngineStatement | SHOW CLUSTER INFO # showClusterInfoStatement | SHOW FUNCTIONS # showRegisterTaskStatement | CREATE FUNCTION udfType udfClassRef (COMMA (udfType)? udfClassRef)* IN filePath = stringLiteral # registerTaskStatement @@ -452,6 +453,8 @@ keyWords | AS | udfType | jobStatus + | ALTER + | PARAMS | WITH | WITHOUT | TAG @@ -543,6 +546,14 @@ removedStorageEngine //============================ +ALTER + : A L T E R + ; + +PARAMS + : P A R A M S + ; + INSERT : I N S E R T ; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/IginxWorker.java b/core/src/main/java/cn/edu/tsinghua/iginx/IginxWorker.java index d6a5d8ded6..017b3df355 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/IginxWorker.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/IginxWorker.java @@ -107,7 +107,7 @@ private boolean addLocalStorageEngineMetas() { metaFromConf.setExtraParams(extraParams); boolean hasAdded = false; for (StorageEngineMeta meta : metaManager.getStorageEngineList()) { - if (isDuplicated(metaFromConf, meta)) { + if (metaFromConf.equals(meta)) { hasAdded = true; break; } @@ -325,13 +325,15 @@ public Status addStorageEngines(AddStorageEnginesReq req) { int port = storageEngine.getPort(); StorageEngineType type = storageEngine.getType(); Map extraParams = storageEngine.getExtraParams(); - boolean hasData = Boolean.parseBoolean(extraParams.getOrDefault(Constants.HAS_DATA, "false")); + // 仅add时,默认为true + boolean hasData = Boolean.parseBoolean(extraParams.getOrDefault(Constants.HAS_DATA, "true")); String dataPrefix = null; if (hasData && extraParams.containsKey(Constants.DATA_PREFIX)) { dataPrefix = extraParams.get(Constants.DATA_PREFIX); } + // 仅add时,默认为true boolean readOnly = - Boolean.parseBoolean(extraParams.getOrDefault(Constants.IS_READ_ONLY, "false")); + Boolean.parseBoolean(extraParams.getOrDefault(Constants.IS_READ_ONLY, "true")); if (!isValidHost(ip)) { // IP 不合法 LOGGER.error("ip {} is invalid.", ip); @@ -400,7 +402,7 @@ private void addStorageEngineMetas( List duplicatedStorageEngines = new ArrayList<>(); for (StorageEngineMeta storageEngine : storageEngineMetas) { for (StorageEngineMeta currentStorageEngine : currentStorageEngines) { - if (isDuplicated(storageEngine, currentStorageEngine)) { + if (storageEngine.equals(currentStorageEngine)) { duplicatedStorageEngines.add(storageEngine); LOGGER.error("repeatedly add storage engine {}.", storageEngine); status.addToSubStatus(RpcUtils.FAILURE); @@ -514,23 +516,52 @@ private void addStorageEngineMetas( } } - private boolean isDuplicated(StorageEngineMeta engine1, StorageEngineMeta engine2) { - if (!engine1.getStorageEngine().equals(engine2.getStorageEngine())) { - return false; - } - if (engine1.getPort() != engine2.getPort()) { - return false; + /** This function is only for read-only dummy, temporarily */ + @Override + public Status alterStorageEngine(AlterStorageEngineReq req) { + if (!sessionManager.checkSession(req.getSessionId(), AuthType.Cluster)) { + return RpcUtils.ACCESS_DENY; } - if (!Objects.equals(engine1.getDataPrefix(), engine2.getDataPrefix())) { - return false; + Status status = new Status(RpcUtils.SUCCESS.code); + long targetId = req.getEngineId(); + Map newParams = req.getNewParams(); + StorageEngineMeta targetMeta = metaManager.getStorageEngine(targetId); + if (targetMeta == null) { + status.setCode(RpcUtils.FAILURE.code); + status.setMessage("No engine found with id:" + targetId); + return status; } - if (!Objects.equals(engine1.getSchemaPrefix(), engine2.getSchemaPrefix())) { - return false; + if (!targetMeta.isHasData() || !targetMeta.isReadOnly()) { + status.setCode(RpcUtils.FAILURE.code); + status.setMessage( + "Only read-only & dummy engines' params can be altered. Engine with id(" + + targetId + + ") cannot be altered."); + return status; + } + + // update meta info + if (newParams.remove(Constants.IP) != null + || newParams.remove(Constants.PORT) != null + || newParams.remove(Constants.DATA_PREFIX) != null + || newParams.remove(Constants.SCHEMA_PREFIX) != null) { + status.setCode(RpcUtils.FAILURE.code); + status.setMessage( + "IP, port, type, data_prefix, schema_prefix cannot be altered. Removing and adding new engine is recommended."); + return status; } - if (isLocalHost(engine1.getIp()) && isLocalHost(engine2.getIp())) { // 都是本机IP - return true; + targetMeta.updateExtraParams(newParams); + + // remove, then add + if (!metaManager.removeDummyStorageEngine(targetId)) { + LOGGER.error("unexpected error during removing dummy storage engine {}.", targetMeta); + status.setCode(RpcUtils.FAILURE.code); + status.setMessage("unexpected error occurred. Please check server log."); + return status; } - return engine1.getIp().equals(engine2.getIp()); + + addStorageEngineMetas(Collections.singletonList(targetMeta), status, true); + return status; } @Override diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/conf/Constants.java b/core/src/main/java/cn/edu/tsinghua/iginx/conf/Constants.java index 2a9dd9e1ef..82d1c61da1 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/conf/Constants.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/conf/Constants.java @@ -45,8 +45,15 @@ public class Constants { public static final String LEVEL_PLACEHOLDER = "*"; + // engine params in sql + public static final String IP = "ip"; + public static final String PORT = "port"; + public static final String HAS_DATA = "has_data"; + // dummy dir path for embedded storage engines + public static final String DUMMY_DIR = "dummy_dir"; + public static final String IS_READ_ONLY = "is_read_only"; public static final String DATA_PREFIX = "data_prefix"; diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/StatementBuilder.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/StatementBuilder.java index a1e9189bdf..f76d16097a 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/StatementBuilder.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/StatementBuilder.java @@ -45,6 +45,7 @@ public class StatementBuilder { typeMap.put(StatementType.EXPORT_CSV_FROM_SELECT, SqlType.ExportCsv); typeMap.put(StatementType.EXPORT_STREAM_FROM_SELECT, SqlType.ExportStream); typeMap.put(StatementType.ADD_STORAGE_ENGINE, SqlType.AddStorageEngines); + typeMap.put(StatementType.ALTER_STORAGE_ENGINE, SqlType.AlterStorageEngine); typeMap.put(StatementType.REMOVE_HISTORY_DATA_SOURCE, SqlType.RemoveHistoryDataSource); typeMap.put(StatementType.SHOW_REPLICATION, SqlType.GetReplicaNum); typeMap.put(StatementType.COUNT_POINTS, SqlType.CountPoints); diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/StorageManager.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/StorageManager.java index 4823983360..3f88625a89 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/StorageManager.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/StorageManager.java @@ -18,6 +18,7 @@ package cn.edu.tsinghua.iginx.engine.physical.storage; import cn.edu.tsinghua.iginx.conf.ConfigDescriptor; +import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; import cn.edu.tsinghua.iginx.metadata.entity.ColumnsInterval; import cn.edu.tsinghua.iginx.metadata.entity.KeyInterval; import cn.edu.tsinghua.iginx.metadata.entity.StorageEngineMeta; @@ -212,4 +213,32 @@ public static IStorage initStorageInstance(StorageEngineMeta meta) { return null; } } + + public boolean releaseStorage(StorageEngineMeta meta) throws PhysicalException { + long id = meta.getId(); + Pair pair = storageMap.get(id); + if (pair == null) { + LOGGER.warn("Storage id {} not found", id); + return false; + } + + ThreadPoolExecutor dispatcher = pair.getV(); + dispatcher.shutdown(); // 停止接收新任务 + try { + if (!dispatcher.awaitTermination(60, TimeUnit.SECONDS)) { // 等待任务完成 + dispatcher.shutdownNow(); // 如果时间内未完成任务,强制关闭 + if (!dispatcher.awaitTermination(60, TimeUnit.SECONDS)) { + LOGGER.error("Executor did not terminate"); + } + } + } catch (InterruptedException ie) { + dispatcher.shutdownNow(); + LOGGER.error("unexpected exception occurred in releasing storage engine: ", ie); + return false; + } + + pair.getK().release(); + storageMap.remove(id); + return true; + } } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java index 599cc05033..514983ac08 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java @@ -298,6 +298,18 @@ private StoragePhysicalTaskExecutor() { if (after.getCreatedBy() != metaManager.getIginxId()) { storageManager.addStorage(after); } + } else if (before != null && after == null) { // 删除引擎时,需要release(目前仅支持dummy & read only) + try { + if (!storageManager.releaseStorage(before)) { + LOGGER.error( + "Fail to release deleted storage engine. Please look into server log."); + } + LOGGER.info("Release storage with id={} succeeded.", before.getId()); + } catch (PhysicalException e) { + LOGGER.error( + "unexpected exception during in releasing storage engine, please contact developer to check: ", + e); + } } }; metaManager.registerStorageEngineChangeHook(storageEngineChangeHook); diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/DefaultMetaManager.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/DefaultMetaManager.java index baf2a41d5b..59e95b1234 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/DefaultMetaManager.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/DefaultMetaManager.java @@ -438,8 +438,11 @@ private void addStorageEngine(long storageEngineId, StorageEngineMeta storageEng public boolean removeDummyStorageEngine(long storageEngineId) { try { storage.removeDummyStorageEngine(storageEngineId); + // release 对接层 + for (StorageEngineChangeHook hook : storageEngineChangeHooks) { + hook.onChange(getStorageEngine(storageEngineId), null); + } return cache.removeDummyStorageEngine(storageEngineId); - // TODO 由于当前 StorageEngineChangeHook 和 StorageUnitHook 只会处理新增事件,因此不必调用相关 onChange 函数 } catch (MetaStorageException e) { LOGGER.error("remove dummy storage engine {} error: ", storageEngineId, e); } diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/StorageEngineMeta.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/StorageEngineMeta.java index 2be914f2d3..991329ba1c 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/StorageEngineMeta.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/entity/StorageEngineMeta.java @@ -17,10 +17,14 @@ */ package cn.edu.tsinghua.iginx.metadata.entity; +import static cn.edu.tsinghua.iginx.utils.HostUtils.isLocalHost; + import cn.edu.tsinghua.iginx.thrift.StorageEngineType; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Objects; +import javax.validation.constraints.NotNull; public final class StorageEngineMeta { @@ -212,6 +216,10 @@ public void setExtraParams(Map extraParams) { this.extraParams = extraParams; } + public void updateExtraParams(Map newParams) { + this.extraParams.putAll(newParams); + } + public StorageEngineType getStorageEngine() { return storageEngine; } @@ -277,6 +285,29 @@ public void setNeedReAllocate(boolean needReAllocate) { this.needReAllocate = needReAllocate; } + public static String extractEmbeddedPrefix(@NotNull String dummyDirPath) { + if (dummyDirPath.isEmpty()) { + return null; + } + String separator = System.getProperty("file.separator"); + // dummyDirPath是规范路径,一定不会以separator结尾 + String prefix = dummyDirPath.substring(dummyDirPath.lastIndexOf(separator) + 1); + // "/" also can be used on windows, just in case + return prefix.substring(prefix.lastIndexOf("/") + 1); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + StorageEngineMeta that = (StorageEngineMeta) o; + return (ip.equals(that.ip) || (isLocalHost(ip) && isLocalHost(that.ip))) + && port == that.port + && storageEngine == that.storageEngine + && Objects.equals(schemaPrefix, that.getSchemaPrefix()) + && Objects.equals(dataPrefix, that.getDataPrefix()); + } + @Override public String toString() { return "StorageEngineMeta {" diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/storage/etcd/ETCDMetaStorage.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/storage/etcd/ETCDMetaStorage.java index 30e582acad..c60eb0457a 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/storage/etcd/ETCDMetaStorage.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/storage/etcd/ETCDMetaStorage.java @@ -121,7 +121,7 @@ public class ETCDMetaStorage implements IMetaStorage { private final int STORAGE_ENGINE_NODE_LENGTH = 10; private String generateID(String prefix, long idLength, long val) { - return String.format(prefix + "%0" + idLength + "d", (int) val); + return String.format(prefix + "%0" + idLength + "d", val); } public ETCDMetaStorage() { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/utils/StorageEngineUtils.java b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/utils/StorageEngineUtils.java index b2e35b8abc..090a350d68 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/metadata/utils/StorageEngineUtils.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/metadata/utils/StorageEngineUtils.java @@ -60,7 +60,7 @@ public static boolean checkEmbeddedStorageExtraParams( if (iginxPort == null || iginxPort.isEmpty()) { return false; } - boolean hasData = Boolean.parseBoolean(extraParams.getOrDefault(HAS_DATA, "false")); + boolean hasData = Boolean.parseBoolean(extraParams.getOrDefault(Constants.HAS_DATA, "false")); boolean readOnly = Boolean.parseBoolean(extraParams.getOrDefault(Constants.IS_READ_ONLY, "false")); if (hasData) { @@ -81,10 +81,7 @@ public static boolean checkEmbeddedStorageExtraParams( return false; } } - String separator = System.getProperty("file.separator"); - // dummyDirPath是规范路径,一定不会以separator结尾 - String dirPrefix = dummyDirPath.substring(dummyDirPath.lastIndexOf(separator) + 1); - extraParams.put(EMBEDDED_PREFIX, dirPrefix); + extraParams.put(EMBEDDED_PREFIX, StorageEngineMeta.extractEmbeddedPrefix(dummyDirPath)); } else { // hasData=false readOnly=true 无意义的引擎 if (readOnly) { diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/IginXSqlVisitor.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/IginXSqlVisitor.java index 30f916b73a..80fb8b8d4b 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/IginXSqlVisitor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/IginXSqlVisitor.java @@ -547,6 +547,13 @@ public Statement visitAddStorageEngineStatement(AddStorageEngineStatementContext return addStorageEngineStatement; } + @Override + public Statement visitAlterEngineStatement(SqlParser.AlterEngineStatementContext ctx) { + long engineId = Long.parseLong(ctx.engineId.getText()); + Map newParams = parseExtra(ctx.params); + return new AlterEngineStatement(engineId, newParams); + } + @Override public Statement visitShowColumnsStatement(ShowColumnsStatementContext ctx) { return parseShowColumnsOptions(ctx.showColumnsOptions()); diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/AlterEngineStatement.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/AlterEngineStatement.java new file mode 100644 index 0000000000..a8af8b1270 --- /dev/null +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/AlterEngineStatement.java @@ -0,0 +1,50 @@ +/* + * IGinX - the polystore system with high performance + * Copyright (C) Tsinghua University + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package cn.edu.tsinghua.iginx.sql.statement; + +import cn.edu.tsinghua.iginx.IginxWorker; +import cn.edu.tsinghua.iginx.engine.shared.RequestContext; +import cn.edu.tsinghua.iginx.engine.shared.Result; +import cn.edu.tsinghua.iginx.engine.shared.exception.StatementExecutionException; +import cn.edu.tsinghua.iginx.thrift.AlterStorageEngineReq; +import cn.edu.tsinghua.iginx.thrift.Status; +import java.util.Map; + +public class AlterEngineStatement extends SystemStatement { + + private final long engineId; + + private final IginxWorker worker = IginxWorker.getInstance(); + + private final Map newParams; + + public AlterEngineStatement(long engineId, Map newParams) { + this.statementType = StatementType.ALTER_STORAGE_ENGINE; + this.engineId = engineId; + this.newParams = newParams; + } + + @Override + public void execute(RequestContext ctx) throws StatementExecutionException { + AlterStorageEngineReq req = new AlterStorageEngineReq(ctx.getSessionId(), engineId, newParams); + Status status = worker.alterStorageEngine(req); + + Result result = new Result(status); + ctx.setResult(result); + } +} diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/StatementType.java b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/StatementType.java index 7130308932..236820ea2a 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/StatementType.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/sql/statement/StatementType.java @@ -28,6 +28,7 @@ public enum StatementType { EXPORT_CSV_FROM_SELECT, EXPORT_STREAM_FROM_SELECT, ADD_STORAGE_ENGINE, + ALTER_STORAGE_ENGINE, SHOW_REPLICATION, COUNT_POINTS, CLEAR_DATA, diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java index 2d280f2384..30ce5d5896 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/BaseCapacityExpansionIT.java @@ -21,8 +21,7 @@ import static cn.edu.tsinghua.iginx.integration.controller.Controller.SUPPORT_KEY; import static cn.edu.tsinghua.iginx.integration.expansion.constant.Constant.*; import static cn.edu.tsinghua.iginx.integration.expansion.utils.SQLTestTools.executeShellScript; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; +import static org.junit.Assert.*; import cn.edu.tsinghua.iginx.exception.SessionException; import cn.edu.tsinghua.iginx.integration.controller.Controller; @@ -35,11 +34,10 @@ import cn.edu.tsinghua.iginx.session.QueryDataSet; import cn.edu.tsinghua.iginx.session.Session; import cn.edu.tsinghua.iginx.thrift.RemovedStorageEngineInfo; +import cn.edu.tsinghua.iginx.thrift.StorageEngineInfo; import cn.edu.tsinghua.iginx.thrift.StorageEngineType; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; +import java.util.*; +import java.util.stream.Collectors; import org.junit.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -51,6 +49,8 @@ public abstract class BaseCapacityExpansionIT { protected static Session session; + protected static final String ALTER_ENGINE_STRING = "alter storageengine %d with params \"%s\";"; + private static final ConfLoader testConf = new ConfLoader(Controller.CONFIG_FILE); protected StorageEngineType type; @@ -59,6 +59,8 @@ public abstract class BaseCapacityExpansionIT { protected List wrongExtraParams = new ArrayList<>(); + protected Map updatedParams = new HashMap<>(); + private final boolean IS_PARQUET_OR_FILE_SYSTEM = this instanceof FileSystemCapacityExpansionIT || this instanceof ParquetCapacityExpansionIT; @@ -68,6 +70,8 @@ public abstract class BaseCapacityExpansionIT { public static final String DBCE_PARQUET_FS_TEST_DIR = "test"; + protected static final String updateParamsScriptDir = ".github/scripts/dataSources/update/"; + protected static BaseHistoryDataGenerator generator; public BaseCapacityExpansionIT( @@ -244,11 +248,13 @@ public void oriNoDataExpNoData() throws InterruptedException { } @Test - public void testReadOnly() throws InterruptedException { + public void testReadOnly() throws InterruptedException, SessionException { // 查询原始只读节点的历史数据,结果不为空 testQueryHistoryDataOriHasData(); + // 测试只读节点的参数修改 + testUpdateEngineParams(); // 测试参数错误的只读节点扩容 - testInvalidDummyParams(readOnlyPort, true, false, null, EXP_SCHEMA_PREFIX); + testInvalidDummyParams(readOnlyPort, true, true, null, READ_ONLY_SCHEMA_PREFIX); // 扩容只读节点 addStorageEngineInProgress(readOnlyPort, true, true, null, READ_ONLY_SCHEMA_PREFIX); // 查询扩容只读节点的历史数据,结果不为空 @@ -320,6 +326,69 @@ protected void testInvalidDummyParams( } } + /** 测试引擎修改参数(目前仅支持dummy & read-only) */ + protected void testUpdateEngineParams() throws SessionException { + // 修改前后通过相同schema_prefix查询判断引擎成功更新 + LOGGER.info("Testing updating engine params..."); + if (updatedParams.isEmpty()) { + LOGGER.info("Engine {} skipped this test.", type); + return; + } + + String prefix = "prefix"; + // 添加只读节点 + addStorageEngine(readOnlyPort, true, true, null, prefix, extraParams); + // 查询 + String statement = "select wt01.status, wt01.temperature from " + prefix + ".tm.wf05;"; + List pathList = + READ_ONLY_PATH_LIST.stream().map(s -> prefix + "." + s).collect(Collectors.toList()); + List> valuesList = READ_ONLY_VALUES_LIST; + SQLTestTools.executeAndCompare(session, statement, pathList, valuesList); + + // 修改数据库参数 + updateParams(readOnlyPort); + + // 修改 + List engineInfoList = session.getClusterInfo().getStorageEngineInfos(); + long id = -1; + for (StorageEngineInfo info : engineInfoList) { + if (info.getIp().equals("127.0.0.1") + && info.getPort() == readOnlyPort + && info.getDataPrefix().equals("null") + && info.getSchemaPrefix().equals(prefix) + && info.getType().equals(type)) { + id = info.getId(); + } + } + assertTrue(id != -1); + + String newParams = + updatedParams.entrySet().stream() + .map(entry -> entry.getKey() + ":" + entry.getValue()) + .collect(Collectors.joining(", ")); + session.executeSql(String.format(ALTER_ENGINE_STRING, id, newParams)); + + // 重新查询 + statement = "select wt01.status, wt01.temperature from " + prefix + ".tm.wf05;"; + pathList = READ_ONLY_PATH_LIST.stream().map(s -> prefix + "." + s).collect(Collectors.toList()); + valuesList = READ_ONLY_VALUES_LIST; + SQLTestTools.executeAndCompare(session, statement, pathList, valuesList); + + // 删除,不影响后续测试 + session.removeHistoryDataSource( + Collections.singletonList( + new RemovedStorageEngineInfo("127.0.0.1", readOnlyPort, prefix, ""))); + + // 改回数据库参数 + restoreParams(readOnlyPort); + } + + /** 这个方法需要实现:通过脚本修改port对应数据源的可变参数,如密码等 */ + protected abstract void updateParams(int port); + + /** 这个方法需要实现:通过脚本恢复updateParams中修改的可变参数 */ + protected abstract void restoreParams(int port); + protected void queryExtendedKeyDummy() { // ori // extended key queryable @@ -731,15 +800,15 @@ protected void startStorageEngineWithIginx(int port, boolean hasData, boolean is if (this instanceof FileSystemCapacityExpansionIT) { if (isOnMac) { - scriptPath = ".github/scripts/dataSources/filesystem_macos.sh"; + scriptPath = ".github/scripts/dataSources/startup/filesystem_macos.sh"; } else { - scriptPath = ".github/scripts/dataSources/filesystem_linux_windows.sh"; + scriptPath = ".github/scripts/dataSources/startup/filesystem_linux_windows.sh"; } } else if (this instanceof ParquetCapacityExpansionIT) { if (isOnMac) { - scriptPath = ".github/scripts/dataSources/parquet_macos.sh"; + scriptPath = ".github/scripts/dataSources/startup/parquet_macos.sh"; } else { - scriptPath = ".github/scripts/dataSources/parquet_linux_windows.sh"; + scriptPath = ".github/scripts/dataSources/startup/parquet_linux_windows.sh"; } } else { throw new IllegalStateException("Only support file system and parquet"); diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java index 449a1d2a52..461ed202e1 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/filesystem/FileSystemCapacityExpansionIT.java @@ -112,4 +112,11 @@ public void testShowColumns() { + "Total line number = 3\n"; SQLTestTools.executeAndCompare(session, statement, expected); } + + // no param is allowed to be updated + @Override + protected void updateParams(int port) {} + + @Override + protected void restoreParams(int port) {} } diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/influxdb/InfluxDBCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/influxdb/InfluxDBCapacityExpansionIT.java index eda0e0b9e1..3a089246c7 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/influxdb/InfluxDBCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/influxdb/InfluxDBCapacityExpansionIT.java @@ -18,7 +18,9 @@ package cn.edu.tsinghua.iginx.integration.expansion.influxdb; +import static cn.edu.tsinghua.iginx.integration.expansion.utils.SQLTestTools.executeShellScript; import static cn.edu.tsinghua.iginx.thrift.StorageEngineType.influxdb; +import static org.junit.Assert.fail; import cn.edu.tsinghua.iginx.integration.controller.Controller; import cn.edu.tsinghua.iginx.integration.expansion.BaseCapacityExpansionIT; @@ -44,9 +46,35 @@ public InfluxDBCapacityExpansionIT() { Constant.readOnlyPort = dbConf.getDBCEPortMap().get(Constant.READ_ONLY_PORT_NAME); wrongExtraParams.add( "username:user, password:12345678, token:testToken, organization:wrongOrg"); + updatedParams.put("organization", "newOrg"); } // dummy key range cannot be extended yet @Override protected void queryExtendedKeyDummy() {} + + @Override + protected void updateParams(int port) { + changeParams(port, "newOrg"); + } + + @Override + protected void restoreParams(int port) { + changeParams(port, "testOrg"); + } + + private void changeParams(int port, String newOrgName) { + String scriptPath = updateParamsScriptDir + "influxdb.sh"; + String os = System.getProperty("os.name").toLowerCase(); + if (os.contains("mac")) { + scriptPath = updateParamsScriptDir + "influxdb_macos.sh"; + } else if (os.contains("win")) { + scriptPath = updateParamsScriptDir + "influxdb_windows.sh"; + } + // 脚本参数:对应端口,新参数 + int res = executeShellScript(scriptPath, String.valueOf(port), newOrgName); + if (res != 0) { + fail("Fail to update influxdb params."); + } + } } diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/iotdb/IoTDB12CapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/iotdb/IoTDB12CapacityExpansionIT.java index aad4f8d6d9..1242fbcbb0 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/iotdb/IoTDB12CapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/iotdb/IoTDB12CapacityExpansionIT.java @@ -18,7 +18,9 @@ package cn.edu.tsinghua.iginx.integration.expansion.iotdb; +import static cn.edu.tsinghua.iginx.integration.expansion.utils.SQLTestTools.executeShellScript; import static cn.edu.tsinghua.iginx.thrift.StorageEngineType.iotdb12; +import static org.junit.Assert.fail; import cn.edu.tsinghua.iginx.integration.expansion.BaseCapacityExpansionIT; import org.slf4j.Logger; @@ -35,5 +37,31 @@ public IoTDB12CapacityExpansionIT() { new IoTDB12HistoryDataGenerator()); wrongExtraParams.add("username:root, password:wrong, sessionPoolSize:20"); wrongExtraParams.add("username:wrong, password:root, sessionPoolSize:20"); + updatedParams.put("password", "newPassword"); + } + + @Override + protected void updateParams(int port) { + changeParams(port, "root", "newPassword"); + } + + @Override + protected void restoreParams(int port) { + changeParams(port, "newPassword", "root"); + } + + private void changeParams(int port, String oldPw, String newPw) { + String scriptPath = updateParamsScriptDir + "iotdb.sh"; + String os = System.getProperty("os.name").toLowerCase(); + if (os.contains("mac")) { + scriptPath = updateParamsScriptDir + "iotdb_macos.sh"; + } else if (os.contains("win")) { + scriptPath = updateParamsScriptDir + "iotdb_windows.sh"; + } + // 脚本参数:对应端口,旧密码,新密码 + int res = executeShellScript(scriptPath, String.valueOf(port), oldPw, newPw); + if (res != 0) { + fail("Fail to update iotdb params."); + } } } diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java index a7b840345e..5806db1b79 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mongodb/MongoDBCapacityExpansionIT.java @@ -353,4 +353,11 @@ public void testShowColumns() { + "Total line number = 3\n"; SQLTestTools.executeAndCompare(session, statement, expected); } + + // no param is allowed to be updated + @Override + protected void updateParams(int port) {} + + @Override + protected void restoreParams(int port) {} } diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mysql/MySQLCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mysql/MySQLCapacityExpansionIT.java index 4e04b6f86f..a0d8944aeb 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mysql/MySQLCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/mysql/MySQLCapacityExpansionIT.java @@ -18,6 +18,9 @@ package cn.edu.tsinghua.iginx.integration.expansion.mysql; +import static cn.edu.tsinghua.iginx.integration.expansion.utils.SQLTestTools.executeShellScript; +import static org.junit.Assert.fail; + import cn.edu.tsinghua.iginx.integration.controller.Controller; import cn.edu.tsinghua.iginx.integration.expansion.BaseCapacityExpansionIT; import cn.edu.tsinghua.iginx.integration.expansion.constant.Constant; @@ -42,5 +45,33 @@ public MySQLCapacityExpansionIT() { Constant.oriPort = dbConf.getDBCEPortMap().get(Constant.ORI_PORT_NAME); Constant.expPort = dbConf.getDBCEPortMap().get(Constant.EXP_PORT_NAME); Constant.readOnlyPort = dbConf.getDBCEPortMap().get(Constant.READ_ONLY_PORT_NAME); + updatedParams.put("password", "newPassword"); + } + + @Override + protected void updateParams(int port) { + changeParams(port, null, "newPassword"); + } + + @Override + protected void restoreParams(int port) { + changeParams(port, "newPassword", null); + } + + private void changeParams(int port, String oldPw, String newPw) { + String scriptPath = updateParamsScriptDir + "mysql.sh"; + String mode = oldPw == null ? "set" : "unset"; + String os = System.getProperty("os.name").toLowerCase(); + if (os.contains("mac")) { + scriptPath = updateParamsScriptDir + "mysql_macos.sh"; + } else if (os.contains("win")) { + scriptPath = updateParamsScriptDir + "mysql_windows.sh"; + } + // 脚本参数:对应端口,模式(是在无密码条件下设置密码,还是在有密码条件下去掉密码),需要设置的密码/需要被去掉的密码 + int res = + executeShellScript(scriptPath, String.valueOf(port), mode, oldPw == null ? newPw : oldPw); + if (res != 0) { + fail("Fail to update mysql params."); + } } } diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetCapacityExpansionIT.java index 60f3aa60ee..589628dc1e 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/parquet/ParquetCapacityExpansionIT.java @@ -38,4 +38,11 @@ protected void testInvalidDummyParams( int port, boolean hasData, boolean isReadOnly, String dataPrefix, String schemaPrefix) { LOGGER.info("parquet skips test for wrong dummy engine params."); } + + // no param is allowed to be updated + @Override + protected void updateParams(int port) {} + + @Override + protected void restoreParams(int port) {} } diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/postgresql/PostgreSQLCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/postgresql/PostgreSQLCapacityExpansionIT.java index c3e7bf6895..03d62aaeca 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/postgresql/PostgreSQLCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/postgresql/PostgreSQLCapacityExpansionIT.java @@ -18,6 +18,9 @@ package cn.edu.tsinghua.iginx.integration.expansion.postgresql; +import static cn.edu.tsinghua.iginx.integration.expansion.utils.SQLTestTools.executeShellScript; +import static org.junit.Assert.fail; + import cn.edu.tsinghua.iginx.integration.controller.Controller; import cn.edu.tsinghua.iginx.integration.expansion.BaseCapacityExpansionIT; import cn.edu.tsinghua.iginx.integration.expansion.constant.Constant; @@ -46,6 +49,8 @@ public PostgreSQLCapacityExpansionIT() { Constant.readOnlyPort = dbConf.getDBCEPortMap().get(Constant.READ_ONLY_PORT_NAME); wrongExtraParams.add("username:wrong, password:postgres"); // wrong password situation cannot be tested because trust mode is used + + updatedParams.put("password", "newPassword"); } @Override @@ -138,4 +143,29 @@ protected void testConcatFunction() { assert false; } } + + @Override + protected void updateParams(int port) { + changeParams(port, "postgres", "newPassword"); + } + + @Override + protected void restoreParams(int port) { + changeParams(port, "newPassword", "postgres"); + } + + private void changeParams(int port, String oldPw, String newPw) { + String scriptPath = updateParamsScriptDir + "postgresql.sh"; + String os = System.getProperty("os.name").toLowerCase(); + if (os.contains("mac")) { + scriptPath = updateParamsScriptDir + "postgresql_macos.sh"; + } else if (os.contains("win")) { + scriptPath = updateParamsScriptDir + "postgresql_windows.sh"; + } + // 脚本参数:对应端口,旧密码,新密码 + int res = executeShellScript(scriptPath, String.valueOf(port), oldPw, newPw); + if (res != 0) { + fail("Fail to update postgresql params."); + } + } } diff --git a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisCapacityExpansionIT.java b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisCapacityExpansionIT.java index 8a9502c46f..cf1e038de4 100644 --- a/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisCapacityExpansionIT.java +++ b/test/src/test/java/cn/edu/tsinghua/iginx/integration/expansion/redis/RedisCapacityExpansionIT.java @@ -96,4 +96,11 @@ public void testShowColumns() { + "Total line number = 2\n"; SQLTestTools.executeAndCompare(session, statement, expected); } + + // no param is allowed to be updated + @Override + protected void updateParams(int port) {} + + @Override + protected void restoreParams(int port) {} } diff --git a/thrift/src/main/proto/rpc.thrift b/thrift/src/main/proto/rpc.thrift index b0429d071b..5d64ad21c7 100644 --- a/thrift/src/main/proto/rpc.thrift +++ b/thrift/src/main/proto/rpc.thrift @@ -59,6 +59,7 @@ enum SqlType { Query, GetReplicaNum, AddStorageEngines, + AlterStorageEngine, CountPoints, ClearData, DeleteColumns, @@ -267,6 +268,12 @@ struct AddStorageEnginesReq { 2: required list storageEngines } +struct AlterStorageEngineReq { + 1: required i64 sessionId + 2: required i64 engineId + 3: required map newParams +} + struct StorageEngine { 1: required string ip 2: required i32 port @@ -730,6 +737,8 @@ service IService { Status addStorageEngines(1: AddStorageEnginesReq req); + Status alterStorageEngine(1: AlterStorageEngineReq req); + Status removeHistoryDataSource(1: RemoveHistoryDataSourceReq req); AggregateQueryResp aggregateQuery(1: AggregateQueryReq req); From de20884e75f77582b3f7d33609bb7116babf977d Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Tue, 6 Aug 2024 13:51:15 +0800 Subject: [PATCH 127/138] push down data prefix --- .../execute/StoragePhysicalTaskExecutor.java | 61 +++-------- .../edu/tsinghua/iginx/utils/StringUtils.java | 100 ++++++++++++++++++ .../tsinghua/iginx/utils/StringUtilsTest.java | 30 ++++++ 3 files changed, 143 insertions(+), 48 deletions(-) diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java index f6161041f4..4848009aa4 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java @@ -44,7 +44,6 @@ import cn.edu.tsinghua.iginx.engine.shared.operator.Select; import cn.edu.tsinghua.iginx.engine.shared.operator.SetTransform; import cn.edu.tsinghua.iginx.engine.shared.operator.ShowColumns; -import cn.edu.tsinghua.iginx.engine.shared.operator.tag.TagFilter; import cn.edu.tsinghua.iginx.engine.shared.operator.type.OperatorType; import cn.edu.tsinghua.iginx.metadata.DefaultMetaManager; import cn.edu.tsinghua.iginx.metadata.IMetaManager; @@ -62,7 +61,6 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadPoolExecutor; -import java.util.regex.Pattern; import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -370,8 +368,7 @@ public TaskExecuteResult executeGlobalTask(GlobalPhysicalTask task) { public TaskExecuteResult executeShowColumns(ShowColumns showColumns) { List storageList = metaManager.getStorageEngineList(); - TreeSet columnSetAfterFilter = - new TreeSet<>(Comparator.comparing(Column::getPhysicalPath)); + TreeSet targetColumns = new TreeSet<>(Comparator.comparing(Column::getPhysicalPath)); for (StorageEngineMeta storage : storageList) { long id = storage.getId(); Pair pair = storageManager.getStorage(id); @@ -380,52 +377,20 @@ public TaskExecuteResult executeShowColumns(ShowColumns showColumns) { } try { Set patterns = showColumns.getPathRegexSet(); - TagFilter tagFilter = showColumns.getTagFilter(); - - String schemaPrefix = storage.getSchemaPrefix(); - // 不下推dataPrefix的原因:非dummy的数据库中如果有原始数据,会在show columns时被查询到并造成误解 - String dataPrefixRegex = - storage.getDataPrefix() == null - ? null - : StringUtils.reformatPath(storage.getDataPrefix() + ".*"); - - // schemaPrefix是在IGinX中定义的,数据源的路径中没有该前缀,因此需要剪掉前缀是schemaPrefix的部分 - Set patternsCutSchemaPrefix = StringUtils.cutSchemaPrefix(schemaPrefix, patterns); - if (patternsCutSchemaPrefix.isEmpty()) { + // schemaPrefix是在IGinX中定义的,数据源的路径中没有该前缀,因此需要剪掉patterns中前缀是schemaPrefix的部分 + patterns = StringUtils.cutSchemaPrefix(storage.getSchemaPrefix(), patterns); + if (patterns.isEmpty()) { continue; } - if (patternsCutSchemaPrefix.contains("*")) { - patternsCutSchemaPrefix = Collections.emptySet(); - } - List columnList = pair.k.getColumns(patternsCutSchemaPrefix, tagFilter); - - if (tagFilter != null) { - columnSetAfterFilter.addAll(columnList); + // 求patterns与dataPrefix的交集 + patterns = StringUtils.intersectDataPrefix(storage.getDataPrefix(), patterns); + if (patterns.isEmpty()) { continue; } - for (Column column : columnList) { - if (!column.isDummy()) { - columnSetAfterFilter.add(column); - continue; - } - if (dataPrefixRegex == null || Pattern.matches(dataPrefixRegex, column.getPath())) { - if (schemaPrefix == null) { - columnSetAfterFilter.add(column); - continue; - } - column.setPath(schemaPrefix + "." + column.getPath()); - boolean isMatch = patterns.isEmpty(); - for (String pathRegex : patterns) { - if (Pattern.matches(StringUtils.reformatPath(pathRegex), column.getPath())) { - isMatch = true; - break; - } - } - if (isMatch) { - columnSetAfterFilter.add(column); - } - } + if (patterns.contains("*")) { + patterns = Collections.emptySet(); } + targetColumns.addAll(pair.k.getColumns(patterns, showColumns.getTagFilter())); } catch (PhysicalException e) { return new TaskExecuteResult(e); } @@ -434,12 +399,12 @@ public TaskExecuteResult executeShowColumns(ShowColumns showColumns) { int limit = showColumns.getLimit(); int offset = showColumns.getOffset(); if (limit == Integer.MAX_VALUE && offset == 0) { - return new TaskExecuteResult(Column.toRowStream(columnSetAfterFilter)); + return new TaskExecuteResult(Column.toRowStream(targetColumns)); } else { // only need part of data. List tsList = new ArrayList<>(); - int cur = 0, size = columnSetAfterFilter.size(); - for (Iterator iter = columnSetAfterFilter.iterator(); iter.hasNext(); cur++) { + int cur = 0, size = targetColumns.size(); + for (Iterator iter = targetColumns.iterator(); iter.hasNext(); cur++) { if (cur >= size || cur - offset >= limit) { break; } diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java index 228d095f7b..824bb4dc55 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java @@ -278,4 +278,104 @@ private static String joinWithDot(String[] strings, int begin) { sb.setLength(sb.length() - 1); return sb.toString(); } + + public static Set intersectDataPrefix(String dataPrefix, Set patterns) { + if (dataPrefix == null || dataPrefix.isEmpty() || patterns.isEmpty()) { + return patterns; + } + String dataPrefixRegex = dataPrefix + ".*"; + if (patterns.contains("*")) { + return Collections.singleton(dataPrefixRegex); + } + + Set target = new HashSet<>(); + for (String pattern : patterns) { + Set tmp = intersectDataPrefix(dataPrefix, pattern); + if (tmp == null) { + continue; + } + if (tmp.contains(dataPrefixRegex)) { + return Collections.singleton(dataPrefixRegex); + } + target.addAll(tmp); + } + + // 移除不必要的pattern + return mergePatterns(target); + } + + private static Set intersectDataPrefix(String dataPrefix, String pattern) { + String[] prefixSplit = dataPrefix.split("\\."); + String[] patternSplit = pattern.split("\\."); + StringBuilder commonPrefix = new StringBuilder(); + int minLen = Math.min(prefixSplit.length, patternSplit.length); + int index = 0; + // 逐级匹配pattern和dataPrefix + while (index < minLen && prefixSplit[index].equals(patternSplit[index])) { + commonPrefix.append(prefixSplit[index]); + index++; + } + + // pattern匹配结束,dataPrefix还有剩余,则交集取dataPrefix + if (index == patternSplit.length) { + return Collections.singleton(dataPrefix + ".*"); + } + + // dataPrefix匹配结束,pattern还有剩余,则交集取pattern + if (index == prefixSplit.length) { + return Collections.singleton(pattern); + } + + // pattern和dataPrefix不匹配 + if (!patternSplit[index].equals("*")) { + return Collections.emptySet(); + } + + Set target = new HashSet<>(); + // 将pattern的'*'视为部分匹配该前缀,即把'*'下推到数据源 + target.add(dataPrefix + "." + joinWithDot(patternSplit, index)); + if (index + 1 < patternSplit.length) { + // 将pattern的'*'视为完全匹配该前缀,即不把'*'下推到数据源 + String patternRemain = joinWithDot(patternSplit, index + 1); + target.add(dataPrefix + "." + patternRemain); + + if (commonPrefix.length() > 0) { + commonPrefix.append("."); + } + // 将dataPrefix的每一级分别匹配'*' + for (int i = index + 1; i < prefixSplit.length; i++) { + commonPrefix.append(prefixSplit[i - 1]).append("."); + String prefixRemain = joinWithDot(prefixSplit, i); + Set ret = intersectDataPrefix(prefixRemain, patternRemain); + ret.forEach(str -> target.add(commonPrefix + str)); + } + } + + return target; + } + + private static Set mergePatterns(Set patterns) { + if (patterns.size() <= 1) { + return patterns; + } + Set target = new HashSet<>(); + List list = new ArrayList<>(patterns); + int size = list.size(); + List toBeRemoved = new ArrayList<>(size); + for (int i = 0; i < size; i++) { + boolean removed = false; + for (int j = 0; j != i && !toBeRemoved.contains(j) && j < size; j++) { + // 第j个pattern包含第i个pattern + if (match(list.get(i), list.get(j))) { + toBeRemoved.add(i); + removed = true; + break; + } + } + if (!removed) { + target.add(list.get(i)); + } + } + return target; + } } diff --git a/shared/src/test/java/cn/edu/tsinghua/iginx/utils/StringUtilsTest.java b/shared/src/test/java/cn/edu/tsinghua/iginx/utils/StringUtilsTest.java index f5d0338cf0..1ac452ae30 100644 --- a/shared/src/test/java/cn/edu/tsinghua/iginx/utils/StringUtilsTest.java +++ b/shared/src/test/java/cn/edu/tsinghua/iginx/utils/StringUtilsTest.java @@ -75,6 +75,36 @@ public void cutSchemaPrefix() { assertEquals(toSet("b.c", "*.b.c"), StringUtils.cutSchemaPrefix("a.b.c", toSet("*.b.c"))); } + @Test + public void intersectDataPrefix() { + assertEquals( + toSet("a.b.c.*"), StringUtils.intersectDataPrefix(null, Collections.singleton("a.b.c.*"))); + assertEquals( + toSet("a.b.*"), StringUtils.intersectDataPrefix("a.b", Collections.singleton("*"))); + assertEquals( + toSet("a.b.c.*"), StringUtils.intersectDataPrefix("a.b", Collections.singleton("a.b.c.*"))); + assertEquals( + toSet("a.b.c"), StringUtils.intersectDataPrefix("a.b", Collections.singleton("a.b.c"))); + assertEquals( + toSet("a.b.*"), StringUtils.intersectDataPrefix("a.b", Collections.singleton("a.*"))); + assertEquals( + toSet("a.b.c.*", "a.b.*.c.*"), + StringUtils.intersectDataPrefix("a.b", Collections.singleton("*.c.*"))); + assertEquals( + toSet("a.b.*"), StringUtils.intersectDataPrefix("a.b", Collections.singleton("*.b.*"))); + assertEquals( + toSet("a.b.c", "a.b.b.c", "a.b.*.b.c"), + StringUtils.intersectDataPrefix("a.b", Collections.singleton("*.b.c"))); + assertEquals( + toSet("a.b.*.c"), StringUtils.intersectDataPrefix("a.b", Collections.singleton("*.b.*.c"))); + assertEquals( + Collections.emptySet(), + StringUtils.intersectDataPrefix("a.b", Collections.singleton("b.*.b.*.c"))); + assertEquals( + Collections.emptySet(), + StringUtils.intersectDataPrefix("a.b", Collections.singleton("a.c.b.*"))); + } + private Set toSet(String... items) { return new HashSet<>(Arrays.asList(items)); } From 355fa6e3678464cf49802557e25f26c2bcb59c65 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Tue, 6 Aug 2024 14:24:44 +0800 Subject: [PATCH 128/138] debug --- .github/workflows/standard-test-suite.yml | 37 +++---------------- .../execute/StoragePhysicalTaskExecutor.java | 3 ++ 2 files changed, 9 insertions(+), 31 deletions(-) diff --git a/.github/workflows/standard-test-suite.yml b/.github/workflows/standard-test-suite.yml index 67e41e0f75..b229f41336 100644 --- a/.github/workflows/standard-test-suite.yml +++ b/.github/workflows/standard-test-suite.yml @@ -1,44 +1,19 @@ name: Standard Test Suite -on: - pull_request: # when a PR is opened or reopened - types: [opened, reopened] - branches: - - main +#on: +# pull_request: # when a PR is opened or reopened +# types: [opened, reopened] +# branches: +# - main +on: [pull_request] concurrency: group: "${{ github.workflow }}-${{ github.ref }}" cancel-in-progress: true jobs: - unit-test: - uses: ./.github/workflows/unit-test.yml - unit-mds: - uses: ./.github/workflows/unit-mds.yml - case-regression: - uses: ./.github/workflows/case-regression.yml - with: - metadata-matrix: '["zookeeper"]' - standalone-test: - uses: ./.github/workflows/standalone-test.yml - with: - metadata-matrix: '["zookeeper"]' - standalone-test-pushdown: - uses: ./.github/workflows/standalone-test-pushdown.yml - with: - metadata-matrix: '["zookeeper"]' db-ce: uses: ./.github/workflows/DB-CE.yml with: metadata-matrix: '["zookeeper"]' - remote-test: - uses: ./.github/workflows/remote-test.yml - with: - metadata-matrix: '["zookeeper"]' - assemebly-test: - uses: ./.github/workflows/assembly-test.yml - tpc-h-regression-test: - uses: ./.github/workflows/tpc-h.yml - with: os-matrix: '["ubuntu-latest"]' - metadata-matrix: '["zookeeper"]' diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java index 4848009aa4..a6742fa18a 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java @@ -383,7 +383,10 @@ public TaskExecuteResult executeShowColumns(ShowColumns showColumns) { continue; } // 求patterns与dataPrefix的交集 + LOGGER.debug("before patterns: {}", patterns); + LOGGER.debug("dataprefix: {}", storage.getDataPrefix()); patterns = StringUtils.intersectDataPrefix(storage.getDataPrefix(), patterns); + LOGGER.debug("after patterns: {}", patterns); if (patterns.isEmpty()) { continue; } From 26bf3e4b74146596fd209a38610f61762886e3a7 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Tue, 6 Aug 2024 15:17:42 +0800 Subject: [PATCH 129/138] push down patterns --- .../filesystem/exec/FileSystemManager.java | 37 +++++-------------- .../iginx/filesystem/exec/LocalExecutor.java | 12 +++--- 2 files changed, 16 insertions(+), 33 deletions(-) diff --git a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java index dca42cde60..3f73003094 100644 --- a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java +++ b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java @@ -34,7 +34,6 @@ import cn.edu.tsinghua.iginx.filesystem.tools.MemoryPool; import cn.edu.tsinghua.iginx.thrift.DataType; import cn.edu.tsinghua.iginx.utils.Pair; -import cn.edu.tsinghua.iginx.utils.StringUtils; import java.io.File; import java.io.IOException; import java.nio.file.*; @@ -393,13 +392,10 @@ public FileVisitResult postVisitDirectory(Path dir, IOException exc) { } public List getTargetFiles( - File dir, - String root, - String storageUnit, - Set patterns, - TagFilter tagFilter, - boolean containsEmptyDir) { + File dir, String root, Set patterns, boolean containsEmptyDir) { dir = FilePathUtils.normalize(dir, FileAccessType.READ); + Set pathPatterns = new HashSet<>(patterns.size()); + patterns.forEach(p -> pathPatterns.add(FilePathUtils.toNormalFilePath(root, p))); List res = new ArrayList<>(); try { @@ -412,31 +408,16 @@ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) if (containsEmptyDir && isDirEmpty(dir)) { res.add(dir.toFile()); } + for (String pathPattern : pathPatterns) { + try (DirectoryStream stream = Files.newDirectoryStream(dir, pathPattern)) { + stream.forEach(path -> res.add(path.toFile())); + } + } return FileVisitResult.CONTINUE; } @Override - public FileVisitResult visitFile(Path filePath, BasicFileAttributes attrs) { - File file = filePath.toFile(); - FileMeta meta = getFileMeta(file); - String columnPath = - FilePathUtils.convertAbsolutePathToPath( - root, file.getAbsolutePath(), storageUnit); - if (meta == null) { - throw new RuntimeException( - String.format( - "encounter error when getting columns of storage unit because file meta %s is null", - file.getAbsolutePath())); - } - // get columns by pattern - if (StringUtils.pathNotMatchPatterns(columnPath, patterns)) { - return FileVisitResult.CONTINUE; - } - // get columns by tag filter - if (tagFilter != null && !TagKVUtils.match(meta.getTags(), tagFilter)) { - return FileVisitResult.CONTINUE; - } - res.add(file); + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { return FileVisitResult.CONTINUE; } diff --git a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java index 8ed46c4a3f..2bbab0f30e 100644 --- a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java +++ b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java @@ -25,6 +25,7 @@ import cn.edu.tsinghua.iginx.engine.physical.exception.PhysicalException; import cn.edu.tsinghua.iginx.engine.physical.memory.execute.stream.EmptyRowStream; import cn.edu.tsinghua.iginx.engine.physical.storage.domain.Column; +import cn.edu.tsinghua.iginx.engine.physical.storage.utils.TagKVUtils; import cn.edu.tsinghua.iginx.engine.physical.task.TaskExecuteResult; import cn.edu.tsinghua.iginx.engine.shared.KeyRange; import cn.edu.tsinghua.iginx.engine.shared.data.read.RowStream; @@ -333,9 +334,7 @@ public List getColumnsOfStorageUnit( List columns = new ArrayList<>(); if (root != null) { File directory = new File(FilePathUtils.toIginxPath(root, storageUnit, null)); - for (File file : - fileSystemManager.getTargetFiles( - directory, root, storageUnit, patterns, tagFilter, false)) { + for (File file : fileSystemManager.getTargetFiles(directory, root, patterns, false)) { FileMeta meta = fileSystemManager.getFileMeta(file); if (meta == null) { throw new PhysicalException( @@ -343,6 +342,10 @@ public List getColumnsOfStorageUnit( "encounter error when getting columns of storage unit because file meta %s is null", file.getAbsolutePath())); } + // get columns by tag filter + if (tagFilter != null && !TagKVUtils.match(meta.getTags(), tagFilter)) { + continue; + } String columnPath = FilePathUtils.convertAbsolutePathToPath(root, file.getAbsolutePath(), storageUnit); columns.add(new Column(columnPath, meta.getDataType(), meta.getTags(), false)); @@ -351,8 +354,7 @@ public List getColumnsOfStorageUnit( // get columns from dummy storage unit if (hasData && dummyRoot != null && tagFilter == null) { for (File file : - fileSystemManager.getTargetFiles( - new File(realDummyRoot), dummyRoot, storageUnit, patterns, null, true)) { + fileSystemManager.getTargetFiles(new File(realDummyRoot), dummyRoot, patterns, true)) { String dummyPath = FilePathUtils.convertAbsolutePathToPath(dummyRoot, file.getAbsolutePath(), storageUnit); columns.add(new Column(dummyPath, DataType.BINARY, null, true)); From 065e92648f0fd141faff069ef4929dcc5c58f762 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Tue, 6 Aug 2024 15:30:20 +0800 Subject: [PATCH 130/138] fix schemaprefix --- .../execute/StoragePhysicalTaskExecutor.java | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java index a6742fa18a..ddc52af986 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java @@ -377,23 +377,31 @@ public TaskExecuteResult executeShowColumns(ShowColumns showColumns) { } try { Set patterns = showColumns.getPathRegexSet(); + String schemaPrefix = storage.getSchemaPrefix(); // schemaPrefix是在IGinX中定义的,数据源的路径中没有该前缀,因此需要剪掉patterns中前缀是schemaPrefix的部分 - patterns = StringUtils.cutSchemaPrefix(storage.getSchemaPrefix(), patterns); + patterns = StringUtils.cutSchemaPrefix(schemaPrefix, patterns); if (patterns.isEmpty()) { continue; } // 求patterns与dataPrefix的交集 - LOGGER.debug("before patterns: {}", patterns); - LOGGER.debug("dataprefix: {}", storage.getDataPrefix()); patterns = StringUtils.intersectDataPrefix(storage.getDataPrefix(), patterns); - LOGGER.debug("after patterns: {}", patterns); if (patterns.isEmpty()) { continue; } if (patterns.contains("*")) { patterns = Collections.emptySet(); } - targetColumns.addAll(pair.k.getColumns(patterns, showColumns.getTagFilter())); + List columnList = pair.k.getColumns(patterns, showColumns.getTagFilter()); + + // 列名前加上schemaPrefix + if (schemaPrefix != null) { + columnList.forEach(column -> { + column.setPath(schemaPrefix + "." + column.getPath()); + targetColumns.add(column); + }); + } else { + targetColumns.addAll(columnList); + } } catch (PhysicalException e) { return new TaskExecuteResult(e); } From a09c673bbce97292b7920a879e8719cb9c81761c Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Tue, 6 Aug 2024 15:32:54 +0800 Subject: [PATCH 131/138] format --- .../storage/execute/StoragePhysicalTaskExecutor.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java index ddc52af986..36d42e3406 100644 --- a/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java +++ b/core/src/main/java/cn/edu/tsinghua/iginx/engine/physical/storage/execute/StoragePhysicalTaskExecutor.java @@ -395,10 +395,11 @@ public TaskExecuteResult executeShowColumns(ShowColumns showColumns) { // 列名前加上schemaPrefix if (schemaPrefix != null) { - columnList.forEach(column -> { - column.setPath(schemaPrefix + "." + column.getPath()); - targetColumns.add(column); - }); + columnList.forEach( + column -> { + column.setPath(schemaPrefix + "." + column.getPath()); + targetColumns.add(column); + }); } else { targetColumns.addAll(columnList); } From 6463d192ad5713e53f2664c322879ce0e6f12028 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Tue, 6 Aug 2024 15:54:07 +0800 Subject: [PATCH 132/138] fix --- .../iginx/filesystem/exec/LocalExecutor.java | 3 +++ .../cn/edu/tsinghua/iginx/utils/StringUtils.java | 12 ------------ 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java index 2bbab0f30e..107ecbfe18 100644 --- a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java +++ b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java @@ -332,6 +332,9 @@ public TaskExecuteResult executeDeleteTask( public List getColumnsOfStorageUnit( String storageUnit, Set patterns, TagFilter tagFilter) throws PhysicalException { List columns = new ArrayList<>(); + if (patterns.isEmpty()) { + patterns.add(WILDCARD); + } if (root != null) { File directory = new File(FilePathUtils.toIginxPath(root, storageUnit, null)); for (File file : fileSystemManager.getTargetFiles(directory, root, patterns, false)) { diff --git a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java index 824bb4dc55..4321a8ea94 100644 --- a/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java +++ b/shared/src/main/java/cn/edu/tsinghua/iginx/utils/StringUtils.java @@ -118,18 +118,6 @@ public static String reformatPath(String path) { return path; } - public static boolean pathNotMatchPatterns(String path, Set patterns) { - if (patterns.isEmpty()) { - return false; - } - for (String pattern : patterns) { - if (match(path, pattern)) { - return false; - } - } - return true; - } - public static boolean match(String string, String iginxPattern) { return toColumnMatcher(iginxPattern).test(string); } From 6fe320969262f0ea09967be42a7d974b061dbf72 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Tue, 6 Aug 2024 16:04:52 +0800 Subject: [PATCH 133/138] fix --- .../iginx/filesystem/exec/FileSystemManager.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java index 3f73003094..5a8efd0ee7 100644 --- a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java +++ b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java @@ -34,6 +34,7 @@ import cn.edu.tsinghua.iginx.filesystem.tools.MemoryPool; import cn.edu.tsinghua.iginx.thrift.DataType; import cn.edu.tsinghua.iginx.utils.Pair; +import cn.edu.tsinghua.iginx.utils.StringUtils; import java.io.File; import java.io.IOException; import java.nio.file.*; @@ -394,8 +395,12 @@ public FileVisitResult postVisitDirectory(Path dir, IOException exc) { public List getTargetFiles( File dir, String root, Set patterns, boolean containsEmptyDir) { dir = FilePathUtils.normalize(dir, FileAccessType.READ); - Set pathPatterns = new HashSet<>(patterns.size()); - patterns.forEach(p -> pathPatterns.add(FilePathUtils.toNormalFilePath(root, p))); + Set pathRegexSet = new HashSet<>(patterns.size()); + patterns.forEach( + p -> { + String pathPattern = FilePathUtils.toNormalFilePath(root, p); + pathRegexSet.add(StringUtils.reformatPath(pathPattern)); + }); List res = new ArrayList<>(); try { @@ -408,8 +413,8 @@ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) if (containsEmptyDir && isDirEmpty(dir)) { res.add(dir.toFile()); } - for (String pathPattern : pathPatterns) { - try (DirectoryStream stream = Files.newDirectoryStream(dir, pathPattern)) { + for (String regex : pathRegexSet) { + try (DirectoryStream stream = Files.newDirectoryStream(dir, regex)) { stream.forEach(path -> res.add(path.toFile())); } } From 996ba6ae5293a081381e265bd323e063c21c8cba Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Tue, 6 Aug 2024 16:23:07 +0800 Subject: [PATCH 134/138] fix --- .../cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java index 107ecbfe18..0fd0a7982b 100644 --- a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java +++ b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java @@ -333,7 +333,7 @@ public List getColumnsOfStorageUnit( String storageUnit, Set patterns, TagFilter tagFilter) throws PhysicalException { List columns = new ArrayList<>(); if (patterns.isEmpty()) { - patterns.add(WILDCARD); + patterns.add("*"); } if (root != null) { File directory = new File(FilePathUtils.toIginxPath(root, storageUnit, null)); From 74d5dbee718406d8374993e1bfc5afb39629d284 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Tue, 6 Aug 2024 16:52:24 +0800 Subject: [PATCH 135/138] fix --- .../iginx/filesystem/exec/FileSystemManager.java | 2 +- .../tsinghua/iginx/filesystem/exec/LocalExecutor.java | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java index 5a8efd0ee7..c46144c1d4 100644 --- a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java +++ b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java @@ -393,7 +393,7 @@ public FileVisitResult postVisitDirectory(Path dir, IOException exc) { } public List getTargetFiles( - File dir, String root, Set patterns, boolean containsEmptyDir) { + File dir, String root, List patterns, boolean containsEmptyDir) { dir = FilePathUtils.normalize(dir, FileAccessType.READ); Set pathRegexSet = new HashSet<>(patterns.size()); patterns.forEach( diff --git a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java index 0fd0a7982b..a9e2807976 100644 --- a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java +++ b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java @@ -332,12 +332,13 @@ public TaskExecuteResult executeDeleteTask( public List getColumnsOfStorageUnit( String storageUnit, Set patterns, TagFilter tagFilter) throws PhysicalException { List columns = new ArrayList<>(); - if (patterns.isEmpty()) { - patterns.add("*"); + List patternList = new ArrayList<>(patterns); + if (patternList.isEmpty()) { + patternList.add("*"); } if (root != null) { File directory = new File(FilePathUtils.toIginxPath(root, storageUnit, null)); - for (File file : fileSystemManager.getTargetFiles(directory, root, patterns, false)) { + for (File file : fileSystemManager.getTargetFiles(directory, root, patternList, false)) { FileMeta meta = fileSystemManager.getFileMeta(file); if (meta == null) { throw new PhysicalException( @@ -357,7 +358,7 @@ public List getColumnsOfStorageUnit( // get columns from dummy storage unit if (hasData && dummyRoot != null && tagFilter == null) { for (File file : - fileSystemManager.getTargetFiles(new File(realDummyRoot), dummyRoot, patterns, true)) { + fileSystemManager.getTargetFiles(new File(realDummyRoot), dummyRoot, patternList, true)) { String dummyPath = FilePathUtils.convertAbsolutePathToPath(dummyRoot, file.getAbsolutePath(), storageUnit); columns.add(new Column(dummyPath, DataType.BINARY, null, true)); From 6556885c1e11d2b87633516717a7d1530d36db8a Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Tue, 6 Aug 2024 17:59:27 +0800 Subject: [PATCH 136/138] fix --- .../iginx/filesystem/exec/FileSystemManager.java | 14 ++++++++------ .../iginx/filesystem/tools/FilePathUtils.java | 12 ++++++++++++ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java index c46144c1d4..5b384d4385 100644 --- a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java +++ b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java @@ -395,11 +395,11 @@ public FileVisitResult postVisitDirectory(Path dir, IOException exc) { public List getTargetFiles( File dir, String root, List patterns, boolean containsEmptyDir) { dir = FilePathUtils.normalize(dir, FileAccessType.READ); - Set pathRegexSet = new HashSet<>(patterns.size()); + List pathRegexList = new ArrayList<>(patterns.size()); patterns.forEach( p -> { String pathPattern = FilePathUtils.toNormalFilePath(root, p); - pathRegexSet.add(StringUtils.reformatPath(pathPattern)); + pathRegexList.add(StringUtils.reformatPath(pathPattern)); }); List res = new ArrayList<>(); @@ -413,10 +413,12 @@ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) if (containsEmptyDir && isDirEmpty(dir)) { res.add(dir.toFile()); } - for (String regex : pathRegexSet) { - try (DirectoryStream stream = Files.newDirectoryStream(dir, regex)) { - stream.forEach(path -> res.add(path.toFile())); - } + try (DirectoryStream stream = + Files.newDirectoryStream( + dir, + path -> + path.toFile().isFile() && FilePathUtils.matches(path, pathRegexList))) { + stream.forEach(path -> res.add(path.toFile())); } return FileVisitResult.CONTINUE; } diff --git a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/FilePathUtils.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/FilePathUtils.java index 745e6d7046..d445f9fadb 100644 --- a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/FilePathUtils.java +++ b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/FilePathUtils.java @@ -25,8 +25,10 @@ import cn.edu.tsinghua.iginx.auth.utils.FilePermissionRuleNameFilters; import java.io.File; import java.nio.file.Path; +import java.util.List; import java.util.Optional; import java.util.function.Predicate; +import java.util.regex.Pattern; public class FilePathUtils { @@ -120,4 +122,14 @@ public static String convertAbsolutePathToPath(String root, String filePath, Str return res.substring(0, res.length() - 1); } } + + public static boolean matches(Path path, List regexList) { + String filePath = path.toAbsolutePath().toString(); + for (String regex : regexList) { + if (Pattern.matches(regex, filePath)) { + return true; + } + } + return false; + } } From e5335e49cb59444d73fac6616c5b290423ac5562 Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Tue, 6 Aug 2024 19:11:33 +0800 Subject: [PATCH 137/138] fix --- .../filesystem/exec/FileSystemManager.java | 7 ++++--- .../iginx/filesystem/exec/LocalExecutor.java | 6 ++++-- .../iginx/filesystem/tools/FilePathUtils.java | 21 +++++++++++++++++++ 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java index 5b384d4385..8e96d87998 100644 --- a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java +++ b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/FileSystemManager.java @@ -393,13 +393,14 @@ public FileVisitResult postVisitDirectory(Path dir, IOException exc) { } public List getTargetFiles( - File dir, String root, List patterns, boolean containsEmptyDir) { + File dir, String root, String storageUnit, List patterns, boolean containsEmptyDir) { dir = FilePathUtils.normalize(dir, FileAccessType.READ); List pathRegexList = new ArrayList<>(patterns.size()); + String suffix = storageUnit == null ? "" : "\\d+"; // 末尾匹配数字 patterns.forEach( p -> { - String pathPattern = FilePathUtils.toNormalFilePath(root, p); - pathRegexList.add(StringUtils.reformatPath(pathPattern)); + String pathPattern = FilePathUtils.toFilePath(root, storageUnit, p); + pathRegexList.add(StringUtils.reformatPath(pathPattern) + suffix); }); List res = new ArrayList<>(); diff --git a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java index a9e2807976..03966d577c 100644 --- a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java +++ b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/exec/LocalExecutor.java @@ -338,7 +338,8 @@ public List getColumnsOfStorageUnit( } if (root != null) { File directory = new File(FilePathUtils.toIginxPath(root, storageUnit, null)); - for (File file : fileSystemManager.getTargetFiles(directory, root, patternList, false)) { + for (File file : + fileSystemManager.getTargetFiles(directory, root, storageUnit, patternList, false)) { FileMeta meta = fileSystemManager.getFileMeta(file); if (meta == null) { throw new PhysicalException( @@ -358,7 +359,8 @@ public List getColumnsOfStorageUnit( // get columns from dummy storage unit if (hasData && dummyRoot != null && tagFilter == null) { for (File file : - fileSystemManager.getTargetFiles(new File(realDummyRoot), dummyRoot, patternList, true)) { + fileSystemManager.getTargetFiles( + new File(realDummyRoot), dummyRoot, null, patternList, true)) { String dummyPath = FilePathUtils.convertAbsolutePathToPath(dummyRoot, file.getAbsolutePath(), storageUnit); columns.add(new Column(dummyPath, DataType.BINARY, null, true)); diff --git a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/FilePathUtils.java b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/FilePathUtils.java index d445f9fadb..df3a10bb46 100644 --- a/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/FilePathUtils.java +++ b/dataSource/filesystem/src/main/java/cn/edu/tsinghua/iginx/filesystem/tools/FilePathUtils.java @@ -123,6 +123,27 @@ public static String convertAbsolutePathToPath(String root, String filePath, Str } } + public static String toFilePath(String root, String storageUnit, String path) { + if (path == null) { + return root; + } + StringBuilder target = new StringBuilder(root); + if (storageUnit != null) { + target.append(storageUnit).append(SEPARATOR); + } + String[] parts = path.split("\\."); + StringBuilder res = new StringBuilder(); + for (String s : parts) { + s = s.replace("\\", "."); + res.append(s).append(SEPARATOR); + } + target.append(res.substring(0, res.length() - 1)); + if (storageUnit != null) { + target.append(FILE_EXTENSION); + } + return target.toString(); + } + public static boolean matches(Path path, List regexList) { String filePath = path.toAbsolutePath().toString(); for (String regex : regexList) { From 8c42d915c5ab6ac9349ee785f1fd8a3104a729ca Mon Sep 17 00:00:00 2001 From: jzl18thu Date: Tue, 6 Aug 2024 19:37:57 +0800 Subject: [PATCH 138/138] open other tests --- .github/workflows/standard-test-suite.yml | 37 +++++++++++++++++++---- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/.github/workflows/standard-test-suite.yml b/.github/workflows/standard-test-suite.yml index b229f41336..67e41e0f75 100644 --- a/.github/workflows/standard-test-suite.yml +++ b/.github/workflows/standard-test-suite.yml @@ -1,19 +1,44 @@ name: Standard Test Suite -#on: -# pull_request: # when a PR is opened or reopened -# types: [opened, reopened] -# branches: -# - main -on: [pull_request] +on: + pull_request: # when a PR is opened or reopened + types: [opened, reopened] + branches: + - main concurrency: group: "${{ github.workflow }}-${{ github.ref }}" cancel-in-progress: true jobs: + unit-test: + uses: ./.github/workflows/unit-test.yml + unit-mds: + uses: ./.github/workflows/unit-mds.yml + case-regression: + uses: ./.github/workflows/case-regression.yml + with: + metadata-matrix: '["zookeeper"]' + standalone-test: + uses: ./.github/workflows/standalone-test.yml + with: + metadata-matrix: '["zookeeper"]' + standalone-test-pushdown: + uses: ./.github/workflows/standalone-test-pushdown.yml + with: + metadata-matrix: '["zookeeper"]' db-ce: uses: ./.github/workflows/DB-CE.yml with: metadata-matrix: '["zookeeper"]' + remote-test: + uses: ./.github/workflows/remote-test.yml + with: + metadata-matrix: '["zookeeper"]' + assemebly-test: + uses: ./.github/workflows/assembly-test.yml + tpc-h-regression-test: + uses: ./.github/workflows/tpc-h.yml + with: os-matrix: '["ubuntu-latest"]' + metadata-matrix: '["zookeeper"]'