/* * Licensed to CRATE Technology GmbH ("Crate") under one or more contributor * license agreements. See the NOTICE file distributed with this work for * additional information regarding copyright ownership. Crate licenses * this file to you 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. * * However, if you have executed another commercial license agreement * with Crate these terms will supersede the license and you may use the * software solely pursuant to the terms of the relevant commercial agreement. */ package io.crate.action.sql.parser; import com.google.common.collect.ImmutableMap; import io.crate.exceptions.SQLParseException; import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentHelper; import org.elasticsearch.common.xcontent.XContentParser; /** * Parser for SQL statements in JSON and other XContent formats * <p> * <pre> * { * "stmt": "select * from...." * } * </pre> */ public class SQLXContentSourceParser { private final SQLXContentSourceContext context; static final class Fields { static final String STMT = "stmt"; static final String ARGS = "args"; static final String BULK_ARGS = "bulk_args"; } private static final ImmutableMap<String, SQLParseElement> elementParsers = ImmutableMap.of( Fields.STMT, (SQLParseElement) new SQLStmtParseElement(), Fields.ARGS, (SQLParseElement) new SQLArgsParseElement(), Fields.BULK_ARGS, (SQLParseElement) new SQLBulkArgsParseElement() ); public SQLXContentSourceParser(SQLXContentSourceContext context) { this.context = context; } private void validate() throws SQLParseSourceException { if (context.stmt() == null) { throw new SQLParseSourceException("Field [stmt] was not defined"); } } public void parseSource(BytesReference source) throws SQLParseException { XContentParser parser = null; try { if (source != null && source.length() != 0) { parser = XContentFactory.xContent(source).createParser(source); parse(parser); } validate(); } catch (Exception e) { String sSource = "_na_"; try { sSource = XContentHelper.convertToJson(source, false); } catch (Throwable e1) { // ignore } throw new SQLParseException("Failed to parse source [" + sSource + "]", e); } finally { if (parser != null) { parser.close(); } } } public void parse(XContentParser parser) throws Exception { XContentParser.Token token; while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { String fieldName = parser.currentName(); parser.nextToken(); SQLParseElement element = elementParsers.get(fieldName); if (element == null) { throw new SQLParseException("No parser for element [" + fieldName + "]"); } element.parse(parser, context); } else if (token == null) { break; } } } }