All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.holonplatform.jdbc.internal.SQLScriptUtils Maven / Gradle / Ivy

There is a newer version: 5.7.0
Show newest version
/*
 * Copyright 2016-2017 Axioma srl.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.holonplatform.jdbc.internal;

import java.io.IOException;
import java.sql.Connection;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import com.holonplatform.core.internal.Logger;
import com.holonplatform.core.internal.utils.ObjectUtils;

/**
 * Utility class to execute a SQL script.
 *
 * @since 5.1.0
 */
public class SQLScriptUtils {

	private static final Logger LOGGER = JdbcLogger.create();

	/**
	 * Statement separator
	 */
	private static final String STATEMENT_SEPARATOR = ";";

	/**
	 * Prefix for single-line comments
	 */
	private static final String COMMENT_PREFIX = "--";

	/**
	 * Start delimiter for block comments
	 */
	private static final String BLOCK_COMMENT_START = "/*";

	/**
	 * End delimiter for block comments
	 */
	private static final String BLOCK_COMMENT_END = "*/";

	/**
	 * Execute given SQL script using provided {@link Connection}.
	 * @param connection Connection on which to execute the script (not null)
	 * @param script SQL script not null
	 * @throws IOException If an execution error occurred
	 */
	public static void executeSqlScript(Connection connection, String script) throws IOException {

		ObjectUtils.argumentNotNull(connection, "Connection must be not null");
		ObjectUtils.argumentNotNull(script, "Script must be not null");

		try {

			final List statements = splitSql(script);

			@SuppressWarnings("resource")
			Statement stmt = connection.createStatement();
			try {
				for (String statement : statements) {
					stmt.execute(statement);
				}
			} finally {
				try {
					stmt.close();
				} catch (Throwable ex) {
					LOGGER.debug(() -> "Failed to close JDBC Statement", ex);
				}
			}

			LOGGER.info("SQL script executed");

		} catch (Exception ex) {
			throw new IOException("Failed to execute SQL script", ex);
		}
	}

	/**
	 * Split given SQL script into separate statements.
	 * @return the individual statements
	 * @throws IOException if an error occurred
	 */
	private static List splitSql(String script) throws IOException {

		final List statements = new ArrayList<>();

		StringBuilder sb = new StringBuilder();

		boolean inSingleQuote = false;
		boolean inDoubleQuote = false;
		boolean inEscape = false;

		for (int i = 0; i < script.length(); i++) {
			char c = script.charAt(i);
			if (inEscape) {
				inEscape = false;
				sb.append(c);
				continue;
			}
			if (c == '\\') {
				inEscape = true;
				sb.append(c);
				continue;
			}
			if (!inDoubleQuote && (c == '\'')) {
				inSingleQuote = !inSingleQuote;
			} else if (!inSingleQuote && (c == '"')) {
				inDoubleQuote = !inDoubleQuote;
			}

			if (!inSingleQuote && !inDoubleQuote) {
				if (script.startsWith(STATEMENT_SEPARATOR, i)) {
					// end of statement
					if (sb.length() > 0) {
						statements.add(sb.toString());
						sb = new StringBuilder();
					}
					i += STATEMENT_SEPARATOR.length() - 1;
					continue;
				} else if (script.startsWith(COMMENT_PREFIX, i)) {
					// single line comment
					int nlIdx = script.indexOf("\n", i);
					if (nlIdx > i) {
						i = nlIdx;
						continue;
					} else {
						break;
					}
				} else if (script.startsWith(BLOCK_COMMENT_START, i)) {
					// block comment
					int indexOfCommentEnd = script.indexOf(BLOCK_COMMENT_END, i);
					if (indexOfCommentEnd > i) {
						i = indexOfCommentEnd + BLOCK_COMMENT_START.length() - 1;
						continue;
					} else {
						throw new IOException("Missing block comment end delimiter at: " + i);
					}
				} else if (c == ' ' || c == '\n' || c == '\t') {
					// trim whitespaces into a single space
					if (sb.length() > 0 && sb.charAt(sb.length() - 1) != ' ') {
						c = ' ';
					} else {
						continue;
					}
				}
			}
			sb.append(c);
		}

		final String stmt = sb.toString();
		if (!stmt.trim().equals("")) {
			statements.add(stmt);
		}

		return statements;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy