JPA-SQL Language Specification

* 0 or more
+ 1 or more
? optional
| or
& and, without defined order
RQL is case-sensitive.

Script:
	ImportStatement*
	QueryMethod*
;

ImportStatement:
	'import' QualifiedName;

QueryMethod:
	DocComment?
	ID '(' (Parameter (',' Parameter)*)? ')'
	'{'
		SelectStatement
	'}'
;

Parameter:
	Type ID;

Type:
	PrimitiveType | 
	QualifiedName
;
	
SelectStatement:
	(
	SelectClause? &
	FromClause
	)
	JoinClause*
	(
	WhereClause? &
	GroupByClause? &
	OrderByClause? &
	OffsetClause? &
	LimitClause? &
	ResultClause? &
	LockModeClause? &
	FetchClause? &
	IntoClause?
	)
;

SelectClause:
	'select' 'distinct'? Selection;

Selection:
	'*' |
	SelectionElement (',' SelectionElement)*
;
	
SelectionElement:
	Expression Alias?;

FromClause:
	'from' FromElement (',' FromElement)*;
	
FromElement:
	QualifiedName Alias?;
	
JoinClause:
	JoinType? 'join' JoinElement Alias? OnClause?;

JoinElement:
	AttributeRef;
	
OnClause:
	'on' Condition;	

WhereClause:
	'where' Condition;

GroupByClause:
	'group' 'by' GroupByElement (',' GroupByElement)* HavingClause?;

GroupByElement:
	Expression;

HavingClause
	'having' Condition;

OrderByClause:
	'order' 'by' OrderByElement (',' OrderByElement)*;

OrderByElement:
	Expression Order?;
	
OffsetClause:
	'offset' PaginationValue;

LimitClause:
	'limit' PaginationValue;

PaginationValue:
	IntegerLiteral | 
	ParameterRef
;

ResultClause:
	'result' ResultCount;
	
LockModeClause:
	'lockmode' LockModeType;
	
FetchClause:
	'fetch' FetchElement (',' FetchElement)*;
	
FetchElement:
	AttributeRef;	
	
IntoClause:
	'into' Type | 'tuple';
	
Alias:
	'as' ID;	

Condition:
	ConditionalOR;

ConditionalOR:
	ConditionalAND ('or' ConditionalAND)*;

ConditionalAND:
	ConditionalNOT ('and' ConditionalNOT)*;

ConditionalNOT:
	ConditionalPrimary | ('not' ConditionalPrimary);

ConditionalPrimary:
	('(' ConditionalOR ')') |
	BooleanExpression
;
	
BooleanExpression:
	Expression
	(
		(ComparisonOperator ComparisonExpressionRight) |
		('between' Expression 'and' Expression) |
		('like' Expression ('escape' Expression)?) |
		('in' '(' CollectionExpression ')')
	) |
	('exists' '(' SubQuery ')')
;

ComparisonExpressionRight:
	Expression | 
	CollectionComparisonExpression
;

CollectionComparisonExpression:
	CollectionComparisonFunction '(' SubQuery ')';

CollectionExpression:
	(Expression (',' Expression)*) | 
	SubQuery
;

Expression:
	ArithmeticLine;

ArithmeticLine:
	ArithmeticTerm (AddSubOperator ArithmeticTerm)*;

ArithmeticTerm:
	ArithmeticFactor (MultDivOperator ArithmeticFactor)*;

ArithmeticFactor:
	ArithmeticPrimary | (AddSubOperator ArithmeticPrimary);

ArithmeticPrimary:
	('(' (ArithmeticLine | SubQuery) ')') | 
	AttributeRef |
	Literal |
	Function |
	AggregateExpression
;

Function:
	LengthFunction |
	LocateFunction |
	ModFunction |
	AbsFunction |
	SizeFunction |
	SqrtFunction |
	UpperFunction |
	LowerFunction |
	ConcatFunction |
	SubstringFunction |
	TrimFunction |
	CurrentDateFunction |
	CurrentTimeFunction |
	CurrentTimestampFunction |
	CustomFunction
;

LengthFunction:
	'length' '(' Expression ')';
	
LocateFunction:
	'locate' '(' Expression ',' Expression (',' Expression)? ')';
	
ModFunction:
	'mod' '(' Expression ',' Expression ')';
	
AbsFunction:
	'abs' '(' Expression ')';
	
SizeFunction:
	'size' '(' Expression ')';
	
SqrtFunction:
	'sqrt' '(' Expression ')';

UpperFunction:
	'upper' '(' Expression ')';

LowerFunction:
	'lower' '(' Expression ')';
	
ConcatFunction:
	'concat' '(' Expression ',' Expression ')';
	
SubstringFunction:
	'substring' '(' Expression ',' Expression (',' Expression)? ')';

TrimFunction:
	'trim' '(' TrimSpecifiction? Expression? 'from' Expression ')';

// since 3.1.1
CustomFuction:
	'function' '(' StringLiteral ',' Type (',' Expression)* ')'

CurrentDateFunction:
	'current_date' ('(' ')')?;

CurrentTimeFunction:
	'current_time' ('(' ')')?;

CurrentTimestampFunction:
	'current_timestamp' ('(' ')')?;

SubQuery:
	(
	SelectClause? &
	FromClause
	)
	(
	WhereClause? &
	GroupByClause? &
	OrderByClause? &
	OffsetClause? &
	LimitClause?
	)
;	
	
AggregateExpression:
	AggregateFunction '(' Expression ')';

AttributeRef:
	AttributeRefStart ('.' AttributeRefPart)*;

AttributeRefStart:
	SimpleName |
	ParameterRef
;

AttributeRefPart:
	SimpleName;
	
SimpleName:
	ID;
	
QualifiedName:
	ID ('.' ID)*;

ParameterRef:
	':' Parameter;

Literal:
	NumericLiteral | StringLiteral | CharacterLiteral | BooleanLiteral | NullLiteral;

NumericLiteral:
	IntegerLiteral | DoubleLiteral;

IntegerLiteral:
	INT;

DoubleLiteral:
	DOUBLE;

StringLiteral:
	STRING;

CharacterLiteral:
	CHAR;

BooleanLiteral:
	'true'|'false';

NullLiteral:
	'null';

enum PrimitiveType:
	byte | short | int | long | float | double | boolean | char;
	
enum JoinType:
	inner | left | right;	
	
enum Order:
	asc | desc;
	
enum AggregateFunction:
	avg | min | max | sum | sumAsLong | sumAsDouble | count | countDistinct;

enum CollectionComparisonFunction:
	all | any | some;

enum TrimSpecifiction:
	both | // default
	leading | 
	trailing;
	
enum AddSubOperator
	plus='+' | minus='-';
	
enum MultDivOperator:
	mult='*' | div='/';		

enum ComparisonOperator:
	lessThan='<' |
	greaterThan='>' |
	lessEqual='<=' |
	greaterEqual='>=' |
	equal='=' |
	notEqual='!=' |
	notEqual2='<>'
;
	
enum ResultCount:
	list | // default 
	single;
	
enum LockModeType:
	NONE='none' |
	READ='read' |
	WRITE='write' |
	OPTIMISTIC='optimistic' |
	OPTIMISTIC_FORCE_INCREMENT='optimisticForceIncrement' |
	PESSIMISTIC_READ='pessimisticRead' |
	PESSIMISTIC_WRITE='pessimisticWrite' |
	PESSIMISTIC_FORCE_INCREMENT='pessimisticForceIncrement'
;