mirror of
https://github.com/t8y2/dbx.git
synced 2026-10-21 04:10:49 +00:00
@@ -10,7 +10,7 @@ use crate::data_grid_sql::{
|
||||
DataGridCopyUpdateStatementOptions, DataGridTableMeta,
|
||||
};
|
||||
use serde_json::Value;
|
||||
use std::collections::HashSet;
|
||||
use std::collections::{hash_map::Entry, HashMap, HashSet};
|
||||
use std::io::Write;
|
||||
|
||||
pub(super) fn write_sql_in_list(
|
||||
@@ -18,23 +18,31 @@ pub(super) fn write_sql_in_list(
|
||||
output: &mut dyn Write,
|
||||
) -> Result<(), DataGridExtractError> {
|
||||
write_bytes(output, b"(")?;
|
||||
for (row_index, row) in context.request.rows.iter().enumerate() {
|
||||
if row_index > 0 {
|
||||
write_bytes(output, b", ")?;
|
||||
}
|
||||
let mut seen_rows = HashMap::<Vec<u8>, ()>::new();
|
||||
let mut has_output = false;
|
||||
for row in &context.request.rows {
|
||||
let mut tuple = Vec::new();
|
||||
if context.selected_columns.len() > 1 {
|
||||
write_bytes(output, b"(")?;
|
||||
tuple.push(b'(');
|
||||
}
|
||||
for (column_index, source_index) in context.selected_source_indexes.iter().enumerate() {
|
||||
if column_index > 0 {
|
||||
write_bytes(output, b", ")?;
|
||||
tuple.extend_from_slice(b", ");
|
||||
}
|
||||
let value = &row[*source_index];
|
||||
let info = context.selected_column_info[column_index];
|
||||
write_bytes(output, format_grid_sql_literal(value, context.request.database_type, info).as_bytes())?;
|
||||
tuple.extend_from_slice(format_grid_sql_literal(value, context.request.database_type, info).as_bytes());
|
||||
}
|
||||
if context.selected_columns.len() > 1 {
|
||||
write_bytes(output, b")")?;
|
||||
tuple.push(b')');
|
||||
}
|
||||
if let Entry::Vacant(entry) = seen_rows.entry(tuple) {
|
||||
if has_output {
|
||||
write_bytes(output, b", ")?;
|
||||
}
|
||||
write_bytes(output, entry.key())?;
|
||||
entry.insert(());
|
||||
has_output = true;
|
||||
}
|
||||
}
|
||||
write_bytes(output, b")")
|
||||
|
||||
@@ -187,6 +187,55 @@ fn extracts_multi_column_sql_in_as_row_value_tuples() {
|
||||
assert_eq!(result.text, "((1, 'Ada'), (2, 'Grace, Hopper'))");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sql_in_list_deduplicates_single_selected_values() {
|
||||
let mut request = request(DataGridExtractorId::SqlInList);
|
||||
request.selected_column_indexes = vec![0];
|
||||
request.rows = vec![
|
||||
vec![json!(1), json!("first")],
|
||||
vec![json!(1), json!("unselected value differs")],
|
||||
vec![json!(2), json!("last")],
|
||||
];
|
||||
|
||||
let result = extract_data_grid_selection(request).expect("SQL IN extraction");
|
||||
|
||||
assert_eq!(result.text, "(1, 2)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sql_in_list_deduplicates_multi_column_tuples_in_first_seen_order() {
|
||||
let mut request = request(DataGridExtractorId::SqlInList);
|
||||
request.rows = vec![
|
||||
vec![json!(2), json!("Grace")],
|
||||
vec![json!(1), json!("Ada")],
|
||||
vec![json!(2), json!("Grace")],
|
||||
vec![json!(1), json!("Lovelace")],
|
||||
vec![json!(1), json!("Ada")],
|
||||
];
|
||||
|
||||
let result = extract_data_grid_selection(request).expect("SQL IN extraction");
|
||||
|
||||
assert_eq!(result.text, "((2, 'Grace'), (1, 'Ada'), (1, 'Lovelace'))");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sql_in_list_deduplicates_only_identical_rendered_literals() {
|
||||
let mut request = request(DataGridExtractorId::SqlInList);
|
||||
request.selected_column_indexes = vec![0];
|
||||
request.rows = vec![
|
||||
vec![json!(1)],
|
||||
vec![json!("1")],
|
||||
vec![Value::Null],
|
||||
vec![Value::Null],
|
||||
vec![json!("O'Reilly")],
|
||||
vec![json!("O'Reilly")],
|
||||
];
|
||||
|
||||
let result = extract_data_grid_selection(request).expect("SQL IN extraction");
|
||||
|
||||
assert_eq!(result.text, "(1, '1', NULL, 'O''Reilly')");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn preserves_duplicate_json_columns_without_overwriting_values() {
|
||||
let mut request = request(DataGridExtractorId::Json);
|
||||
|
||||
Reference in New Issue
Block a user