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

Helper for join array of SQLStatements? #32

Open
Strate opened this issue Mar 30, 2017 · 5 comments · May be fixed by #35
Open

Helper for join array of SQLStatements? #32

Strate opened this issue Mar 30, 2017 · 5 comments · May be fixed by #35

Comments

@Strate
Copy link

Strate commented Mar 30, 2017

Just ran into this: need to join array of condition parts with and separator:

// I have this:
const parts: SQLStatement[] = [
  SQL`a = ${value1}`,
  SQL`b = ${value2}`,
]

// I need this:
SQL`a = ${value1} AND b = ${value2}`

It is not big deal to write function for that, but maybe it is better to have this one in the library? What do you think about it?

@Strate
Copy link
Author

Strate commented Mar 30, 2017

This is my implementation for that:

function joinStatements(separator: SQLStatement, parts: SQLStatement[]): SQLStatement {
    const result = SQL``
    for (let i = 0, count = parts.length; i < count; i++) {
        result.append(parts[i])
        if (i < count - 1) {
            result.append(separator)
        }
    }

    return result
}

@KaidenR
Copy link

KaidenR commented Apr 8, 2017

I just ran into this same exact need. My use case is that I want my query to insert multiple rows like this:

INSERT INTO authors (id, user_handle, first_name, last_name) 
VALUES ($1, $2, $3, $4), ($5, $6, $7, $8), ($9, $10, $11, $12), ...

So I played around with monkey-patching a new appendAll() function which lets you pass in an array of SQLStatements or strings and an optional delimiter (defaults to a space):

SQLStatement.prototype.appendAll = function(statements:(SQLStatement|string|number)[], delimiter:string = ' ') {
  for (let i = 0; i < statements.length; i++) {
    this.append(statements[i])
      .append(i < statements.length - 1 ? delimiter : '')
  }
  return this
}

Which allowed me to do:

const query = sql`INSERT INTO authors (id, user_handle, first_name, last_name) VALUES `
  .appendAll(authors.map(a => sql`(${a.id}, ${a.authorHandle}, ${a.userHandle}, ${a.firstName}, ${a.lastName})`), ', ')

Another option would be add this functionality to the .append() function instead of to a new .appendAll().

@felixfbecker What do you think? I'd love to submit a PR (along with tests and type updates) if you're okay with this.

@felixfbecker
Copy link
Owner

For anyone stumbling upon this, appendAll is equivalent to

toAppend.reduce((prev, curr) => prev.append(delimeter).append(curr), statement)

@KaidenR KaidenR linked a pull request Jun 28, 2017 that will close this issue
@Janpot
Copy link

Janpot commented Oct 17, 2019

For me, the main difference between .append and a join function (like pg-template-tag has) is mutability. join leaves the original query untouched, which leads to a program that is easier to reason about.

@trygveaa
Copy link

trygveaa commented Mar 5, 2022

@felixfbecker: Like @Janpot said, it would be really nice with a join function. This would make inserting multiple rows as simple as:

const queryValues = SQL.join(values.map((value) => SQL`(${value})`), ", ")
const query = SQL`INSERT INTO table (value) VALUES ${queryValues}`

This is really easy to read and write IMO, allows you to be immutable and you don't have to check if you are on the last value or not to know if you should add a ,. Are you opposed to adding support for this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants