Skip to content

Commit 344a0c5

Browse files
committed
자동 포멧팅 기능 개선
1 parent fcb0ac0 commit 344a0c5

44 files changed

Lines changed: 3074 additions & 182 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/db/connection.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,18 @@ impl DatabaseType {
653653
backend_for(self).supports_mysql_delimiter_commands()
654654
}
655655

656+
pub(crate) fn supports_explicit_analytic_null_treatment(self) -> bool {
657+
backend_for(self).supports_explicit_analytic_null_treatment()
658+
}
659+
660+
pub(crate) fn uses_mysql_analytic_null_treatment_rules(self) -> bool {
661+
backend_for(self).uses_mysql_analytic_null_treatment_rules()
662+
}
663+
664+
pub(crate) fn supports_trailing_select_into_after_set_limit(self) -> bool {
665+
backend_for(self).supports_trailing_select_into_after_set_limit()
666+
}
667+
656668
pub(crate) fn preserves_quoted_routine_lookup_spelling(self) -> bool {
657669
backend_for(self).preserves_quoted_routine_lookup_spelling()
658670
}
@@ -1968,6 +1980,9 @@ pub(crate) trait DbBackend: Sync {
19681980
fn advanced_settings_form_spec(&self) -> DbAdvancedSettingsFormSpec;
19691981
fn sql_dialect(&self) -> SqlDialect;
19701982
fn supports_mysql_delimiter_commands(&self) -> bool;
1983+
fn supports_explicit_analytic_null_treatment(&self) -> bool;
1984+
fn uses_mysql_analytic_null_treatment_rules(&self) -> bool;
1985+
fn supports_trailing_select_into_after_set_limit(&self) -> bool;
19711986
fn preserves_quoted_routine_lookup_spelling(&self) -> bool;
19721987
fn backend_kind(&self) -> DatabaseBackendKind;
19731988
fn cache_key(&self) -> u8;
@@ -2112,6 +2127,9 @@ struct MysqlBackend {
21122127
display_name: &'static str,
21132128
choice_label: &'static str,
21142129
cache_key: u8,
2130+
supports_explicit_analytic_null_treatment: bool,
2131+
uses_mysql_analytic_null_treatment_rules: bool,
2132+
supports_trailing_select_into_after_set_limit: bool,
21152133
session_time_zone_in_range: fn(SessionTimeZoneOffset) -> bool,
21162134
session_time_zone_error_message: &'static str,
21172135
}
@@ -2145,6 +2163,9 @@ static MYSQL_BACKEND: MysqlBackend = MysqlBackend {
21452163
display_name: "MySQL",
21462164
choice_label: "MySQL",
21472165
cache_key: 1,
2166+
supports_explicit_analytic_null_treatment: true,
2167+
uses_mysql_analytic_null_treatment_rules: true,
2168+
supports_trailing_select_into_after_set_limit: true,
21482169
session_time_zone_in_range: mysql_session_time_zone_in_range,
21492170
session_time_zone_error_message:
21502171
"MySQL session time zone must be blank or an offset from -13:59 through +14:00",
@@ -2154,6 +2175,9 @@ static MARIADB_BACKEND: MysqlBackend = MysqlBackend {
21542175
display_name: "MariaDB",
21552176
choice_label: "MariaDB",
21562177
cache_key: 2,
2178+
supports_explicit_analytic_null_treatment: false,
2179+
uses_mysql_analytic_null_treatment_rules: false,
2180+
supports_trailing_select_into_after_set_limit: false,
21572181
session_time_zone_in_range: mariadb_session_time_zone_in_range,
21582182
session_time_zone_error_message:
21592183
"MariaDB session time zone must be blank or an offset from -12:59 through +13:00",
@@ -2235,6 +2259,18 @@ impl DbBackend for OracleBackend {
22352259
false
22362260
}
22372261

2262+
fn supports_explicit_analytic_null_treatment(&self) -> bool {
2263+
true
2264+
}
2265+
2266+
fn uses_mysql_analytic_null_treatment_rules(&self) -> bool {
2267+
false
2268+
}
2269+
2270+
fn supports_trailing_select_into_after_set_limit(&self) -> bool {
2271+
false
2272+
}
2273+
22382274
fn preserves_quoted_routine_lookup_spelling(&self) -> bool {
22392275
true
22402276
}
@@ -2692,6 +2728,18 @@ impl DbBackend for MysqlBackend {
26922728
true
26932729
}
26942730

2731+
fn supports_explicit_analytic_null_treatment(&self) -> bool {
2732+
self.supports_explicit_analytic_null_treatment
2733+
}
2734+
2735+
fn uses_mysql_analytic_null_treatment_rules(&self) -> bool {
2736+
self.uses_mysql_analytic_null_treatment_rules
2737+
}
2738+
2739+
fn supports_trailing_select_into_after_set_limit(&self) -> bool {
2740+
self.supports_trailing_select_into_after_set_limit
2741+
}
2742+
26952743
fn preserves_quoted_routine_lookup_spelling(&self) -> bool {
26962744
false
26972745
}
@@ -6452,6 +6500,9 @@ mod tests {
64526500
DatabaseType::from_cache_key(DatabaseType::Oracle.cache_key()),
64536501
DatabaseType::Oracle
64546502
);
6503+
assert!(DatabaseType::Oracle.supports_explicit_analytic_null_treatment());
6504+
assert!(!DatabaseType::Oracle.uses_mysql_analytic_null_treatment_rules());
6505+
assert!(!DatabaseType::Oracle.supports_trailing_select_into_after_set_limit());
64556506

64566507
assert_eq!(DatabaseType::MySQL.sql_dialect(), SqlDialect::MySql);
64576508
assert_eq!(
@@ -6462,6 +6513,9 @@ mod tests {
64626513
DatabaseType::from_cache_key(DatabaseType::MySQL.cache_key()),
64636514
DatabaseType::MySQL
64646515
);
6516+
assert!(DatabaseType::MySQL.supports_explicit_analytic_null_treatment());
6517+
assert!(DatabaseType::MySQL.uses_mysql_analytic_null_treatment_rules());
6518+
assert!(DatabaseType::MySQL.supports_trailing_select_into_after_set_limit());
64656519

64666520
assert_eq!(DatabaseType::MariaDB.sql_dialect(), SqlDialect::MySql);
64676521
assert_eq!(
@@ -6473,6 +6527,9 @@ mod tests {
64736527
DatabaseType::MariaDB
64746528
);
64756529
assert_eq!(DatabaseType::MariaDB.choice_label(), "MariaDB");
6530+
assert!(!DatabaseType::MariaDB.supports_explicit_analytic_null_treatment());
6531+
assert!(!DatabaseType::MariaDB.uses_mysql_analytic_null_treatment_rules());
6532+
assert!(!DatabaseType::MariaDB.supports_trailing_select_into_after_set_limit());
64766533
}
64776534

64786535
#[test]

src/ui/intellisense_context.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,7 +1250,7 @@ fn is_from_consuming_function(name: &str) -> bool {
12501250
sql_text::is_from_consuming_function(name)
12511251
}
12521252

1253-
fn is_nth_value_from_modifier(tokens: &[SqlToken], from_idx: usize) -> bool {
1253+
pub(crate) fn is_nth_value_from_modifier(tokens: &[SqlToken], from_idx: usize) -> bool {
12541254
if !next_word_upper(tokens, from_idx.saturating_add(1))
12551255
.is_some_and(|(word, _)| matches!(word.as_str(), "FIRST" | "LAST"))
12561256
{
@@ -12775,7 +12775,9 @@ fn select_list_end_index(tokens: &[SqlToken], start: usize) -> usize {
1277512775
if is_top_level_depth(&token_depths, idx) {
1277612776
if let SqlToken::Word(w) = token {
1277712777
let upper = w.to_ascii_uppercase();
12778-
if matches!(upper.as_str(), "FROM" | "INTO" | "BULK") {
12778+
if matches!(upper.as_str(), "FROM" | "INTO" | "BULK")
12779+
&& !(upper == "FROM" && is_nth_value_from_modifier(tokens, idx))
12780+
{
1277912781
break;
1278012782
}
1278112783
}

src/ui/sql_editor/format_sweep_tests.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4022,6 +4022,52 @@ fn formatting_sweep_mysql_non_parenthesized_lists_have_dedicated_frames() {
40224022
}
40234023
}
40244024

4025+
#[test]
4026+
fn formatting_sweep_mariadb_oracle_mode_declare_is_a_block_not_a_name_list() {
4027+
let source = "DELIMITER /\nDECLARE TYPE row_t IS RECORD(row_id INT, label_text VARCHAR2(30)); TYPE map_t IS TABLE OF row_t INDEX BY VARCHAR2(20); rows_by_key map_t; BEGIN rows_by_key('alpha') := row_t(1, 'parse'); END;\n/\nDELIMITER ;";
4028+
let run = format_sweep_run(source, DatabaseType::MariaDB);
4029+
4030+
assert!(
4031+
run.issues.is_empty(),
4032+
"MariaDB Oracle-mode DECLARE frame issues: {:#?}\n{}",
4033+
run.issues,
4034+
run.formatted
4035+
);
4036+
assert!(
4037+
run.managed_frame_kinds
4038+
.contains(&FormatManagedFrameKind::Block),
4039+
"top-level Oracle-mode DECLARE must create a block frame: {:?}\n{}",
4040+
run.managed_frame_kinds,
4041+
run.formatted
4042+
);
4043+
assert!(
4044+
!run.managed_list_owner_kinds
4045+
.contains(&ListOwnerKind::DeclarationNames),
4046+
"top-level Oracle-mode DECLARE must not create a MySQL declaration-name list: {:?}\n{}",
4047+
run.managed_list_owner_kinds,
4048+
run.formatted
4049+
);
4050+
4051+
let mysql = format_sweep_run(
4052+
"CREATE PROCEDURE p() BEGIN DECLARE first_value, second_value INT; SET first_value = 1; END;",
4053+
DatabaseType::MySQL,
4054+
);
4055+
assert!(
4056+
mysql.issues.is_empty(),
4057+
"MySQL compound DECLARE frame issues: {:#?}\n{}",
4058+
mysql.issues,
4059+
mysql.formatted
4060+
);
4061+
assert!(
4062+
mysql
4063+
.managed_list_owner_kinds
4064+
.contains(&ListOwnerKind::DeclarationNames),
4065+
"compound-block DECLARE must retain its declaration-name list: {:?}\n{}",
4066+
mysql.managed_list_owner_kinds,
4067+
mysql.formatted
4068+
);
4069+
}
4070+
40254071
#[test]
40264072
fn formatting_sweep_mysql_top_level_current_diagnostics_keeps_item_list_attached() {
40274073
let source = "SET @changed = TRUE;\nGET CURRENT DIAGNOSTICS\n @condition_count = NUMBER,\n @affected_rows = ROW_COUNT;\nSELECT @condition_count, @affected_rows;";

src/ui/sql_editor/formatter.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16641,8 +16641,7 @@ impl SqlEditorWidget {
1664116641
line_indent,
1664216642
);
1664316643
}
16644-
if mysql_compatible
16645-
&& upper == "DECLARE"
16644+
if mysql_compound_declare
1664616645
&& (recent_statement_word_indices.is_empty()
1664716646
|| matches!(
1664816647
loop_previous_non_comment_token,

0 commit comments

Comments
 (0)