blob: 024359e6f17cc26a0bbd6a8038da878d0daf151c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.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.
*/
package com.ceresdb.sql;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import com.ceresdb.MetricParser;
import com.ceresdb.common.util.Requires;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.create.table.ColumnDefinition;
import net.sf.jsqlparser.statement.create.table.CreateTable;
import net.sf.jsqlparser.statement.create.table.Index;
import net.sf.jsqlparser.util.TablesNamesFinder;
/**
*
* @author jiachun.fjc
*/
public class SqlParserUtil {
private static final String _TIMESTAMP_KEY_UC = "TIMESTAMP KEY";
private static final String _TIMESTAMP_KEY_LC = _TIMESTAMP_KEY_UC.toLowerCase();
// This syntax is not supported in CeresDB
private static final String _UNIQUE_KEY = "UNIQUE KEY";
private static final String _TAG = "TAG";
private static final String _CREATE_TABLE = "CREATE TABLE";
public static List<String> extractTableNames(final Statement stmt) {
final TablesNamesFinder tablesFinder = new TablesNamesFinder();
return tablesFinder.getTableList(stmt);
}
public static String amendSql(final String sql) {
final String ucSql = sql.trim().toUpperCase();
// Can not parse `TIMESTAMP KEY` in create table yet.
if (ucSql.startsWith(_CREATE_TABLE)) {
Requires.requireTrue(!ucSql.contains(_UNIQUE_KEY), "`unique key` not supported");
// Case mixing is not supported
return sql.replace(_TIMESTAMP_KEY_UC, _UNIQUE_KEY) //
.replace(_TIMESTAMP_KEY_LC, _UNIQUE_KEY);
}
return sql;
}
public static List<MetricParser.Column> extractCreateColumns(final CreateTable createTable) {
final String metricName = createTable.getTable().getName();
// timestamp
final String tsColName = createTable.getIndexes() // must not null
.stream()
.filter(SqlParserUtil::isTimestampColumn)
.flatMap(idx -> idx.getColumnsNames().stream())
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("There must be a `timestamp` column"));
final Set<String> tags = createTable.getColumnDefinitions()
.stream()
.filter(SqlParserUtil::isTagColumn)
.map(ColumnDefinition::getColumnName)
.collect(Collectors.toSet());
return createTable.getColumnDefinitions()
.stream()
.map(col -> new MetricParser.Column() {
@Override
public String metricName() {
return metricName;
}
@Override
public String columnName() {
return col.getColumnName();
}
@Override
public ColumnType columnType() {
if (tsColName.equals(columnName())) {
return ColumnType.Timestamp;
}
if (tags.contains(columnName())) {
return ColumnType.Tag;
}
return ColumnType.Field;
}
@Override
public String valueType() {
return col.getColDataType().getDataType();
}
})
.collect(Collectors.toList());
}
private static boolean isTagColumn(final ColumnDefinition col) {
final List<String> specs = col.getColumnSpecs();
if (specs == null || specs.isEmpty()) {
return false;
}
for (final String spec : specs) {
if (_TAG.equalsIgnoreCase(spec)) {
return true;
}
}
return false;
}
private static boolean isTimestampColumn(final Index idx) {
return _UNIQUE_KEY.equalsIgnoreCase(idx.getType());
}
}