fix(doris): use Doris column rename syntax
This commit is contained in:
parent
b52dcb8623
commit
c545d40fc5
|
|
@ -54,13 +54,13 @@ async function copy() {
|
|||
</div>
|
||||
|
||||
<!-- centered: 居中占满 -->
|
||||
<div v-else class="flex-1 flex flex-col items-center justify-center gap-2 px-6 text-center">
|
||||
<div v-else class="flex-1 min-h-0 flex flex-col items-center justify-center gap-2 px-6 py-4 text-center">
|
||||
<TriangleAlert class="h-8 w-8 text-destructive/50" aria-hidden="true" />
|
||||
<div class="space-y-1 select-text text-destructive" @mousedown.stop @click.stop>
|
||||
<div class="min-h-0 max-h-48 max-w-lg overflow-auto space-y-1 select-text text-destructive" @mousedown.stop @click.stop>
|
||||
<div class="text-sm font-medium">{{ displayTitle }}</div>
|
||||
<div class="text-xs max-w-lg break-all cursor-text text-destructive/80 select-text">{{ message }}</div>
|
||||
<div class="text-xs break-all cursor-text text-destructive/80 select-text">{{ message }}</div>
|
||||
</div>
|
||||
<div class="flex flex-wrap items-center justify-center gap-2 text-foreground">
|
||||
<div class="shrink-0 flex flex-wrap items-center justify-center gap-2 text-foreground">
|
||||
<Button variant="outline" size="sm" class="h-7 gap-1.5 px-2 text-xs" @click.stop="copy">
|
||||
<Copy class="h-3.5 w-3.5" />
|
||||
{{ t("grid.copy") }}
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ pub fn build_single_column_alter_sql(options: SingleColumnAlterSqlOptions) -> Ta
|
|||
|
||||
match dialect {
|
||||
StructureDialect::Mysql => statements.extend(build_mysql_existing_column_sql(&table, &options.column, "")),
|
||||
StructureDialect::Doris => statements.extend(build_doris_existing_column_sql(&table, &options.column, "")),
|
||||
StructureDialect::Postgres => statements.extend(build_postgres_existing_column_sql(&table, &options.column)),
|
||||
StructureDialect::Oracle => {
|
||||
statements.extend(build_oracle_like_existing_column_sql(dialect, &table, &options.column))
|
||||
|
|
@ -247,6 +248,41 @@ pub(super) fn build_mysql_existing_column_sql(
|
|||
vec![format!("ALTER TABLE {table} {operation}{position_clause};")]
|
||||
}
|
||||
|
||||
pub(super) fn build_doris_existing_column_sql(
|
||||
table: &str,
|
||||
column: &EditableStructureColumn,
|
||||
position_clause: &str,
|
||||
) -> Vec<String> {
|
||||
let Some(original) = &column.original else {
|
||||
return Vec::new();
|
||||
};
|
||||
let mut statements = Vec::new();
|
||||
let mut current_column = column.clone();
|
||||
|
||||
if column.name != original.name {
|
||||
// Doris follows its own lightweight schema-change grammar: no MySQL CHANGE and no TO keyword.
|
||||
statements.push(format!(
|
||||
"ALTER TABLE {table} RENAME COLUMN {} {};",
|
||||
quote_ident(StructureDialect::Doris, &original.name),
|
||||
quote_ident(StructureDialect::Doris, &column.name)
|
||||
));
|
||||
current_column.name = column.name.clone();
|
||||
}
|
||||
|
||||
let type_changed = column.data_type.trim() != original.data_type.trim();
|
||||
let nullable_changed = column.is_nullable != original.is_nullable;
|
||||
let default_changed = normalize_default(Some(&column.default_value)) != original_default(column);
|
||||
let comment_changed = clean(&column.comment) != original_comment(column);
|
||||
if type_changed || nullable_changed || default_changed || comment_changed || !position_clause.is_empty() {
|
||||
statements.push(format!(
|
||||
"ALTER TABLE {table} MODIFY COLUMN {}{position_clause};",
|
||||
column_definition(StructureDialect::Doris, ¤t_column)
|
||||
));
|
||||
}
|
||||
|
||||
statements
|
||||
}
|
||||
|
||||
pub(super) fn build_postgres_existing_column_sql(table: &str, column: &EditableStructureColumn) -> Vec<String> {
|
||||
let Some(original) = &column.original else {
|
||||
return Vec::new();
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ pub(super) fn column_definition(dialect: StructureDialect, column: &EditableStru
|
|||
parts.push("ON UPDATE CURRENT_TIMESTAMP".to_string());
|
||||
}
|
||||
}
|
||||
if dialect == StructureDialect::Mysql && !clean(&column.comment).is_empty() {
|
||||
if matches!(dialect, StructureDialect::Mysql | StructureDialect::Doris) && !clean(&column.comment).is_empty() {
|
||||
parts.push(format!("COMMENT {}", quote_string(&clean(&column.comment))));
|
||||
}
|
||||
parts.join(" ")
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use super::column_alter::{
|
||||
build_clickhouse_existing_column_sql, build_h2_existing_column_sql, build_informix_existing_column_sql,
|
||||
build_mysql_existing_column_sql, build_oracle_like_existing_column_sql, build_postgres_existing_column_sql,
|
||||
build_questdb_existing_column_sql, build_sqlite_existing_column_sql, build_sqlserver_existing_column_sql,
|
||||
has_column_extra_change, has_existing_column_attribute_change,
|
||||
build_clickhouse_existing_column_sql, build_doris_existing_column_sql, build_h2_existing_column_sql,
|
||||
build_informix_existing_column_sql, build_mysql_existing_column_sql, build_oracle_like_existing_column_sql,
|
||||
build_postgres_existing_column_sql, build_questdb_existing_column_sql, build_sqlite_existing_column_sql,
|
||||
build_sqlserver_existing_column_sql, has_column_extra_change, has_existing_column_attribute_change,
|
||||
};
|
||||
use super::column_format::column_definition;
|
||||
use super::comments::build_sqlserver_column_comment_sql;
|
||||
|
|
@ -142,6 +142,7 @@ pub(super) fn build_column_sql(options: &TableStructureSqlOptions, warnings: &mu
|
|||
column,
|
||||
if has_position_change { &position_clause } else { "" },
|
||||
)),
|
||||
StructureDialect::Doris => statements.extend(build_doris_existing_column_sql(&table, column, "")),
|
||||
StructureDialect::Postgres => statements.extend(build_postgres_existing_column_sql(&table, column)),
|
||||
StructureDialect::Oracle => {
|
||||
statements.extend(build_oracle_like_existing_column_sql(dialect, &table, column))
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use crate::models::connection::DatabaseType;
|
|||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub(super) enum StructureDialect {
|
||||
Mysql,
|
||||
Doris,
|
||||
Postgres,
|
||||
Sqlite,
|
||||
#[cfg(feature = "duckdb-bundled")]
|
||||
|
|
@ -65,7 +66,6 @@ pub(super) fn capabilities_for(database_type: Option<DatabaseType>) -> TableStru
|
|||
match database_type {
|
||||
Some(
|
||||
DatabaseType::Mysql
|
||||
| DatabaseType::Doris
|
||||
| DatabaseType::StarRocks
|
||||
| DatabaseType::Goldendb
|
||||
| DatabaseType::Sundb
|
||||
|
|
@ -87,6 +87,15 @@ pub(super) fn capabilities_for(database_type: Option<DatabaseType>) -> TableStru
|
|||
foreign_key: true,
|
||||
..base
|
||||
},
|
||||
Some(DatabaseType::Doris) => TableStructureCapabilities {
|
||||
dialect: StructureDialect::Doris,
|
||||
add_column: true,
|
||||
drop_column: true,
|
||||
rename_column: true,
|
||||
alter_existing_column: true,
|
||||
comment: true,
|
||||
..base
|
||||
},
|
||||
Some(DatabaseType::Gbase) => TableStructureCapabilities {
|
||||
dialect: StructureDialect::Mysql,
|
||||
add_column: true,
|
||||
|
|
@ -268,6 +277,7 @@ pub(super) fn database_label(database_type: Option<DatabaseType>) -> String {
|
|||
pub(super) fn dialect_label(dialect: StructureDialect) -> String {
|
||||
match dialect {
|
||||
StructureDialect::Mysql => "mysql",
|
||||
StructureDialect::Doris => "doris",
|
||||
StructureDialect::Postgres => "postgres",
|
||||
StructureDialect::Sqlite => "sqlite",
|
||||
#[cfg(feature = "duckdb-bundled")]
|
||||
|
|
@ -287,6 +297,7 @@ pub(super) fn dialect_label(dialect: StructureDialect) -> String {
|
|||
pub(super) fn database_type_for_dialect(dialect: StructureDialect) -> Option<DatabaseType> {
|
||||
match dialect {
|
||||
StructureDialect::Mysql => Some(DatabaseType::Mysql),
|
||||
StructureDialect::Doris => Some(DatabaseType::Doris),
|
||||
StructureDialect::Postgres => Some(DatabaseType::Postgres),
|
||||
StructureDialect::Sqlite => Some(DatabaseType::Sqlite),
|
||||
#[cfg(feature = "duckdb-bundled")]
|
||||
|
|
|
|||
|
|
@ -138,6 +138,69 @@ fn builds_mysql_unsigned_integer_column_with_length_before_attribute() {
|
|||
assert_eq!(result.statements, vec!["ALTER TABLE `users` ADD COLUMN `score` int(11) unsigned;"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn doris_table_editor_renames_column_without_mysql_change_syntax() {
|
||||
let mut renamed = column("dtp_flag_jt");
|
||||
renamed.data_type = "int".to_string();
|
||||
renamed.comment = "Group DTP".to_string();
|
||||
renamed.original = Some(ColumnInfo {
|
||||
name: "dtp_flag".to_string(),
|
||||
data_type: "int".to_string(),
|
||||
is_nullable: true,
|
||||
column_default: None,
|
||||
is_primary_key: false,
|
||||
extra: None,
|
||||
comment: Some("Group DTP".to_string()),
|
||||
});
|
||||
|
||||
let result = build_table_structure_change_sql(TableStructureSqlOptions {
|
||||
database_type: Some(DatabaseType::Doris),
|
||||
schema: Some("qybiprod".to_string()),
|
||||
table_name: "dim_prod_sp_vkorg".to_string(),
|
||||
columns: vec![renamed],
|
||||
indexes: Vec::new(),
|
||||
foreign_keys: Vec::new(),
|
||||
triggers: Vec::new(),
|
||||
table_comment: None,
|
||||
original_table_comment: None,
|
||||
});
|
||||
|
||||
assert_eq!(result.warnings, Vec::<String>::new());
|
||||
assert_eq!(result.statements, vec!["ALTER TABLE `dim_prod_sp_vkorg` RENAME COLUMN `dtp_flag` `dtp_flag_jt`;"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn doris_single_column_alter_renames_then_modifies_column_definition() {
|
||||
let mut renamed = column("dtp_flag_jt");
|
||||
renamed.data_type = "int".to_string();
|
||||
renamed.comment = "Group DTP".to_string();
|
||||
renamed.original = Some(ColumnInfo {
|
||||
name: "dtp_flag".to_string(),
|
||||
data_type: "int".to_string(),
|
||||
is_nullable: true,
|
||||
column_default: None,
|
||||
is_primary_key: false,
|
||||
extra: None,
|
||||
comment: Some("Division DTP".to_string()),
|
||||
});
|
||||
|
||||
let result = build_single_column_alter_sql(SingleColumnAlterSqlOptions {
|
||||
database_type: Some(DatabaseType::Doris),
|
||||
schema: Some("qybiprod".to_string()),
|
||||
table_name: "dim_prod_sp_vkorg".to_string(),
|
||||
column: renamed,
|
||||
});
|
||||
|
||||
assert_eq!(result.warnings, Vec::<String>::new());
|
||||
assert_eq!(
|
||||
result.statements,
|
||||
vec![
|
||||
"ALTER TABLE `dim_prod_sp_vkorg` RENAME COLUMN `dtp_flag` `dtp_flag_jt`;",
|
||||
"ALTER TABLE `dim_prod_sp_vkorg` MODIFY COLUMN `dtp_flag_jt` int COMMENT 'Group DTP';",
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dameng_integer_column_omits_mysql_display_width() {
|
||||
let mut age = column("age");
|
||||
|
|
|
|||
|
|
@ -18,7 +18,10 @@ pub(super) fn qualified_table(dialect: StructureDialect, schema: Option<&str>, t
|
|||
|
||||
pub(super) fn quote_ident(dialect: StructureDialect, name: &str) -> String {
|
||||
match dialect {
|
||||
StructureDialect::Mysql | StructureDialect::ManticoreSearch | StructureDialect::Questdb => {
|
||||
StructureDialect::Mysql
|
||||
| StructureDialect::Doris
|
||||
| StructureDialect::ManticoreSearch
|
||||
| StructureDialect::Questdb => {
|
||||
format!("`{}`", name.replace('`', "``"))
|
||||
}
|
||||
StructureDialect::SqlServer => format!("[{}]", name.replace(']', "]]")),
|
||||
|
|
@ -117,7 +120,9 @@ pub(super) fn is_protected_manticore_id_column(dialect: StructureDialect, column
|
|||
pub(super) fn is_temporal_type_for_default(dialect: StructureDialect, base_type: &str) -> bool {
|
||||
let normalized = base_type.split_whitespace().collect::<Vec<_>>().join(" ").to_ascii_lowercase();
|
||||
match dialect {
|
||||
StructureDialect::Mysql => matches!(normalized.as_str(), "date" | "datetime" | "timestamp" | "time" | "year"),
|
||||
StructureDialect::Mysql | StructureDialect::Doris => {
|
||||
matches!(normalized.as_str(), "date" | "datetime" | "timestamp" | "time" | "year")
|
||||
}
|
||||
StructureDialect::Postgres => {
|
||||
matches!(
|
||||
normalized.as_str(),
|
||||
|
|
@ -183,7 +188,7 @@ pub(super) fn is_temporal_expression(value: &str) -> bool {
|
|||
pub(super) fn is_string_type_for_default(dialect: StructureDialect, base_type: &str) -> bool {
|
||||
let normalized = base_type.split_whitespace().collect::<Vec<_>>().join(" ").to_ascii_lowercase();
|
||||
match dialect {
|
||||
StructureDialect::Mysql => matches!(
|
||||
StructureDialect::Mysql | StructureDialect::Doris => matches!(
|
||||
normalized.as_str(),
|
||||
"char"
|
||||
| "varchar"
|
||||
|
|
|
|||
Loading…
Reference in New Issue