17

In R, how can I import the contents of a multiline text file (containing SQL) to a single string?

The sql.txt file looks like this:

SELECT TOP 100 
 setpoint, 
 tph 
FROM rates

I need to import that text file into an R string such that it looks like this:

> sqlString
[1] "SELECT TOP 100 setpoint, tph FROM rates"

That's so that I can feed it to the RODBC like this

> library(RODBC)
> myconn<-odbcConnect("RPM")
> results<-sqlQuery(myconn,sqlString)

I've tried the readLines command as follows but it doesn't give the string format that RODBC needs.

> filecon<-file("sql.txt","r")
> sqlString<-readLines(filecon, warn=FALSE)
> sqlString
[1] "SELECT TOP 100 "                              "\t[Reclaim Setpoint Mean (tph)] as setpoint, "
[3] "\t[Reclaim Rate Mean (tph)] as tphmean "       "FROM [Dampier_RC1P].[dbo].[Rates]"           
> 

7 Answers 7

17

The versatile paste() command can do that with argument collapse="":

lines <- readLines("/tmp/sql.txt")
lines
[1] "SELECT TOP 100 " " setpoint, "     " tph "           "FROM rates"     

sqlcmd <- paste(lines, collapse="")
sqlcmd
[1] "SELECT TOP 100  setpoint,  tph FROM rates"
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks Dirk - that works, except the string looks like this "SELECT TOP 100\t setpoint,\t tph\t FROM rates\t". Just needed to add gsub("\t","", sqlcmd)
Well what I copied had not tabs, in any event the SQL parser will probably ignore the tabs anyway and you found the gsub() -- all good.
This will likely butcher your query if you have any -- comments, won't it? I'd use paste(readLines('pathto/query.sql'), collapse = "\n")
Removing tabs might break the SQL query, as a tab could be the only whitespace between terms. Better to leave them in, as the database will just ignore them anyway.
9

Below is an R function that reads in a multiline SQL query (from a text file) and converts it into a single-line string. The function removes formatting and whole-line comments.

To use it, run the code to define the functions, and your single-line string will be the result of running ONELINEQ("querytextfile.sql","~/path/to/thefile").

How it works: Inline comments detail this; it reads each line of the query and deletes (replaces with nothing) whatever isn't needed to write out a single-line version of the query (as asked for in the question). The result is a list of lines, some of which are blank and get filtered out; the last step is to paste this (unlisted) list together and return the single line.

#
# This set of functions allows us to read in formatted, commented SQL queries
# Comments must be entire-line comments, not on same line as SQL code, and begun with "--"
# The parsing function, to be applied to each line:
LINECLEAN <- function(x) {
  x = gsub("\t+", "", x, perl=TRUE); # remove all tabs
  x = gsub("^\\s+", "", x, perl=TRUE); # remove leading whitespace
  x = gsub("\\s+$", "", x, perl=TRUE); # remove trailing whitespace
  x = gsub("[ ]+", " ", x, perl=TRUE); # collapse multiple spaces to a single space
  x = gsub("^[--]+.*$", "", x, perl=TRUE); # destroy any comments
  return(x)
}
# PRETTYQUERY is the filename of your formatted query in quotes, eg "myquery.sql"
# DIRPATH is the path to that file, eg "~/Documents/queries"
ONELINEQ <- function(PRETTYQUERY,DIRPATH) { 
  A <- readLines(paste0(DIRPATH,"/",PRETTYQUERY)) # read in the query to a list of lines
  B <- lapply(A,LINECLEAN) # process each line
  C <- Filter(function(x) x != "",B) # remove blank and/or comment lines
  D <- paste(unlist(C),collapse=" ") # paste lines together into one-line string, spaces between.
  return(D)
}
# TODO: add eof newline automatically to remove warning
#############################################################################################

2 Comments

...You know, this is probably the single best self-promotion answer I've seen yet. Could you add a brief explanation of how it works to your answer as well? (And by that, I mean edit your answer)
Gotta love a clean and straighforward base R approach! Thanks for sharing this gem!
4

Here's the final version of what I'm using. Thanks Dirk.

fileconn<-file("sql.txt","r")           
sqlString<-readLines(fileconn)          
sqlString<-paste(sqlString,collapse="")
gsub("\t","", sqlString)
library(RODBC)
sqlconn<-odbcConnect("RPM")
results<-sqlQuery(sqlconn,sqlString)
library(qcc)
tph <- qcc(results$tphmean[1:50], type="xbar.one", ylim=c(4000,12000), std.dev=600)
close(fileconn)
close(sqlconn)

Comments

2

This is what I use:

# Set Filename
fileName <- 'Input File.txt'

doSub <- function(src, dest_var_name, src_pattern, dest_pattern) {
    assign(
            x       = dest_var_name
        ,   value   = gsub(
                            pattern     = src_pattern
                        ,   replacement = dest_pattern
                        ,   x = src
                    )
        ,   envir   = .GlobalEnv
    )
}


# Read File Contents
original_text <- readChar(fileName, file.info(fileName)$size)

# Convert to UNIX line ending for ease of use
doSub(src = original_text, dest_var_name = 'unix_text', src_pattern = '\r\n', dest_pattern = '\n')

# Remove Block Comments
doSub(src = unix_text, dest_var_name = 'wo_bc_text', src_pattern = '/\\*.*?\\*/', dest_pattern = '')

# Remove Line Comments
doSub(src = wo_bc_text, dest_var_name = 'wo_bc_lc_text', src_pattern = '--.*?\n', dest_pattern = '')

# Remove Line Endings to get Flat Text
doSub(src = wo_bc_lc_text, dest_var_name = 'flat_text', src_pattern = '\n', dest_pattern = ' ')

# Remove Contiguous Spaces
doSub(src = flat_text, dest_var_name = 'clean_flat_text', src_pattern = ' +', dest_pattern = ' ')

Comments

1

try paste(sqlString, collapse=" ")

Comments

1

It's possible to use readChar() instead of readLines(). I had an ongoing issue with mixed commenting (-- or /* */) and this has always worked well for me.

sql <- readChar(path.to.file, file.size(path.to.file))
query <- sqlQuery(con, sql, stringsAsFactors = TRUE)

Comments

0

I use sql <- gsub("\n","",sql) and sql <- gsub("\t","",sql) together.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.