devj
devj

Reputation: 1153

Scala string interpolation for variables instead of literals

Starting with an apology that being a beginner in Scala, I could not find better wordings for the question.

I have a properties file where I need to define a few parameterized commands (or sql queries). Following is an example of this:

[section abc]
stage: StageA
query: Select count(*) FROM tableA WHERE account_id=${account_id} AND dt=$dt AND source=$source

[section def]
stage: StageB
query: Select count(*) FROM tableB WHERE event_date=${event_date} AND template=$template

In my code, I have a config object (consider a Map) which has the values for the variables in my query string (account_id, source, dt, event_date, template, etc.,). After reading the properties file I need to substitute all the macros in my query string. For this I want to write a single function with a signature like:

def resolve_query(query: String, config: Map[String, Any]): String

which should return the query text with the macros substituted with values from the config. I tried writing my own String Interpolator, but it didn't work. Is there anything else that I can try?

Upvotes: 2

Views: 575

Answers (1)

jwvh
jwvh

Reputation: 51271

With string interpolation, the compiler cuts up a String literal into its parts before sending them to be recombined via StringContext. The compiler won't do that to a string value in a variable so you have to do the cutting yourself.

def resolve_query(query: String, config: Map[String, Any]): String =
  "(.*)\\$\\{([^}]+)}(.*)".r
    .findFirstMatchIn(query)
    .fold(query){ m =>
      resolve_query(StringContext(m.group(1)
                                 ,m.group(3)
                                 ).s(config.getOrElse(m.group(2), "unknown")
                                    )
                   ,config
                   )
                }

testing:

resolve_query(
  "Select count(*) FROM tableA WHERE account_id=${account_id} AND source=${source}"
 ,Map("account_id" -> 47, "source" -> "UK")
             )
//res0: String = Select count(*) FROM tableA WHERE account_id=47 AND source=UK

You'll note that I've only implemented the easier ${braces} delimited form. The $dollar delimited form isn't much trickier but allowing for both (either/or) would be more work than I'm willing to put in to it for now.

Upvotes: 2

Related Questions