/******************************************************************************* | |
* Copyright (c) 2011 Oracle. All rights reserved. | |
* This program and the accompanying materials are made available under the | |
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 | |
* which accompanies this distribution. | |
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html | |
* and the Eclipse Distribution License is available at | |
* http://www.eclipse.org/org/documents/edl-v10.php. | |
* | |
* Contributors: | |
* Mike Norman - June 10 2011, created DDL parser package | |
******************************************************************************/ | |
options { | |
STATIC = false; | |
SUPPORT_CLASS_VISIBILITY_PUBLIC = true; | |
ERROR_REPORTING = false; | |
JAVA_UNICODE_ESCAPE = true; | |
UNICODE_INPUT = true; | |
NODE_USES_PARSER = false; | |
NODE_DEFAULT_VOID = true; | |
VISITOR = true; | |
FORCE_LA_CHECK = true; | |
} | |
PARSER_BEGIN(DDLParser) | |
/******************************************************************************* | |
* Copyright (c) 2011 Oracle. All rights reserved. | |
* This program and the accompanying materials are made available under the | |
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 | |
* which accompanies this distribution. | |
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html | |
* and the Eclipse Distribution License is available at | |
* http://www.eclipse.org/org/documents/edl-v10.php. | |
* | |
* Contributors: | |
* Mike Norman - June 10 2011, created DDL parser package | |
******************************************************************************/ | |
package org.eclipse.persistence.tools.oracleddl.parser; | |
//javase imports | |
import java.io.InputStream; | |
import java.util.List; | |
import java.util.HashMap; | |
import java.util.Map; | |
//metadata imports | |
import org.eclipse.persistence.tools.oracleddl.metadata.ArgumentType; | |
import org.eclipse.persistence.tools.oracleddl.metadata.ArgumentTypeDirection; | |
import org.eclipse.persistence.tools.oracleddl.metadata.BlobType; | |
import org.eclipse.persistence.tools.oracleddl.metadata.CharType; | |
import org.eclipse.persistence.tools.oracleddl.metadata.ClobType; | |
import org.eclipse.persistence.tools.oracleddl.metadata.CompositeDatabaseType; | |
import org.eclipse.persistence.tools.oracleddl.metadata.DatabaseType; | |
import org.eclipse.persistence.tools.oracleddl.metadata.DecimalType; | |
import org.eclipse.persistence.tools.oracleddl.metadata.DoubleType; | |
import org.eclipse.persistence.tools.oracleddl.metadata.FieldType; | |
import org.eclipse.persistence.tools.oracleddl.metadata.FloatType; | |
import org.eclipse.persistence.tools.oracleddl.metadata.FunctionType; | |
import org.eclipse.persistence.tools.oracleddl.metadata.IntervalDayToSecond; | |
import org.eclipse.persistence.tools.oracleddl.metadata.IntervalYearToMonth; | |
import org.eclipse.persistence.tools.oracleddl.metadata.LongType; | |
import org.eclipse.persistence.tools.oracleddl.metadata.LongRawType; | |
import org.eclipse.persistence.tools.oracleddl.metadata.NCharType; | |
import org.eclipse.persistence.tools.oracleddl.metadata.NClobType; | |
import org.eclipse.persistence.tools.oracleddl.metadata.NumericType; | |
import org.eclipse.persistence.tools.oracleddl.metadata.NVarChar2Type; | |
import org.eclipse.persistence.tools.oracleddl.metadata.ObjectType; | |
import org.eclipse.persistence.tools.oracleddl.metadata.ObjectTableType; | |
import org.eclipse.persistence.tools.oracleddl.metadata.PLSQLCollectionType; | |
import org.eclipse.persistence.tools.oracleddl.metadata.PLSQLCursorType; | |
import org.eclipse.persistence.tools.oracleddl.metadata.PLSQLPackageType; | |
import org.eclipse.persistence.tools.oracleddl.metadata.PLSQLRecordType; | |
import org.eclipse.persistence.tools.oracleddl.metadata.PLSQLType; | |
import org.eclipse.persistence.tools.oracleddl.metadata.PLSQLSubType; | |
import org.eclipse.persistence.tools.oracleddl.metadata.ProcedureType; | |
import org.eclipse.persistence.tools.oracleddl.metadata.RawType; | |
import org.eclipse.persistence.tools.oracleddl.metadata.RealType; | |
import org.eclipse.persistence.tools.oracleddl.metadata.ROWTYPEType; | |
import org.eclipse.persistence.tools.oracleddl.metadata.TableType; | |
import org.eclipse.persistence.tools.oracleddl.metadata.TimeStampType; | |
import org.eclipse.persistence.tools.oracleddl.metadata.TYPEType; | |
import org.eclipse.persistence.tools.oracleddl.metadata.URowIdType; | |
import org.eclipse.persistence.tools.oracleddl.metadata.UnresolvedSizedType; | |
import org.eclipse.persistence.tools.oracleddl.metadata.UnresolvedType; | |
import org.eclipse.persistence.tools.oracleddl.metadata.VarCharType; | |
import org.eclipse.persistence.tools.oracleddl.metadata.VarChar2Type; | |
import org.eclipse.persistence.tools.oracleddl.metadata.VArrayType; | |
import org.eclipse.persistence.tools.oracleddl.util.DatabaseTypesRepository; | |
import static org.eclipse.persistence.tools.oracleddl.metadata.ScalarDatabaseTypeEnum.BFILE_TYPE; | |
import static org.eclipse.persistence.tools.oracleddl.metadata.ScalarDatabaseTypeEnum.BINARY_INTEGER_TYPE; | |
import static org.eclipse.persistence.tools.oracleddl.metadata.ScalarDatabaseTypeEnum.BINARY_FLOAT_TYPE; | |
import static org.eclipse.persistence.tools.oracleddl.metadata.ScalarDatabaseTypeEnum.BINARY_DOUBLE_TYPE; | |
import static org.eclipse.persistence.tools.oracleddl.metadata.ScalarDatabaseTypeEnum.BOOLEAN_TYPE; | |
import static org.eclipse.persistence.tools.oracleddl.metadata.ScalarDatabaseTypeEnum.DATE_TYPE; | |
import static org.eclipse.persistence.tools.oracleddl.metadata.ScalarDatabaseTypeEnum.INTEGER_TYPE; | |
import static org.eclipse.persistence.tools.oracleddl.metadata.ScalarDatabaseTypeEnum.MLSLABEL_TYPE; | |
import static org.eclipse.persistence.tools.oracleddl.metadata.ScalarDatabaseTypeEnum.NATURAL_TYPE; | |
import static org.eclipse.persistence.tools.oracleddl.metadata.ScalarDatabaseTypeEnum.PLS_INTEGER_TYPE; | |
import static org.eclipse.persistence.tools.oracleddl.metadata.ScalarDatabaseTypeEnum.POSITIVE_TYPE; | |
import static org.eclipse.persistence.tools.oracleddl.metadata.ScalarDatabaseTypeEnum.ROWID_TYPE; | |
import static org.eclipse.persistence.tools.oracleddl.metadata.ScalarDatabaseTypeEnum.SIGN_TYPE; | |
import static org.eclipse.persistence.tools.oracleddl.metadata.ScalarDatabaseTypeEnum.SIMPLE_INTEGER_TYPE; | |
import static org.eclipse.persistence.tools.oracleddl.metadata.ScalarDatabaseTypeEnum.SIMPLE_DOUBLE_TYPE; | |
import static org.eclipse.persistence.tools.oracleddl.metadata.ScalarDatabaseTypeEnum.SIMPLE_FLOAT_TYPE; | |
import static org.eclipse.persistence.tools.oracleddl.metadata.ScalarDatabaseTypeEnum.SMALLINT_TYPE; | |
import static org.eclipse.persistence.tools.oracleddl.metadata.ScalarDatabaseTypeEnum.SYS_REFCURSOR_TYPE; | |
import static org.eclipse.persistence.tools.oracleddl.metadata.ScalarDatabaseTypeEnum.TIME_TYPE; | |
public class DDLParser { | |
protected Map<String, DatabaseType> localTypes = new HashMap<String, DatabaseType>(); | |
protected DatabaseTypesRepository typesRepository = new DatabaseTypesRepository(); | |
public DDLParser() { | |
super(); | |
} | |
public void setTypesRepository(DatabaseTypesRepository typesRepository) { | |
this.typesRepository = typesRepository; | |
} | |
public DatabaseTypesRepository getTypesRepository() { | |
return typesRepository; | |
} | |
protected String removeQuotes(String quotedString) { | |
return quotedString.substring(1, quotedString.length() - 1); | |
} | |
} | |
PARSER_END(DDLParser) | |
// white-space | |
SKIP: { | |
" " | "\t" | "\n" | "\r" | "\f" | |
} | |
// comments | |
SKIP: { | |
<COMMENT_LINE: "--" (~["\n","\r"])* ("\n"|"\r"|"\r\n") > | |
} | |
SKIP:{ | |
<COMMENT_BLOCK: "/*" (~["*"])* "*" ("*" | (~["*","/"] (~["*"])* "*"))* "/"> | |
} | |
// token classes | |
// separators and operators (prefix with O_ to avoid naming conflicts) | |
TOKEN: { | |
<O_ASSIGN: ":="> | |
| <O_ASTERISK: "*"> | |
| <O_ATSIGN: "@"> | |
| <O_CLOSEPAREN: ")"> | |
| <O_CONCAT: "||"> | |
| <O_COLON: ":"> | |
| <O_COMMA: ","> | |
| <O_DOT: "."> | |
| <O_DOUBLEDOT: ".."> | |
| <O_DOLLAR: "$"> | |
| <O_PERCENT: "%"> | |
| <O_EQUAL: "="> | |
| <O_GREATER: ">"> | |
| <O_GREATEREQUAL: ">="> | |
| <O_JOINPLUS: "(+)"> | |
| <O_LESS: "<"> | |
| <O_LESSEQUAL: "<="> | |
| <O_MINUS: "-"> | |
| <O_NOTEQUAL2: "<>"> | |
| <O_NOTEQUAL: "!="> | |
| <O_OPENPAREN: "("> | |
| <O_PLUS: "+"> | |
| <O_POUND: "#"> | |
| <O_QUESTIONMARK: "?"> | |
| <O_SEMICOLON: ";"> | |
| <O_SLASH: "/"> | |
| <O_TILDE: "~"> | |
} | |
// numeric literals | |
TOKEN : { | |
<S_NUMBER: <FLOAT> | <FLOAT> ( ["e","E"] ([ "-","+"])? <FLOAT> )? > | |
| <#FLOAT: <INTEGER> | <INTEGER> ( "." <INTEGER> )? | "." <INTEGER> > | |
| <#INTEGER: ( <DIGIT> )+ > | |
| <#DIGIT: ["0" - "9"] > | |
} | |
//reserved words and keywords literals | |
/* | |
PLSQL reserved words (prefix with R_ ) and keyword (prefix with K_) | |
http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/fundamentals.htm#CBJGBIGI | |
"You cannot use reserved words as ordinary user-defined identifiers. | |
You can use keywords as ordinary user-defined identifiers, but it is not recommended." | |
*/ | |
TOKEN [IGNORE_CASE]: { | |
//reserved words | |
<R_ALL: "ALL"> | |
| <R_ALTER: "ALTER"> | |
| <R_ANCHORED_ROWTYPE: "%ROWTYPE"> | |
| <R_ANCHORED_TYPE: "%TYPE"> | |
| <R_AND: "AND"> | |
| <R_AS: "AS"> | |
| <R_ASC: "ASC"> | |
| <R_AT: "AT"> | |
| <R_BEGIN: "BEGIN"> | |
| <R_BETWEEN: "BETWEEN"> | |
| <R_BY: "BY"> | |
| <R_CASE: "CASE"> | |
| <R_CHECK: "CHECK"> | |
| <R_CLUSTERS: "CLUSTERS"> | |
| <R_CLUSTER: "CLUSTER"> | |
| <R_COLAUTH: "COLAUTH"> | |
| <R_COLUMNS: "COLUMNS"> | |
| <R_COMPRESS: "COMPRESS"> | |
| <R_CONNECT: "CONNECT"> | |
| <R_CRASH: "CRASH"> | |
| <R_CREATE: "CREATE"> | |
| <R_CURSOR: "CURSOR"> | |
| <R_DECLARE: "DECLARE"> | |
| <R_DEFAULT: "DEFAULT"> | |
| <R_DESC: "DESC"> | |
| <R_DISTINCT: "DISTINCT"> | |
| <R_DROP: "DROP"> | |
| <R_ELSE: "ELSE"> | |
| <R_END: "END"> | |
| <R_EXCEPTION: "EXCEPTION"> | |
| <R_EXCLUSIVE: "EXCLUSIVE"> | |
| <R_FETCH: "FETCH"> | |
| <R_FOR: "FOR"> | |
| <R_FROM: "FROM"> | |
| <R_FUNCTION: "FUNCTION"> | |
| <R_GOTO: "GOTO"> | |
| <R_GRANT: "GRANT"> | |
| <R_GROUP: "GROUP"> | |
| <R_HAVING: "HAVING"> | |
| <R_IDENTIFIED: "IDENTIFIED"> | |
| <R_IF: "IF"> | |
| <R_IN: "IN"> | |
| <R_INDEX: "INDEX"> | |
| <R_INDEXES: "INDEXES"> | |
| <R_INSERT: "INSERT"> | |
| <R_INTERSECT: "INTERSECT"> | |
| <R_INTO: "INTO"> | |
| <R_IS: "IS"> | |
| <R_LIKE: "LIKE"> | |
| <R_LOCK: "LOCK"> | |
| <R_MINUS: "MINUS"> | |
| <R_MODE: "MODE"> | |
| <R_NOCOMPRESS: "NOCOMPRESS"> | |
| <R_NO: "'NO'"> | |
| <R_NOT: "NOT"> | |
| <R_NOWAIT: "NOWAIT"> | |
| <R_NULL: "NULL"> | |
| <R_OF: "OF"> | |
| <R_ON: "ON"> | |
| <R_OPTION: "OPTION"> | |
| <R_OR: "OR"> | |
| <R_ORDER: "ORDER"> | |
| <R_OVERLAPS: "OVERLAPS"> | |
| <R_PROCEDURE: "PROCEDURE"> | |
| <R_PUBLIC: "PUBLIC"> | |
| <R_RESOURCE: "RESOURCE"> | |
| <R_REVOKE: "REVOLE"> | |
| <R_SELECT: "SELECT"> | |
| <R_SHARE: "SHARE"> | |
| <R_SIZE: "SIZE"> | |
| <R_SQL: "SQL"> | |
| <R_START: "START"> | |
| <R_SUBTYPE: "SUBTYPE"> | |
| <R_TABAUTH: "TABAUTH"> | |
| <R_TABLE: "TABLE"> | |
| <R_THEN: "THEN"> | |
| <R_TO: "TO"> | |
| <R_TYPE: "TYPE"> | |
| <R_UNION: "UNION"> | |
| <R_UNIQUE: "UNIQUE"> | |
| <R_UPDATE: "UPDATE"> | |
| <R_VALUES: "VALUES"> | |
| <R_VIEW: "VIEW"> | |
| <R_VIEWS: "VIEWS"> | |
| <R_WHEN: "WHEN"> | |
| <R_WHERE: "WHERE"> | |
| <R_WITH: "WITH"> | |
| <R_YES: "'YES'"> | |
//keywords - not a complete list, just was is sufficient for this parser | |
| <K_ARRAY: "ARRAY"> | |
| <K_AUTHID: "AUTHID"> | |
| <K_AUTONOMOUS_TRANSACTION: "AUTONOMOUS_TRANSACTION"> | |
| <K_BFILE: "BFILE"> | |
| <K_BINARY_DOUBLE: "BINARY_DOUBLE"> | |
| <K_BINARY_FLOAT: "BINARY_FLOAT"> | |
| <K_BINARY_INTEGER: "BINARY_INTEGER"> | |
| <K_BLOB: "BLOB"> | |
| <K_BOOLEAN: "BOOLEAN"> | |
| <K_BYTE: "BYTE"> | |
| <K_CHAR: "CHAR"> | |
| <K_CHARACTER: "CHARACTER"> | |
| <K_CHARSET: "CHARSET"> | |
| <K_CLOB: "CLOB"> | |
| <K_COMMIT: "COMMIT"> | |
| <K_CONSTANT: "CONSTANT"> | |
| <K_CONSTRAINT: "CONSTRAINT"> | |
| <K_CURRENT_USER: "CURRENT_USER"> | |
| <K_DATE :"DATE"> | |
| <K_DAY: "DAY"> | |
| <K_DEC: "DEC"> | |
| <K_DECIMAL: "DECIMAL"> | |
| <K_DEFINER: "DEFINER"> | |
| <K_DELETE: "DELETE"> | |
| <K_DETERMINISTIC: "DETERMINISTIC"> | |
| <K_DOUBLE: "DOUBLE"> | |
| <K_ENABLE: "ENABLE"> | |
| <K_EXCEPTION_INIT: "EXCEPTION_INIT"> | |
| <K_FINAL: "FINAL"> | |
| <K_FLOAT: "FLOAT"> | |
| <K_FORCE: "FORCE"> | |
| <K_GLOBAL: "GLOBAL"> | |
| <K_INLINE: "INLINE"> | |
| <K_INSTANTIABLE: "INSTANTIABLE"> | |
| <K_INT: "INT"> | |
| <K_INTEGER: "INTEGER"> | |
| <K_INTERVAL: "INTERVAL"> | |
| <K_KEY: "KEY"> | |
| <K_LOCAL: "LOCAL"> | |
| <K_LONG: "LONG"> | |
| <K_MLSLABEL: "MLSLABEL"> | |
| <K_MONTH: "MONTH"> | |
| <K_NATIONAL: "NATIONAL"> | |
| <K_NATURAL: "NATURAL"> | |
| <K_NCHAR: "NCHAR"> | |
| <K_NCLOB: "NCLOB"> | |
| <K_NOCOPY: "NOCOPY"> | |
| <K_NUMBER: "NUMBER"> | |
| <K_NUMERIC: "NUMERIC"> | |
| <K_NVARCHAR2: "NVARCHAR2"> | |
| <K_NVARCHAR: "NVARCHAR"> | |
| <K_OBJECT: "OBJECT"> | |
| <K_OID: "OID"> | |
| <K_ORGANIZATION: "ORGANIZATION"> | |
| <K_OUT: "OUT"> | |
| <K_OVERFLOW: "OVERFLOW"> | |
| <K_PACKAGE: "PACKAGE"> | |
| <K_PARALLEL_ENABLE: "PARALLEL_ENABLE"> | |
| <K_PIPELINED: "PIPELINED"> | |
| <K_PLS_INTEGER:"PLS_INTEGER"> | |
| <K_POSITIVE: "POSITIVE"> | |
| <K_PRAGMA: "PRAGMA"> | |
| <K_PRECISION:"PRECISION"> | |
| <K_PRESERVE: "PRESERVE"> | |
| <K_PRIMARY: "PRIMARY"> | |
| <K_RANGE: "RANGE"> | |
| <K_RAW: "RAW"> | |
| <K_REAL:"REAL"> | |
| <K_RECORD: "RECORD"> | |
| <K_REF: "REF"> | |
| <K_REPLACE: "REPLACE"> | |
| <K_RESTRICT_REFERENCES: "RESTRICT_REFERENCES"> | |
| <K_RESULT_CACHE: "RESULT_CACHE"> | |
| <K_RETURN: "RETURN"> | |
| <K_RNDS: "RNDS"> | |
| <K_RNPS: "RNPS"> | |
| <K_ROWID:"ROWID"> | |
| <K_ROWS: "ROWS"> | |
| <K_SECOND: "SECOND"> | |
| <K_SERIALLY_REUSABLE: "SERIALLY_REUSABLE"> | |
| <K_SET: "SET"> | |
| <K_SIGNTYPE: "SIGNTYPE"> | |
| <K_SIMPLE_DOUBLE:"SIMPLE_DOUBLE"> | |
| <K_SIMPLE_FLOAT:"SIMPLE_FLOAT"> | |
| <K_SIMPLE_INTEGER:"SIMPLE_INTEGER"> | |
| <K_SMALLINT:"SMALLINT"> | |
| <K_STRING: "STRING"> | |
| <K_SYS_REFCURSOR:"SYS_REFCURSOR"> | |
| <K_TEMPORARY: "TEMPORARY"> | |
| <K_TIME: "TIME"> | |
| <K_TIMESTAMP: "TIMESTAMP"> | |
| <K_TRUST: "TRUST"> | |
| <K_UROWID:"UROWID"> | |
| <K_VARCHAR2: "VARCHAR2"> | |
| <K_VARCHAR: "VARCHAR"> | |
| <K_VARRAY: "VARRAY"> | |
| <K_VARYING: "VARYING"> | |
| <K_WNDS: "WNDS"> | |
| <K_WNPS: "WNPS"> | |
| <K_YEAR: "YEAR"> | |
| <K_ZONE: "ZONE"> | |
} | |
// identifiers | |
TOKEN: | |
{ | |
<S_IDENTIFIER: (<LETTER>)+ (<DIGIT> | <LETTER> | <SPECIAL_CHARS>)* > | |
| <#LETTER: ["a"-"z", "A"-"Z"] > | |
| <#SPECIAL_CHARS: "$" | "_" | "#" | "@" > | |
| <S_BIND: ":" ( <S_NUMBER> | <S_IDENTIFIER> ("." <S_IDENTIFIER>)?) > | |
| <S_CHAR_LITERAL: "'" (~["'"])* "'" ("'" (~["'"])* "'")*> | |
| <S_QUOTED_IDENTIFIER: "\"" (~["\n","\r","\""])* "\"" > | |
} | |
// stripped-down version of PLSQL grammar: only parses package/top-level DDL specifications | |
// PLSQLPackage at 'top-level' | |
PLSQLPackageType parsePLSQLPackage(): | |
{PLSQLPackageType packageType = new PLSQLPackageType(); | |
String schema = null; | |
String packageName = null; | |
} | |
{ | |
<R_CREATE> [ orReplace() ] <K_PACKAGE> | |
[LOOKAHEAD(2) schema=OracleObjectName() <O_DOT> ] packageName=OracleObjectName() | |
{ | |
if (schema != null) { | |
packageType.setSchema(schema); | |
} | |
packageType.setPackageName(packageName); | |
} | |
[ invokerRights() ] as() | |
( packageDeclaration(packageType) )* | |
<R_END> [ OracleObjectName() ] <O_SEMICOLON> | |
<EOF> | |
{ | |
typesRepository.setDatabaseType(packageName, packageType); | |
return packageType; | |
} | |
} | |
// procedure at 'top-level' | |
ProcedureType parseTopLevelProcedure(): | |
{ProcedureType procedureType = null; | |
String schema = null; | |
String procedureName = null;} | |
{ | |
<R_CREATE> [ orReplace() ] <R_PROCEDURE> | |
[LOOKAHEAD(2) schema=OracleObjectName() <O_DOT> ] procedureName=OracleObjectName() | |
{ | |
procedureType = new ProcedureType(procedureName); | |
if (schema != null) { | |
procedureType.setSchema(schema); | |
} } | |
[ <O_OPENPAREN> argumentList(procedureType) <O_CLOSEPAREN> ] as() | |
skipToEnd() | |
{ | |
typesRepository.setDatabaseType(procedureName, procedureType); | |
return procedureType; | |
} | |
} | |
// function at 'top-level' | |
FunctionType parseTopLevelFunction(): | |
{FunctionType functionType = null; | |
String schema = null; | |
String functionName = null; | |
ArgumentType returnType = null;} | |
{ | |
<R_CREATE> [ orReplace() ] <R_FUNCTION> | |
[LOOKAHEAD(2) schema=OracleObjectName() <O_DOT> ] functionName=OracleObjectName() | |
{ | |
functionType = new FunctionType(functionName); | |
if (schema != null) { | |
functionType.setSchema(schema); | |
} } | |
[ <O_OPENPAREN> argumentList(functionType) <O_CLOSEPAREN> ] returnType=functionReturnSpec() as() | |
skipToEnd() | |
{ | |
functionType.setReturnArgument(returnType); | |
typesRepository.setDatabaseType(functionName, functionType); | |
return functionType; | |
} | |
} | |
// table at 'top-level' | |
TableType parseTable(): | |
{TableType tableType = null; | |
String schema = null; | |
String tableName = null; | |
Token iot = null; | |
} | |
{ | |
<R_CREATE> [ <K_GLOBAL> <K_TEMPORARY> ] <R_TABLE> | |
[LOOKAHEAD(2) schema=OracleObjectName() <O_DOT> ] tableName=OracleObjectName() | |
{ | |
tableType = new TableType(tableName); | |
if (schema != null) { | |
tableType.setSchema(schema); | |
} } | |
<O_OPENPAREN> columnDeclarations(tableType) <O_CLOSEPAREN> | |
[ <K_ORGANIZATION> ] [ iot=<R_INDEX> ] [ <R_NOCOMPRESS> ] [ <K_OVERFLOW> ] | |
[ <R_ON> <K_COMMIT > [<K_DELETE> | <K_PRESERVE> ] <K_ROWS> ] <O_SEMICOLON> | |
<EOF> | |
{ | |
if (iot != null) { | |
tableType.setIOT(true); | |
} | |
typesRepository.setDatabaseType(tableName, tableType); | |
return tableType; | |
} | |
} | |
// type at 'top-level' | |
CompositeDatabaseType parseType(): | |
{CompositeDatabaseType databaseType = null; | |
DatabaseType enclosedType = null; | |
String schema = null; | |
String typeName = null; | |
Token vsize = null; | |
boolean varray = false; | |
boolean nestedTable = false; | |
} | |
{ | |
<R_CREATE> [ orReplace() ] <R_TYPE> | |
[LOOKAHEAD(2) schema=OracleObjectName() <O_DOT> ] typeName=OracleObjectName() | |
[ <K_FORCE> ] [ <K_OID> <S_CHAR_LITERAL> ] [ invokerRights() ] as() | |
[ <K_OBJECT> <O_OPENPAREN> | |
{ | |
databaseType = new ObjectType(typeName); | |
if (schema != null) { | |
((ObjectType)databaseType).setSchema(schema); } | |
} columnDeclarations(databaseType) <O_CLOSEPAREN> | |
| <K_VARRAY> <O_OPENPAREN> vsize=<S_NUMBER> <O_CLOSEPAREN> <R_OF> | |
{ databaseType = new VArrayType(typeName); | |
if (schema != null) { | |
((VArrayType)databaseType).setSchema(schema); | |
} | |
if (vsize != null) { | |
Long size = Long.decode(vsize.image); | |
((VArrayType)databaseType).setSize(size); | |
} | |
} enclosedType=columnTypeSpec(databaseType) | |
| <R_TABLE> <R_OF> { | |
databaseType = new ObjectTableType(typeName); | |
if (schema != null) { | |
((ObjectTableType)databaseType).setSchema(schema); | |
} } enclosedType=columnTypeSpec(databaseType) | |
] | |
[ [ <R_NOT> ] ( <K_FINAL> | <K_INSTANTIABLE> ) ] [ <O_SEMICOLON> ] | |
<EOF> | |
{ | |
if (enclosedType != null) { | |
((CompositeDatabaseType)databaseType).setEnclosedType(enclosedType); } | |
typesRepository.setDatabaseType(typeName, databaseType); | |
return databaseType; | |
} | |
} | |
void columnDeclarations(CompositeDatabaseType enclosingType): | |
{} | |
{ | |
columnDeclaration(enclosingType) [ <O_COMMA> columnDeclarations(enclosingType) ] | |
} | |
void columnDeclaration(CompositeDatabaseType enclosingType): | |
{String s = null; | |
String pk = null; | |
boolean notNull = false; | |
DatabaseType columnType = null; | |
FieldType column = null; | |
} | |
{ | |
( LOOKAHEAD(2) s=OracleObjectName() | |
{ | |
column = new FieldType(s); | |
if (enclosingType != null) { | |
if (enclosingType.isPLSQLRecordType()) { | |
((PLSQLRecordType)enclosingType).addField(column); | |
} | |
else if (enclosingType.isTableType()) { | |
((TableType)enclosingType).addColumn(column); | |
} | |
else if (enclosingType.isObjectType()) { | |
((ObjectType)enclosingType).addField(column); | |
} | |
} } | |
columnType=columnTypeSpec(enclosingType) [ <R_NOT> <R_NULL> [ <K_ENABLE> ] {notNull = true;} ] | |
| LOOKAHEAD(2) | |
[ <K_CONSTRAINT> ] [ OracleObjectName() ] | |
( | |
<K_PRIMARY> <K_KEY> <O_OPENPAREN> pkList((TableType)enclosingType) <O_CLOSEPAREN> | |
| <R_CHECK> <O_OPENPAREN> skipToClosingParen() <O_CLOSEPAREN> | |
| <R_UNIQUE> <O_OPENPAREN> uniqList() <O_CLOSEPAREN> ) <K_ENABLE> | |
) | |
{ | |
if (column != null) { | |
column.setEnclosedType(columnType); | |
if (columnType instanceof UnresolvedType) { | |
((UnresolvedType)columnType).setOwningType(column); | |
} | |
if (notNull) { | |
column.setNotNull(); | |
} | |
} | |
} | |
} | |
DatabaseType columnTypeSpec(CompositeDatabaseType enclosingType): | |
{String s = null; | |
Token t = null; | |
DatabaseType dt = null;} | |
{ | |
( | |
dt=datatype() | |
| s=columnSpec() [ <O_OPENPAREN> t=<S_NUMBER> <O_CLOSEPAREN> ] | |
) [ <K_CONSTRAINT> <S_QUOTED_IDENTIFIER> ] | |
{ | |
if (s != null) { | |
for (String typeName : localTypes.keySet()) { | |
if (typeName.equals(s)) { | |
dt = localTypes.get(s); | |
break; | |
} | |
} | |
if (dt == null) { | |
if (t != null) { | |
Long size = Long.decode(t.image); | |
dt = new UnresolvedSizedType(s, size); | |
} | |
else { | |
dt = new UnresolvedType(s); | |
} | |
((UnresolvedType)dt).setOwningType(enclosingType); | |
} | |
} | |
return dt; | |
} | |
} | |
void uniqList(): | |
{} | |
{ | |
OracleObjectName() ( <O_COMMA> OracleObjectName() )* | |
} | |
void pkList(TableType tableType): | |
{} | |
{ | |
pk(tableType) ( <O_COMMA> pk(tableType) )* | |
} | |
void pk(TableType tableType): | |
{ | |
String s = null; | |
} | |
{ | |
s=OracleObjectName() | |
{ | |
List<FieldType> columns = tableType.getColumns(); | |
for (FieldType column : columns) { | |
if (column.getFieldName().equals(s)) { | |
column.setPk(); | |
break; | |
} | |
} } | |
} | |
void packageDeclaration(PLSQLPackageType packageType) : | |
{} | |
{ | |
LOOKAHEAD(2) variableDeclaration(packageType) | |
| typeOrSubTypeDeclaration(packageType) | |
| cursorDeclaration(packageType) | |
| procedureSpec(packageType) | |
| functionSpec(packageType) | |
| exceptionDeclaration(packageType) | |
| pragmaDeclaration(packageType) | |
} | |
void variableDeclaration(PLSQLPackageType packageType): | |
{Token varName = null; | |
DatabaseType varType;} | |
{ | |
varName=<S_IDENTIFIER> [ <K_CONSTANT> ] varType=typeSpec() [ <R_NOT> <R_NULL> ] | |
[ variableDefaultAssignment() ] | |
<O_SEMICOLON> | |
{ | |
FieldType variable = new FieldType(varName.image); | |
variable.setEnclosedType(varType); | |
packageType.addLocalVariable(variable); } } | |
void variableDefaultAssignment(): | |
{} | |
{ | |
( <O_ASSIGN> | <R_DEFAULT> ) skipToSemiColon() | |
} | |
DatabaseType datatype(): | |
{Token t = null; | |
DatabaseType dt = null; | |
Token precision = null; | |
Long sl; | |
Long pl; | |
Token scale = null; | |
Token withTimeZone = null; | |
Token withLocalTimeZone = null; | |
} | |
{ | |
<K_BINARY_INTEGER> { return BINARY_INTEGER_TYPE;} | |
| <K_BINARY_FLOAT> { return BINARY_FLOAT_TYPE;} | |
| <K_BINARY_DOUBLE> { return BINARY_DOUBLE_TYPE;} | |
| <K_NATURAL> { return NATURAL_TYPE;} | |
| <K_POSITIVE> { return POSITIVE_TYPE;} | |
| <K_SIGNTYPE> { return SIGN_TYPE;} | |
| ( t=<K_NUMBER> | |
| t=<K_NUMERIC> | |
| t=<K_DECIMAL> | |
| t=<K_DEC> | |
) [ <O_OPENPAREN> [ precision=<O_ASTERISK > | precision=<S_NUMBER> ] ( <O_COMMA> scale=<S_NUMBER> )* <O_CLOSEPAREN> ] | |
{ | |
if (t.kind == K_NUMBER || t.kind == K_NUMERIC) { | |
if (precision != null && precision.image.equals("*")) { | |
precision = null; } | |
if (precision == null) { | |
if (scale != null && scale.image.equals("0")) { | |
dt = INTEGER_TYPE; } else { | |
dt = new NumericType(); } | |
} | |
else { | |
pl = Long.decode(precision.image); | |
if (scale == null) { | |
dt = new NumericType(pl); | |
} | |
else { | |
sl = Long.decode(scale.image); | |
dt = new NumericType(pl, sl); | |
} | |
} | |
//sometimes need to know difference between NUMERIC and NUMBER | |
if (dt != INTEGER_TYPE && t.kind == K_NUMBER) { | |
((NumericType)dt).setNumberSynonym(true); | |
} | |
} | |
else if (t.kind == K_DECIMAL || t.kind == K_DEC) { | |
if (precision != null && precision.image.equals("*")) { | |
precision = null; | |
} | |
if (precision == null) { | |
dt = new DecimalType(); | |
} | |
else { | |
pl = Long.decode(precision.image); | |
if (scale == null) { | |
dt = new DecimalType(pl); | |
} | |
else { | |
sl = Long.decode(scale.image); | |
dt = new DecimalType(pl, sl); | |
} | |
} | |
} return dt; } | |
| <K_LONG> [ t=<K_RAW> ] [ <O_OPENPAREN> precision=<S_NUMBER> <O_CLOSEPAREN> ] { | |
if (t == null) { | |
if (precision == null) { | |
dt = new LongType(); | |
} | |
else { | |
pl = Long.decode(precision.image); | |
dt = new LongType(pl); | |
} | |
} | |
else { | |
if (precision == null) { | |
dt = new LongRawType(); | |
} | |
else { | |
pl = Long.decode(precision.image); | |
dt = new LongRawType(pl); | |
} | |
} | |
return dt; } | |
| <K_RAW> [ <O_OPENPAREN> precision=<S_NUMBER> <O_CLOSEPAREN> ] { | |
if (precision == null) { | |
dt = new RawType(); | |
} | |
else { | |
pl = Long.decode(precision.image); | |
dt = new RawType(pl); | |
} | |
return dt; | |
} | |
| <K_BOOLEAN> { return BOOLEAN_TYPE;} | |
| <K_DATE> { return DATE_TYPE;} | |
| LOOKAHEAD(2) <K_INTERVAL> <K_DAY> [ <O_OPENPAREN> precision=<S_NUMBER> <O_CLOSEPAREN> ] <R_TO> <K_SECOND> [ <O_OPENPAREN> scale=<S_NUMBER> <O_CLOSEPAREN> ] | |
{ | |
if (precision == null) { | |
dt = new IntervalDayToSecond(); | |
} | |
else { | |
pl = Long.decode(precision.image); | |
if (scale == null) { | |
dt = new IntervalDayToSecond(pl); | |
} | |
else { | |
sl = Long.decode(scale.image); | |
dt = new IntervalDayToSecond(pl, sl); | |
} | |
} | |
return dt; } | |
| <K_INTERVAL> <K_YEAR> [ <O_OPENPAREN> <S_NUMBER> <O_CLOSEPAREN> ] <R_TO> <K_MONTH> { | |
if (precision == null) { | |
dt = new IntervalYearToMonth(); | |
} | |
else { | |
pl = Long.decode(precision.image); | |
dt = new IntervalYearToMonth(pl); | |
} | |
return dt; } | |
| <K_TIME> { return TIME_TYPE;} | |
| <K_TIMESTAMP> [ <O_OPENPAREN> precision=<S_NUMBER> <O_CLOSEPAREN> ] | |
[ <R_WITH> [ withLocalTimeZone=<K_LOCAL> ] withTimeZone=<K_TIME> <K_ZONE> ] | |
{ | |
if (precision == null) { | |
dt = new TimeStampType(); | |
} | |
else { | |
pl = Long.decode(precision.image); | |
dt = new TimeStampType(pl); | |
} | |
if (withLocalTimeZone != null) { | |
((TimeStampType)dt).setWithLocalTimeZone(); } | |
else if (withTimeZone != null) { | |
((TimeStampType)dt).setWithTimeZone(); } | |
return dt; } | |
| <K_INTEGER> { return INTEGER_TYPE;} | |
| <K_INT> { return INTEGER_TYPE;} | |
| <K_SMALLINT> { return SMALLINT_TYPE;} | |
| <K_FLOAT> [ <O_OPENPAREN> precision=<S_NUMBER> <O_CLOSEPAREN> ] | |
{ | |
if (precision == null) { | |
return new FloatType(); | |
} | |
else { | |
pl = Long.decode(precision.image); | |
FloatType ft = new FloatType(pl); | |
return ft; } | |
} | |
| <K_REAL> { return new RealType();} | |
| <K_MLSLABEL> { return MLSLABEL_TYPE;} | |
| <K_PLS_INTEGER> { return PLS_INTEGER_TYPE;} | |
| <K_SIMPLE_INTEGER> { return SIMPLE_INTEGER_TYPE;} | |
| <K_SIMPLE_FLOAT> { return SIMPLE_FLOAT_TYPE;} | |
| <K_SIMPLE_DOUBLE> { return SIMPLE_DOUBLE_TYPE;} | |
| <K_SYS_REFCURSOR> { return SYS_REFCURSOR_TYPE;} | |
| <K_BLOB > { return new BlobType();} | |
| <K_NCLOB> { return new NClobType();} | |
| <K_BFILE> { return BFILE_TYPE;} | |
| <K_ROWID> { return ROWID_TYPE;} | |
| <K_UROWID> [ <O_OPENPAREN> precision=<S_NUMBER> <O_CLOSEPAREN> ] | |
{ | |
if (precision == null) { | |
return new URowIdType(); | |
} | |
else { | |
pl = Long.decode(precision.image); | |
return new URowIdType(pl); | |
} } | |
| <K_DOUBLE> <K_PRECISION> { return new DoubleType();} | |
| <K_CHAR> [ t=<K_VARYING> ] [ <O_OPENPAREN> precision=<S_NUMBER> [ <K_BYTE> | <K_CHAR> ] <O_CLOSEPAREN> ] | |
[ LOOKAHEAD(2) <K_CHARACTER> <K_SET> [ LOOKAHEAD(2) <S_IDENTIFIER> | columnSpec() <K_CHARSET> ] ] { | |
if (t == null) { | |
if (precision == null) { | |
return new CharType(); | |
} | |
else { | |
pl = Long.decode(precision.image); | |
return new CharType(pl); } | |
} | |
else { | |
// ANSI syntax for VARCHAR2 | |
if (precision == null) { | |
return new VarChar2Type(); | |
} | |
else { | |
pl = Long.decode(precision.image); | |
return new VarChar2Type(pl); | |
} } } | |
| <K_VARCHAR> [ <K_VARYING> ] [ <O_OPENPAREN> precision=<S_NUMBER> [ <K_BYTE> | <K_CHAR> ] <O_CLOSEPAREN> ] | |
[ LOOKAHEAD(2) <K_CHARACTER> <K_SET> [ LOOKAHEAD(2) <S_IDENTIFIER> | columnSpec() <K_CHARSET> ] ] | |
{ | |
if (precision == null) { | |
return new VarCharType(); | |
} | |
else { | |
pl = Long.decode(precision.image); | |
return new VarCharType(pl); | |
} | |
} | |
| <K_VARCHAR2> [ <K_VARYING> ] [ <O_OPENPAREN> precision=<S_NUMBER> [ <K_BYTE> | <K_CHAR> ] <O_CLOSEPAREN> ] | |
[ LOOKAHEAD(2) <K_CHARACTER> <K_SET> [ LOOKAHEAD(2) <S_IDENTIFIER> | columnSpec() <K_CHARSET> ] ] | |
{ | |
if (precision == null) { | |
return new VarChar2Type(); | |
} | |
else { | |
pl = Long.decode(precision.image); | |
return new VarChar2Type(pl); } } | |
| <K_CHARACTER> [ t=<K_VARYING> ] [ <O_OPENPAREN> precision=<S_NUMBER> <O_CLOSEPAREN> ] | |
{ | |
if (t == null) { | |
if (precision == null) { | |
return new CharType(); | |
} | |
else { | |
pl = Long.decode(precision.image); | |
return new CharType(pl); | |
} | |
} | |
else { | |
// ANSI syntax for VARCHAR | |
if (precision == null) { | |
return new VarCharType(); | |
} | |
else { | |
pl = Long.decode(precision.image); | |
return new VarCharType(pl); | |
} | |
} | |
} | |
| <K_NCHAR> [ t=<K_VARYING> ] [ <O_OPENPAREN> precision=<S_NUMBER> <O_CLOSEPAREN> ] | |
{ | |
if (t == null) { | |
if (precision == null) { | |
return new NCharType(); | |
} | |
else { | |
pl = Long.decode(precision.image); | |
return new NCharType(pl); | |
} | |
} | |
else { | |
// ANSI syntax for NVARCHAR2 | |
if (precision == null) { | |
return new NVarChar2Type(); | |
} | |
else { | |
pl = Long.decode(precision.image); | |
return new NVarChar2Type(pl); | |
} | |
} | |
} | |
| <K_NVARCHAR> [ <O_OPENPAREN> precision=<S_NUMBER> <O_CLOSEPAREN> ] { | |
if (precision == null) { | |
return new NVarChar2Type(); | |
} | |
else { | |
pl = Long.decode(precision.image); | |
return new NVarChar2Type(pl); | |
} } | |
| <K_NVARCHAR2> [ <O_OPENPAREN> precision=<S_NUMBER> <O_CLOSEPAREN> ] | |
{ | |
if (precision == null) { | |
return new NVarChar2Type(); | |
} | |
else { | |
pl = Long.decode(precision.image); | |
return new NVarChar2Type(pl); | |
} | |
} | |
| <K_NATIONAL> ( <K_CHARACTER> | <K_CHAR> ) [ t=<K_VARYING> ] [ <O_OPENPAREN> precision=<S_NUMBER> <O_CLOSEPAREN> ] | |
{ | |
if (t == null) { | |
if (precision == null) { | |
return new NCharType(); | |
} | |
else { | |
pl = Long.decode(precision.image); | |
return new NCharType(pl); | |
} | |
} | |
else { | |
// ANSI syntax for NVARCHAR2 | |
if (precision == null) { | |
return new NVarChar2Type(); | |
} | |
else { | |
pl = Long.decode(precision.image); | |
return new NVarChar2Type(pl); | |
} | |
} | |
} | |
| <K_CLOB> [ LOOKAHEAD(2) <K_CHARACTER> <K_SET> [ LOOKAHEAD(2) <S_IDENTIFIER> | columnSpec() <K_CHARSET> ] ] { return new ClobType();} | |
} | |
DatabaseType typeSpec(): | |
{boolean isTYPEType = false; | |
boolean isROWTYPEType = false; | |
DatabaseType dataType = null; | |
String spec = null; | |
String s = null;} | |
{ | |
( | |
dataType=datatype() | |
| | |
spec=columnSpec() | |
[ | |
( <O_OPENPAREN> <S_NUMBER> <O_CLOSEPAREN> ) | |
| | |
<R_ANCHORED_TYPE> | |
{ | |
isTYPEType=true; | |
s = spec + removeQuotes(tokenImage[R_ANCHORED_TYPE]); | |
} | |
| | |
<R_ANCHORED_ROWTYPE> | |
{ | |
isROWTYPEType =true; | |
s = spec + removeQuotes(tokenImage[R_ANCHORED_ROWTYPE]); | |
} | |
] | |
) | |
{ | |
if (dataType == null && localTypes != null) { | |
for (String typeName : localTypes.keySet()) { | |
if (typeName.equals(spec)) { | |
dataType = localTypes.get(spec); | |
break; | |
} | |
} | |
} | |
if (dataType == null) { | |
UnresolvedType uType = new UnresolvedType(spec); | |
if (isTYPEType) { | |
TYPEType tType = new TYPEType(s); | |
tType.setEnclosedType(uType); | |
uType.setOwningType(tType); | |
dataType = tType; | |
localTypes.put(spec, dataType); | |
} | |
else if (isROWTYPEType) { | |
ROWTYPEType rType = new ROWTYPEType(s); | |
rType.setEnclosedType(uType); | |
uType.setOwningType(rType); | |
dataType = rType; | |
localTypes.put(spec, dataType); | |
} | |
else { | |
dataType = uType; | |
} | |
} | |
return dataType; } | |
} | |
String columnSpec(): | |
{String s1 = null; | |
String s2 = null; | |
String s3 = null;} | |
{ | |
s1=OracleObjectName() [ <O_DOT> s2=OracleObjectName() [ <O_DOT> s3=OracleObjectName() ] ] | |
{ | |
StringBuilder sb = new StringBuilder(s1); | |
if (s2 != null) { | |
sb.append('.'); | |
sb.append(s2); | |
if (s3 != null) { | |
sb.append('.'); | |
sb.append(s3); | |
} | |
} | |
return sb.toString(); | |
} | |
} | |
String tableSpec(): | |
{} | |
{ | |
OracleObjectName() [ <O_DOT> OracleObjectName() [ <O_ATSIGN> <S_IDENTIFIER> ] ] | |
{return token.image;} | |
} | |
String typeName(): | |
{} | |
{ | |
OracleObjectName() [ <O_DOT> OracleObjectName() ] | |
{return token.image;} | |
} | |
void typeOrSubTypeDeclaration(PLSQLPackageType packageType) : | |
{String s = null;} | |
{ | |
typeDeclaration(packageType) | |
| subtypeDeclaration(packageType) | |
} | |
void typeDeclaration(PLSQLPackageType packageType) : | |
{String s = null;} | |
{ | |
<R_TYPE> s=typeName() <R_IS> aTypeDeclaration(packageType, s) <O_SEMICOLON> | |
} | |
void aTypeDeclaration(PLSQLPackageType packageType, String typeName) : | |
{} | |
{ | |
recordDeclaration(packageType, typeName) | |
| plsqlTableDeclaration(packageType, typeName) | |
| varrayDeclaration(packageType) | |
| refCursorDeclaration(packageType, typeName) | |
} | |
void recordDeclaration(PLSQLPackageType packageType, String typeName) : | |
{ | |
PLSQLRecordType plsqlRecordType = new PLSQLRecordType(typeName); | |
plsqlRecordType.setParentType(packageType); | |
} | |
{ | |
<K_RECORD> <O_OPENPAREN> | |
fieldDeclarations(plsqlRecordType) | |
<O_CLOSEPAREN> | |
{ packageType.addType(plsqlRecordType); | |
localTypes.put(typeName, plsqlRecordType); | |
} | |
} | |
void fieldDeclarations(PLSQLRecordType plsqlRecordType) : | |
{} | |
{ | |
fieldDeclaration(plsqlRecordType) [ <O_COMMA> fieldDeclarations(plsqlRecordType) ] | |
} | |
void fieldDeclaration(PLSQLRecordType plsqlRecordType): | |
{ | |
String s = null; | |
DatabaseType dataType = null; | |
FieldType fieldType = null; | |
} | |
{ | |
s=typeName() dataType=typeSpec() [ <R_NOT> <R_NULL> ] [ fieldDefaultAssignment() ] | |
{ | |
fieldType = new FieldType(s); | |
fieldType.setEnclosedType(dataType); | |
plsqlRecordType.addField(fieldType); | |
if (dataType instanceof UnresolvedType) { | |
((UnresolvedType)dataType).setOwningType(plsqlRecordType); | |
} } | |
} | |
void fieldDefaultAssignment(): | |
{} | |
{ | |
( <O_ASSIGN> | <R_DEFAULT> ) skipToNextArg() | |
} | |
void subtypeDeclaration(PLSQLPackageType packageType) : | |
{String subtypeName; | |
DatabaseType subtype; | |
Token notNull = null; | |
Token rangeStart = null; | |
Token rangeEnd = null;} | |
{ | |
<R_SUBTYPE> subtypeName=OracleObjectName() <R_IS> subtype=typeSpec() | |
[ <K_RANGE> rangeStart=<S_NUMBER> <O_DOUBLEDOT> rangeEnd=<S_NUMBER> ] | |
[ <R_NOT> notNull=<R_NULL> ] <O_SEMICOLON> | |
{ | |
PLSQLSubType newPLSQLSubType = new PLSQLSubType(subtypeName); | |
newPLSQLSubType.setEnclosedType(subtype); | |
if (subtype instanceof UnresolvedType) { | |
((UnresolvedType)subtype).setOwningType(newPLSQLSubType); } | |
packageType.addType(newPLSQLSubType); | |
if (notNull != null) { | |
newPLSQLSubType.setNotNull(true); } | |
if (rangeStart != null) { | |
long rStart = Long.decode(rangeStart.image).longValue(); | |
long rEnd = Long.decode(rangeEnd.image).longValue(); | |
newPLSQLSubType.setHasRange(true); | |
newPLSQLSubType.setRangeStart(rStart); | |
newPLSQLSubType.setRangeEnd(rEnd); } | |
localTypes.put(subtypeName, newPLSQLSubType); | |
} | |
} | |
void plsqlTableDeclaration(PLSQLPackageType packageType, String typeName) : | |
{ | |
PLSQLCollectionType plsqlTable = new PLSQLCollectionType(typeName); | |
plsqlTable.setParentType(packageType); | |
DatabaseType nestedType; | |
} | |
{ | |
<R_TABLE> <R_OF> nestedType = typeSpec() [ <R_NOT> <R_NULL> ] | |
[ <R_INDEX> <R_BY> plsqlTableIndexByDeclaration(plsqlTable) ] | |
{ | |
if (nestedType instanceof UnresolvedType) { | |
((UnresolvedType)nestedType).setOwningType(plsqlTable); } | |
plsqlTable.setEnclosedType(nestedType); | |
packageType.addType(plsqlTable); | |
localTypes.put(typeName, plsqlTable); | |
} | |
} | |
void plsqlTableIndexByDeclaration(PLSQLCollectionType plsqlTable) : | |
{ | |
DatabaseType indexType = null; | |
Token precision = null; | |
Token otherIndexByType = null; | |
} | |
{ | |
( <K_PLS_INTEGER> {indexType = PLS_INTEGER_TYPE; } | |
| <K_BINARY_INTEGER> {indexType = BINARY_INTEGER_TYPE; } | |
| <K_VARCHAR2> <O_OPENPAREN> precision=<S_NUMBER> <O_CLOSEPAREN> | |
{ | |
if (precision == null) { | |
indexType = new VarChar2Type(); | |
} | |
else { | |
Long pl = Long.decode(precision.image); | |
indexType = new VarChar2Type(pl); | |
} | |
} | |
| otherIndexByType=<K_STRING> <O_OPENPAREN> <S_NUMBER> <O_CLOSEPAREN> | |
{ | |
String indexTypename = otherIndexByType.image; | |
for (String typeName : localTypes.keySet()) { | |
if (typeName.equals(indexTypename)) { | |
indexType = localTypes.get(indexTypename); | |
break; | |
} | |
} | |
//what else can INDEX BY be? Unresolved for now ... | |
if (indexType == null) { | |
indexType = new UnresolvedType(indexTypename); | |
((UnresolvedType)indexType).setOwningType(plsqlTable); | |
} | |
} | |
) | |
{ plsqlTable.setIndexed(true); | |
plsqlTable.setIndexType(indexType); | |
} | |
} | |
void varrayDeclaration(PLSQLPackageType packageType) : | |
{} | |
{ | |
( <K_VARRAY> | <K_VARYING> <K_ARRAY> ) <O_OPENPAREN> <S_NUMBER> <O_CLOSEPAREN> | |
<R_OF> datatype() [ <R_NOT> <R_NULL> ] | |
} | |
void refCursorDeclaration(PLSQLPackageType packageType, String cursorTypeName) : | |
{PLSQLCursorType cursorType = null;} | |
{ | |
<K_REF> <R_CURSOR> | |
{ | |
cursorType = new PLSQLCursorType(cursorTypeName); | |
packageType.addCursor(cursorType); | |
localTypes.put(cursorTypeName, cursorType); | |
} | |
[ refCursorTypeSpec(cursorType, packageType) ] | |
} | |
void refCursorTypeSpec(PLSQLCursorType cursorType, PLSQLPackageType packageType) : | |
{String s = null; | |
String spec = null; | |
boolean isTYPEType = false; | |
boolean isROWTYPEType = false; | |
DatabaseType localType = null; | |
} | |
{ | |
<K_RETURN> [LOOKAHEAD(3) spec=columnSpec() [ <R_ANCHORED_TYPE> | |
{ | |
isTYPEType = true; | |
s = spec + tokenImage[R_ANCHORED_TYPE].substring(1, tokenImage[R_ANCHORED_TYPE].length() - 1); | |
} | |
] | |
| LOOKAHEAD(3) spec=tableSpec() [ <R_ANCHORED_ROWTYPE> | |
{ | |
isROWTYPEType = true; | |
s = spec + tokenImage[R_ANCHORED_ROWTYPE].substring(1, tokenImage[R_ANCHORED_ROWTYPE].length() - 1); | |
} | |
] | |
] | |
{ | |
//check local variables first | |
for (FieldType varField : packageType.getLocalVariables()) { | |
if (spec.equals(varField.getFieldName())) { | |
if (isTYPEType) { | |
TYPEType tType = new TYPEType(s); | |
UnresolvedType uType = new UnresolvedType(s); | |
tType.setEnclosedType(uType); | |
uType.setOwningType(tType); | |
localType = tType; | |
} | |
else if (isROWTYPEType) { | |
ROWTYPEType rType = new ROWTYPEType(s); | |
UnresolvedType uType = new UnresolvedType(s); | |
rType.setEnclosedType(uType); | |
uType.setOwningType(rType); | |
localType = rType; | |
} | |
else { | |
localType = varField.getEnclosedType(); } | |
cursorType.setEnclosedType(localType); | |
break; | |
} | |
} | |
if (localType == null) { | |
localType = localTypes.get(spec); | |
if (localType == null) { | |
UnresolvedType uType = new UnresolvedType(spec); | |
if (isTYPEType) { | |
TYPEType tType = new TYPEType(s); | |
tType.setEnclosedType(uType); | |
uType.setOwningType(tType); | |
cursorType.setEnclosedType(tType); | |
} | |
else if (isROWTYPEType) { | |
ROWTYPEType rType = new ROWTYPEType(s); | |
rType.setEnclosedType(uType); | |
uType.setOwningType(rType); | |
cursorType.setEnclosedType(rType); | |
} | |
else { | |
uType.setOwningType(cursorType); | |
cursorType.setEnclosedType(uType); | |
} | |
} | |
else { | |
cursorType.setEnclosedType(localType); } | |
} } | |
} | |
void cursorDeclaration(PLSQLPackageType packageType) : | |
{Token t = null;} | |
{ | |
<R_CURSOR> t=<S_IDENTIFIER> <O_SEMICOLON> | |
} | |
// Procedure Specification | |
void procedureSpec(PLSQLPackageType packageType) : | |
{Token t = null; | |
ProcedureType procedureType = null; | |
} | |
{ | |
<R_PROCEDURE> t=<S_IDENTIFIER> { | |
procedureType = new ProcedureType(t.image); | |
procedureType.setCatalogName(packageType.getPackageName()); | |
procedureType.setSchema(packageType.getSchema()); } | |
[ <O_OPENPAREN> argumentList(procedureType) <O_CLOSEPAREN> ] | |
<O_SEMICOLON> | |
{ packageType.addProcedure(procedureType); | |
} | |
} | |
void argumentList(ProcedureType procedureType) : | |
{} | |
{ | |
argument(procedureType) ( <O_COMMA> argument(procedureType) )* | |
} | |
// Function Specification | |
void functionSpec(PLSQLPackageType packageType) : | |
{Token t = null; | |
FunctionType functionType = null; | |
ArgumentType returnDataType = null; | |
} | |
{ | |
<R_FUNCTION> t=<S_IDENTIFIER> | |
{ | |
functionType = new FunctionType(t.image); | |
functionType.setCatalogName(packageType.getPackageName()); | |
functionType.setSchema(packageType.getSchema()); | |
} | |
[ <O_OPENPAREN> argumentList(functionType) <O_CLOSEPAREN> ] | |
returnDataType = functionReturnSpec() | |
[ <K_DETERMINISTIC> | <K_PIPELINED> | <K_PARALLEL_ENABLE> | <K_RESULT_CACHE> ] | |
<O_SEMICOLON> | |
{ | |
functionType.setReturnArgument(returnDataType); | |
packageType.addProcedure(functionType); | |
} | |
} | |
ArgumentType functionReturnSpec(): | |
{DatabaseType dataType = null;} { (<K_RETURN> dataType=typeSpec()) | |
{ | |
ArgumentType returnType = new ArgumentType(null); | |
returnType.setDirection(ArgumentTypeDirection.RETURN); | |
returnType.setEnclosedType(dataType); | |
if (dataType instanceof UnresolvedType) { | |
((UnresolvedType)dataType).setOwningType(returnType); } | |
return returnType; | |
} | |
} | |
void argument(ProcedureType procedureType) : | |
{Token t = null; | |
ArgumentType argumentType = null; | |
DatabaseType argumentDataType = null; | |
ArgumentTypeDirection argDirection = ArgumentTypeDirection.IN; // by default, arguments are IN | |
String direction = null; | |
boolean defaultAssignment = false; | |
} | |
{ | |
t=<S_IDENTIFIER> [(direction=direction())] | |
[ <K_NOCOPY> ] argumentDataType=typeSpec() [ defaultAssignment=argumentDefaultAssignment() ] | |
{ | |
argumentType = new ArgumentType(t.image); | |
argumentType.setEnclosedType(argumentDataType); | |
if (argumentDataType instanceof UnresolvedType) { | |
((UnresolvedType)argumentDataType).setOwningType(argumentType); | |
} | |
if (direction != null) { | |
if ("OUT".equals(direction)) { | |
argDirection = ArgumentTypeDirection.OUT; | |
} | |
else if ("IN OUT".equals(direction)) { | |
argDirection = ArgumentTypeDirection.INOUT; } | |
argumentType.setDirection(argDirection); } if (defaultAssignment) { | |
argumentType.setOptional(); } | |
procedureType.addArgument(argumentType); | |
} | |
} | |
boolean argumentDefaultAssignment(): | |
{} | |
{ | |
( <O_ASSIGN> | <R_DEFAULT> ) skipToNextArg() | |
{ | |
return true; | |
} | |
} | |
void exceptionDeclaration(PLSQLPackageType packageType) : | |
{} | |
{ | |
<S_IDENTIFIER> <R_EXCEPTION> <O_SEMICOLON> | |
} | |
void pragmaDeclaration(PLSQLPackageType packageType) : | |
{} | |
{ <K_PRAGMA> | |
[ <K_AUTONOMOUS_TRANSACTION> | |
| <K_EXCEPTION_INIT> <O_OPENPAREN> <S_IDENTIFIER> <O_COMMA> <S_NUMBER> <O_CLOSEPAREN> | |
| <K_SERIALLY_REUSABLE> | |
| <K_INLINE> <O_OPENPAREN> <S_IDENTIFIER> <O_COMMA> [ <R_YES> | <R_NO> ] <O_CLOSEPAREN> | |
| <K_RESTRICT_REFERENCES> <O_OPENPAREN> [ <S_IDENTIFIER> | <R_DEFAULT> ] | |
( <O_COMMA> [ <K_RNDS> | <K_WNDS> | <K_RNPS> | <K_WNPS> | <K_TRUST>] )+ <O_CLOSEPAREN> | |
] | |
<O_SEMICOLON> | |
} | |
void orReplace(): | |
{ | |
} | |
{ | |
<R_OR> <K_REPLACE> | |
} | |
void invokerRights(): | |
{ | |
} | |
{ | |
<K_AUTHID> (<K_CURRENT_USER> | <K_DEFINER>) | |
} | |
void as(): | |
{ | |
} | |
{ | |
<R_AS> | <R_IS> | |
} | |
String direction(): | |
{String dir = ""; | |
} | |
{ | |
( | |
<R_IN> {dir = "IN";} [ <K_OUT> {dir += " OUT";} ] | |
| <K_OUT> {dir = "OUT";} | |
) | |
{ | |
return dir; | |
} | |
} | |
String OracleObjectName(): | |
{} | |
{ | |
<S_IDENTIFIER> {return token.image;} | |
| <S_QUOTED_IDENTIFIER> { return removeQuotes(token.image);} | |
} | |
void skipToSemiColon(): | |
{} | |
{ | |
{ | |
Token t = getNextToken(); | |
while (t.kind != O_SEMICOLON) { | |
t = getNextToken(); | |
} | |
token_source.input_stream.backup(1); | |
} | |
} | |
void skipToClosingParen(): | |
{} | |
{ | |
{ | |
Token t = getNextToken(); | |
while (t.kind != O_CLOSEPAREN) { | |
t = getNextToken(); | |
} | |
token_source.input_stream.backup(1); | |
} | |
} | |
void skipToNextArg(): | |
{} | |
{ | |
{ | |
Token t = getNextToken(); | |
while (t.kind != O_COMMA && t.kind != O_CLOSEPAREN) { | |
t = getNextToken(); | |
} | |
token_source.input_stream.backup(1); | |
} | |
} | |
void skipToEnd(): | |
{} | |
{ | |
{ | |
/** skip through all the tokens. */ | |
Token t = getNextToken(); | |
while (t.kind != EOF) { | |
t = getNextToken(); | |
} | |
} | |
} |