Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE]: native CASE WHEN support #1065

Open
Cherry opened this issue Aug 17, 2023 · 2 comments · May be fixed by #2812
Open

[FEATURE]: native CASE WHEN support #1065

Cherry opened this issue Aug 17, 2023 · 2 comments · May be fixed by #2812
Labels
enhancement New feature or request

Comments

@Cherry
Copy link
Contributor

Cherry commented Aug 17, 2023

Using case in queries can be a really nice way to restructure data, or omit things entirely if unset. https://www.postgresql.org/docs/current/functions-conditional.html

It's also very useful in orderBy queries, such as like this:

sql`
	case
		when ${table.scope} = 'a' 	then 1
		when ${table.scope} = 'b' 	then 2
		when ${table.scope} = 'c' 	then 3
		when ${table.scope} = 'd' 	then 4
	end
`,

Or when querying from multiple tables but wanting to conditionally change where data is coming from:

sql`
	case
		when ${table.type} = 'a' then ${someTable.name}
		when ${table.type} = 'b' then ${otherTable.title}
	end
`,

This is fine, but could be more ergonomic I think with a native helper.

Psuedo-example without much thought of what this could look like:

case(
	eq(table.type, 'a'), someTable.name,
	eq(table.type, 'b'), otherTable.title,
)
@Cherry Cherry added the enhancement New feature or request label Aug 17, 2023
@DrSensor
Copy link

DrSensor commented Dec 3, 2023

I also need this when treating INTEGER as enum in SQLite. Currently this is what I do

const { photo: _, ...csv } = getTableColumns(table);
for (const col in csv) {
  const enum_ = enums[col];
  if (enum_) {
    const stmt = sql`case ${table}`;
    for (const int in enum_) {
      stmt.append(sql`when ${Number(int)} then ${enum_[int]}`);
    }
    csv[col] = stmt.append(sql`end`);
  }
}
const result = await db.select(csv).from(table).values();

@floriangosse
Copy link

floriangosse commented Dec 19, 2023

This is an implementation I've just drafted but couldn't test yet. Feel free to give feedback.

function nehw<T>(condition: SQL<unknown>, value: T): SQL<T> {
    return sql`when ${condition} then ${value}`;
}
function esle<T>(value: T): SQL<T> {
    return sql`else ${value}`;
}

function esac<TRuleReturn>(...rules: SQL<TRuleReturn>[]): SQL<TRuleReturn> {
    const s = sql<TRuleReturn>`case`;
    rules.forEach((rule) => {
        s.append(rule);
    });
    s.append(sql`end`);
    return s;
}

// Example usage:
const caseSQL = esac(
    nehw(companyIsNew(), 'new'),
    nehw(companyIsInitializing(), 'initializing'),
    nehw(companyIsActive(), 'active'),
    esle('archived')
);

@louneskmt louneskmt linked a pull request Aug 20, 2024 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants