sqlutils icon indicating copy to clipboard operation
sqlutils copied to clipboard

Non set SQL user variables `:=` leads to error

Open GeraudK opened this issue 7 years ago • 0 comments

It seems that when setting multiple := to use user variables within SELECT in MySQL the getSQL function will throw the following error:

Error in if (!is.null(params) & length(params[params$param == v, "default"]) >  : 
  argument is of length zer

The reason is that the getParameters function only looks for ":" and then takes everything in between without any further test.

Taking an example here:

SELECT  source,
        MIN(value) AS min,
        MAX(value) AS max,
        SUM(value) AS sum,
        CAST(AVG(value) AS DECIMAL(20, 2)) AS avg
FROM    (
        SELECT  @series := @series + (COALESCE(@source <> source, 0)) AS series,
                @source := source AS newsource,
                q.*
        FROM    (
                SELECT  @series := 1, @source := NULL
                ) vars
        STRAIGHT_JOIN
                (
                SELECT  1 AS id, 1 AS source, 10 AS value
                UNION ALL
                SELECT  2 AS id, 1 AS source, 20 AS value
                UNION ALL
                SELECT  3 AS id, 2 AS source, 15 AS value
                UNION ALL
                SELECT  4 AS id, 2 AS source, 25 AS value
                UNION ALL
                SELECT  5 AS id, 1 AS source, 45 AS value
                UNION ALL
                SELECT  6 AS id, 3 AS source, 50 AS value
                UNION ALL
                SELECT  7 AS id, 3 AS source, 35 AS value
                UNION ALL
                SELECT  8 AS id, 1 AS source, 40 AS value
                UNION ALL
                SELECT  9 AS id, 1 AS source, 10 AS value
                ) q
        ORDER BY
                id
        ) q
GROUP BY
        series

When using the sqlutils::getSQL function this will throw an error as it will consider:

  1. "= @series + (COALESCE(@source <> source, 0)) AS series, @source"
  2. "= 1, @source "

as being parameters.

My suggestion would be to replace here:

pos = gregexpr(":", sql)
by
pos = gregexpr(":(?!=)", sql, perl = T)
or even
pos = gregexpr("(?<=[@\\b\\s]):(?!=)", sql, perl = T)

I understand that another solution for this example would be to use sqlutils::getSQLRaw(query) however it would not allow users to add any extra parameters.

I can help with a PR if you want.

GeraudK avatar Sep 12 '17 12:09 GeraudK