mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2026-05-23 00:10:38 +00:00
feat!: unify all index creation grammars (#5486)
* column options Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * handle table constrain Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * update test assertions Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * change inverted index table constrain usage Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * update sqlness result Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * don't create inverted index for pk on alter table Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * remove remaining pk-as-inverted-index Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * more inverted index magic Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * update sqlness result again Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * fix clippy Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * Update src/sql/src/statements.rs Co-authored-by: jeremyhi <jiachun_feng@proton.me> * drop support for index def in table constrain Signed-off-by: Ruihang Xia <waynestxia@gmail.com> --------- Signed-off-by: Ruihang Xia <waynestxia@gmail.com> Co-authored-by: jeremyhi <jiachun_feng@proton.me>
This commit is contained in:
@@ -228,12 +228,6 @@ impl InformationSchemaKeyColumnUsageBuilder {
|
||||
let keys = &table_info.meta.primary_key_indices;
|
||||
let schema = table.schema();
|
||||
|
||||
// For compatibility, use primary key columns as inverted index columns.
|
||||
let pk_as_inverted_index = !schema
|
||||
.column_schemas()
|
||||
.iter()
|
||||
.any(|c| c.has_inverted_index_key());
|
||||
|
||||
for (idx, column) in schema.column_schemas().iter().enumerate() {
|
||||
let mut constraints = vec![];
|
||||
if column.is_time_index() {
|
||||
@@ -251,10 +245,6 @@ impl InformationSchemaKeyColumnUsageBuilder {
|
||||
// TODO(dimbtp): foreign key constraint not supported yet
|
||||
if keys.contains(&idx) {
|
||||
constraints.push(PRI_CONSTRAINT_NAME);
|
||||
|
||||
if pk_as_inverted_index {
|
||||
constraints.push(INVERTED_INDEX_CONSTRAINT_NAME);
|
||||
}
|
||||
}
|
||||
if column.is_inverted_indexed() {
|
||||
constraints.push(INVERTED_INDEX_CONSTRAINT_NAME);
|
||||
|
||||
@@ -183,12 +183,6 @@ impl ColumnSchema {
|
||||
self
|
||||
}
|
||||
|
||||
// Put a placeholder to invalidate schemas.all(!has_inverted_index_key).
|
||||
pub fn insert_inverted_index_placeholder(&mut self) {
|
||||
self.metadata
|
||||
.insert(INVERTED_INDEX_KEY.to_string(), "".to_string());
|
||||
}
|
||||
|
||||
pub fn is_inverted_indexed(&self) -> bool {
|
||||
self.metadata
|
||||
.get(INVERTED_INDEX_KEY)
|
||||
|
||||
@@ -137,14 +137,8 @@ pub(crate) async fn create_external_expr(
|
||||
// expanded form
|
||||
let time_index = find_time_index(&create.constraints)?;
|
||||
let primary_keys = find_primary_keys(&create.columns, &create.constraints)?;
|
||||
let inverted_index_cols = find_inverted_index_cols(&create.columns, &create.constraints)?;
|
||||
let column_schemas = columns_to_column_schemas(
|
||||
&create.columns,
|
||||
&time_index,
|
||||
&inverted_index_cols,
|
||||
&primary_keys,
|
||||
Some(&query_ctx.timezone()),
|
||||
)?;
|
||||
let column_schemas =
|
||||
columns_to_column_schemas(&create.columns, &time_index, Some(&query_ctx.timezone()))?;
|
||||
(time_index, primary_keys, column_schemas)
|
||||
} else {
|
||||
// inferred form
|
||||
@@ -199,7 +193,6 @@ pub fn create_to_expr(
|
||||
);
|
||||
|
||||
let primary_keys = find_primary_keys(&create.columns, &create.constraints)?;
|
||||
let inverted_index_cols = find_inverted_index_cols(&create.columns, &create.constraints)?;
|
||||
|
||||
let expr = CreateTableExpr {
|
||||
catalog_name,
|
||||
@@ -210,7 +203,6 @@ pub fn create_to_expr(
|
||||
&create.columns,
|
||||
&time_index,
|
||||
&primary_keys,
|
||||
&inverted_index_cols,
|
||||
Some(&query_ctx.timezone()),
|
||||
)?,
|
||||
time_index,
|
||||
@@ -378,71 +370,24 @@ pub fn find_time_index(constraints: &[TableConstraint]) -> Result<String> {
|
||||
Ok(time_index.first().unwrap().to_string())
|
||||
}
|
||||
|
||||
/// Finds the inverted index columns from the constraints. If no inverted index
|
||||
/// columns are provided in the constraints, return `None`.
|
||||
fn find_inverted_index_cols(
|
||||
columns: &[SqlColumn],
|
||||
constraints: &[TableConstraint],
|
||||
) -> Result<Option<Vec<String>>> {
|
||||
let inverted_index_cols = constraints.iter().find_map(|constraint| {
|
||||
if let TableConstraint::InvertedIndex { columns } = constraint {
|
||||
Some(
|
||||
columns
|
||||
.iter()
|
||||
.map(|ident| ident.value.clone())
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
let Some(inverted_index_cols) = inverted_index_cols else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
for col in &inverted_index_cols {
|
||||
if !columns.iter().any(|c| c.name().value == *col) {
|
||||
return InvalidSqlSnafu {
|
||||
err_msg: format!("inverted index column `{}` not found in column list", col),
|
||||
}
|
||||
.fail();
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Some(inverted_index_cols))
|
||||
}
|
||||
|
||||
fn columns_to_expr(
|
||||
column_defs: &[SqlColumn],
|
||||
time_index: &str,
|
||||
primary_keys: &[String],
|
||||
invereted_index_cols: &Option<Vec<String>>,
|
||||
timezone: Option<&Timezone>,
|
||||
) -> Result<Vec<api::v1::ColumnDef>> {
|
||||
let column_schemas = columns_to_column_schemas(
|
||||
column_defs,
|
||||
time_index,
|
||||
invereted_index_cols,
|
||||
primary_keys,
|
||||
timezone,
|
||||
)?;
|
||||
let column_schemas = columns_to_column_schemas(column_defs, time_index, timezone)?;
|
||||
column_schemas_to_defs(column_schemas, primary_keys)
|
||||
}
|
||||
|
||||
fn columns_to_column_schemas(
|
||||
columns: &[SqlColumn],
|
||||
time_index: &str,
|
||||
invereted_index_cols: &Option<Vec<String>>,
|
||||
primary_keys: &[String],
|
||||
timezone: Option<&Timezone>,
|
||||
) -> Result<Vec<ColumnSchema>> {
|
||||
columns
|
||||
.iter()
|
||||
.map(|c| {
|
||||
column_to_schema(c, time_index, invereted_index_cols, primary_keys, timezone)
|
||||
.context(ParseSqlSnafu)
|
||||
})
|
||||
.map(|c| column_to_schema(c, time_index, timezone).context(ParseSqlSnafu))
|
||||
.collect::<Result<Vec<ColumnSchema>>>()
|
||||
}
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ fn create_column(column_schema: &ColumnSchema, quote_style: char) -> Result<Colu
|
||||
opt.case_sensitive.to_string(),
|
||||
),
|
||||
]);
|
||||
extensions.fulltext_options = Some(map.into());
|
||||
extensions.fulltext_index_options = Some(map.into());
|
||||
}
|
||||
|
||||
if let Some(opt) = column_schema
|
||||
@@ -134,6 +134,10 @@ fn create_column(column_schema: &ColumnSchema, quote_style: char) -> Result<Colu
|
||||
extensions.skipping_index_options = Some(map.into());
|
||||
}
|
||||
|
||||
if column_schema.is_inverted_indexed() {
|
||||
extensions.inverted_index_options = Some(HashMap::new().into());
|
||||
}
|
||||
|
||||
Ok(Column {
|
||||
column_def: ColumnDef {
|
||||
name: Ident::with_quote(quote_style, name),
|
||||
@@ -148,25 +152,6 @@ fn create_column(column_schema: &ColumnSchema, quote_style: char) -> Result<Colu
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the column schemas for `SHOW CREATE TABLE` statement.
|
||||
///
|
||||
/// For metric engine, it will only return the column schemas that are not internal columns.
|
||||
fn column_schemas_for_show_create<'a>(
|
||||
schema: &'a SchemaRef,
|
||||
engine: &str,
|
||||
) -> Vec<&'a ColumnSchema> {
|
||||
let is_metric_engine = is_metric_engine(engine);
|
||||
if is_metric_engine {
|
||||
schema
|
||||
.column_schemas()
|
||||
.iter()
|
||||
.filter(|c| !is_metric_engine_internal_column(&c.name))
|
||||
.collect()
|
||||
} else {
|
||||
schema.column_schemas().iter().collect()
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the primary key columns for `SHOW CREATE TABLE` statement.
|
||||
///
|
||||
/// For metric engine, it will only return the primary key columns that are not internal columns.
|
||||
@@ -206,20 +191,6 @@ fn create_table_constraints(
|
||||
constraints.push(TableConstraint::PrimaryKey { columns });
|
||||
}
|
||||
|
||||
let column_schemas = column_schemas_for_show_create(schema, engine);
|
||||
let inverted_index_set = column_schemas.iter().any(|c| c.has_inverted_index_key());
|
||||
if inverted_index_set {
|
||||
let inverted_index_cols = column_schemas
|
||||
.iter()
|
||||
.filter(|c| c.is_inverted_indexed())
|
||||
.map(|c| Ident::with_quote(quote_style, &c.name))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
constraints.push(TableConstraint::InvertedIndex {
|
||||
columns: inverted_index_cols,
|
||||
});
|
||||
}
|
||||
|
||||
constraints
|
||||
}
|
||||
|
||||
@@ -353,14 +324,13 @@ mod tests {
|
||||
r#"
|
||||
CREATE TABLE IF NOT EXISTS "system_metrics" (
|
||||
"id" INT UNSIGNED NULL SKIPPING INDEX WITH(granularity = '4096', type = 'BLOOM'),
|
||||
"host" STRING NULL,
|
||||
"host" STRING NULL INVERTED INDEX,
|
||||
"cpu" DOUBLE NULL,
|
||||
"disk" FLOAT NULL,
|
||||
"msg" STRING NULL FULLTEXT WITH(analyzer = 'English', case_sensitive = 'false'),
|
||||
"ts" TIMESTAMP(3) NOT NULL DEFAULT current_timestamp(),
|
||||
TIME INDEX ("ts"),
|
||||
PRIMARY KEY ("id", "host"),
|
||||
INVERTED INDEX ("host")
|
||||
PRIMARY KEY ("id", "host")
|
||||
)
|
||||
ENGINE=mito
|
||||
WITH(
|
||||
|
||||
@@ -430,6 +430,7 @@ impl<'a> ParserContext<'a> {
|
||||
Ok(values)
|
||||
}
|
||||
|
||||
/// Parse the columns and constraints.
|
||||
fn parse_columns(&mut self) -> Result<(Vec<Column>, Vec<TableConstraint>)> {
|
||||
let mut columns = vec![];
|
||||
let mut constraints = vec![];
|
||||
@@ -666,6 +667,11 @@ impl<'a> ParserContext<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a column option extensions.
|
||||
///
|
||||
/// This function will handle:
|
||||
/// - Vector type
|
||||
/// - Indexes
|
||||
fn parse_column_extensions(
|
||||
parser: &mut Parser<'_>,
|
||||
column_name: &Ident,
|
||||
@@ -697,8 +703,10 @@ impl<'a> ParserContext<'a> {
|
||||
column_extensions.vector_options = Some(options.into());
|
||||
}
|
||||
|
||||
// parse index options in column definition
|
||||
let mut is_index_declared = false;
|
||||
|
||||
// skipping index
|
||||
if let Token::Word(word) = parser.peek_token().token
|
||||
&& word.value.eq_ignore_ascii_case(SKIPPING)
|
||||
{
|
||||
@@ -731,7 +739,7 @@ impl<'a> ParserContext<'a> {
|
||||
validate_column_skipping_index_create_option(key),
|
||||
InvalidColumnOptionSnafu {
|
||||
name: column_name.to_string(),
|
||||
msg: format!("invalid SKIP option: {key}"),
|
||||
msg: format!("invalid SKIPPING INDEX option: {key}"),
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -740,12 +748,22 @@ impl<'a> ParserContext<'a> {
|
||||
is_index_declared |= true;
|
||||
}
|
||||
|
||||
// fulltext index
|
||||
if parser.parse_keyword(Keyword::FULLTEXT) {
|
||||
// Consume `INDEX` keyword
|
||||
ensure!(
|
||||
column_extensions.fulltext_options.is_none(),
|
||||
parser.parse_keyword(Keyword::INDEX),
|
||||
InvalidColumnOptionSnafu {
|
||||
name: column_name.to_string(),
|
||||
msg: "duplicated FULLTEXT option",
|
||||
msg: "expect INDEX after FULLTEXT keyword",
|
||||
}
|
||||
);
|
||||
|
||||
ensure!(
|
||||
column_extensions.fulltext_index_options.is_none(),
|
||||
InvalidColumnOptionSnafu {
|
||||
name: column_name.to_string(),
|
||||
msg: "duplicated FULLTEXT INDEX option",
|
||||
}
|
||||
);
|
||||
|
||||
@@ -771,12 +789,54 @@ impl<'a> ParserContext<'a> {
|
||||
validate_column_fulltext_create_option(key),
|
||||
InvalidColumnOptionSnafu {
|
||||
name: column_name.to_string(),
|
||||
msg: format!("invalid FULLTEXT option: {key}"),
|
||||
msg: format!("invalid FULLTEXT INDEX option: {key}"),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
column_extensions.fulltext_options = Some(options.into());
|
||||
column_extensions.fulltext_index_options = Some(options.into());
|
||||
is_index_declared |= true;
|
||||
}
|
||||
|
||||
// inverted index
|
||||
if let Token::Word(word) = parser.peek_token().token
|
||||
&& word.value.eq_ignore_ascii_case(INVERTED)
|
||||
{
|
||||
parser.next_token();
|
||||
// Consume `INDEX` keyword
|
||||
ensure!(
|
||||
parser.parse_keyword(Keyword::INDEX),
|
||||
InvalidColumnOptionSnafu {
|
||||
name: column_name.to_string(),
|
||||
msg: "expect INDEX after INVERTED keyword",
|
||||
}
|
||||
);
|
||||
|
||||
ensure!(
|
||||
column_extensions.inverted_index_options.is_none(),
|
||||
InvalidColumnOptionSnafu {
|
||||
name: column_name.to_string(),
|
||||
msg: "duplicated INVERTED index option",
|
||||
}
|
||||
);
|
||||
|
||||
// inverted index doesn't have options, skipping `WITH`
|
||||
// try cache `WITH` and throw error
|
||||
let with_token = parser.peek_token();
|
||||
ensure!(
|
||||
with_token.token
|
||||
!= Token::Word(Word {
|
||||
value: "WITH".to_string(),
|
||||
keyword: Keyword::WITH,
|
||||
quote_style: None,
|
||||
}),
|
||||
InvalidColumnOptionSnafu {
|
||||
name: column_name.to_string(),
|
||||
msg: "INVERTED index doesn't support options",
|
||||
}
|
||||
);
|
||||
|
||||
column_extensions.inverted_index_options = Some(OptionMap::default());
|
||||
is_index_declared |= true;
|
||||
}
|
||||
|
||||
@@ -836,28 +896,6 @@ impl<'a> ParserContext<'a> {
|
||||
column: columns.pop().unwrap(),
|
||||
}))
|
||||
}
|
||||
TokenWithLocation {
|
||||
token: Token::Word(w),
|
||||
..
|
||||
} if w.value.eq_ignore_ascii_case(INVERTED) => {
|
||||
self.parser
|
||||
.expect_keyword(Keyword::INDEX)
|
||||
.context(error::UnexpectedSnafu {
|
||||
expected: "INDEX",
|
||||
actual: self.peek_token_as_string(),
|
||||
})?;
|
||||
|
||||
let raw_columns = self
|
||||
.parser
|
||||
// allow empty list to unset inverted index
|
||||
.parse_parenthesized_column_list(Mandatory, true)
|
||||
.context(error::SyntaxSnafu)?;
|
||||
let columns = raw_columns
|
||||
.into_iter()
|
||||
.map(Self::canonicalize_identifier)
|
||||
.collect::<Vec<_>>();
|
||||
Ok(Some(TableConstraint::InvertedIndex { columns }))
|
||||
}
|
||||
_ => {
|
||||
self.parser.prev_token();
|
||||
Ok(None)
|
||||
@@ -1037,6 +1075,8 @@ mod tests {
|
||||
use common_error::ext::ErrorExt;
|
||||
use sqlparser::ast::ColumnOption::NotNull;
|
||||
use sqlparser::ast::{BinaryOperator, Expr, ObjectName, Value};
|
||||
use sqlparser::dialect::GenericDialect;
|
||||
use sqlparser::tokenizer::Tokenizer;
|
||||
|
||||
use super::*;
|
||||
use crate::dialect::GreptimeDbDialect;
|
||||
@@ -1151,7 +1191,6 @@ mod tests {
|
||||
memory float64,
|
||||
TIME INDEX (ts),
|
||||
PRIMARY KEY(ts, host),
|
||||
INVERTED INDEX(host)
|
||||
) with(location='/var/data/city.csv',format='csv');";
|
||||
|
||||
let options = HashMap::from([
|
||||
@@ -1187,12 +1226,6 @@ mod tests {
|
||||
columns: vec![Ident::new("ts"), Ident::new("host")]
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
&constraints[2],
|
||||
&TableConstraint::InvertedIndex {
|
||||
columns: vec![Ident::new("host")]
|
||||
}
|
||||
);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
@@ -1811,7 +1844,6 @@ ENGINE=mito";
|
||||
memory float64,
|
||||
TIME INDEX (ts),
|
||||
PRIMARY KEY(ts, host),
|
||||
INVERTED INDEX(host)
|
||||
) engine=mito
|
||||
with(ttl='10s');
|
||||
";
|
||||
@@ -1844,12 +1876,7 @@ ENGINE=mito";
|
||||
columns: vec![Ident::new("ts"), Ident::new("host")]
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
&constraints[2],
|
||||
&TableConstraint::InvertedIndex {
|
||||
columns: vec![Ident::new("host")]
|
||||
}
|
||||
);
|
||||
// inverted index is merged into column options
|
||||
assert_eq!(1, c.options.len());
|
||||
assert_eq!(
|
||||
[("ttl", "10s")].into_iter().collect::<HashMap<_, _>>(),
|
||||
@@ -1907,33 +1934,6 @@ ENGINE=mito";
|
||||
assert_matches!(result, Err(crate::error::Error::InvalidTimeIndex { .. }));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_inverted_index_empty_list() {
|
||||
let sql = r"create table demo(
|
||||
host string,
|
||||
ts timestamp time index,
|
||||
cpu float64 default 0,
|
||||
memory float64,
|
||||
TIME INDEX (ts),
|
||||
inverted index()
|
||||
) engine=mito;
|
||||
";
|
||||
let result =
|
||||
ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
|
||||
.unwrap();
|
||||
|
||||
if let Statement::CreateTable(c) = &result[0] {
|
||||
let tc = &c
|
||||
.constraints
|
||||
.iter()
|
||||
.find(|c| matches!(c, TableConstraint::InvertedIndex { .. }))
|
||||
.unwrap();
|
||||
assert_eq!(*tc, &TableConstraint::InvertedIndex { columns: vec![] });
|
||||
} else {
|
||||
unreachable!("should be create table statement");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invalid_column_name() {
|
||||
let sql = "create table foo(user string, i timestamp time index)";
|
||||
@@ -2019,7 +2019,7 @@ non TIMESTAMP(6) TIME INDEX,
|
||||
let sql1 = r"
|
||||
CREATE TABLE log (
|
||||
ts TIMESTAMP TIME INDEX,
|
||||
msg TEXT FULLTEXT,
|
||||
msg TEXT FULLTEXT INDEX,
|
||||
)";
|
||||
let result1 = ParserContext::create_with_dialect(
|
||||
sql1,
|
||||
@@ -2031,7 +2031,12 @@ CREATE TABLE log (
|
||||
if let Statement::CreateTable(c) = &result1[0] {
|
||||
c.columns.iter().for_each(|col| {
|
||||
if col.name().value == "msg" {
|
||||
assert!(col.extensions.fulltext_options.as_ref().unwrap().is_empty());
|
||||
assert!(col
|
||||
.extensions
|
||||
.fulltext_index_options
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.is_empty());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
@@ -2041,7 +2046,7 @@ CREATE TABLE log (
|
||||
let sql2 = r"
|
||||
CREATE TABLE log (
|
||||
ts TIMESTAMP TIME INDEX,
|
||||
msg STRING FULLTEXT WITH (analyzer='English', case_sensitive='false')
|
||||
msg STRING FULLTEXT INDEX WITH (analyzer='English', case_sensitive='false')
|
||||
)";
|
||||
let result2 = ParserContext::create_with_dialect(
|
||||
sql2,
|
||||
@@ -2053,7 +2058,7 @@ CREATE TABLE log (
|
||||
if let Statement::CreateTable(c) = &result2[0] {
|
||||
c.columns.iter().for_each(|col| {
|
||||
if col.name().value == "msg" {
|
||||
let options = col.extensions.fulltext_options.as_ref().unwrap();
|
||||
let options = col.extensions.fulltext_index_options.as_ref().unwrap();
|
||||
assert_eq!(options.len(), 2);
|
||||
assert_eq!(options.get("analyzer").unwrap(), "English");
|
||||
assert_eq!(options.get("case_sensitive").unwrap(), "false");
|
||||
@@ -2066,8 +2071,8 @@ CREATE TABLE log (
|
||||
let sql3 = r"
|
||||
CREATE TABLE log (
|
||||
ts TIMESTAMP TIME INDEX,
|
||||
msg1 TINYTEXT FULLTEXT WITH (analyzer='English', case_sensitive='false'),
|
||||
msg2 CHAR(20) FULLTEXT WITH (analyzer='Chinese', case_sensitive='true')
|
||||
msg1 TINYTEXT FULLTEXT INDEX WITH (analyzer='English', case_sensitive='false'),
|
||||
msg2 CHAR(20) FULLTEXT INDEX WITH (analyzer='Chinese', case_sensitive='true')
|
||||
)";
|
||||
let result3 = ParserContext::create_with_dialect(
|
||||
sql3,
|
||||
@@ -2079,12 +2084,12 @@ CREATE TABLE log (
|
||||
if let Statement::CreateTable(c) = &result3[0] {
|
||||
c.columns.iter().for_each(|col| {
|
||||
if col.name().value == "msg1" {
|
||||
let options = col.extensions.fulltext_options.as_ref().unwrap();
|
||||
let options = col.extensions.fulltext_index_options.as_ref().unwrap();
|
||||
assert_eq!(options.len(), 2);
|
||||
assert_eq!(options.get("analyzer").unwrap(), "English");
|
||||
assert_eq!(options.get("case_sensitive").unwrap(), "false");
|
||||
} else if col.name().value == "msg2" {
|
||||
let options = col.extensions.fulltext_options.as_ref().unwrap();
|
||||
let options = col.extensions.fulltext_index_options.as_ref().unwrap();
|
||||
assert_eq!(options.len(), 2);
|
||||
assert_eq!(options.get("analyzer").unwrap(), "Chinese");
|
||||
assert_eq!(options.get("case_sensitive").unwrap(), "true");
|
||||
@@ -2100,7 +2105,7 @@ CREATE TABLE log (
|
||||
let sql = r"
|
||||
CREATE TABLE log (
|
||||
ts TIMESTAMP TIME INDEX,
|
||||
msg INT FULLTEXT,
|
||||
msg INT FULLTEXT INDEX,
|
||||
)";
|
||||
let result =
|
||||
ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
|
||||
@@ -2116,7 +2121,7 @@ CREATE TABLE log (
|
||||
let sql = r"
|
||||
CREATE TABLE log (
|
||||
ts TIMESTAMP TIME INDEX,
|
||||
msg STRING FULLTEXT WITH (analyzer='English', analyzer='Chinese') FULLTEXT WITH (case_sensitive='false')
|
||||
msg STRING FULLTEXT INDEX WITH (analyzer='English', analyzer='Chinese') FULLTEXT INDEX WITH (case_sensitive='false')
|
||||
)";
|
||||
let result =
|
||||
ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
|
||||
@@ -2124,7 +2129,7 @@ CREATE TABLE log (
|
||||
assert!(result
|
||||
.unwrap_err()
|
||||
.to_string()
|
||||
.contains("duplicated FULLTEXT option"));
|
||||
.contains("duplicated FULLTEXT INDEX option"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -2132,7 +2137,7 @@ CREATE TABLE log (
|
||||
let sql = r"
|
||||
CREATE TABLE log (
|
||||
ts TIMESTAMP TIME INDEX,
|
||||
msg STRING FULLTEXT WITH (analyzer='English', invalid_option='Chinese')
|
||||
msg STRING FULLTEXT INDEX WITH (analyzer='English', invalid_option='Chinese')
|
||||
)";
|
||||
let result =
|
||||
ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
|
||||
@@ -2140,7 +2145,7 @@ CREATE TABLE log (
|
||||
assert!(result
|
||||
.unwrap_err()
|
||||
.to_string()
|
||||
.contains("invalid FULLTEXT option"));
|
||||
.contains("invalid FULLTEXT INDEX option"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -2274,4 +2279,200 @@ CREATE TABLE log (
|
||||
ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_column_extensions_vector() {
|
||||
let sql = "VECTOR(128)";
|
||||
let dialect = GenericDialect {};
|
||||
let mut tokenizer = Tokenizer::new(&dialect, sql);
|
||||
let tokens = tokenizer.tokenize().unwrap();
|
||||
let mut parser = Parser::new(&dialect).with_tokens(tokens);
|
||||
let name = Ident::new("vec_col");
|
||||
let data_type = DataType::Custom(
|
||||
ObjectName(vec![Ident::new("VECTOR")]),
|
||||
vec!["128".to_string()],
|
||||
);
|
||||
let mut extensions = ColumnExtensions::default();
|
||||
|
||||
let result =
|
||||
ParserContext::parse_column_extensions(&mut parser, &name, &data_type, &mut extensions);
|
||||
assert!(result.is_ok());
|
||||
assert!(extensions.vector_options.is_some());
|
||||
let vector_options = extensions.vector_options.unwrap();
|
||||
assert_eq!(vector_options.get(VECTOR_OPT_DIM), Some(&"128".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_column_extensions_vector_invalid() {
|
||||
let sql = "VECTOR()";
|
||||
let dialect = GenericDialect {};
|
||||
let mut tokenizer = Tokenizer::new(&dialect, sql);
|
||||
let tokens = tokenizer.tokenize().unwrap();
|
||||
let mut parser = Parser::new(&dialect).with_tokens(tokens);
|
||||
let name = Ident::new("vec_col");
|
||||
let data_type = DataType::Custom(ObjectName(vec![Ident::new("VECTOR")]), vec![]);
|
||||
let mut extensions = ColumnExtensions::default();
|
||||
|
||||
let result =
|
||||
ParserContext::parse_column_extensions(&mut parser, &name, &data_type, &mut extensions);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_column_extensions_indices() {
|
||||
// Test skipping index
|
||||
{
|
||||
let sql = "SKIPPING INDEX";
|
||||
let dialect = GenericDialect {};
|
||||
let mut tokenizer = Tokenizer::new(&dialect, sql);
|
||||
let tokens = tokenizer.tokenize().unwrap();
|
||||
let mut parser = Parser::new(&dialect).with_tokens(tokens);
|
||||
let name = Ident::new("col");
|
||||
let data_type = DataType::String(None);
|
||||
let mut extensions = ColumnExtensions::default();
|
||||
let result = ParserContext::parse_column_extensions(
|
||||
&mut parser,
|
||||
&name,
|
||||
&data_type,
|
||||
&mut extensions,
|
||||
);
|
||||
assert!(result.is_ok());
|
||||
assert!(extensions.skipping_index_options.is_some());
|
||||
}
|
||||
|
||||
// Test fulltext index with options
|
||||
{
|
||||
let sql = "FULLTEXT INDEX WITH (analyzer = 'English', case_sensitive = 'true')";
|
||||
let dialect = GenericDialect {};
|
||||
let mut tokenizer = Tokenizer::new(&dialect, sql);
|
||||
let tokens = tokenizer.tokenize().unwrap();
|
||||
let mut parser = Parser::new(&dialect).with_tokens(tokens);
|
||||
let name = Ident::new("text_col");
|
||||
let data_type = DataType::String(None);
|
||||
let mut extensions = ColumnExtensions::default();
|
||||
let result = ParserContext::parse_column_extensions(
|
||||
&mut parser,
|
||||
&name,
|
||||
&data_type,
|
||||
&mut extensions,
|
||||
);
|
||||
assert!(result.unwrap());
|
||||
assert!(extensions.fulltext_index_options.is_some());
|
||||
let fulltext_options = extensions.fulltext_index_options.unwrap();
|
||||
assert_eq!(
|
||||
fulltext_options.get("analyzer"),
|
||||
Some(&"English".to_string())
|
||||
);
|
||||
assert_eq!(
|
||||
fulltext_options.get("case_sensitive"),
|
||||
Some(&"true".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
// Test fulltext index with invalid type (should fail)
|
||||
{
|
||||
let sql = "FULLTEXT INDEX WITH (analyzer = 'English')";
|
||||
let dialect = GenericDialect {};
|
||||
let mut tokenizer = Tokenizer::new(&dialect, sql);
|
||||
let tokens = tokenizer.tokenize().unwrap();
|
||||
let mut parser = Parser::new(&dialect).with_tokens(tokens);
|
||||
let name = Ident::new("num_col");
|
||||
let data_type = DataType::Int(None); // Non-string type
|
||||
let mut extensions = ColumnExtensions::default();
|
||||
let result = ParserContext::parse_column_extensions(
|
||||
&mut parser,
|
||||
&name,
|
||||
&data_type,
|
||||
&mut extensions,
|
||||
);
|
||||
assert!(result.is_err());
|
||||
assert!(result
|
||||
.unwrap_err()
|
||||
.to_string()
|
||||
.contains("FULLTEXT index only supports string type"));
|
||||
}
|
||||
|
||||
// Test fulltext index with invalid option (won't fail, the parser doesn't check the option's content)
|
||||
{
|
||||
let sql = "FULLTEXT INDEX WITH (analyzer = 'Invalid', case_sensitive = 'true')";
|
||||
let dialect = GenericDialect {};
|
||||
let mut tokenizer = Tokenizer::new(&dialect, sql);
|
||||
let tokens = tokenizer.tokenize().unwrap();
|
||||
let mut parser = Parser::new(&dialect).with_tokens(tokens);
|
||||
let name = Ident::new("text_col");
|
||||
let data_type = DataType::String(None);
|
||||
let mut extensions = ColumnExtensions::default();
|
||||
let result = ParserContext::parse_column_extensions(
|
||||
&mut parser,
|
||||
&name,
|
||||
&data_type,
|
||||
&mut extensions,
|
||||
);
|
||||
assert!(result.unwrap());
|
||||
}
|
||||
|
||||
// Test inverted index
|
||||
{
|
||||
let sql = "INVERTED INDEX";
|
||||
let dialect = GenericDialect {};
|
||||
let mut tokenizer = Tokenizer::new(&dialect, sql);
|
||||
let tokens = tokenizer.tokenize().unwrap();
|
||||
let mut parser = Parser::new(&dialect).with_tokens(tokens);
|
||||
let name = Ident::new("col");
|
||||
let data_type = DataType::String(None);
|
||||
let mut extensions = ColumnExtensions::default();
|
||||
let result = ParserContext::parse_column_extensions(
|
||||
&mut parser,
|
||||
&name,
|
||||
&data_type,
|
||||
&mut extensions,
|
||||
);
|
||||
assert!(result.is_ok());
|
||||
assert!(extensions.inverted_index_options.is_some());
|
||||
}
|
||||
|
||||
// Test inverted index with options (should fail)
|
||||
{
|
||||
let sql = "INVERTED INDEX WITH (analyzer = 'English')";
|
||||
let dialect = GenericDialect {};
|
||||
let mut tokenizer = Tokenizer::new(&dialect, sql);
|
||||
let tokens = tokenizer.tokenize().unwrap();
|
||||
let mut parser = Parser::new(&dialect).with_tokens(tokens);
|
||||
let name = Ident::new("col");
|
||||
let data_type = DataType::String(None);
|
||||
let mut extensions = ColumnExtensions::default();
|
||||
let result = ParserContext::parse_column_extensions(
|
||||
&mut parser,
|
||||
&name,
|
||||
&data_type,
|
||||
&mut extensions,
|
||||
);
|
||||
assert!(result.is_err());
|
||||
assert!(result
|
||||
.unwrap_err()
|
||||
.to_string()
|
||||
.contains("INVERTED index doesn't support options"));
|
||||
}
|
||||
|
||||
// Test multiple indices
|
||||
{
|
||||
let sql = "SKIPPING INDEX FULLTEXT INDEX";
|
||||
let dialect = GenericDialect {};
|
||||
let mut tokenizer = Tokenizer::new(&dialect, sql);
|
||||
let tokens = tokenizer.tokenize().unwrap();
|
||||
let mut parser = Parser::new(&dialect).with_tokens(tokens);
|
||||
let name = Ident::new("col");
|
||||
let data_type = DataType::String(None);
|
||||
let mut extensions = ColumnExtensions::default();
|
||||
let result = ParserContext::parse_column_extensions(
|
||||
&mut parser,
|
||||
&name,
|
||||
&data_type,
|
||||
&mut extensions,
|
||||
);
|
||||
assert!(result.unwrap());
|
||||
assert!(extensions.skipping_index_options.is_some());
|
||||
assert!(extensions.fulltext_index_options.is_some());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -463,8 +463,6 @@ pub fn has_primary_key_option(column_def: &ColumnDef) -> bool {
|
||||
pub fn column_to_schema(
|
||||
column: &Column,
|
||||
time_index: &str,
|
||||
invereted_index_cols: &Option<Vec<String>>,
|
||||
primary_keys: &[String],
|
||||
timezone: Option<&Timezone>,
|
||||
) -> Result<ColumnSchema> {
|
||||
let is_time_index = column.name().value == time_index;
|
||||
@@ -487,20 +485,6 @@ pub fn column_to_schema(
|
||||
column: &column.name().value,
|
||||
})?;
|
||||
|
||||
// To keep compatibility,
|
||||
// 1. if inverted index columns is not set, leave it empty meaning primary key columns will be used
|
||||
// 2. if inverted index columns is set and non-empty, set selected columns to be inverted indexed
|
||||
// 3. if inverted index columns is set and empty, set primary key columns to be non-inverted indexed explicitly
|
||||
if let Some(inverted_index_cols) = invereted_index_cols {
|
||||
if inverted_index_cols.is_empty() {
|
||||
if primary_keys.contains(&column.name().value) {
|
||||
column_schema.insert_inverted_index_placeholder();
|
||||
}
|
||||
} else if inverted_index_cols.contains(&column.name().value) {
|
||||
column_schema.set_inverted_index(true);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ColumnOption::Comment(c)) = column.options().iter().find_map(|o| {
|
||||
if matches!(o.option, ColumnOption::Comment(_)) {
|
||||
Some(&o.option)
|
||||
@@ -525,6 +509,8 @@ pub fn column_to_schema(
|
||||
.context(SetSkippingIndexOptionSnafu)?;
|
||||
}
|
||||
|
||||
column_schema.set_inverted_index(column.extensions.inverted_index_options.is_some());
|
||||
|
||||
Ok(column_schema)
|
||||
}
|
||||
|
||||
@@ -1382,7 +1368,7 @@ mod tests {
|
||||
extensions: ColumnExtensions::default(),
|
||||
};
|
||||
|
||||
let column_schema = column_to_schema(&column_def, "ts", &None, &[], None).unwrap();
|
||||
let column_schema = column_to_schema(&column_def, "ts", None).unwrap();
|
||||
|
||||
assert_eq!("col", column_schema.name);
|
||||
assert_eq!(
|
||||
@@ -1392,7 +1378,7 @@ mod tests {
|
||||
assert!(column_schema.is_nullable());
|
||||
assert!(!column_schema.is_time_index());
|
||||
|
||||
let column_schema = column_to_schema(&column_def, "col", &None, &[], None).unwrap();
|
||||
let column_schema = column_to_schema(&column_def, "col", None).unwrap();
|
||||
|
||||
assert_eq!("col", column_schema.name);
|
||||
assert_eq!(
|
||||
@@ -1421,7 +1407,7 @@ mod tests {
|
||||
extensions: ColumnExtensions::default(),
|
||||
};
|
||||
|
||||
let column_schema = column_to_schema(&column_def, "ts", &None, &[], None).unwrap();
|
||||
let column_schema = column_to_schema(&column_def, "ts", None).unwrap();
|
||||
|
||||
assert_eq!("col2", column_schema.name);
|
||||
assert_eq!(ConcreteDataType::string_datatype(), column_schema.data_type);
|
||||
@@ -1456,8 +1442,6 @@ mod tests {
|
||||
let column_schema = column_to_schema(
|
||||
&column,
|
||||
"ts",
|
||||
&None,
|
||||
&[],
|
||||
Some(&Timezone::from_tz_string("Asia/Shanghai").unwrap()),
|
||||
)
|
||||
.unwrap();
|
||||
@@ -1476,7 +1460,7 @@ mod tests {
|
||||
);
|
||||
|
||||
// without timezone
|
||||
let column_schema = column_to_schema(&column, "ts", &None, &[], None).unwrap();
|
||||
let column_schema = column_to_schema(&column, "ts", None).unwrap();
|
||||
|
||||
assert_eq!("col", column_schema.name);
|
||||
assert_eq!(
|
||||
@@ -1502,7 +1486,7 @@ mod tests {
|
||||
options: vec![],
|
||||
},
|
||||
extensions: ColumnExtensions {
|
||||
fulltext_options: Some(
|
||||
fulltext_index_options: Some(
|
||||
HashMap::from_iter([
|
||||
(
|
||||
COLUMN_FULLTEXT_OPT_KEY_ANALYZER.to_string(),
|
||||
@@ -1517,10 +1501,11 @@ mod tests {
|
||||
),
|
||||
vector_options: None,
|
||||
skipping_index_options: None,
|
||||
inverted_index_options: None,
|
||||
},
|
||||
};
|
||||
|
||||
let column_schema = column_to_schema(&column, "ts", &None, &[], None).unwrap();
|
||||
let column_schema = column_to_schema(&column, "ts", None).unwrap();
|
||||
assert_eq!("col", column_schema.name);
|
||||
assert_eq!(ConcreteDataType::string_datatype(), column_schema.data_type);
|
||||
let fulltext_options = column_schema.fulltext_options().unwrap().unwrap();
|
||||
|
||||
@@ -65,8 +65,6 @@ pub enum TableConstraint {
|
||||
PrimaryKey { columns: Vec<Ident> },
|
||||
/// Time index constraint.
|
||||
TimeIndex { column: Ident },
|
||||
/// Inverted index constraint.
|
||||
InvertedIndex { columns: Vec<Ident> },
|
||||
}
|
||||
|
||||
impl Display for TableConstraint {
|
||||
@@ -78,9 +76,6 @@ impl Display for TableConstraint {
|
||||
TableConstraint::TimeIndex { column } => {
|
||||
write!(f, "TIME INDEX ({})", column)
|
||||
}
|
||||
TableConstraint::InvertedIndex { columns } => {
|
||||
write!(f, "INVERTED INDEX ({})", format_list_comma!(columns))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -112,12 +107,17 @@ pub struct Column {
|
||||
/// Column extensions for greptimedb dialect.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Visit, VisitMut, Default, Serialize)]
|
||||
pub struct ColumnExtensions {
|
||||
/// Fulltext options.
|
||||
pub fulltext_options: Option<OptionMap>,
|
||||
/// Vector options.
|
||||
/// Vector type options.
|
||||
pub vector_options: Option<OptionMap>,
|
||||
|
||||
/// Fulltext index options.
|
||||
pub fulltext_index_options: Option<OptionMap>,
|
||||
/// Skipping index options.
|
||||
pub skipping_index_options: Option<OptionMap>,
|
||||
/// Inverted index options.
|
||||
///
|
||||
/// Inverted index doesn't have options at present. There won't be any options in that map.
|
||||
pub inverted_index_options: Option<OptionMap>,
|
||||
}
|
||||
|
||||
impl Column {
|
||||
@@ -152,7 +152,8 @@ impl Display for Column {
|
||||
}
|
||||
|
||||
write!(f, "{}", self.column_def)?;
|
||||
if let Some(fulltext_options) = &self.extensions.fulltext_options {
|
||||
|
||||
if let Some(fulltext_options) = &self.extensions.fulltext_index_options {
|
||||
if !fulltext_options.is_empty() {
|
||||
let options = fulltext_options.kv_pairs();
|
||||
write!(f, " FULLTEXT WITH({})", format_list_comma!(options))?;
|
||||
@@ -169,13 +170,22 @@ impl Display for Column {
|
||||
write!(f, " SKIPPING INDEX")?;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(inverted_index_options) = &self.extensions.inverted_index_options {
|
||||
if !inverted_index_options.is_empty() {
|
||||
let options = inverted_index_options.kv_pairs();
|
||||
write!(f, " INVERTED INDEX WITH({})", format_list_comma!(options))?;
|
||||
} else {
|
||||
write!(f, " INVERTED INDEX")?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ColumnExtensions {
|
||||
pub fn build_fulltext_options(&self) -> Result<Option<FulltextOptions>> {
|
||||
let Some(options) = self.fulltext_options.as_ref() else {
|
||||
let Some(options) = self.fulltext_index_options.as_ref() else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
|
||||
@@ -633,36 +633,12 @@ impl RegionMetadataBuilder {
|
||||
.map(|col| col.column_schema.name.clone())
|
||||
.collect();
|
||||
|
||||
let pk_as_inverted_index = !self
|
||||
.column_metadatas
|
||||
.iter()
|
||||
.any(|c| c.column_schema.has_inverted_index_key());
|
||||
let mut set_inverted_index_for_primary_keys = false;
|
||||
|
||||
for add_column in columns {
|
||||
if names.contains(&add_column.column_metadata.column_schema.name) {
|
||||
// Column already exists.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Handles using primary key as inverted index.
|
||||
let has_inverted_index_key = add_column
|
||||
.column_metadata
|
||||
.column_schema
|
||||
.has_inverted_index_key();
|
||||
|
||||
if pk_as_inverted_index
|
||||
&& has_inverted_index_key
|
||||
&& !set_inverted_index_for_primary_keys
|
||||
{
|
||||
self.column_metadatas.iter_mut().for_each(|col| {
|
||||
if col.semantic_type == SemanticType::Tag {
|
||||
col.column_schema.set_inverted_index(true);
|
||||
}
|
||||
});
|
||||
set_inverted_index_for_primary_keys = true;
|
||||
}
|
||||
|
||||
let column_id = add_column.column_metadata.column_id;
|
||||
let semantic_type = add_column.column_metadata.semantic_type;
|
||||
let column_name = add_column.column_metadata.column_schema.name.clone();
|
||||
@@ -1526,6 +1502,8 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_add_column_with_inverted_index() {
|
||||
// only set inverted index to true explicitly will this column be inverted indexed
|
||||
|
||||
// a (tag), b (field), c (ts)
|
||||
let metadata = build_test_region_metadata();
|
||||
let mut builder = RegionMetadataBuilder::from_existing(metadata);
|
||||
@@ -1550,7 +1528,7 @@ mod test {
|
||||
check_columns(&metadata, &["a", "b", "c", "d", "e"]);
|
||||
assert_eq!([1, 4, 5], &metadata.primary_key[..]);
|
||||
let column_metadata = metadata.column_by_name("a").unwrap();
|
||||
assert!(column_metadata.column_schema.is_inverted_indexed());
|
||||
assert!(!column_metadata.column_schema.is_inverted_indexed());
|
||||
let column_metadata = metadata.column_by_name("b").unwrap();
|
||||
assert!(!column_metadata.column_schema.is_inverted_indexed());
|
||||
let column_metadata = metadata.column_by_name("c").unwrap();
|
||||
|
||||
@@ -283,34 +283,10 @@ impl TableMeta {
|
||||
let mut columns: Vec<ColumnSchema> =
|
||||
Vec::with_capacity(table_schema.column_schemas().len());
|
||||
|
||||
// When we are setting inverted index for the first time
|
||||
// (schemas.all(!has_inverted_index_key)).
|
||||
// We need to make sure the table's primary index's inverted index
|
||||
// property is set to true.
|
||||
let pk_as_inverted_index = !self
|
||||
.schema
|
||||
.column_schemas()
|
||||
.iter()
|
||||
.any(|c| c.has_inverted_index_key());
|
||||
|
||||
for (i, column_schema) in table_schema.column_schemas().iter().enumerate() {
|
||||
for column_schema in table_schema.column_schemas().iter() {
|
||||
if column_schema.name == column_name {
|
||||
// If user explicitly unset an inverted index in primary keys.
|
||||
// We should invalidate the primary key as inverted index
|
||||
// on the condition of schemas.all(!has_inverted_index_key).
|
||||
if !value && self.primary_key_indices.contains(&i) {
|
||||
let mut new_column_schema = column_schema.clone();
|
||||
new_column_schema.insert_inverted_index_placeholder();
|
||||
columns.push(new_column_schema);
|
||||
} else {
|
||||
let mut new_column_schema = column_schema.clone();
|
||||
new_column_schema.set_inverted_index(value);
|
||||
columns.push(new_column_schema);
|
||||
}
|
||||
} else if pk_as_inverted_index && self.primary_key_indices.contains(&i) {
|
||||
// Need to set inverted_indexed=true for all other columns in primary key.
|
||||
let mut new_column_schema = column_schema.clone();
|
||||
new_column_schema.set_inverted_index(true);
|
||||
new_column_schema.set_inverted_index(value);
|
||||
columns.push(new_column_schema);
|
||||
} else {
|
||||
columns.push(column_schema.clone());
|
||||
|
||||
@@ -34,36 +34,34 @@ SELECT fox FROM fox WHERE MATCHES(fox, '"fox jumps"') ORDER BY ts;
|
||||
|
||||
SHOW CREATE TABLE fox;
|
||||
|
||||
+-------+------------------------------------+
|
||||
| Table | Create Table |
|
||||
+-------+------------------------------------+
|
||||
| fox | CREATE TABLE IF NOT EXISTS "fox" ( |
|
||||
| | "ts" TIMESTAMP(3) NOT NULL, |
|
||||
| | "fox" STRING NULL, |
|
||||
| | TIME INDEX ("ts"), |
|
||||
| | INVERTED INDEX ("fox") |
|
||||
| | ) |
|
||||
| | |
|
||||
| | ENGINE=mito |
|
||||
| | |
|
||||
+-------+------------------------------------+
|
||||
+-------+-------------------------------------+
|
||||
| Table | Create Table |
|
||||
+-------+-------------------------------------+
|
||||
| fox | CREATE TABLE IF NOT EXISTS "fox" ( |
|
||||
| | "ts" TIMESTAMP(3) NOT NULL, |
|
||||
| | "fox" STRING NULL INVERTED INDEX, |
|
||||
| | TIME INDEX ("ts") |
|
||||
| | ) |
|
||||
| | |
|
||||
| | ENGINE=mito |
|
||||
| | |
|
||||
+-------+-------------------------------------+
|
||||
|
||||
-- SQLNESS ARG restart=true
|
||||
SHOW CREATE TABLE fox;
|
||||
|
||||
+-------+------------------------------------+
|
||||
| Table | Create Table |
|
||||
+-------+------------------------------------+
|
||||
| fox | CREATE TABLE IF NOT EXISTS "fox" ( |
|
||||
| | "ts" TIMESTAMP(3) NOT NULL, |
|
||||
| | "fox" STRING NULL, |
|
||||
| | TIME INDEX ("ts"), |
|
||||
| | INVERTED INDEX ("fox") |
|
||||
| | ) |
|
||||
| | |
|
||||
| | ENGINE=mito |
|
||||
| | |
|
||||
+-------+------------------------------------+
|
||||
+-------+-------------------------------------+
|
||||
| Table | Create Table |
|
||||
+-------+-------------------------------------+
|
||||
| fox | CREATE TABLE IF NOT EXISTS "fox" ( |
|
||||
| | "ts" TIMESTAMP(3) NOT NULL, |
|
||||
| | "fox" STRING NULL INVERTED INDEX, |
|
||||
| | TIME INDEX ("ts") |
|
||||
| | ) |
|
||||
| | |
|
||||
| | ENGINE=mito |
|
||||
| | |
|
||||
+-------+-------------------------------------+
|
||||
|
||||
SHOW INDEX FROM fox;
|
||||
|
||||
@@ -127,13 +125,13 @@ Affected Rows: 0
|
||||
|
||||
SHOW INDEX FROM test_pk;
|
||||
|
||||
+---------+------------+-------------------------+--------------+-------------+-----------+-------------+----------+--------+------+-----------------------------------------------------+---------+---------------+---------+------------+
|
||||
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
|
||||
+---------+------------+-------------------------+--------------+-------------+-----------+-------------+----------+--------+------+-----------------------------------------------------+---------+---------------+---------+------------+
|
||||
| test_pk | 1 | PRIMARY, INVERTED INDEX | 3 | bar | A | | | | YES | greptime-primary-key-v1, greptime-inverted-index-v1 | | | YES | |
|
||||
| test_pk | 1 | PRIMARY, INVERTED INDEX | 2 | foo | A | | | | YES | greptime-primary-key-v1, greptime-inverted-index-v1 | | | YES | |
|
||||
| test_pk | 1 | TIME INDEX | 1 | ts | A | | | | NO | | | | YES | |
|
||||
+---------+------------+-------------------------+--------------+-------------+-----------+-------------+----------+--------+------+-----------------------------------------------------+---------+---------------+---------+------------+
|
||||
+---------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+-------------------------+---------+---------------+---------+------------+
|
||||
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
|
||||
+---------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+-------------------------+---------+---------------+---------+------------+
|
||||
| test_pk | 1 | PRIMARY | 3 | bar | A | | | | YES | greptime-primary-key-v1 | | | YES | |
|
||||
| test_pk | 1 | PRIMARY | 2 | foo | A | | | | YES | greptime-primary-key-v1 | | | YES | |
|
||||
| test_pk | 1 | TIME INDEX | 1 | ts | A | | | | NO | | | | YES | |
|
||||
+---------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+-------------------------+---------+---------------+---------+------------+
|
||||
|
||||
ALTER TABLE test_pk MODIFY COLUMN foo UNSET INVERTED INDEX;
|
||||
|
||||
@@ -141,13 +139,13 @@ Affected Rows: 0
|
||||
|
||||
SHOW INDEX FROM test_pk;
|
||||
|
||||
+---------+------------+-------------------------+--------------+-------------+-----------+-------------+----------+--------+------+-----------------------------------------------------+---------+---------------+---------+------------+
|
||||
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
|
||||
+---------+------------+-------------------------+--------------+-------------+-----------+-------------+----------+--------+------+-----------------------------------------------------+---------+---------------+---------+------------+
|
||||
| test_pk | 1 | PRIMARY, INVERTED INDEX | 3 | bar | A | | | | YES | greptime-primary-key-v1, greptime-inverted-index-v1 | | | YES | |
|
||||
| test_pk | 1 | PRIMARY | 2 | foo | A | | | | YES | greptime-primary-key-v1 | | | YES | |
|
||||
| test_pk | 1 | TIME INDEX | 1 | ts | A | | | | NO | | | | YES | |
|
||||
+---------+------------+-------------------------+--------------+-------------+-----------+-------------+----------+--------+------+-----------------------------------------------------+---------+---------------+---------+------------+
|
||||
+---------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+-------------------------+---------+---------------+---------+------------+
|
||||
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
|
||||
+---------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+-------------------------+---------+---------------+---------+------------+
|
||||
| test_pk | 1 | PRIMARY | 3 | bar | A | | | | YES | greptime-primary-key-v1 | | | YES | |
|
||||
| test_pk | 1 | PRIMARY | 2 | foo | A | | | | YES | greptime-primary-key-v1 | | | YES | |
|
||||
| test_pk | 1 | TIME INDEX | 1 | ts | A | | | | NO | | | | YES | |
|
||||
+---------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+-------------------------+---------+---------------+---------+------------+
|
||||
|
||||
ALTER TABLE test_pk MODIFY COLUMN bar UNSET INVERTED INDEX;
|
||||
|
||||
|
||||
@@ -73,24 +73,23 @@ DESC TABLE phy;
|
||||
|
||||
SHOW CREATE TABLE phy;
|
||||
|
||||
+-------+------------------------------------+
|
||||
| Table | Create Table |
|
||||
+-------+------------------------------------+
|
||||
| phy | CREATE TABLE IF NOT EXISTS "phy" ( |
|
||||
| | "ts" TIMESTAMP(3) NOT NULL, |
|
||||
| | "val" DOUBLE NULL, |
|
||||
| | "host" STRING NULL, |
|
||||
| | "job" STRING NULL, |
|
||||
| | TIME INDEX ("ts"), |
|
||||
| | PRIMARY KEY ("host", "job"), |
|
||||
| | INVERTED INDEX ("host", "job") |
|
||||
| | ) |
|
||||
| | |
|
||||
| | ENGINE=metric |
|
||||
| | WITH( |
|
||||
| | physical_metric_table = '' |
|
||||
| | ) |
|
||||
+-------+------------------------------------+
|
||||
+-------+--------------------------------------+
|
||||
| Table | Create Table |
|
||||
+-------+--------------------------------------+
|
||||
| phy | CREATE TABLE IF NOT EXISTS "phy" ( |
|
||||
| | "ts" TIMESTAMP(3) NOT NULL, |
|
||||
| | "val" DOUBLE NULL, |
|
||||
| | "host" STRING NULL INVERTED INDEX, |
|
||||
| | "job" STRING NULL INVERTED INDEX, |
|
||||
| | TIME INDEX ("ts"), |
|
||||
| | PRIMARY KEY ("host", "job") |
|
||||
| | ) |
|
||||
| | |
|
||||
| | ENGINE=metric |
|
||||
| | WITH( |
|
||||
| | physical_metric_table = '' |
|
||||
| | ) |
|
||||
+-------+--------------------------------------+
|
||||
|
||||
DESC TABLE t1;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
CREATE TABLE log (
|
||||
ts TIMESTAMP TIME INDEX,
|
||||
msg STRING FULLTEXT,
|
||||
msg STRING FULLTEXT INDEX,
|
||||
);
|
||||
|
||||
Affected Rows: 0
|
||||
@@ -26,7 +26,7 @@ Affected Rows: 0
|
||||
|
||||
CREATE TABLE log_with_opts (
|
||||
ts TIMESTAMP TIME INDEX,
|
||||
msg TEXT FULLTEXT WITH (analyzer='English', case_sensitive='true'),
|
||||
msg TEXT FULLTEXT INDEX WITH (analyzer='English', case_sensitive='true'),
|
||||
);
|
||||
|
||||
Affected Rows: 0
|
||||
@@ -52,8 +52,8 @@ Affected Rows: 0
|
||||
|
||||
CREATE TABLE log_multi_fulltext_cols (
|
||||
ts TIMESTAMP TIME INDEX,
|
||||
msg TINYTEXT FULLTEXT,
|
||||
msg2 VARCHAR FULLTEXT,
|
||||
msg TINYTEXT FULLTEXT INDEX,
|
||||
msg2 VARCHAR FULLTEXT INDEX,
|
||||
);
|
||||
|
||||
Affected Rows: 0
|
||||
@@ -83,19 +83,19 @@ CREATE TABLE log_dup_fulltext_opts (
|
||||
msg TEXT FULLTEXT FULLTEXT,
|
||||
);
|
||||
|
||||
Error: 1004(InvalidArguments), Invalid column option, column name: msg, error: duplicated FULLTEXT option
|
||||
Error: 1004(InvalidArguments), Invalid column option, column name: msg, error: expect INDEX after FULLTEXT keyword
|
||||
|
||||
CREATE TABLE log_with_invalid_type (
|
||||
ts TIMESTAMP TIME INDEX,
|
||||
msg INT FULLTEXT,
|
||||
msg INT FULLTEXT INDEX,
|
||||
);
|
||||
|
||||
Error: 1004(InvalidArguments), Invalid column option, column name: msg, error: FULLTEXT index only supports string type
|
||||
|
||||
CREATE TABLE log_with_invalid_option (
|
||||
ts TIMESTAMP TIME INDEX,
|
||||
msg TEXT FULLTEXT WITH (analyzer='English', invalid_option='true'),
|
||||
msg TEXT FULLTEXT INDEX WITH (analyzer='English', invalid_option='true'),
|
||||
);
|
||||
|
||||
Error: 1004(InvalidArguments), Invalid column option, column name: msg, error: invalid FULLTEXT option: invalid_option
|
||||
Error: 1004(InvalidArguments), Invalid column option, column name: msg, error: invalid FULLTEXT INDEX option: invalid_option
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
CREATE TABLE log (
|
||||
ts TIMESTAMP TIME INDEX,
|
||||
msg STRING FULLTEXT,
|
||||
msg STRING FULLTEXT INDEX,
|
||||
);
|
||||
|
||||
SHOW CREATE TABLE log;
|
||||
@@ -10,7 +10,7 @@ DROP TABLE log;
|
||||
|
||||
CREATE TABLE log_with_opts (
|
||||
ts TIMESTAMP TIME INDEX,
|
||||
msg TEXT FULLTEXT WITH (analyzer='English', case_sensitive='true'),
|
||||
msg TEXT FULLTEXT INDEX WITH (analyzer='English', case_sensitive='true'),
|
||||
);
|
||||
|
||||
SHOW CREATE TABLE log_with_opts;
|
||||
@@ -20,8 +20,8 @@ DROP TABLE log_with_opts;
|
||||
|
||||
CREATE TABLE log_multi_fulltext_cols (
|
||||
ts TIMESTAMP TIME INDEX,
|
||||
msg TINYTEXT FULLTEXT,
|
||||
msg2 VARCHAR FULLTEXT,
|
||||
msg TINYTEXT FULLTEXT INDEX,
|
||||
msg2 VARCHAR FULLTEXT INDEX,
|
||||
);
|
||||
|
||||
SHOW CREATE TABLE log_multi_fulltext_cols;
|
||||
@@ -36,10 +36,10 @@ CREATE TABLE log_dup_fulltext_opts (
|
||||
|
||||
CREATE TABLE log_with_invalid_type (
|
||||
ts TIMESTAMP TIME INDEX,
|
||||
msg INT FULLTEXT,
|
||||
msg INT FULLTEXT INDEX,
|
||||
);
|
||||
|
||||
CREATE TABLE log_with_invalid_option (
|
||||
ts TIMESTAMP TIME INDEX,
|
||||
msg TEXT FULLTEXT WITH (analyzer='English', invalid_option='true'),
|
||||
msg TEXT FULLTEXT INDEX WITH (analyzer='English', invalid_option='true'),
|
||||
);
|
||||
|
||||
@@ -5,7 +5,7 @@ CREATE TABLE `ngx_access_log` (
|
||||
`referer` STRING NULL,
|
||||
`method` STRING NULL,
|
||||
`endpoint` STRING NULL,
|
||||
`trace_id` STRING NULL FULLTEXT,
|
||||
`trace_id` STRING NULL FULLTEXT INDEX,
|
||||
`protocol` STRING NULL,
|
||||
`status` SMALLINT UNSIGNED NULL,
|
||||
`size` DOUBLE NULL,
|
||||
|
||||
@@ -5,7 +5,7 @@ CREATE TABLE `ngx_access_log` (
|
||||
`referer` STRING NULL,
|
||||
`method` STRING NULL,
|
||||
`endpoint` STRING NULL,
|
||||
`trace_id` STRING NULL FULLTEXT,
|
||||
`trace_id` STRING NULL FULLTEXT INDEX,
|
||||
`protocol` STRING NULL,
|
||||
`status` SMALLINT UNSIGNED NULL,
|
||||
`size` DOUBLE NULL,
|
||||
|
||||
@@ -121,23 +121,22 @@ Affected Rows: 0
|
||||
|
||||
show create table phy;
|
||||
|
||||
+-------+------------------------------------+
|
||||
| Table | Create Table |
|
||||
+-------+------------------------------------+
|
||||
| phy | CREATE TABLE IF NOT EXISTS "phy" ( |
|
||||
| | "ts" TIMESTAMP(3) NOT NULL, |
|
||||
| | "val" DOUBLE NULL, |
|
||||
| | "host" STRING NULL, |
|
||||
| | TIME INDEX ("ts"), |
|
||||
| | PRIMARY KEY ("host"), |
|
||||
| | INVERTED INDEX ("host") |
|
||||
| | ) |
|
||||
| | |
|
||||
| | ENGINE=metric |
|
||||
| | WITH( |
|
||||
| | physical_metric_table = '' |
|
||||
| | ) |
|
||||
+-------+------------------------------------+
|
||||
+-------+--------------------------------------+
|
||||
| Table | Create Table |
|
||||
+-------+--------------------------------------+
|
||||
| phy | CREATE TABLE IF NOT EXISTS "phy" ( |
|
||||
| | "ts" TIMESTAMP(3) NOT NULL, |
|
||||
| | "val" DOUBLE NULL, |
|
||||
| | "host" STRING NULL INVERTED INDEX, |
|
||||
| | TIME INDEX ("ts"), |
|
||||
| | PRIMARY KEY ("host") |
|
||||
| | ) |
|
||||
| | |
|
||||
| | ENGINE=metric |
|
||||
| | WITH( |
|
||||
| | physical_metric_table = '' |
|
||||
| | ) |
|
||||
+-------+--------------------------------------+
|
||||
|
||||
show create table t1;
|
||||
|
||||
@@ -302,10 +301,9 @@ CREATE TABLE "specify_invereted_index_cols" (
|
||||
"ts" TIMESTAMP(3) NOT NULL,
|
||||
"val" DOUBLE NULL,
|
||||
"host" STRING NULL,
|
||||
"job" STRING NULL,
|
||||
"job" STRING NULL INVERTED INDEX,
|
||||
TIME INDEX ("ts"),
|
||||
PRIMARY KEY ("host", "job"),
|
||||
INVERTED INDEX ("job")
|
||||
);
|
||||
|
||||
Affected Rows: 0
|
||||
@@ -319,10 +317,9 @@ show create table specify_invereted_index_cols;
|
||||
| | "ts" TIMESTAMP(3) NOT NULL, |
|
||||
| | "val" DOUBLE NULL, |
|
||||
| | "host" STRING NULL, |
|
||||
| | "job" STRING NULL, |
|
||||
| | "job" STRING NULL INVERTED INDEX, |
|
||||
| | TIME INDEX ("ts"), |
|
||||
| | PRIMARY KEY ("host", "job"), |
|
||||
| | INVERTED INDEX ("job") |
|
||||
| | PRIMARY KEY ("host", "job") |
|
||||
| | ) |
|
||||
| | |
|
||||
| | ENGINE=mito |
|
||||
@@ -340,7 +337,6 @@ CREATE TABLE "specify_empty_invereted_index_cols" (
|
||||
"job" STRING NULL,
|
||||
TIME INDEX ("ts"),
|
||||
PRIMARY KEY ("host", "job"),
|
||||
INVERTED INDEX ()
|
||||
);
|
||||
|
||||
Affected Rows: 0
|
||||
@@ -356,8 +352,7 @@ show create table specify_empty_invereted_index_cols;
|
||||
| | "host" STRING NULL, |
|
||||
| | "job" STRING NULL, |
|
||||
| | TIME INDEX ("ts"), |
|
||||
| | PRIMARY KEY ("host", "job"), |
|
||||
| | INVERTED INDEX () |
|
||||
| | PRIMARY KEY ("host", "job") |
|
||||
| | ) |
|
||||
| | |
|
||||
| | ENGINE=mito |
|
||||
@@ -368,3 +363,32 @@ drop table specify_empty_invereted_index_cols;
|
||||
|
||||
Affected Rows: 0
|
||||
|
||||
CREATE TABLE test_column_constrain_composite_indexes (
|
||||
`id` INT SKIPPING INDEX INVERTED INDEX,
|
||||
host STRING PRIMARY KEY SKIPPING INDEX FULLTEXT INDEX INVERTED INDEX,
|
||||
ts TIMESTAMP TIME INDEX,
|
||||
);
|
||||
|
||||
Affected Rows: 0
|
||||
|
||||
show create table test_column_constrain_composite_indexes;
|
||||
|
||||
+-----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| Table | Create Table |
|
||||
+-----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| test_column_constrain_composite_indexes | CREATE TABLE IF NOT EXISTS "test_column_constrain_composite_indexes" ( |
|
||||
| | "id" INT NULL SKIPPING INDEX WITH(granularity = '10240', type = 'BLOOM') INVERTED INDEX, |
|
||||
| | "host" STRING NULL FULLTEXT WITH(analyzer = 'English', case_sensitive = 'false') SKIPPING INDEX WITH(granularity = '10240', type = 'BLOOM') INVERTED INDEX, |
|
||||
| | "ts" TIMESTAMP(3) NOT NULL, |
|
||||
| | TIME INDEX ("ts"), |
|
||||
| | PRIMARY KEY ("host") |
|
||||
| | ) |
|
||||
| | |
|
||||
| | ENGINE=mito |
|
||||
| | |
|
||||
+-----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
|
||||
drop table test_column_constrain_composite_indexes;
|
||||
|
||||
Affected Rows: 0
|
||||
|
||||
|
||||
@@ -122,10 +122,9 @@ CREATE TABLE "specify_invereted_index_cols" (
|
||||
"ts" TIMESTAMP(3) NOT NULL,
|
||||
"val" DOUBLE NULL,
|
||||
"host" STRING NULL,
|
||||
"job" STRING NULL,
|
||||
"job" STRING NULL INVERTED INDEX,
|
||||
TIME INDEX ("ts"),
|
||||
PRIMARY KEY ("host", "job"),
|
||||
INVERTED INDEX ("job")
|
||||
);
|
||||
|
||||
show create table specify_invereted_index_cols;
|
||||
@@ -139,9 +138,18 @@ CREATE TABLE "specify_empty_invereted_index_cols" (
|
||||
"job" STRING NULL,
|
||||
TIME INDEX ("ts"),
|
||||
PRIMARY KEY ("host", "job"),
|
||||
INVERTED INDEX ()
|
||||
);
|
||||
|
||||
show create table specify_empty_invereted_index_cols;
|
||||
|
||||
drop table specify_empty_invereted_index_cols;
|
||||
|
||||
CREATE TABLE test_column_constrain_composite_indexes (
|
||||
`id` INT SKIPPING INDEX INVERTED INDEX,
|
||||
host STRING PRIMARY KEY SKIPPING INDEX FULLTEXT INDEX INVERTED INDEX,
|
||||
ts TIMESTAMP TIME INDEX,
|
||||
);
|
||||
|
||||
show create table test_column_constrain_composite_indexes;
|
||||
|
||||
drop table test_column_constrain_composite_indexes;
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
CREATE TABLE IF NOT EXISTS system_metrics (
|
||||
host STRING,
|
||||
idc STRING FULLTEXT,
|
||||
idc STRING FULLTEXT INDEX INVERTED INDEX,
|
||||
cpu_util DOUBLE,
|
||||
memory_util DOUBLE,
|
||||
disk_util DOUBLE,
|
||||
desc1 STRING,
|
||||
desc2 STRING FULLTEXT,
|
||||
desc3 STRING FULLTEXT,
|
||||
desc2 STRING FULLTEXT INDEX,
|
||||
desc3 STRING FULLTEXT INDEX,
|
||||
ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY(host, idc),
|
||||
INVERTED INDEX(idc, desc1, desc2),
|
||||
TIME INDEX(ts)
|
||||
);
|
||||
|
||||
@@ -32,25 +31,42 @@ CREATE TABLE IF NOT EXISTS test_no_inverted_index (
|
||||
c DOUBLE,
|
||||
ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY(a, b),
|
||||
INVERTED INDEX(),
|
||||
TIME INDEX(ts)
|
||||
);
|
||||
|
||||
Affected Rows: 0
|
||||
|
||||
show create table test_no_inverted_index;
|
||||
|
||||
+------------------------+-------------------------------------------------------------------------------+
|
||||
| Table | Create Table |
|
||||
+------------------------+-------------------------------------------------------------------------------+
|
||||
| test_no_inverted_index | CREATE TABLE IF NOT EXISTS "test_no_inverted_index" ( |
|
||||
| | "a" STRING NULL, |
|
||||
| | "b" STRING NULL SKIPPING INDEX WITH(granularity = '10240', type = 'BLOOM'), |
|
||||
| | "c" DOUBLE NULL, |
|
||||
| | "ts" TIMESTAMP(3) NOT NULL DEFAULT current_timestamp(), |
|
||||
| | TIME INDEX ("ts"), |
|
||||
| | PRIMARY KEY ("a", "b") |
|
||||
| | ) |
|
||||
| | |
|
||||
| | ENGINE=mito |
|
||||
| | |
|
||||
+------------------------+-------------------------------------------------------------------------------+
|
||||
|
||||
SHOW INDEX;
|
||||
|
||||
Error: 2000(InvalidSyntax), Unexpected token while parsing SQL statement, expected: '{FROM | IN} table', found: ;
|
||||
|
||||
SHOW INDEX FROM test;
|
||||
|
||||
+-------+------------+-----------------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+-------------------------------------------------------------------------------+---------+---------------+---------+------------+
|
||||
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
|
||||
+-------+------------+-----------------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+-------------------------------------------------------------------------------+---------+---------------+---------+------------+
|
||||
| test | 1 | PRIMARY, INVERTED INDEX | 1 | a | A | | | | YES | greptime-primary-key-v1, greptime-inverted-index-v1 | | | YES | |
|
||||
| test | 1 | PRIMARY, INVERTED INDEX, SKIPPING INDEX | 2 | b | A | | | | YES | greptime-primary-key-v1, greptime-inverted-index-v1, greptime-bloom-filter-v1 | | | YES | |
|
||||
| test | 1 | TIME INDEX | 1 | ts | A | | | | NO | | | | YES | |
|
||||
+-------+------------+-----------------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+-------------------------------------------------------------------------------+---------+---------------+---------+------------+
|
||||
+-------+------------+-------------------------+--------------+-------------+-----------+-------------+----------+--------+------+---------------------------------------------------+---------+---------------+---------+------------+
|
||||
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
|
||||
+-------+------------+-------------------------+--------------+-------------+-----------+-------------+----------+--------+------+---------------------------------------------------+---------+---------------+---------+------------+
|
||||
| test | 1 | PRIMARY | 1 | a | A | | | | YES | greptime-primary-key-v1 | | | YES | |
|
||||
| test | 1 | PRIMARY, SKIPPING INDEX | 2 | b | A | | | | YES | greptime-primary-key-v1, greptime-bloom-filter-v1 | | | YES | |
|
||||
| test | 1 | TIME INDEX | 1 | ts | A | | | | NO | | | | YES | |
|
||||
+-------+------------+-------------------------+--------------+-------------+-----------+-------------+----------+--------+------+---------------------------------------------------+---------+---------------+---------+------------+
|
||||
|
||||
SHOW INDEX FROM test_no_inverted_index;
|
||||
|
||||
@@ -67,8 +83,7 @@ SHOW INDEX FROM system_metrics;
|
||||
+----------------+------------+-----------------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+---------------------------------------------------------------------------------+---------+---------------+---------+------------+
|
||||
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
|
||||
+----------------+------------+-----------------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+---------------------------------------------------------------------------------+---------+---------------+---------+------------+
|
||||
| system_metrics | 1 | INVERTED INDEX | 6 | desc1 | A | | | | YES | greptime-inverted-index-v1 | | | YES | |
|
||||
| system_metrics | 1 | INVERTED INDEX, FULLTEXT INDEX | 7 | desc2 | A | | | | YES | greptime-inverted-index-v1, greptime-fulltext-index-v1 | | | YES | |
|
||||
| system_metrics | 1 | FULLTEXT INDEX | 7 | desc2 | A | | | | YES | greptime-fulltext-index-v1 | | | YES | |
|
||||
| system_metrics | 1 | FULLTEXT INDEX | 8 | desc3 | A | | | | YES | greptime-fulltext-index-v1 | | | YES | |
|
||||
| system_metrics | 1 | PRIMARY | 1 | host | A | | | | YES | greptime-primary-key-v1 | | | YES | |
|
||||
| system_metrics | 1 | PRIMARY, INVERTED INDEX, FULLTEXT INDEX | 2 | idc | A | | | | YES | greptime-primary-key-v1, greptime-inverted-index-v1, greptime-fulltext-index-v1 | | | YES | |
|
||||
@@ -80,8 +95,7 @@ SHOW INDEX FROM system_metrics in public;
|
||||
+----------------+------------+-----------------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+---------------------------------------------------------------------------------+---------+---------------+---------+------------+
|
||||
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
|
||||
+----------------+------------+-----------------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+---------------------------------------------------------------------------------+---------+---------------+---------+------------+
|
||||
| system_metrics | 1 | INVERTED INDEX | 6 | desc1 | A | | | | YES | greptime-inverted-index-v1 | | | YES | |
|
||||
| system_metrics | 1 | INVERTED INDEX, FULLTEXT INDEX | 7 | desc2 | A | | | | YES | greptime-inverted-index-v1, greptime-fulltext-index-v1 | | | YES | |
|
||||
| system_metrics | 1 | FULLTEXT INDEX | 7 | desc2 | A | | | | YES | greptime-fulltext-index-v1 | | | YES | |
|
||||
| system_metrics | 1 | FULLTEXT INDEX | 8 | desc3 | A | | | | YES | greptime-fulltext-index-v1 | | | YES | |
|
||||
| system_metrics | 1 | PRIMARY | 1 | host | A | | | | YES | greptime-primary-key-v1 | | | YES | |
|
||||
| system_metrics | 1 | PRIMARY, INVERTED INDEX, FULLTEXT INDEX | 2 | idc | A | | | | YES | greptime-primary-key-v1, greptime-inverted-index-v1, greptime-fulltext-index-v1 | | | YES | |
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
CREATE TABLE IF NOT EXISTS system_metrics (
|
||||
host STRING,
|
||||
idc STRING FULLTEXT,
|
||||
idc STRING FULLTEXT INDEX INVERTED INDEX,
|
||||
cpu_util DOUBLE,
|
||||
memory_util DOUBLE,
|
||||
disk_util DOUBLE,
|
||||
desc1 STRING,
|
||||
desc2 STRING FULLTEXT,
|
||||
desc3 STRING FULLTEXT,
|
||||
desc2 STRING FULLTEXT INDEX,
|
||||
desc3 STRING FULLTEXT INDEX,
|
||||
ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY(host, idc),
|
||||
INVERTED INDEX(idc, desc1, desc2),
|
||||
TIME INDEX(ts)
|
||||
);
|
||||
|
||||
@@ -28,10 +27,11 @@ CREATE TABLE IF NOT EXISTS test_no_inverted_index (
|
||||
c DOUBLE,
|
||||
ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY(a, b),
|
||||
INVERTED INDEX(),
|
||||
TIME INDEX(ts)
|
||||
);
|
||||
|
||||
show create table test_no_inverted_index;
|
||||
|
||||
SHOW INDEX;
|
||||
|
||||
SHOW INDEX FROM test;
|
||||
|
||||
@@ -586,24 +586,24 @@ select * from KEY_COLUMN_USAGE where CONSTRAINT_NAME = 'TIME INDEX';
|
||||
|
||||
select * from KEY_COLUMN_USAGE where CONSTRAINT_NAME != 'TIME INDEX';
|
||||
|
||||
+--------------------+-------------------+-------------------------+---------------+--------------------+--------------+------------+-------------+------------------+-------------------------------+-------------------------+-----------------------+------------------------+
|
||||
| constraint_catalog | constraint_schema | constraint_name | table_catalog | real_table_catalog | table_schema | table_name | column_name | ordinal_position | position_in_unique_constraint | referenced_table_schema | referenced_table_name | referenced_column_name |
|
||||
+--------------------+-------------------+-------------------------+---------------+--------------------+--------------+------------+-------------+------------------+-------------------------------+-------------------------+-----------------------+------------------------+
|
||||
| def | public | PRIMARY, INVERTED INDEX | def | greptime | public | numbers | number | 1 | | | | |
|
||||
+--------------------+-------------------+-------------------------+---------------+--------------------+--------------+------------+-------------+------------------+-------------------------------+-------------------------+-----------------------+------------------------+
|
||||
+--------------------+-------------------+-----------------+---------------+--------------------+--------------+------------+-------------+------------------+-------------------------------+-------------------------+-----------------------+------------------------+
|
||||
| constraint_catalog | constraint_schema | constraint_name | table_catalog | real_table_catalog | table_schema | table_name | column_name | ordinal_position | position_in_unique_constraint | referenced_table_schema | referenced_table_name | referenced_column_name |
|
||||
+--------------------+-------------------+-----------------+---------------+--------------------+--------------+------------+-------------+------------------+-------------------------------+-------------------------+-----------------------+------------------------+
|
||||
| def | public | PRIMARY | def | greptime | public | numbers | number | 1 | | | | |
|
||||
+--------------------+-------------------+-----------------+---------------+--------------------+--------------+------------+-------------+------------------+-------------------------------+-------------------------+-----------------------+------------------------+
|
||||
|
||||
select * from KEY_COLUMN_USAGE where CONSTRAINT_NAME LIKE '%INDEX';
|
||||
|
||||
+--------------------+-------------------+-------------------------+---------------+--------------------+--------------+------------+-------------+------------------+-------------------------------+-------------------------+-----------------------+------------------------+
|
||||
| constraint_catalog | constraint_schema | constraint_name | table_catalog | real_table_catalog | table_schema | table_name | column_name | ordinal_position | position_in_unique_constraint | referenced_table_schema | referenced_table_name | referenced_column_name |
|
||||
+--------------------+-------------------+-------------------------+---------------+--------------------+--------------+------------+-------------+------------------+-------------------------------+-------------------------+-----------------------+------------------------+
|
||||
| def | public | PRIMARY, INVERTED INDEX | def | greptime | public | numbers | number | 1 | | | | |
|
||||
+--------------------+-------------------+-------------------------+---------------+--------------------+--------------+------------+-------------+------------------+-------------------------------+-------------------------+-----------------------+------------------------+
|
||||
++
|
||||
++
|
||||
|
||||
select * from KEY_COLUMN_USAGE where CONSTRAINT_NAME NOT LIKE '%INDEX';
|
||||
|
||||
++
|
||||
++
|
||||
+--------------------+-------------------+-----------------+---------------+--------------------+--------------+------------+-------------+------------------+-------------------------------+-------------------------+-----------------------+------------------------+
|
||||
| constraint_catalog | constraint_schema | constraint_name | table_catalog | real_table_catalog | table_schema | table_name | column_name | ordinal_position | position_in_unique_constraint | referenced_table_schema | referenced_table_name | referenced_column_name |
|
||||
+--------------------+-------------------+-----------------+---------------+--------------------+--------------+------------+-------------+------------------+-------------------------------+-------------------------+-----------------------+------------------------+
|
||||
| def | public | PRIMARY | def | greptime | public | numbers | number | 1 | | | | |
|
||||
+--------------------+-------------------+-----------------+---------------+--------------------+--------------+------------+-------------+------------------+-------------------------------+-------------------------+-----------------------+------------------------+
|
||||
|
||||
select * from KEY_COLUMN_USAGE where CONSTRAINT_NAME == 'TIME INDEX' AND CONSTRAINT_SCHEMA != 'my_db';
|
||||
|
||||
@@ -685,11 +685,11 @@ desc table key_column_usage;
|
||||
|
||||
select * from key_column_usage;
|
||||
|
||||
+--------------------+-------------------+-------------------------+---------------+--------------------+--------------+------------+-------------+------------------+-------------------------------+-------------------------+-----------------------+------------------------+
|
||||
| constraint_catalog | constraint_schema | constraint_name | table_catalog | real_table_catalog | table_schema | table_name | column_name | ordinal_position | position_in_unique_constraint | referenced_table_schema | referenced_table_name | referenced_column_name |
|
||||
+--------------------+-------------------+-------------------------+---------------+--------------------+--------------+------------+-------------+------------------+-------------------------------+-------------------------+-----------------------+------------------------+
|
||||
| def | public | PRIMARY, INVERTED INDEX | def | greptime | public | numbers | number | 1 | | | | |
|
||||
+--------------------+-------------------+-------------------------+---------------+--------------------+--------------+------------+-------------+------------------+-------------------------------+-------------------------+-----------------------+------------------------+
|
||||
+--------------------+-------------------+-----------------+---------------+--------------------+--------------+------------+-------------+------------------+-------------------------------+-------------------------+-----------------------+------------------------+
|
||||
| constraint_catalog | constraint_schema | constraint_name | table_catalog | real_table_catalog | table_schema | table_name | column_name | ordinal_position | position_in_unique_constraint | referenced_table_schema | referenced_table_name | referenced_column_name |
|
||||
+--------------------+-------------------+-----------------+---------------+--------------------+--------------+------------+-------------+------------------+-------------------------------+-------------------------+-----------------------+------------------------+
|
||||
| def | public | PRIMARY | def | greptime | public | numbers | number | 1 | | | | |
|
||||
+--------------------+-------------------+-----------------+---------------+--------------------+--------------+------------+-------------+------------------+-------------------------------+-------------------------+-----------------------+------------------------+
|
||||
|
||||
-- tables not implemented
|
||||
DESC TABLE COLUMN_PRIVILEGES;
|
||||
|
||||
Reference in New Issue
Block a user