You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ofbiz.apache.org by Scott Gray <sc...@hotwaxmedia.com> on 2009/11/13 00:35:23 UTC

Re: svn commit: r835637 - in /ofbiz/trunk/framework/entity: build.xml src/org/ofbiz/entity/sql/ src/org/ofbiz/entity/sql/Parser.jjt src/org/ofbiz/entity/sql/SQLSelect.java

Hi Adam,

What exactly does this do?

Thanks
Scott

HotWax Media
http://www.hotwaxmedia.com

On 13/11/2009, at 12:23 PM, doogie@apache.org wrote:

> Author: doogie
> Date: Thu Nov 12 23:23:12 2009
> New Revision: 835637
>
> URL: http://svn.apache.org/viewvc?rev=835637&view=rev
> Log:
> Start of new sql parsing code.  Not completely tested.  It *does*  
> parse
> a test SELECT; what is not tested is actually running the built
> DynamicViewEntity.
>
> Added:
>    ofbiz/trunk/framework/entity/src/org/ofbiz/entity/sql/
>    ofbiz/trunk/framework/entity/src/org/ofbiz/entity/sql/Parser.jjt
>    ofbiz/trunk/framework/entity/src/org/ofbiz/entity/sql/ 
> SQLSelect.java
> Modified:
>    ofbiz/trunk/framework/entity/build.xml
>
> Modified: ofbiz/trunk/framework/entity/build.xml
> URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/entity/build.xml?rev=835637&r1=835636&r2=835637&view=diff
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- ofbiz/trunk/framework/entity/build.xml (original)
> +++ ofbiz/trunk/framework/entity/build.xml Thu Nov 12 23:23:12 2009
> @@ -38,6 +38,10 @@
>         <fileset dir="../base/lib/scripting" includes="*.jar"/>
>         <fileset dir="../base/build/lib" includes="*.jar"/>
>     </path>
> +    <path id="src-path">
> +        <pathelement location="build/gen-src/javacc"/>
> +        <pathelement location="build/gen-src/jjtree"/>
> +    </path>
>
>     <patternset id="src.exc.set">
>         <exclude name="org/ofbiz/entity/connection/ 
> XaPoolConnectionFactory.java"/>
> @@ -48,7 +52,11 @@
>     <!-- Compilation of the source  
> files 
>                                                                                                                          -->
>     <!--  
> ================================================================== -->
>
> -    <target name="classes" depends="prepare">
> +    <target name="gen-src">
> +        <ofbiz-jjtree dir="org/ofbiz/entity/sql" file="Parser"/>
> +    </target>
> +
> +    <target name="classes" depends="prepare,gen-src">
>         <javac15/>
>     </target>
>
>
> Added: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/sql/ 
> Parser.jjt
> URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/entity/src/org/ofbiz/entity/sql/Parser.jjt?rev=835637&view=auto
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- ofbiz/trunk/framework/entity/src/org/ofbiz/entity/sql/Parser.jjt  
> (added)
> +++ ofbiz/trunk/framework/entity/src/org/ofbiz/entity/sql/Parser.jjt  
> Thu Nov 12 23:23:12 2009
> @@ -0,0 +1,414 @@
> +options {
> +  JAVA_UNICODE_ESCAPE = false;
> +  ERROR_REPORTING = true;
> +  STATIC = false;
> +  MULTI = true;
> +  JDK_VERSION = "1.5";
> +  VISITOR = true;
> +  BUILD_NODE_FILES = true;
> +  NODE_FACTORY = false;
> +  NODE_USES_PARSER = true;
> +//  NODE_SCOPE_HOOK = true;
> +  NODE_PREFIX = "SQL";
> +//  DEBUG_PARSER = true;
> +//  DEBUG_LOOKAHEAD = true;
> +//  DEBUG_TOKEN_MANAGER = true;
> +  LOOKAHEAD = 1;
> +//  CHOICE_AMBIGUITY_CHECK = 3;
> +//  OTHER_AMBIGUITY_CHECK = 3;
> +  IGNORE_CASE = true;
> +}
> +PARSER_BEGIN(Parser)
> +
> +package org.ofbiz.entity.sql;
> +
> +import java.io.*;
> +import java.util.List;
> +import java.util.LinkedList;
> +import java.util.Set;
> +
> +import javolution.util.FastList;
> +import javolution.util.FastSet;
> +
> +import org.ofbiz.base.conversion.ConversionException;
> +import org.ofbiz.base.conversion.Converter;
> +import org.ofbiz.base.conversion.Converters;
> +import org.ofbiz.entity.condition.EntityComparisonOperator;
> +import org.ofbiz.entity.condition.EntityCondition;
> +import org.ofbiz.entity.condition.EntityConditionValue;
> +import org.ofbiz.entity.condition.EntityFieldValue;
> +import org.ofbiz.entity.condition.EntityOperator;
> +import org.ofbiz.entity.model.DynamicViewEntity;
> +import org.ofbiz.entity.model.ModelKeyMap;
> +
> +public class Parser {
> +}
> +
> +PARSER_END(Parser)
> +TOKEN_MGR_DECLS: {
> +	private final LinkedList<Integer> stack = new LinkedList<Integer>();
> +
> +	void pushState(int newState) {
> +		stack.add(curLexState);
> +		SwitchTo(newState);
> +	}
> +
> +	void popState() {
> +		SwitchTo(stack.removeLast());
> +	}
> +}
> +
> +TOKEN: {
> +	<OPEN_PAREN: "(">
> +|	<CLOSE_PAREN: ")">
> +|	<AND: "AND">
> +|	<OR: "OR">
> +|	<PERIOD: ".">
> +|	<JOIN: "JOIN">
> +|	<LEFT: "LEFT">
> +|	<RIGHT: "RIGHT">
> +|	<AS: "AS">
> +|	<WHERE: "WHERE">
> +|	<HAVING: "HAVING">
> +|	<GROUP: "GROUP">
> +|	<ORDER: "ORDER">
> +|	<UNION: "UNION">
> +|	<BY: "BY">
> +|	<ON: "ON">
> +|	<LIMIT: "LIMIT">
> +|	<OFFSET: "OFFSET">
> +|	<SELECT: "SELECT">
> +|	<DELETE: "DELETE">
> +|	<UPDATE: "UPDATE">
> +|	<SET: "SET">
> +|	<FROM: "FROM">
> +|	<SEMI: ";">
> +|	<STAR: "*">
> +|	<COMMA: ",">
> +|	<START_DQUOTE: "\""> { pushState(IN_DQUOTE); }
> +|	<START_SQUOTE: "'"> { pushState(IN_SQUOTE); }
> +|	<INTEGER:
> +	"0" (
> +		"x" (["0"-"9","a"-"b"])+
> +		| (["0"-"7"])+
> +	)
> +	| ["1"-"9"] (["0"-"9"])*
> +	>
> +|	<NAME:	(["a"-"z"])+>
> +//|	<WORD: (~["'", "\"", "/", " ", "\f", "\n", "\r", "\t", "*"])+>
> +}
> +
> +<DEFAULT>
> +SKIP: {
> +	<SPACE: " " | "\f" | "\n" | "\r" | "\t">
> +}
> +
> +<*>
> +MORE: {
> +	<COMMENT_START: "/*"> { if (curLexState != IN_COMMENT)  
> pushState(IN_COMMENT); }
> +}
> +
> +<IN_COMMENT>
> +MORE: {
> +	<(~[])>
> +|	<COMMENT_END: ("\n" | "\r" | "\r\n")> { popState(); }
> +}
> +
> +<IN_DQUOTE,IN_SQUOTE>
> +TOKEN: {
> +	<ESCAPED: "\\" ["r", "n", "b", "t", "f"]>
> +}
> +
> +<IN_DQUOTE>
> +TOKEN: {
> +	<END_DQUOTE: "\""> { popState(); }
> +}
> +
> +<IN_SQUOTE>
> +TOKEN: {
> +	<ESCAPE_SQUOTE: "''">
> +|	<END_SQUOTE: "'"> { popState(); }
> +}
> +
> +<DEFAULT,IN_DQUOTE,IN_SQUOTE>
> +TOKEN: {
> +	<TEXT: (~[])>
> +}
> +
> +// -------------------
> +
> +
> +SQLSelect Select():
> +{
> +	EntityCondition condition;
> +	int i;
> +	DynamicViewEntity dve = new DynamicViewEntity();
> +}
> +{
> +	<SELECT> FieldDefs(dve)
> +	<FROM> Table(dve)
> +	( <WHERE> condition=ConditionExpression()  
> { jjtThis.setWhereCondition(condition); } )?
> +	( <HAVING> condition=ConditionExpression()  
> { jjtThis.setHavingCondition(condition); } )?
> +	( <GROUP> <BY> FieldList() )?
> +	( <ORDER> <BY> FieldList() )?
> +	( <OFFSET> i=Integer() { jjtThis.setOffset(i); } )?
> +	( <LIMIT> i=Integer() { jjtThis.setLimit(i); } )?
> +	<SEMI>
> +	{ return jjtThis; }
> +}
> +/*
> +CSSUpdate Update():
> +{}
> +{
> +	<UPDATE> Table()
> +	( Set() )+
> +	( <FROM> TableList() )?
> +	( <WHERE> ConditionExpression() )?
> +	<SEMI>
> +}
> +
> +CSSDelete Delete():
> +{}
> +{
> +	<DELETE> <FROM>	Table()
> +	( <USING> TableList() )?
> +	( <WHERE> ConditionExpression() )?
> +	<SEMI>
> +}
> +*/
> +
> +private void Table(DynamicViewEntity dve) #void:
> +{
> +	String leftAlias, rightAlias;
> +	Boolean relOptional;
> +	Set<String> availableAliases = FastSet.newInstance();
> +	List<ModelKeyMap> keyMaps;
> +}
> +{
> +	leftAlias=TableName(dve) { availableAliases.add(leftAlias); }
> +	(
> +		relOptional=Joiner() rightAlias=TableName(dve)  
> { availableAliases.add(rightAlias); }
> +		<ON> keyMaps=KeyMaps(leftAlias, rightAlias) {
> +    			dve.addViewLink(leftAlias, rightAlias, relOptional, keyMaps);
> +		}
> +		
> +	)*
> +
> +}
> +
> +private List<ModelKeyMap> KeyMaps(String leftAlias, String  
> rightAlias) #void:
> +{
> +	List<ModelKeyMap> keyMaps = FastList.newInstance();
> +	ModelKeyMap keyMap;
> +}
> +{
> +	keyMap=KeyMap(leftAlias, rightAlias) { keyMaps.add(keyMap); }
> +	( <AND> keyMap=KeyMap(leftAlias, rightAlias) )*  
> { keyMaps.add(keyMap); }
> +	{ return keyMaps; }
> +}
> +
> +private ModelKeyMap KeyMap(String leftAlias, String rightAlias)  
> #void:
> +{
> +	String alias1, field1;
> +	String alias2, field2;
> +	EntityComparisonOperator op;
> +}
> +{
> +	alias1=NamePart() <PERIOD> field1=NamePart()
> +	op=ComparisonOperator()
> +	alias2=NamePart() <PERIOD> field2=NamePart()
> +	{
> +		if (op != EntityOperator.EQUALS) throw new  
> IllegalArgumentException(op + " not supported");
> +		if (alias1.equals(leftAlias)) {
> +			if (!alias2.equals(rightAlias)) throw new  
> IllegalArgumentException("invalid right alias(" + alias2 + "),  
> expected(" + rightAlias + ")");
> +			return new ModelKeyMap(field1, field2);
> +		} else if (alias1.equals(rightAlias)) {
> +			if (!alias2.equals(leftAlias)) throw new  
> IllegalArgumentException("invalid left alias(" + alias2 + "),  
> expected(" + leftAlias + ")");
> +			return new ModelKeyMap(field2, field1);
> +		} else {
> +			throw new IllegalArgumentException("invalid aliases, expected("  
> + leftAlias + " or " + rightAlias + ")");
> +		}
> +	}
> +}
> +
> +private String TableName(DynamicViewEntity dve) #void:
> +{
> +	String name, alias = null;
> +}
> +{
> +	name=NamePart() ( (<AS>)? alias=NamePart() )?
> +	{
> +		if (alias == null) alias = name;
> +		dve.addMemberEntity(alias, name);
> +		return alias;
> +	}
> +}
> +
> +private Boolean Joiner() #void:
> +{}
> +{
> +	<LEFT> <JOIN> { return Boolean.TRUE; }
> +|	<JOIN> { return Boolean.FALSE; }
> +}
> +private void FieldDefs(DynamicViewEntity dve) #void:
> +{}
> +{
> +	FieldDef(dve) ( <COMMA> FieldDef(dve) )*
> +}
> +
> +private void FieldDef(DynamicViewEntity dve) #void:
> +{}
> +{
> +	LOOKAHEAD(AllField()) AllField(dve)
> +|	FieldSpec(dve)
> +}
> +
> +private void AllField(DynamicViewEntity dve) #void:
> +{
> +	String n;
> +}
> +{
> +	n=NamePart() <PERIOD>
> +	<STAR>
> +	{ dve.addAliasAll(n, null); }
> +}
> +
> +private String NamePart() #void:
> +{}
> +{
> +	( LOOKAHEAD(2) <NAME>)+ { return getToken(0).image; }
> +}
> +
> +private void FieldSpec(DynamicViewEntity dve) #void:
> +{
> +	List<String> fieldUse;
> +	String tableAlias, fieldName, fieldAlias = null;
> +}
> +{
> +	tableAlias=NamePart() <PERIOD> fieldName=NamePart()
> +	( <AS> fieldAlias=NamePart() )?
> +	{
> +		if (fieldAlias == null) {
> +			dve.addAlias(tableAlias, fieldName);
> +		} else {
> +			dve.addAlias(tableAlias, fieldAlias, fieldName, null, null,  
> null, null);
> +		}
> +	}
> +}
> +
> +private String DQuoted() #void:
> +{ StringBuilder sb = new StringBuilder(); }
> +{
> +	<START_DQUOTE> (<TEXT> { sb.append(getToken(0).image); } |  
> <ESCAPED> { sb.append(getToken(0).image); })* <END_DQUOTE>
> +	{ return sb.toString(); }
> +}
> +
> +private String SQuoted() #void:
> +{ StringBuilder sb = new StringBuilder(); }
> +{
> +	<START_SQUOTE> (
> +		<TEXT> { sb.append(getToken(0).image); }
> +	|	<ESCAPED> { sb.append(getToken(0).image); }
> +	|	<ESCAPE_SQUOTE> { sb.append("'"); }
> +	)* <END_SQUOTE>
> +	{ return sb.toString(); }
> +}
> +
> +private void FieldList():
> +{}
> +{
> +	FieldUse() ( <COMMA> FieldUse() )*
> +}
> +
> +private List<String> FieldUse() #void:
> +{
> +	List<String> list = FastList.newInstance();
> +	String s;
> +}
> +{
> +	s=NamePart() { list.add(s); }
> +	( <PERIOD> s=NamePart() { list.add(s); } )?
> +	{ return list; }
> +}
> +
> +private Integer Integer() #void:
> +{}
> +{
> +	<INTEGER> {
> +		try {
> +			Converter<String, Integer> converter =  
> Converters.getConverter(String.class, Integer.class);
> +			return converter.convert(getToken(0).image);
> +		} catch (ClassNotFoundException e) {
> +			return null;
> +		} catch (ConversionException e) {
> +			return null;
> +		}
> +	}
> +}
> +
> +private Object Expression() #void:
> +{
> +	EntityConditionValue ecv;
> +	String s;
> +	List<String> fieldUse;
> +	int i;
> +}
> +{
> +	fieldUse=FieldUse() {
> +		if (fieldUse.size() == 1) return  
> EntityFieldValue.makeFieldValue(fieldUse.get(0));
> +		if (fieldUse.size() == 2) return  
> EntityFieldValue.makeFieldValue(fieldUse.get(1), fieldUse.get(1),  
> null, null);
> +		return null;
> +}
> +|	i=Integer() { return i; }
> +|	s=SQuoted() { return s; }
> +}
> +
> +private EntityCondition ConditionExpression() #void:
> +{ EntityCondition ec; }
> +{
> +	ec=AndExpression() { return ec; }
> +}
> +
> +private EntityCondition AndExpression() #void:
> +{
> +	List<EntityCondition> list = FastList.newInstance();
> +	EntityCondition ec;
> +}
> +{
> +	ec=OrExpression() { list.add(ec); }
> +        ( <AND> ec=OrExpression() { list.add(ec); } )*
> +	{
> +		if (list.size() == 1) return list.get(0);
> +		return EntityCondition.makeCondition(list, EntityOperator.AND);
> +	}
> +}
> +
> +private EntityCondition OrExpression() #void:
> +{
> +	List<EntityCondition> list = FastList.newInstance();
> +	EntityCondition ec;
> +}
> +{
> +	ec=BooleanExpression() { list.add(ec); }
> +        ( <OR> ec=BooleanExpression() { list.add(ec); } )*
> +	{
> +		if (list.size() == 1) return list.get(0);
> +		return EntityCondition.makeCondition(list, EntityOperator.OR);
> +	}
> +}
> +
> +private EntityCondition BooleanExpression() #void:
> +{
> +	Object v1, v2;
> +	EntityComparisonOperator op;
> +}
> +{
> +	v1=Expression() op=ComparisonOperator() v2=Expression()
> +	{ return EntityCondition.makeCondition(v1, op, v2); }
> +}
> +
> +private EntityComparisonOperator ComparisonOperator() #void:
> +{}
> +{
> +	( <TEXT> )+ { return  
> EntityOperator.lookupComparison(getToken(0).image); }
> +}
>
> Added: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/sql/ 
> SQLSelect.java
> URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/entity/src/org/ofbiz/entity/sql/SQLSelect.java?rev=835637&view=auto
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- ofbiz/trunk/framework/entity/src/org/ofbiz/entity/sql/ 
> SQLSelect.java (added)
> +++ ofbiz/trunk/framework/entity/src/org/ofbiz/entity/sql/ 
> SQLSelect.java Thu Nov 12 23:23:12 2009
> @@ -0,0 +1,116 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements.  See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership.  The ASF 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.
> + */
> +package org.ofbiz.entity.sql;
> +
> +import org.ofbiz.entity.Delegator;
> +import org.ofbiz.entity.GenericEntityException;
> +import org.ofbiz.entity.condition.EntityCondition;
> +import org.ofbiz.entity.model.DynamicViewEntity;
> +import org.ofbiz.entity.util.EntityListIterator;
> +
> +public class SQLSelect extends SimpleNode {
> +    private DynamicViewEntity dve;
> +    private EntityCondition whereCondition;
> +    private EntityCondition havingCondition;
> +    private int offset = -1;
> +    private int limit = -1;
> +
> +    public SQLSelect(int id) {
> +        super(id);
> +    }
> +
> +    public SQLSelect(Parser p, int id) {
> +        super(p, id);
> +    }
> +
> +
> +    /** Accept the visitor. **/
> +    public Object jjtAccept(ParserVisitor visitor, Object data) {
> +        return visitor.visit(this, data);
> +    }
> +
> +    public EntityListIterator getEntityListIterator(Delegator  
> delegator) throws GenericEntityException {
> +        return delegator.findListIteratorByCondition(dve,  
> whereCondition, havingCondition, null, null, null);
> +    }
> +
> +    void setDynamicViewEntity(DynamicViewEntity dve) {
> +        this.dve = dve;
> +    }
> +
> +    public DynamicViewEntity getDynamicViewEntity() {
> +        return dve;
> +    }
> +
> +    void setWhereCondition(EntityCondition whereCondition) {
> +        this.whereCondition = whereCondition;
> +    }
> +
> +    public EntityCondition getWhereCondition() {
> +        return whereCondition;
> +    }
> +
> +    void setHavingCondition(EntityCondition havingCondition) {
> +        this.havingCondition = havingCondition;
> +    }
> +
> +    public EntityCondition getHavingCondition() {
> +        return havingCondition;
> +    }
> +
> +    void setOffset(int offset) {
> +        this.offset = offset;
> +    }
> +
> +    public int getOffset() {
> +        return offset;
> +    }
> +
> +    void setLimit(int limit) {
> +        this.limit = limit;
> +    }
> +
> +    public int getLimit() {
> +        return limit;
> +    }
> +
> +    public String toString() {
> +        StringBuilder sb = new StringBuilder();
> +        sb.append("dve=" + dve);
> +        if (whereCondition != null) {
> +            if (sb.length() > 0) sb.append(", ");
> +            sb.append("where=(").append(whereCondition).append(")");
> +        }
> +        if (havingCondition != null) {
> +            if (sb.length() > 0) sb.append(", ");
> +             
> sb.append("having=(").append(havingCondition).append(")");
> +        }
> +        if (offset != -1) {
> +            if (sb.length() > 0) sb.append(", ");
> +            sb.append("offset=").append(offset);
> +        }
> +        if (limit != -1) {
> +            if (sb.length() > 0) sb.append(", ");
> +            sb.append("limit=").append(limit);
> +        }
> +        sb.append("]");
> +        sb.insert(0, "[").insert(0, super.toString());
> +        return sb.toString();
> +    }
> +}
> +/* JavaCC - OriginalChecksum=49309c1a721b16d029f160d2568a03bc (do  
> not edit this line) */
>
>


Re: svn commit: r835637 - in /ofbiz/trunk/framework/entity: build.xml src/org/ofbiz/entity/sql/ src/org/ofbiz/entity/sql/Parser.jjt src/org/ofbiz/entity/sql/SQLSelect.java

Posted by Adrian Crum <ad...@hlmksw.com>.
Adam,

I just committed a minor change to the Converters class that will help 
simplify your code. You can create a static instance of StringToInteger 
and eliminate the factory method call.

The factory method is intended to be used when you don't know the source 
and target classes at compile time.

-Adrian

Adrian Crum wrote:
> Adam Heath wrote:
>> Adrian Crum wrote:
>>> I'm wondering that too.
>>>
>>> Btw, in the "classic" visitor pattern, the code should be:
>>>
>>> /** Accept the visitor. **/
>>>     public Object jjtAccept(ParserVisitor visitor) {
>>>         return visitor.visit(this);
>>>     }
>>>
>>> The SQLSelect class shouldn't be concerned with (or know about) Object
>>> data.
>>
>> I can't change that.  jjtree auto-generates missing node classes, and
>> this is the pattern is uses.  I only have to override the nodes that
>> need special functionality.
> 
> Thanks. I figured that out after I pressed Send.
> 
> 

Re: svn commit: r835637 - in /ofbiz/trunk/framework/entity: build.xml src/org/ofbiz/entity/sql/ src/org/ofbiz/entity/sql/Parser.jjt src/org/ofbiz/entity/sql/SQLSelect.java

Posted by Adrian Crum <ad...@hlmksw.com>.
Adam Heath wrote:
> Adrian Crum wrote:
>> I'm wondering that too.
>>
>> Btw, in the "classic" visitor pattern, the code should be:
>>
>> /** Accept the visitor. **/
>>     public Object jjtAccept(ParserVisitor visitor) {
>>         return visitor.visit(this);
>>     }
>>
>> The SQLSelect class shouldn't be concerned with (or know about) Object
>> data.
> 
> I can't change that.  jjtree auto-generates missing node classes, and
> this is the pattern is uses.  I only have to override the nodes that
> need special functionality.

Thanks. I figured that out after I pressed Send.


Re: svn commit: r835637 - in /ofbiz/trunk/framework/entity: build.xml src/org/ofbiz/entity/sql/ src/org/ofbiz/entity/sql/Parser.jjt src/org/ofbiz/entity/sql/SQLSelect.java

Posted by Adam Heath <do...@brainfood.com>.
Adrian Crum wrote:
> I'm wondering that too.
> 
> Btw, in the "classic" visitor pattern, the code should be:
> 
> /** Accept the visitor. **/
>     public Object jjtAccept(ParserVisitor visitor) {
>         return visitor.visit(this);
>     }
> 
> The SQLSelect class shouldn't be concerned with (or know about) Object
> data.

I can't change that.  jjtree auto-generates missing node classes, and
this is the pattern is uses.  I only have to override the nodes that
need special functionality.

Re: svn commit: r835637 - in /ofbiz/trunk/framework/entity: build.xml src/org/ofbiz/entity/sql/ src/org/ofbiz/entity/sql/Parser.jjt src/org/ofbiz/entity/sql/SQLSelect.java

Posted by Adrian Crum <ad...@hlmksw.com>.
I'm wondering that too.

Btw, in the "classic" visitor pattern, the code should be:

/** Accept the visitor. **/
     public Object jjtAccept(ParserVisitor visitor) {
         return visitor.visit(this);
     }

The SQLSelect class shouldn't be concerned with (or know about) Object data.

-Adrian

Scott Gray wrote:
> Hi Adam,
> 
> What exactly does this do?
> 
> Thanks
> Scott
> 
> HotWax Media
> http://www.hotwaxmedia.com
> 
> On 13/11/2009, at 12:23 PM, doogie@apache.org wrote:
> 
>> Author: doogie
>> Date: Thu Nov 12 23:23:12 2009
>> New Revision: 835637
>>
>> URL: http://svn.apache.org/viewvc?rev=835637&view=rev
>> Log:
>> Start of new sql parsing code.  Not completely tested.  It *does* parse
>> a test SELECT; what is not tested is actually running the built
>> DynamicViewEntity.
>>
>> Added:
>>    ofbiz/trunk/framework/entity/src/org/ofbiz/entity/sql/
>>    ofbiz/trunk/framework/entity/src/org/ofbiz/entity/sql/Parser.jjt
>>    ofbiz/trunk/framework/entity/src/org/ofbiz/entity/sql/SQLSelect.java
>> Modified:
>>    ofbiz/trunk/framework/entity/build.xml
>>
>> Modified: ofbiz/trunk/framework/entity/build.xml
>> URL: 
>> http://svn.apache.org/viewvc/ofbiz/trunk/framework/entity/build.xml?rev=835637&r1=835636&r2=835637&view=diff 
>>
>> ============================================================================== 
>>
>> --- ofbiz/trunk/framework/entity/build.xml (original)
>> +++ ofbiz/trunk/framework/entity/build.xml Thu Nov 12 23:23:12 2009
>> @@ -38,6 +38,10 @@
>>         <fileset dir="../base/lib/scripting" includes="*.jar"/>
>>         <fileset dir="../base/build/lib" includes="*.jar"/>
>>     </path>
>> +    <path id="src-path">
>> +        <pathelement location="build/gen-src/javacc"/>
>> +        <pathelement location="build/gen-src/jjtree"/>
>> +    </path>
>>
>>     <patternset id="src.exc.set">
>>         <exclude 
>> name="org/ofbiz/entity/connection/XaPoolConnectionFactory.java"/>
>> @@ -48,7 +52,11 @@
>>     <!-- Compilation of the source 
>> files                                                                                                                         
>> -->
>>     <!-- 
>> ================================================================== -->
>>
>> -    <target name="classes" depends="prepare">
>> +    <target name="gen-src">
>> +        <ofbiz-jjtree dir="org/ofbiz/entity/sql" file="Parser"/>
>> +    </target>
>> +
>> +    <target name="classes" depends="prepare,gen-src">
>>         <javac15/>
>>     </target>
>>
>>
>> Added: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/sql/Parser.jjt
>> URL: 
>> http://svn.apache.org/viewvc/ofbiz/trunk/framework/entity/src/org/ofbiz/entity/sql/Parser.jjt?rev=835637&view=auto 
>>
>> ============================================================================== 
>>
>> --- ofbiz/trunk/framework/entity/src/org/ofbiz/entity/sql/Parser.jjt 
>> (added)
>> +++ ofbiz/trunk/framework/entity/src/org/ofbiz/entity/sql/Parser.jjt 
>> Thu Nov 12 23:23:12 2009
>> @@ -0,0 +1,414 @@
>> +options {
>> +  JAVA_UNICODE_ESCAPE = false;
>> +  ERROR_REPORTING = true;
>> +  STATIC = false;
>> +  MULTI = true;
>> +  JDK_VERSION = "1.5";
>> +  VISITOR = true;
>> +  BUILD_NODE_FILES = true;
>> +  NODE_FACTORY = false;
>> +  NODE_USES_PARSER = true;
>> +//  NODE_SCOPE_HOOK = true;
>> +  NODE_PREFIX = "SQL";
>> +//  DEBUG_PARSER = true;
>> +//  DEBUG_LOOKAHEAD = true;
>> +//  DEBUG_TOKEN_MANAGER = true;
>> +  LOOKAHEAD = 1;
>> +//  CHOICE_AMBIGUITY_CHECK = 3;
>> +//  OTHER_AMBIGUITY_CHECK = 3;
>> +  IGNORE_CASE = true;
>> +}
>> +PARSER_BEGIN(Parser)
>> +
>> +package org.ofbiz.entity.sql;
>> +
>> +import java.io.*;
>> +import java.util.List;
>> +import java.util.LinkedList;
>> +import java.util.Set;
>> +
>> +import javolution.util.FastList;
>> +import javolution.util.FastSet;
>> +
>> +import org.ofbiz.base.conversion.ConversionException;
>> +import org.ofbiz.base.conversion.Converter;
>> +import org.ofbiz.base.conversion.Converters;
>> +import org.ofbiz.entity.condition.EntityComparisonOperator;
>> +import org.ofbiz.entity.condition.EntityCondition;
>> +import org.ofbiz.entity.condition.EntityConditionValue;
>> +import org.ofbiz.entity.condition.EntityFieldValue;
>> +import org.ofbiz.entity.condition.EntityOperator;
>> +import org.ofbiz.entity.model.DynamicViewEntity;
>> +import org.ofbiz.entity.model.ModelKeyMap;
>> +
>> +public class Parser {
>> +}
>> +
>> +PARSER_END(Parser)
>> +TOKEN_MGR_DECLS: {
>> +    private final LinkedList<Integer> stack = new LinkedList<Integer>();
>> +
>> +    void pushState(int newState) {
>> +        stack.add(curLexState);
>> +        SwitchTo(newState);
>> +    }
>> +
>> +    void popState() {
>> +        SwitchTo(stack.removeLast());
>> +    }
>> +}
>> +
>> +TOKEN: {
>> +    <OPEN_PAREN: "(">
>> +|    <CLOSE_PAREN: ")">
>> +|    <AND: "AND">
>> +|    <OR: "OR">
>> +|    <PERIOD: ".">
>> +|    <JOIN: "JOIN">
>> +|    <LEFT: "LEFT">
>> +|    <RIGHT: "RIGHT">
>> +|    <AS: "AS">
>> +|    <WHERE: "WHERE">
>> +|    <HAVING: "HAVING">
>> +|    <GROUP: "GROUP">
>> +|    <ORDER: "ORDER">
>> +|    <UNION: "UNION">
>> +|    <BY: "BY">
>> +|    <ON: "ON">
>> +|    <LIMIT: "LIMIT">
>> +|    <OFFSET: "OFFSET">
>> +|    <SELECT: "SELECT">
>> +|    <DELETE: "DELETE">
>> +|    <UPDATE: "UPDATE">
>> +|    <SET: "SET">
>> +|    <FROM: "FROM">
>> +|    <SEMI: ";">
>> +|    <STAR: "*">
>> +|    <COMMA: ",">
>> +|    <START_DQUOTE: "\""> { pushState(IN_DQUOTE); }
>> +|    <START_SQUOTE: "'"> { pushState(IN_SQUOTE); }
>> +|    <INTEGER:
>> +    "0" (
>> +        "x" (["0"-"9","a"-"b"])+
>> +        | (["0"-"7"])+
>> +    )
>> +    | ["1"-"9"] (["0"-"9"])*
>> +    >
>> +|    <NAME:    (["a"-"z"])+>
>> +//|    <WORD: (~["'", "\"", "/", " ", "\f", "\n", "\r", "\t", "*"])+>
>> +}
>> +
>> +<DEFAULT>
>> +SKIP: {
>> +    <SPACE: " " | "\f" | "\n" | "\r" | "\t">
>> +}
>> +
>> +<*>
>> +MORE: {
>> +    <COMMENT_START: "/*"> { if (curLexState != IN_COMMENT) 
>> pushState(IN_COMMENT); }
>> +}
>> +
>> +<IN_COMMENT>
>> +MORE: {
>> +    <(~[])>
>> +|    <COMMENT_END: ("\n" | "\r" | "\r\n")> { popState(); }
>> +}
>> +
>> +<IN_DQUOTE,IN_SQUOTE>
>> +TOKEN: {
>> +    <ESCAPED: "\\" ["r", "n", "b", "t", "f"]>
>> +}
>> +
>> +<IN_DQUOTE>
>> +TOKEN: {
>> +    <END_DQUOTE: "\""> { popState(); }
>> +}
>> +
>> +<IN_SQUOTE>
>> +TOKEN: {
>> +    <ESCAPE_SQUOTE: "''">
>> +|    <END_SQUOTE: "'"> { popState(); }
>> +}
>> +
>> +<DEFAULT,IN_DQUOTE,IN_SQUOTE>
>> +TOKEN: {
>> +    <TEXT: (~[])>
>> +}
>> +
>> +// -------------------
>> +
>> +
>> +SQLSelect Select():
>> +{
>> +    EntityCondition condition;
>> +    int i;
>> +    DynamicViewEntity dve = new DynamicViewEntity();
>> +}
>> +{
>> +    <SELECT> FieldDefs(dve)
>> +    <FROM> Table(dve)
>> +    ( <WHERE> condition=ConditionExpression() { 
>> jjtThis.setWhereCondition(condition); } )?
>> +    ( <HAVING> condition=ConditionExpression() { 
>> jjtThis.setHavingCondition(condition); } )?
>> +    ( <GROUP> <BY> FieldList() )?
>> +    ( <ORDER> <BY> FieldList() )?
>> +    ( <OFFSET> i=Integer() { jjtThis.setOffset(i); } )?
>> +    ( <LIMIT> i=Integer() { jjtThis.setLimit(i); } )?
>> +    <SEMI>
>> +    { return jjtThis; }
>> +}
>> +/*
>> +CSSUpdate Update():
>> +{}
>> +{
>> +    <UPDATE> Table()
>> +    ( Set() )+
>> +    ( <FROM> TableList() )?
>> +    ( <WHERE> ConditionExpression() )?
>> +    <SEMI>
>> +}
>> +
>> +CSSDelete Delete():
>> +{}
>> +{
>> +    <DELETE> <FROM>    Table()
>> +    ( <USING> TableList() )?
>> +    ( <WHERE> ConditionExpression() )?
>> +    <SEMI>
>> +}
>> +*/
>> +
>> +private void Table(DynamicViewEntity dve) #void:
>> +{
>> +    String leftAlias, rightAlias;
>> +    Boolean relOptional;
>> +    Set<String> availableAliases = FastSet.newInstance();
>> +    List<ModelKeyMap> keyMaps;
>> +}
>> +{
>> +    leftAlias=TableName(dve) { availableAliases.add(leftAlias); }
>> +    (
>> +        relOptional=Joiner() rightAlias=TableName(dve) { 
>> availableAliases.add(rightAlias); }
>> +        <ON> keyMaps=KeyMaps(leftAlias, rightAlias) {
>> +                dve.addViewLink(leftAlias, rightAlias, relOptional, 
>> keyMaps);
>> +        }
>> +       
>> +    )*
>> +
>> +}
>> +
>> +private List<ModelKeyMap> KeyMaps(String leftAlias, String 
>> rightAlias) #void:
>> +{
>> +    List<ModelKeyMap> keyMaps = FastList.newInstance();
>> +    ModelKeyMap keyMap;
>> +}
>> +{
>> +    keyMap=KeyMap(leftAlias, rightAlias) { keyMaps.add(keyMap); }
>> +    ( <AND> keyMap=KeyMap(leftAlias, rightAlias) )* { 
>> keyMaps.add(keyMap); }
>> +    { return keyMaps; }
>> +}
>> +
>> +private ModelKeyMap KeyMap(String leftAlias, String rightAlias) #void:
>> +{
>> +    String alias1, field1;
>> +    String alias2, field2;
>> +    EntityComparisonOperator op;
>> +}
>> +{
>> +    alias1=NamePart() <PERIOD> field1=NamePart()
>> +    op=ComparisonOperator()
>> +    alias2=NamePart() <PERIOD> field2=NamePart()
>> +    {
>> +        if (op != EntityOperator.EQUALS) throw new 
>> IllegalArgumentException(op + " not supported");
>> +        if (alias1.equals(leftAlias)) {
>> +            if (!alias2.equals(rightAlias)) throw new 
>> IllegalArgumentException("invalid right alias(" + alias2 + "), 
>> expected(" + rightAlias + ")");
>> +            return new ModelKeyMap(field1, field2);
>> +        } else if (alias1.equals(rightAlias)) {
>> +            if (!alias2.equals(leftAlias)) throw new 
>> IllegalArgumentException("invalid left alias(" + alias2 + "), 
>> expected(" + leftAlias + ")");
>> +            return new ModelKeyMap(field2, field1);
>> +        } else {
>> +            throw new IllegalArgumentException("invalid aliases, 
>> expected(" + leftAlias + " or " + rightAlias + ")");
>> +        }
>> +    }
>> +}
>> +
>> +private String TableName(DynamicViewEntity dve) #void:
>> +{
>> +    String name, alias = null;
>> +}
>> +{
>> +    name=NamePart() ( (<AS>)? alias=NamePart() )?
>> +    {
>> +        if (alias == null) alias = name;
>> +        dve.addMemberEntity(alias, name);
>> +        return alias;
>> +    }
>> +}
>> +
>> +private Boolean Joiner() #void:
>> +{}
>> +{
>> +    <LEFT> <JOIN> { return Boolean.TRUE; }
>> +|    <JOIN> { return Boolean.FALSE; }
>> +}
>> +private void FieldDefs(DynamicViewEntity dve) #void:
>> +{}
>> +{
>> +    FieldDef(dve) ( <COMMA> FieldDef(dve) )*
>> +}
>> +
>> +private void FieldDef(DynamicViewEntity dve) #void:
>> +{}
>> +{
>> +    LOOKAHEAD(AllField()) AllField(dve)
>> +|    FieldSpec(dve)
>> +}
>> +
>> +private void AllField(DynamicViewEntity dve) #void:
>> +{
>> +    String n;
>> +}
>> +{
>> +    n=NamePart() <PERIOD>
>> +    <STAR>
>> +    { dve.addAliasAll(n, null); }
>> +}
>> +
>> +private String NamePart() #void:
>> +{}
>> +{
>> +    ( LOOKAHEAD(2) <NAME>)+ { return getToken(0).image; }
>> +}
>> +
>> +private void FieldSpec(DynamicViewEntity dve) #void:
>> +{
>> +    List<String> fieldUse;
>> +    String tableAlias, fieldName, fieldAlias = null;
>> +}
>> +{
>> +    tableAlias=NamePart() <PERIOD> fieldName=NamePart()
>> +    ( <AS> fieldAlias=NamePart() )?
>> +    {
>> +        if (fieldAlias == null) {
>> +            dve.addAlias(tableAlias, fieldName);
>> +        } else {
>> +            dve.addAlias(tableAlias, fieldAlias, fieldName, null, 
>> null, null, null);
>> +        }
>> +    }
>> +}
>> +
>> +private String DQuoted() #void:
>> +{ StringBuilder sb = new StringBuilder(); }
>> +{
>> +    <START_DQUOTE> (<TEXT> { sb.append(getToken(0).image); } | 
>> <ESCAPED> { sb.append(getToken(0).image); })* <END_DQUOTE>
>> +    { return sb.toString(); }
>> +}
>> +
>> +private String SQuoted() #void:
>> +{ StringBuilder sb = new StringBuilder(); }
>> +{
>> +    <START_SQUOTE> (
>> +        <TEXT> { sb.append(getToken(0).image); }
>> +    |    <ESCAPED> { sb.append(getToken(0).image); }
>> +    |    <ESCAPE_SQUOTE> { sb.append("'"); }
>> +    )* <END_SQUOTE>
>> +    { return sb.toString(); }
>> +}
>> +
>> +private void FieldList():
>> +{}
>> +{
>> +    FieldUse() ( <COMMA> FieldUse() )*
>> +}
>> +
>> +private List<String> FieldUse() #void:
>> +{
>> +    List<String> list = FastList.newInstance();
>> +    String s;
>> +}
>> +{
>> +    s=NamePart() { list.add(s); }
>> +    ( <PERIOD> s=NamePart() { list.add(s); } )?
>> +    { return list; }
>> +}
>> +
>> +private Integer Integer() #void:
>> +{}
>> +{
>> +    <INTEGER> {
>> +        try {
>> +            Converter<String, Integer> converter = 
>> Converters.getConverter(String.class, Integer.class);
>> +            return converter.convert(getToken(0).image);
>> +        } catch (ClassNotFoundException e) {
>> +            return null;
>> +        } catch (ConversionException e) {
>> +            return null;
>> +        }
>> +    }
>> +}
>> +
>> +private Object Expression() #void:
>> +{
>> +    EntityConditionValue ecv;
>> +    String s;
>> +    List<String> fieldUse;
>> +    int i;
>> +}
>> +{
>> +    fieldUse=FieldUse() {
>> +        if (fieldUse.size() == 1) return 
>> EntityFieldValue.makeFieldValue(fieldUse.get(0));
>> +        if (fieldUse.size() == 2) return 
>> EntityFieldValue.makeFieldValue(fieldUse.get(1), fieldUse.get(1), 
>> null, null);
>> +        return null;
>> +}
>> +|    i=Integer() { return i; }
>> +|    s=SQuoted() { return s; }
>> +}
>> +
>> +private EntityCondition ConditionExpression() #void:
>> +{ EntityCondition ec; }
>> +{
>> +    ec=AndExpression() { return ec; }
>> +}
>> +
>> +private EntityCondition AndExpression() #void:
>> +{
>> +    List<EntityCondition> list = FastList.newInstance();
>> +    EntityCondition ec;
>> +}
>> +{
>> +    ec=OrExpression() { list.add(ec); }
>> +        ( <AND> ec=OrExpression() { list.add(ec); } )*
>> +    {
>> +        if (list.size() == 1) return list.get(0);
>> +        return EntityCondition.makeCondition(list, EntityOperator.AND);
>> +    }
>> +}
>> +
>> +private EntityCondition OrExpression() #void:
>> +{
>> +    List<EntityCondition> list = FastList.newInstance();
>> +    EntityCondition ec;
>> +}
>> +{
>> +    ec=BooleanExpression() { list.add(ec); }
>> +        ( <OR> ec=BooleanExpression() { list.add(ec); } )*
>> +    {
>> +        if (list.size() == 1) return list.get(0);
>> +        return EntityCondition.makeCondition(list, EntityOperator.OR);
>> +    }
>> +}
>> +
>> +private EntityCondition BooleanExpression() #void:
>> +{
>> +    Object v1, v2;
>> +    EntityComparisonOperator op;
>> +}
>> +{
>> +    v1=Expression() op=ComparisonOperator() v2=Expression()
>> +    { return EntityCondition.makeCondition(v1, op, v2); }
>> +}
>> +
>> +private EntityComparisonOperator ComparisonOperator() #void:
>> +{}
>> +{
>> +    ( <TEXT> )+ { return 
>> EntityOperator.lookupComparison(getToken(0).image); }
>> +}
>>
>> Added: 
>> ofbiz/trunk/framework/entity/src/org/ofbiz/entity/sql/SQLSelect.java
>> URL: 
>> http://svn.apache.org/viewvc/ofbiz/trunk/framework/entity/src/org/ofbiz/entity/sql/SQLSelect.java?rev=835637&view=auto 
>>
>> ============================================================================== 
>>
>> --- 
>> ofbiz/trunk/framework/entity/src/org/ofbiz/entity/sql/SQLSelect.java 
>> (added)
>> +++ 
>> ofbiz/trunk/framework/entity/src/org/ofbiz/entity/sql/SQLSelect.java 
>> Thu Nov 12 23:23:12 2009
>> @@ -0,0 +1,116 @@
>> +/*
>> + * Licensed to the Apache Software Foundation (ASF) under one
>> + * or more contributor license agreements.  See the NOTICE file
>> + * distributed with this work for additional information
>> + * regarding copyright ownership.  The ASF 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.
>> + */
>> +package org.ofbiz.entity.sql;
>> +
>> +import org.ofbiz.entity.Delegator;
>> +import org.ofbiz.entity.GenericEntityException;
>> +import org.ofbiz.entity.condition.EntityCondition;
>> +import org.ofbiz.entity.model.DynamicViewEntity;
>> +import org.ofbiz.entity.util.EntityListIterator;
>> +
>> +public class SQLSelect extends SimpleNode {
>> +    private DynamicViewEntity dve;
>> +    private EntityCondition whereCondition;
>> +    private EntityCondition havingCondition;
>> +    private int offset = -1;
>> +    private int limit = -1;
>> +
>> +    public SQLSelect(int id) {
>> +        super(id);
>> +    }
>> +
>> +    public SQLSelect(Parser p, int id) {
>> +        super(p, id);
>> +    }
>> +
>> +
>> +    /** Accept the visitor. **/
>> +    public Object jjtAccept(ParserVisitor visitor, Object data) {
>> +        return visitor.visit(this, data);
>> +    }
>> +
>> +    public EntityListIterator getEntityListIterator(Delegator 
>> delegator) throws GenericEntityException {
>> +        return delegator.findListIteratorByCondition(dve, 
>> whereCondition, havingCondition, null, null, null);
>> +    }
>> +
>> +    void setDynamicViewEntity(DynamicViewEntity dve) {
>> +        this.dve = dve;
>> +    }
>> +
>> +    public DynamicViewEntity getDynamicViewEntity() {
>> +        return dve;
>> +    }
>> +
>> +    void setWhereCondition(EntityCondition whereCondition) {
>> +        this.whereCondition = whereCondition;
>> +    }
>> +
>> +    public EntityCondition getWhereCondition() {
>> +        return whereCondition;
>> +    }
>> +
>> +    void setHavingCondition(EntityCondition havingCondition) {
>> +        this.havingCondition = havingCondition;
>> +    }
>> +
>> +    public EntityCondition getHavingCondition() {
>> +        return havingCondition;
>> +    }
>> +
>> +    void setOffset(int offset) {
>> +        this.offset = offset;
>> +    }
>> +
>> +    public int getOffset() {
>> +        return offset;
>> +    }
>> +
>> +    void setLimit(int limit) {
>> +        this.limit = limit;
>> +    }
>> +
>> +    public int getLimit() {
>> +        return limit;
>> +    }
>> +
>> +    public String toString() {
>> +        StringBuilder sb = new StringBuilder();
>> +        sb.append("dve=" + dve);
>> +        if (whereCondition != null) {
>> +            if (sb.length() > 0) sb.append(", ");
>> +            sb.append("where=(").append(whereCondition).append(")");
>> +        }
>> +        if (havingCondition != null) {
>> +            if (sb.length() > 0) sb.append(", ");
>> +            sb.append("having=(").append(havingCondition).append(")");
>> +        }
>> +        if (offset != -1) {
>> +            if (sb.length() > 0) sb.append(", ");
>> +            sb.append("offset=").append(offset);
>> +        }
>> +        if (limit != -1) {
>> +            if (sb.length() > 0) sb.append(", ");
>> +            sb.append("limit=").append(limit);
>> +        }
>> +        sb.append("]");
>> +        sb.insert(0, "[").insert(0, super.toString());
>> +        return sb.toString();
>> +    }
>> +}
>> +/* JavaCC - OriginalChecksum=49309c1a721b16d029f160d2568a03bc (do not 
>> edit this line) */
>>
>>
> 

Re: svn commit: r835637 - in /ofbiz/trunk/framework/entity: build.xml src/org/ofbiz/entity/sql/ src/org/ofbiz/entity/sql/Parser.jjt src/org/ofbiz/entity/sql/SQLSelect.java

Posted by Adam Heath <do...@brainfood.com>.
Scott Gray wrote:
> What would be cool and what I would use is a tool that is capable of
> generating a view entity xml definition from a sql query.

While not related at all to sql parsing, I just committed a good start
at this in 835764.

Re: svn commit: r835637 - in /ofbiz/trunk/framework/entity: build.xml src/org/ofbiz/entity/sql/ src/org/ofbiz/entity/sql/Parser.jjt src/org/ofbiz/entity/sql/SQLSelect.java

Posted by Scott Gray <sc...@hotwaxmedia.com>.
On 13/11/2009, at 1:27 PM, Adam Heath wrote:

> Scott Gray wrote:
>> I could see that it doesn't send the raw sql to the database I was  
>> just
>> trying to point out that offset isn't currently supported by the  
>> entity
>> engine and that adding support for it could be problematic.
>
> Offset is simple, relatively.  Just need to issue a bunch of rs.next()
> calls early, and then a flag to EntityListIterator to forbid calling
> rs.previous() past the beginning.

That is a possibility but it wouldn't really achieve much.  The main  
advantage I see to using offset is to avoid the need to stream  
unneeded results, especially for jdbc drivers that don't support  
cursors.

>
>> I agree view-entity definitions can at times be quite verbose and it
>> could be useful there in some situations, but will these sql  
>> statements
>> be reusable in the same way that view entities are?  Also I actually
>> like the java-ness of constructing dynamic view entities rather that
>> building a string, it makes the code easier to read IMO.
>
> Absolutely.  It's rather trival to extend the parser, to have multiple
> selects defined in some global .sql file, giving each a NAME, then
> also extending the condition parser to have a ?NAME type syntax.
>
> Maybe using this api(brainstorming):
>
> eli = EntitySql.getListIterator(delegator, "path/to/resource.sql",
> "my-special-query", Map<String, Object> params)

What would be cool and what I would use is a tool that is capable of  
generating a view entity xml definition from a sql query.



Re: svn commit: r835637 - in /ofbiz/trunk/framework/entity: build.xml src/org/ofbiz/entity/sql/ src/org/ofbiz/entity/sql/Parser.jjt src/org/ofbiz/entity/sql/SQLSelect.java

Posted by Adam Heath <do...@brainfood.com>.
Scott Gray wrote:
> I could see that it doesn't send the raw sql to the database I was just
> trying to point out that offset isn't currently supported by the entity
> engine and that adding support for it could be problematic.

Offset is simple, relatively.  Just need to issue a bunch of rs.next()
calls early, and then a flag to EntityListIterator to forbid calling
rs.previous() past the beginning.

> I agree view-entity definitions can at times be quite verbose and it
> could be useful there in some situations, but will these sql statements
> be reusable in the same way that view entities are?  Also I actually
> like the java-ness of constructing dynamic view entities rather that
> building a string, it makes the code easier to read IMO.

Absolutely.  It's rather trival to extend the parser, to have multiple
 selects defined in some global .sql file, giving each a NAME, then
also extending the condition parser to have a ?NAME type syntax.

Maybe using this api(brainstorming):

eli = EntitySql.getListIterator(delegator, "path/to/resource.sql",
"my-special-query", Map<String, Object> params)


Re: svn commit: r835637 - in /ofbiz/trunk/framework/entity: build.xml src/org/ofbiz/entity/sql/ src/org/ofbiz/entity/sql/Parser.jjt src/org/ofbiz/entity/sql/SQLSelect.java

Posted by Scott Gray <sc...@hotwaxmedia.com>.
On 13/11/2009, at 1:10 PM, Adam Heath wrote:

> Scott Gray wrote:
>> I'd be careful with the limit/offset, support tends to vary among
>> vendors, e.g. http://blogs.sun.com/kah/entry/derby_10_5_preview_fetch
>
> You are mistaken.  This does *not* send raw sql to the database.  It
> parses the sql into a DynamicViewEntity, which ofbiz then reconverts
> back to whatever sql dialect is required by the underlying database.
> Offset/limit can be completely handled in java.
>
> Besides, I currently don't have them fully implemented.  And
> EntityFindOptions has a maxRows option.

I could see that it doesn't send the raw sql to the database I was  
just trying to point out that offset isn't currently supported by the  
entity engine and that adding support for it could be problematic.

>
>> I like the concept, but to be honest I have to deal with raw sql so
>> rarely these days that given the choice I probably wouldn't use it.
>
> Which is easier; editting a <view-entity> xml definition, or creating
> a sql string?  Consider the case when you have option parts of a query
> you have to deal with.
>
> In addition, I'll be adding helper methods to parse *just* entity
> conditions.  It's mostly there, I just haven't made the methods  
> public.

I agree view-entity definitions can at times be quite verbose and it  
could be useful there in some situations, but will these sql  
statements be reusable in the same way that view entities are?  Also I  
actually like the java-ness of constructing dynamic view entities  
rather that building a string, it makes the code easier to read IMO.


Re: svn commit: r835637 - in /ofbiz/trunk/framework/entity: build.xml src/org/ofbiz/entity/sql/ src/org/ofbiz/entity/sql/Parser.jjt src/org/ofbiz/entity/sql/SQLSelect.java

Posted by Adam Heath <do...@brainfood.com>.
Scott Gray wrote:
> I'd be careful with the limit/offset, support tends to vary among
> vendors, e.g. http://blogs.sun.com/kah/entry/derby_10_5_preview_fetch

You are mistaken.  This does *not* send raw sql to the database.  It
parses the sql into a DynamicViewEntity, which ofbiz then reconverts
back to whatever sql dialect is required by the underlying database.
Offset/limit can be completely handled in java.

Besides, I currently don't have them fully implemented.  And
EntityFindOptions has a maxRows option.

> I like the concept, but to be honest I have to deal with raw sql so
> rarely these days that given the choice I probably wouldn't use it.

Which is easier; editting a <view-entity> xml definition, or creating
a sql string?  Consider the case when you have option parts of a query
you have to deal with.

In addition, I'll be adding helper methods to parse *just* entity
conditions.  It's mostly there, I just haven't made the methods public.


Re: svn commit: r835637 - in /ofbiz/trunk/framework/entity: build.xml src/org/ofbiz/entity/sql/ src/org/ofbiz/entity/sql/Parser.jjt src/org/ofbiz/entity/sql/SQLSelect.java

Posted by Scott Gray <sc...@hotwaxmedia.com>.
I'd be careful with the limit/offset, support tends to vary among  
vendors, e.g. http://blogs.sun.com/kah/entry/derby_10_5_preview_fetch

I like the concept, but to be honest I have to deal with raw sql so  
rarely these days that given the choice I probably wouldn't use it.

Regards
Scott

On 13/11/2009, at 12:43 PM, Adam Heath wrote:

> Scott Gray wrote:
>> Hi Adam,
>>
>> What exactly does this do?
>
> In a nutshell, and just to get you guys all excited and wet, here's
> the string I've been testing this with:
> ==
> select
>        a.*,
>        b.firstName,
>        b.lastName
> FROM
>        Party a JOIN Person b ON a.partyId = b.partyId
> WHERE
>        a.partyId='foo'
> OFFSET 5
> LIMIT 10
> ;
> ==
>
> ps: My previous versions of this were based on an oracle grammar, that
> had no real license applied.  This new version I wrote completely from
> scratch today, based on my knowledge of javacc/jjtree, and postgres
> sql syntax.


Re: svn commit: r835637 - in /ofbiz/trunk/framework/entity: build.xml src/org/ofbiz/entity/sql/ src/org/ofbiz/entity/sql/Parser.jjt src/org/ofbiz/entity/sql/SQLSelect.java

Posted by Adam Heath <do...@brainfood.com>.
Scott Gray wrote:
> Hi Adam,
> 
> What exactly does this do?

In a nutshell, and just to get you guys all excited and wet, here's
the string I've been testing this with:
==
select
        a.*,
        b.firstName,
        b.lastName
FROM
        Party a JOIN Person b ON a.partyId = b.partyId
WHERE
        a.partyId='foo'
OFFSET 5
LIMIT 10
;
==

ps: My previous versions of this were based on an oracle grammar, that
had no real license applied.  This new version I wrote completely from
scratch today, based on my knowledge of javacc/jjtree, and postgres
sql syntax.