1 parent
f621e40655
commit
e2fa810f2e
16 files changed
+146
-10
No files matched your search
@@ -1036,6 +1036,8 @@ const allFilterModeOptions: Array<{ value: FilterMode; labelKey: string }> = [
|
|||||||
{ value: "not-between", labelKey: "grid.filterBuilderNotBetween" },
|
{ value: "not-between", labelKey: "grid.filterBuilderNotBetween" },
|
||||||
{ value: "is-null", labelKey: "grid.filterBuilderIsNull" },
|
{ value: "is-null", labelKey: "grid.filterBuilderIsNull" },
|
||||||
{ value: "is-not-null", labelKey: "grid.filterBuilderIsNotNull" },
|
{ value: "is-not-null", labelKey: "grid.filterBuilderIsNotNull" },
|
||||||
|
{ value: "is-blank", labelKey: "grid.filterBuilderIsBlank" },
|
||||||
|
{ value: "is-not-blank", labelKey: "grid.filterBuilderIsNotBlank" },
|
||||||
];
|
];
|
||||||
const filterModeOptions = computed(() => allFilterModeOptions.filter((option) => filterModeIsSupportedForDatabase(option.value, resolvedDatabaseType.value)));
|
const filterModeOptions = computed(() => allFilterModeOptions.filter((option) => filterModeIsSupportedForDatabase(option.value, resolvedDatabaseType.value)));
|
||||||
const filterBuilderColumnOptions = computed(() => filterBuilderColumns.value.map((column) => column.name));
|
const filterBuilderColumnOptions = computed(() => filterBuilderColumns.value.map((column) => column.name));
|
||||||
@@ -6372,7 +6374,7 @@ async function contextFilterCondition(target: ContextFilterTarget, mode: FilterM
|
|||||||
const { columnName, sourceResult, sourceIndex, sourceValue, requiresHydration } = target;
|
const { columnName, sourceResult, sourceIndex, sourceValue, requiresHydration } = target;
|
||||||
// CustomContextMenu closes before invoking its action. Keep the target
|
// CustomContextMenu closes before invoking its action. Keep the target
|
||||||
// stable across hydration after the close lifecycle clears contextCell.
|
// stable across hydration after the close lifecycle clears contextCell.
|
||||||
if (mode !== "is-null" && mode !== "is-not-null") {
|
if (filterModeNeedsValue(mode)) {
|
||||||
if (!(await hydrateLargeValueCell(target.rowId, target.col))) return null;
|
if (!(await hydrateLargeValueCell(target.rowId, target.col))) return null;
|
||||||
}
|
}
|
||||||
if (props.result !== sourceResult) return null;
|
if (props.result !== sourceResult) return null;
|
||||||
|
|||||||
@@ -1711,6 +1711,8 @@ export default {
|
|||||||
filterBuilderNotBetween: "Outside range",
|
filterBuilderNotBetween: "Outside range",
|
||||||
filterBuilderIsNull: "Is NULL",
|
filterBuilderIsNull: "Is NULL",
|
||||||
filterBuilderIsNotNull: "Is not NULL",
|
filterBuilderIsNotNull: "Is not NULL",
|
||||||
|
filterBuilderIsBlank: "Is blank (NULL or empty)",
|
||||||
|
filterBuilderIsNotBlank: "Is not blank (not NULL and not empty)",
|
||||||
columnActions: "Column actions",
|
columnActions: "Column actions",
|
||||||
localFilter: "Local value filter",
|
localFilter: "Local value filter",
|
||||||
localFilterFor: "Local Values For '{column}'",
|
localFilterFor: "Local Values For '{column}'",
|
||||||
|
|||||||
@@ -1594,6 +1594,8 @@ export default withEnglishFallback({
|
|||||||
filterBuilderNotBetween: "Fuera de rango",
|
filterBuilderNotBetween: "Fuera de rango",
|
||||||
filterBuilderIsNull: "Es NULL",
|
filterBuilderIsNull: "Es NULL",
|
||||||
filterBuilderIsNotNull: "No es NULL",
|
filterBuilderIsNotNull: "No es NULL",
|
||||||
|
filterBuilderIsBlank: "Está vacío (NULL o cadena vacía)",
|
||||||
|
filterBuilderIsNotBlank: "No está vacío (ni NULL ni cadena vacía)",
|
||||||
columnActions: "Acciones de columna",
|
columnActions: "Acciones de columna",
|
||||||
localFilter: "Filtro local de valores",
|
localFilter: "Filtro local de valores",
|
||||||
localFilterFor: "Valores locales para '{column}'",
|
localFilterFor: "Valores locales para '{column}'",
|
||||||
|
|||||||
@@ -1592,6 +1592,8 @@ export default withEnglishFallback({
|
|||||||
filterBuilderNotBetween: "Fuori intervallo",
|
filterBuilderNotBetween: "Fuori intervallo",
|
||||||
filterBuilderIsNull: "È NULL",
|
filterBuilderIsNull: "È NULL",
|
||||||
filterBuilderIsNotNull: "Non è NULL",
|
filterBuilderIsNotNull: "Non è NULL",
|
||||||
|
filterBuilderIsBlank: "È vuoto (NULL o stringa vuota)",
|
||||||
|
filterBuilderIsNotBlank: "Non è vuoto (né NULL né stringa vuota)",
|
||||||
columnActions: "Azioni colonna",
|
columnActions: "Azioni colonna",
|
||||||
localFilter: "Filtro valori locale",
|
localFilter: "Filtro valori locale",
|
||||||
localFilterFor: "Valori locali per '{column}'",
|
localFilterFor: "Valori locali per '{column}'",
|
||||||
|
|||||||
@@ -1610,6 +1610,8 @@ export default withEnglishFallback({
|
|||||||
filterBuilderNotBetween: "範囲外",
|
filterBuilderNotBetween: "範囲外",
|
||||||
filterBuilderIsNull: "NULLである",
|
filterBuilderIsNull: "NULLである",
|
||||||
filterBuilderIsNotNull: "NULLでない",
|
filterBuilderIsNotNull: "NULLでない",
|
||||||
|
filterBuilderIsBlank: "空(NULLまたは空文字)",
|
||||||
|
filterBuilderIsNotBlank: "空でない(NULLでも空文字でもない)",
|
||||||
columnActions: "列の操作",
|
columnActions: "列の操作",
|
||||||
localFilter: "ローカル値フィルター",
|
localFilter: "ローカル値フィルター",
|
||||||
localFilterFor: "'{column}'のローカル値",
|
localFilterFor: "'{column}'のローカル値",
|
||||||
|
|||||||
@@ -1587,6 +1587,8 @@ export default withEnglishFallback({
|
|||||||
filterBuilderNotBetween: "범위 외",
|
filterBuilderNotBetween: "범위 외",
|
||||||
filterBuilderIsNull: "NULL임",
|
filterBuilderIsNull: "NULL임",
|
||||||
filterBuilderIsNotNull: "NULL이 아님",
|
filterBuilderIsNotNull: "NULL이 아님",
|
||||||
|
filterBuilderIsBlank: "비어 있음(NULL 또는 빈 문자열)",
|
||||||
|
filterBuilderIsNotBlank: "비어 있지 않음(NULL도 빈 문자열도 아님)",
|
||||||
columnActions: "컬럼 작업",
|
columnActions: "컬럼 작업",
|
||||||
localFilter: "로컬 값 필터",
|
localFilter: "로컬 값 필터",
|
||||||
localFilterFor: "'{column}' 로컬 값",
|
localFilterFor: "'{column}' 로컬 값",
|
||||||
|
|||||||
@@ -1594,6 +1594,8 @@ export default withEnglishFallback({
|
|||||||
filterBuilderNotBetween: "Fora do intervalo",
|
filterBuilderNotBetween: "Fora do intervalo",
|
||||||
filterBuilderIsNull: "É NULL",
|
filterBuilderIsNull: "É NULL",
|
||||||
filterBuilderIsNotNull: "Não é NULL",
|
filterBuilderIsNotNull: "Não é NULL",
|
||||||
|
filterBuilderIsBlank: "Está em branco (NULL ou string vazia)",
|
||||||
|
filterBuilderIsNotBlank: "Não está em branco (nem NULL nem string vazia)",
|
||||||
columnActions: "Ações da coluna",
|
columnActions: "Ações da coluna",
|
||||||
localFilter: "Filtro local de valores",
|
localFilter: "Filtro local de valores",
|
||||||
localFilterFor: "Valores locais para '{column}'",
|
localFilterFor: "Valores locais para '{column}'",
|
||||||
|
|||||||
@@ -1634,8 +1634,10 @@ export default withEnglishFallback({
|
|||||||
filterBuilderNotIn: "列表外",
|
filterBuilderNotIn: "列表外",
|
||||||
filterBuilderBetween: "介于",
|
filterBuilderBetween: "介于",
|
||||||
filterBuilderNotBetween: "不介于",
|
filterBuilderNotBetween: "不介于",
|
||||||
filterBuilderIsNull: "为空",
|
filterBuilderIsNull: "为 NULL",
|
||||||
filterBuilderIsNotNull: "不为空",
|
filterBuilderIsNotNull: "不为 NULL",
|
||||||
|
filterBuilderIsBlank: "为空(NULL 或空字符串)",
|
||||||
|
filterBuilderIsNotBlank: "不为空(非 NULL 且非空字符串)",
|
||||||
columnActions: "字段操作",
|
columnActions: "字段操作",
|
||||||
localFilter: "本地值筛选",
|
localFilter: "本地值筛选",
|
||||||
localFilterFor: "本地值筛选“{column}”",
|
localFilterFor: "本地值筛选“{column}”",
|
||||||
|
|||||||
@@ -1591,8 +1591,10 @@ export default withEnglishFallback({
|
|||||||
filterBuilderNotIn: "清單外",
|
filterBuilderNotIn: "清單外",
|
||||||
filterBuilderBetween: "介於",
|
filterBuilderBetween: "介於",
|
||||||
filterBuilderNotBetween: "不介於",
|
filterBuilderNotBetween: "不介於",
|
||||||
filterBuilderIsNull: "為空",
|
filterBuilderIsNull: "為 NULL",
|
||||||
filterBuilderIsNotNull: "不為空",
|
filterBuilderIsNotNull: "不為 NULL",
|
||||||
|
filterBuilderIsBlank: "為空(NULL 或空字串)",
|
||||||
|
filterBuilderIsNotBlank: "不為空(非 NULL 且非空字串)",
|
||||||
columnActions: "欄位操作",
|
columnActions: "欄位操作",
|
||||||
localFilter: "本機值篩選",
|
localFilter: "本機值篩選",
|
||||||
localFilterFor: "本機值篩選「{column}」",
|
localFilterFor: "本機值篩選「{column}」",
|
||||||
|
|||||||
@@ -36,6 +36,19 @@ describe("normalizeColumnFormatter", () => {
|
|||||||
expect(normalizeColumnFormatter({ ...base, filter: { column: "dict_type", mode: "between", value: "A" } })).toBeUndefined();
|
expect(normalizeColumnFormatter({ ...base, filter: { column: "dict_type", mode: "between", value: "A" } })).toBeUndefined();
|
||||||
expect(normalizeColumnFormatter({ ...base, filter: { column: "dict_type", mode: "raw-sql", value: "1=1" } })).toBeUndefined();
|
expect(normalizeColumnFormatter({ ...base, filter: { column: "dict_type", mode: "raw-sql", value: "1=1" } })).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it.each(["is-blank", "is-not-blank"] as const)("preserves the value-less %s manual reference filter", (mode) => {
|
||||||
|
expect(
|
||||||
|
normalizeColumnFormatter({
|
||||||
|
kind: "foreign-key-display",
|
||||||
|
referenceMode: "manual",
|
||||||
|
refTable: "dictionary",
|
||||||
|
refColumn: "dict_key",
|
||||||
|
displayColumn: "dict_value",
|
||||||
|
filter: { column: "dict_type", mode },
|
||||||
|
}),
|
||||||
|
).toMatchObject({ filter: { column: "dict_type", mode, value: undefined, endValue: undefined } });
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("normalizeSupportedDateTimePattern", () => {
|
describe("normalizeSupportedDateTimePattern", () => {
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ import type { DataGridContextFilterMode } from "@/lib/dataGrid/dataGridSql";
|
|||||||
|
|
||||||
describe("VictoriaMetrics data grid filters", () => {
|
describe("VictoriaMetrics data grid filters", () => {
|
||||||
it("does not expose SQL filter modes for MetricsQL results", () => {
|
it("does not expose SQL filter modes for MetricsQL results", () => {
|
||||||
const modes: DataGridContextFilterMode[] = ["equals", "not-equals", "is-null", "is-not-null", "like", "not-like", "less-than", "greater-than", "in", "not-in", "between", "not-between"];
|
const modes: DataGridContextFilterMode[] = ["equals", "not-equals", "is-null", "is-not-null", "is-blank", "is-not-blank", "like", "not-like", "less-than", "greater-than", "in", "not-in", "between", "not-between"];
|
||||||
|
|
||||||
expect(modes.every((mode) => !filterModeIsSupportedForDatabase(mode, "victoriametrics"))).toBe(true);
|
expect(modes.every((mode) => !filterModeIsSupportedForDatabase(mode, "victoriametrics"))).toBe(true);
|
||||||
expect(filterModeIsSupportedForDatabase("equals", "postgres")).toBe(true);
|
expect(filterModeIsSupportedForDatabase("equals", "postgres")).toBe(true);
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ export function normalizeColumnFormatter(value: unknown): ColumnFormatterConfig
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const FOREIGN_KEY_DISPLAY_FILTER_MODES = new Set<DataGridContextFilterMode>(["equals", "not-equals", "is-null", "is-not-null", "like", "not-like", "less-than", "less-than-or-equal", "greater-than", "greater-than-or-equal", "in", "not-in", "between", "not-between"]);
|
const FOREIGN_KEY_DISPLAY_FILTER_MODES = new Set<DataGridContextFilterMode>(["equals", "not-equals", "is-null", "is-not-null", "is-blank", "is-not-blank", "like", "not-like", "less-than", "less-than-or-equal", "greater-than", "greater-than-or-equal", "in", "not-in", "between", "not-between"]);
|
||||||
|
|
||||||
function normalizeForeignKeyDisplayFilter(value: unknown): ForeignKeyDisplayFilterConfig | undefined {
|
function normalizeForeignKeyDisplayFilter(value: unknown): ForeignKeyDisplayFilterConfig | undefined {
|
||||||
if (!value || typeof value !== "object") return undefined;
|
if (!value || typeof value !== "object") return undefined;
|
||||||
@@ -200,7 +200,7 @@ function normalizeForeignKeyDisplayFilter(value: unknown): ForeignKeyDisplayFilt
|
|||||||
const mode = filter.mode as DataGridContextFilterMode;
|
const mode = filter.mode as DataGridContextFilterMode;
|
||||||
const rawValue = typeof filter.value === "string" ? filter.value.trim() : "";
|
const rawValue = typeof filter.value === "string" ? filter.value.trim() : "";
|
||||||
const rawEndValue = typeof filter.endValue === "string" ? filter.endValue.trim() : "";
|
const rawEndValue = typeof filter.endValue === "string" ? filter.endValue.trim() : "";
|
||||||
if (mode !== "is-null" && mode !== "is-not-null" && !rawValue) return undefined;
|
if (mode !== "is-null" && mode !== "is-not-null" && mode !== "is-blank" && mode !== "is-not-blank" && !rawValue) return undefined;
|
||||||
if ((mode === "between" || mode === "not-between") && !rawEndValue) return undefined;
|
if ((mode === "between" || mode === "not-between") && !rawEndValue) return undefined;
|
||||||
return {
|
return {
|
||||||
column: filter.column.trim(),
|
column: filter.column.trim(),
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ export function combineWhereInputs(manualWhereInput?: string, structuredWhereInp
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function filterModeNeedsValue(mode: DataGridContextFilterMode): boolean {
|
export function filterModeNeedsValue(mode: DataGridContextFilterMode): boolean {
|
||||||
return mode !== "is-null" && mode !== "is-not-null";
|
return mode !== "is-null" && mode !== "is-not-null" && mode !== "is-blank" && mode !== "is-not-blank";
|
||||||
}
|
}
|
||||||
|
|
||||||
export function filterModeUsesList(mode: DataGridContextFilterMode): boolean {
|
export function filterModeUsesList(mode: DataGridContextFilterMode): boolean {
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ export interface DataGridCopyInsertStatementOptions {
|
|||||||
insertMode?: DataGridCopyInsertMode;
|
insertMode?: DataGridCopyInsertMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type DataGridContextFilterMode = "equals" | "not-equals" | "is-null" | "is-not-null" | "like" | "not-like" | "less-than" | "less-than-or-equal" | "greater-than" | "greater-than-or-equal" | "in" | "not-in" | "between" | "not-between";
|
export type DataGridContextFilterMode = "equals" | "not-equals" | "is-null" | "is-not-null" | "is-blank" | "is-not-blank" | "like" | "not-like" | "less-than" | "less-than-or-equal" | "greater-than" | "greater-than-or-equal" | "in" | "not-in" | "between" | "not-between";
|
||||||
|
|
||||||
export interface DataGridContextFilterConditionOptions {
|
export interface DataGridContextFilterConditionOptions {
|
||||||
databaseType?: DatabaseType;
|
databaseType?: DatabaseType;
|
||||||
|
|||||||
@@ -149,6 +149,8 @@ pub enum DataGridContextFilterMode {
|
|||||||
NotEquals,
|
NotEquals,
|
||||||
IsNull,
|
IsNull,
|
||||||
IsNotNull,
|
IsNotNull,
|
||||||
|
IsBlank,
|
||||||
|
IsNotBlank,
|
||||||
Like,
|
Like,
|
||||||
NotLike,
|
NotLike,
|
||||||
LessThan,
|
LessThan,
|
||||||
@@ -546,6 +548,18 @@ pub fn build_data_grid_context_filter_condition(options: DataGridContextFilterCo
|
|||||||
match options.mode {
|
match options.mode {
|
||||||
DataGridContextFilterMode::IsNull => Some(format!("{column} IS NULL")),
|
DataGridContextFilterMode::IsNull => Some(format!("{column} IS NULL")),
|
||||||
DataGridContextFilterMode::IsNotNull => Some(format!("{column} IS NOT NULL")),
|
DataGridContextFilterMode::IsNotNull => Some(format!("{column} IS NOT NULL")),
|
||||||
|
DataGridContextFilterMode::IsBlank
|
||||||
|
if matches!(options.database_type, Some(DatabaseType::Oracle | DatabaseType::OceanbaseOracle)) =>
|
||||||
|
{
|
||||||
|
Some(format!("{column} IS NULL"))
|
||||||
|
}
|
||||||
|
DataGridContextFilterMode::IsNotBlank
|
||||||
|
if matches!(options.database_type, Some(DatabaseType::Oracle | DatabaseType::OceanbaseOracle)) =>
|
||||||
|
{
|
||||||
|
Some(format!("{column} IS NOT NULL"))
|
||||||
|
}
|
||||||
|
DataGridContextFilterMode::IsBlank => Some(format!("({column} IS NULL OR {column} = '')")),
|
||||||
|
DataGridContextFilterMode::IsNotBlank => Some(format!("({column} IS NOT NULL AND {column} <> '')")),
|
||||||
DataGridContextFilterMode::Equals if value.is_null() => Some(format!("{column} IS NULL")),
|
DataGridContextFilterMode::Equals if value.is_null() => Some(format!("{column} IS NULL")),
|
||||||
DataGridContextFilterMode::NotEquals if value.is_null() => Some(format!("{column} IS NOT NULL")),
|
DataGridContextFilterMode::NotEquals if value.is_null() => Some(format!("{column} IS NOT NULL")),
|
||||||
DataGridContextFilterMode::Like => Some(format!(
|
DataGridContextFilterMode::Like => Some(format!(
|
||||||
@@ -4152,6 +4166,73 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn builds_blank_and_nonblank_context_filter_conditions() {
|
||||||
|
let build = |database_type: DatabaseType,
|
||||||
|
mode: DataGridContextFilterMode,
|
||||||
|
identifier_quote: Option<&str>,
|
||||||
|
column_name: &str| {
|
||||||
|
build_data_grid_context_filter_condition(DataGridContextFilterConditionOptions {
|
||||||
|
database_type: Some(database_type),
|
||||||
|
identifier_quote: identifier_quote.map(str::to_string),
|
||||||
|
column_name: column_name.to_string(),
|
||||||
|
mode,
|
||||||
|
value: Value::Null,
|
||||||
|
values: Vec::new(),
|
||||||
|
end_value: None,
|
||||||
|
column_info: Some(column(column_name, "varchar", true, None)),
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
build(DatabaseType::Mysql, DataGridContextFilterMode::IsBlank, None, "status"),
|
||||||
|
Some("(`status` IS NULL OR `status` = '')".to_string())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
build(DatabaseType::Mysql, DataGridContextFilterMode::IsNotBlank, None, "status"),
|
||||||
|
Some("(`status` IS NOT NULL AND `status` <> '')".to_string())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
build(DatabaseType::Mysql, DataGridContextFilterMode::IsNull, None, "status"),
|
||||||
|
Some("`status` IS NULL".to_string())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
build(DatabaseType::Mysql, DataGridContextFilterMode::IsNotNull, None, "status"),
|
||||||
|
Some("`status` IS NOT NULL".to_string())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
build(DatabaseType::Kingbase, DataGridContextFilterMode::IsBlank, Some("`"), "order detail"),
|
||||||
|
Some("(`order detail` IS NULL OR `order detail` = '')".to_string())
|
||||||
|
);
|
||||||
|
|
||||||
|
for database_type in [DatabaseType::Oracle, DatabaseType::OceanbaseOracle] {
|
||||||
|
assert_eq!(
|
||||||
|
build(database_type, DataGridContextFilterMode::IsBlank, None, "STATUS"),
|
||||||
|
Some("\"STATUS\" IS NULL".to_string())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
build(database_type, DataGridContextFilterMode::IsNotBlank, None, "STATUS"),
|
||||||
|
Some("\"STATUS\" IS NOT NULL".to_string())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn keeps_context_filter_mode_serialization_stable() {
|
||||||
|
assert_eq!(serde_json::to_string(&DataGridContextFilterMode::IsNull).unwrap(), "\"is-null\"");
|
||||||
|
assert_eq!(serde_json::to_string(&DataGridContextFilterMode::IsNotNull).unwrap(), "\"is-not-null\"");
|
||||||
|
assert!(matches!(
|
||||||
|
serde_json::from_str::<DataGridContextFilterMode>("\"is-null\"").unwrap(),
|
||||||
|
DataGridContextFilterMode::IsNull
|
||||||
|
));
|
||||||
|
assert!(matches!(
|
||||||
|
serde_json::from_str::<DataGridContextFilterMode>("\"is-not-null\"").unwrap(),
|
||||||
|
DataGridContextFilterMode::IsNotNull
|
||||||
|
));
|
||||||
|
assert_eq!(serde_json::to_string(&DataGridContextFilterMode::IsBlank).unwrap(), "\"is-blank\"");
|
||||||
|
assert_eq!(serde_json::to_string(&DataGridContextFilterMode::IsNotBlank).unwrap(), "\"is-not-blank\"");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn builds_oracle_synthetic_rowid_context_filter_conditions() {
|
fn builds_oracle_synthetic_rowid_context_filter_conditions() {
|
||||||
let equals = |database_type, column_name: &str, value| {
|
let equals = |database_type, column_name: &str, value| {
|
||||||
@@ -4405,6 +4486,8 @@ mod tests {
|
|||||||
DataGridContextFilterMode::Like,
|
DataGridContextFilterMode::Like,
|
||||||
DataGridContextFilterMode::GreaterThan,
|
DataGridContextFilterMode::GreaterThan,
|
||||||
DataGridContextFilterMode::IsNull,
|
DataGridContextFilterMode::IsNull,
|
||||||
|
DataGridContextFilterMode::IsBlank,
|
||||||
|
DataGridContextFilterMode::IsNotBlank,
|
||||||
DataGridContextFilterMode::In,
|
DataGridContextFilterMode::In,
|
||||||
DataGridContextFilterMode::Between,
|
DataGridContextFilterMode::Between,
|
||||||
] {
|
] {
|
||||||
|
|||||||
+22
@@ -136,6 +136,7 @@ test("hides list and range modes for unsupported dialects", () => {
|
|||||||
}
|
}
|
||||||
assert.equal(filterModeIsSupportedForDatabase("between", "postgres"), true);
|
assert.equal(filterModeIsSupportedForDatabase("between", "postgres"), true);
|
||||||
assert.equal(filterModeIsSupportedForDatabase("is-null", "influxdb"), true);
|
assert.equal(filterModeIsSupportedForDatabase("is-null", "influxdb"), true);
|
||||||
|
assert.equal(filterModeIsSupportedForDatabase("is-blank", "influxdb"), true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("requires usable values for structured list and range filters", () => {
|
test("requires usable values for structured list and range filters", () => {
|
||||||
@@ -144,6 +145,27 @@ test("requires usable values for structured list and range filters", () => {
|
|||||||
assert.equal(filterModeHasCompleteValue("between", "10", ""), false);
|
assert.equal(filterModeHasCompleteValue("between", "10", ""), false);
|
||||||
assert.equal(filterModeHasCompleteValue("not-between", "10", "20"), true);
|
assert.equal(filterModeHasCompleteValue("not-between", "10", "20"), true);
|
||||||
assert.equal(filterModeHasCompleteValue("is-null", "", ""), true);
|
assert.equal(filterModeHasCompleteValue("is-null", "", ""), true);
|
||||||
|
assert.equal(filterModeHasCompleteValue("is-not-null", "", ""), true);
|
||||||
|
assert.equal(filterModeHasCompleteValue("is-blank", "", ""), true);
|
||||||
|
assert.equal(filterModeHasCompleteValue("is-not-blank", "", ""), true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("passes value-less blank modes through the shared context filter API", async () => {
|
||||||
|
installFilterFetchMock();
|
||||||
|
for (const mode of ["is-blank", "is-not-blank"] as const) {
|
||||||
|
await buildDataGridContextFilterCondition({
|
||||||
|
databaseType: "mysql",
|
||||||
|
columnName: "status",
|
||||||
|
mode,
|
||||||
|
value: null,
|
||||||
|
});
|
||||||
|
assert.deepEqual(lastContextFilterOptions, {
|
||||||
|
databaseType: "mysql",
|
||||||
|
columnName: "status",
|
||||||
|
mode,
|
||||||
|
value: null,
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test("passes list and range values through the shared context filter API", async () => {
|
test("passes list and range values through the shared context filter API", async () => {
|
||||||
|
|||||||
Reference in new issue
Block a user