5

Description

I am working as a new member on a Spring Boot Project that utilizes 2 different properties files for 2 different configurations related to DB settings:

  • production mode: postgres SQL DB
  • development mode: h2 in memory DB

Since I'm trying to minimize differences in the two scripts, I have started writing functions that will take case of differences related to date/time handling.

One example is adding hours since postgres uses intervals and h2 uses the oracle similar date_add function.

Unfortunately I am getting an exception for function creation statements that work in the console.

Existing Files

Config/Properties

spring.profiles.active=pre-prod

spring.datasource.url=jdbc:postgresql://localhost:5432/db
spring.datasource.username=postgres
spring.datasource.password=root
spring.datasource.driver-class-name=org.postgresql.Driver

spring.datasource.data=classpath:db/migration/postgres/db_functions.sql,classpath:db/migration/postgres/data.sql
spring.jpa.hibernate.ddl-auto=create

db_functions.sql

--Adds a cast to date to the specific statement
--for h2 simply make a wrapper
CREATE OR REPLACE FUNCTION db_pgres_cast_varchar_to_date(d VARCHAR ) RETURNS date AS $$
        BEGIN
                RETURN d::date;
        END;
$$ LANGUAGE plpgsql;

--Common function for h2 and vct to add hours
--References: http://stackoverflow.com/questions/9376350/postgresql-how-to-concat-interval-value-2-days
CREATE OR REPLACE FUNCTION db_add_hours(d timestamp, hours int) RETURNS timestamp AS $$
        BEGIN
                RETURN d +  (hours || ' hours')::interval;
        END;
$$ LANGUAGE plpgsql;

Exception

NFO] org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor Shutting down ExecutorService 'createTaskExecutor'
Exception in thread "main" org.springframework.jdbc.datasource.init.UncategorizedScriptException: Failed to execute database script from resource [class path resource [db/migration/postgres/vct_functions.sql]]; nested exception is java.lang.ArrayIndexOutOfBoundsException
    at org.springframework.jdbc.datasource.init.ScriptUtils.executeSqlScript(ScriptUtils.java:509)

Update

I started debugging and see that instead of the split/parser code creating 2 statements, my scripts are being interpreted as 6 SQL commands:

enter image description here

Update 2

The problem seems to be with the implementation of splitSqlScript, definition:

public static void splitSqlScript(EncodedResource resource, String script, String separator, String commentPrefix,
            String blockCommentStartDelimiter, String blockCommentEndDelimiter, List<String> statements)
            throws ScriptException

https://www.codatlas.com/github.com/spring-projects/spring-framework/HEAD/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptUtils.java?line=166

Update 3

Since Spring Utils of Spring seems to be the problem I am trying a different syntax to create my functions:

--Adds a cast to date to the specific statement
--for h2 simply a wrapper
CREATE OR REPLACE FUNCTION vct_pgres_cast_varchar_to_date(VARCHAR ) RETURNS date
    AS 'select $1::date;'
    LANGUAGE SQL
    RETURNS NULL ON NULL INPUT;


--Common function for h2 and vct to add hours
--References: http://stackoverflow.com/questions/9376350/postgresql-how-to-concat-interval-value-2-days

CREATE OR REPLACE FUNCTION vct_add_hours(timestamp, integer) RETURNS timestamp
    AS 'select $1 +  ($2 || '' hours'')::interval'
    LANGUAGE SQL
    RETURNS NULL ON NULL INPUT;
5
  • 1
    Make sure you're using the latest PgJDBC, older versions IIRC had issues with $$ quoting. Are you sure that's the bottom exception on the stack? Commented Oct 15, 2015 at 9:00
  • @Craig Ringer Please see update... it seems the parser is even interpreting ';' as a delimiter. I will also check if $$ is the problem. Commented Oct 15, 2015 at 9:06
  • The exception reports vct_functions.sql instead of db_functions.sql. A typing mistake? Commented Oct 15, 2015 at 9:17
  • @Tommaso Di Bucchianico No, I generally change the names of stuff in my code excepts on stackoverflow. The name of the SQL file is not the issue, thanks. Commented Oct 15, 2015 at 9:18
  • @Craig Ringer Does 9.4-1200-jdbc4 have this issue? Commented Oct 15, 2015 at 9:24

2 Answers 2

2

The problem is SplitSqlScript of spring: https://www.codatlas.com/github.com/spring-projects/spring-framework/HEAD/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptUtils.java?line=166

I worked through this by changing the syntax of my create function statement to avoid $$ and enclose the SQL statement within quotes.

E.g.

CREATE OR REPLACE FUNCTION vct_pgres_cast_varchar_to_date(VARCHAR ) RETURNS date
    AS 'select $1::date;'
    LANGUAGE SQL
    RETURNS NULL ON NULL INPUT;
Sign up to request clarification or add additional context in comments.

Comments

0

I had this issue today, trying to load a PostGreSQL dump file containing a stored procedure. The SP had ; within the block, and there is no way to "escape" this. I got the ScriptUtils.executeSqlScript call to work by changing the delimiter from ; to this:

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/jdbc/datasource/init/ScriptUtils.html#EOF_STATEMENT_SEPARATOR

ScriptUtils.executeSqlScript(dataSource.getConnection(), new EncodedResource(resourceLoader.getResource(String.format("file:%s%s", getCwd(), SCHEMA_SQL_FILE))), false, false, DEFAULT_COMMENT_PREFIX, EOF_STATEMENT_SEPARATOR, DEFAULT_BLOCK_COMMENT_START_DELIMITER, DEFAULT_BLOCK_COMMENT_END_DELIMITER);

The constants I'm using in the parameters can be imported via:

import static org.springframework.jdbc.datasource.init.ScriptUtils.*;

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.