/* This file is part of VoltDB. * Copyright (C) 2008-2017 VoltDB Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with VoltDB. If not, see <http://www.gnu.org/licenses/>. */ package org.voltdb.parser; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Provides an API for performing various lexing operations on SQL/DML/DDL text. * Ideally it shouldn't be doing "parsing", i.e. language-aware token processing. * In reality the code is not split cleanly and lexing and parsing overlap a bit. * * Keep the regular expressions private and just expose methods needed for parsing. * * Avoid external dependencies since this is linked with the client. */ public class JDBCParser { //private static final VoltLogger COMPILER_LOG = new VoltLogger("COMPILER"); //========== Private Parsing Data ========== private static final Pattern PAT_CALL_WITH_PARAMETERS = Pattern.compile( "^\\s*\\{\\s*call\\s+([^\\s()]+)\\s*\\(([?,\\s]+)\\)\\s*\\}\\s*$", Pattern.CASE_INSENSITIVE); private static final Pattern PAT_CALL_WITHOUT_PARAMETERS = Pattern.compile( "^\\s*\\{\\s*call\\s+([^\\s()]+)\\s*\\}\\s*$", Pattern.CASE_INSENSITIVE); private static final Pattern PAT_CLEAN_CALL_PARAMETERS = Pattern.compile("[\\s,]+"); //========== Public Methods ========== /** * Object class returned by parseJDBCCall() */ public static class ParsedCall { public String sql; public int parameterCount; ParsedCall(String sql, int parameterCount) { this.sql = sql; this.parameterCount = parameterCount; } } /** * Parse call statements for JDBC. * @param jdbcCall statement to parse * @return object with parsed data or null if it didn't parse * @throws SQLParser.Exception */ public static ParsedCall parseJDBCCall(String jdbcCall) throws SQLParser.Exception { Matcher m = PAT_CALL_WITH_PARAMETERS.matcher(jdbcCall); if (m.matches()) { String sql = m.group(1); int parameterCount = PAT_CLEAN_CALL_PARAMETERS.matcher(m.group(2)).replaceAll("").length(); return new ParsedCall(sql, parameterCount); } m = PAT_CALL_WITHOUT_PARAMETERS.matcher(jdbcCall); if (m.matches()) { return new ParsedCall(m.group(1), 0); } return null; } }