Skip to content

[requesting assistance] Can the same parameter be used in multiple places in the same prepared statement? #571

Closed
@margaretselzer

Description

@margaretselzer

In an SQLite database I am using a prepared statement to look up a record in a table storing component data. Each component has two names, a schematicName and a name (which can be null), When I search the table I need to find records that match the name or schematicName. So far this could be easily done with something like this:

    return sqlpp::select(
         all_of(components)
         .from(components)
         .where(
             (components.name.is_not_null() and (components.name == sqlpp::parameter(components.name))
                 or (components.schematicName == sqlpp::parameter(components.schematicName)))
         );

But I also need to know what the match was made on, the name or the schematicName. To this I would ideally use a calculated column with an alias, e.g.:

    auto matchCalc_exp =
        case_when(components.name == sqlpp::parameter(components.name))
            .then(0)
            .else_(case_when(components.schematicName
                                    == sqlpp::parameter(components.schematicName))
                       .then(1)
                       .else_(3))
            .as(matchQualifier);

In an ideal world I could use this alias matchQualifier in the where clause instead of doing the equality checks again. If it worked, it could translate into the following SQL:

SELECT tblComponents.*, 
      (CASE WHEN (tblComponents.name=?1) THEN 1 
            ELSE (CASE WHEN (tblComponents.schematicName=?2) THEN 0 
                    ELSE 3 
                  END) 
       END) AS matchQualifier 
FROM tblComponents 
WHERE (matchQualifier != 3)

But I just could not find any way to make this work.

  1. I could not find any way to use an aliased column in the where clause.
  2. Directly using the expression in the where clause makes duplicating the parameters which results in a compile error. (Even if it worked, the resulting query would not be too efficient either.)
  3. Ideally, I would like to use just one parameter, a searchName instead of needing to assign the same string value to both myQuery.params.name and myQuery.params.schematicName, but this results in duplication as well, so does not compile.
  4. Tried to use sqlpp::verbatim() in the where clause to add matchQualifier != 3 but could not make it work. All it gave me was a static_assert: Invalid operand(s)
  5. I tried to make a temporary table alias to the query with the extra matchQualifier column which actually compiled, but then the parameters of the expression are not visible in the prepared statement and I am back to square one. Besides, with this approach I would run the select twice on the table (SELECT * FROM (SELECT *, CASE WHEN ... AS matchQualifier) WHERE ...) WHERE matchQualifier != 3) which is not too healthy.

Update
I found how I can use the expression in the WHERE clause. Removing the .as(matchQualifier) part does the trick. Then the expression can be directly compared with another sqlpp value, e.g.: .where(matchCalc_exp != sqlpp::value(3)).

However, I now realize that my initial query design is less than optimal, To be able to utilize indexes on the name fields I have to have the names in the where clause. In this case if I wanted to have my calculated matchQualifier field I would need to use the same expression there, but it would then require me to use different parameter aliases.

So all my above questions really boil down to:
Can the same parameter be used in multiple places in the same prepared statement?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions