Question

I'm trying to unload data from RedShift to S3 using Java + Hibernate, but cannot figure out how to get it to accept the string-within-a-string in the SQL.

No matter the escape sequences I try to use to get the quote characters correctly passed to RedShift, I just get exception after exception.

Any ideas would be welcome. Thanks.

Here's the query I'm trying to run on RedShift (and if I type this directly into RedShift, it works):

unload ('select raw_line from stl_load_errors where starttime > \'2013-01-01\' ')
  to 's3://myBucket/myTable/'
  credentials 'aws_access_key_id=*;aws_secret_access_key=*' gzip;

And here are the various commands I've tried in Java, with the errors I've encountered:

Single backslash

session.createSQLQuery("unload ('select raw_line from stl_load_errors where starttime > \'2013-01-01\' ')"
  + " to 's3://myBucket/myTable/'"
  + " credentials 'aws_access_key_id=" + key + ";aws_secret_access_key=" + secret + "'  gzip")
  .executeUpdate();

RESULTS
WARN org.hibernate.engine.jdbc.spi.SqlExceptionHelper - SQL Error: 0, SQLState: 42601
ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper - ERROR: syntax error at or near "2013" Position: 66
ERROR org.hibernate.exception.SQLGrammarException: could not execute statement

Double backslash

session.createSQLQuery("unload ('select raw_line from stl_load_errors where starttime > \\'2013-01-01\\' ')"
  + " to 's3://myBucket/myTable/'"
  + " credentials 'aws_access_key_id=" + key + ";aws_secret_access_key=" + secret + "'  gzip")
  .executeUpdate();

RESULTS
ERROR org.hibernate.QueryException: Space is not allowed after parameter prefix ':' [unload ('select raw_line from stl_load_errors where starttime > \'2013-01-01\' ') to 's3://myBucket/myTable/' credentials 'aws_access_key_id=*;aws_secret_access_key=*' gzip]
at org.hibernate.engine.query.spi.ParameterParser.parse(ParameterParser.java:95)

Triple backslash

session.createSQLQuery("unload ('select raw_line from stl_load_errors where starttime > \\\'2013-01-01\\\' ')"
  + " to 's3://myBucket/myTable/'"
  + " credentials 'aws_access_key_id=" + key + ";aws_secret_access_key=" + secret + "'  gzip")
  .executeUpdate();

RESULTS
2013-06-19 01:39:59,233 ERROR org.hibernate.QueryException: Space is not allowed after parameter prefix ':' [unload ('select raw_line from stl_load_errors where starttime > \'2013-01-01\' ') to 's3://myBucket/myTable/' credentials 'aws_access_key_id=*;aws_secret_access_key=*' gzip]
at org.hibernate.engine.query.spi.ParameterParser.parse(ParameterParser.java:95)

Quadruple backslash

session.createSQLQuery("unload ('select raw_line from stl_load_errors where starttime > \\\\'2013-01-01\\\\' ')"
  + " to 's3://myBucket/myTable/'"
  + " credentials 'aws_access_key_id=" + key + ";aws_secret_access_key=" + secret + "'  gzip")
  .executeUpdate();

RESULTS
WARN org.hibernate.engine.jdbc.spi.SqlExceptionHelper - SQL Error: 0, SQLState: 42601
ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper - ERROR: syntax error at or near "2013" Position: 68
ERROR org.hibernate.exception.SQLGrammarException: could not execute statement

Named parameter

session.createSQLQuery("unload (:query)"
  + " to 's3://myBucket/myTable/'"
  + " credentials 'aws_access_key_id=" + key + ";aws_secret_access_key=" + secret + "'  gzip")
  .setString("query", "select raw_line from stl_load_errors where starttime > '2013-01-01'")
  .executeUpdate();

RESULTS:
WARN org.hibernate.engine.jdbc.spi.SqlExceptionHelper - SQL Error: 0, SQLState: 42601
ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper - ERROR: syntax error at or near "$1" Position: 9
ERROR org.hibernate.exception.SQLGrammarException: could not execute statement

Was it helpful?

OTHER TIPS

I was given the suggestion to try to put the s3 path as a named parameter, as Hibernate (in the double and triple backslash cases) seems to not like the colon character.

Doing so, gave me this error:

ERROR java.lang.IllegalArgumentException: Parameter s3 does not exist as a named parameter in [unload ('select raw_line from stl_load_errors where starttime > \'2014-01-01\'') to :s3 credentials 'aws_access_key_id=*;aws_secret_access_key=*' gzip]

I get the impression that Hibernate is getting confused with the escaped single quotes and loses track of what is supposed to be quoted and what isn't (the colon after s3 shouldn't have posed a problem in the first place, as it was inside quoted text, but apparently Hibernate can't figure that out).

Sometimes you're just too close to the problem. After not thinking about it for a while, the obvious solution (workaround, really), is that I'll be doing the following:

  1. Create a temporary table
  2. Insert the needed data into the temporary table (no need for nested strings)
  3. Unload the entire contents of the temporary table to S3 (no need for nested strings)
  4. Drop the temporary table
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top