├── bin └── o2t.exe ├── lib ├── antlr-3.2.jar ├── antlrworks-1.4.jar ├── antlr-runtime-3.2.jar ├── tdwpl ├── tdw_loader.py ├── tdw.py └── tdw_sql_lib.py ├── run_antlrworks.sh ├── input ├── test1.sql ├── test2.sql └── test3.sql ├── Makefile ├── ANTLRNoCaseFileStream.java ├── README ├── output └── PLSQL.tokens ├── pl2py.java └── PLSQL.g /bin/o2t.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/macan/PL-SQL2Python/HEAD/bin/o2t.exe -------------------------------------------------------------------------------- /lib/antlr-3.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/macan/PL-SQL2Python/HEAD/lib/antlr-3.2.jar -------------------------------------------------------------------------------- /lib/antlrworks-1.4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/macan/PL-SQL2Python/HEAD/lib/antlrworks-1.4.jar -------------------------------------------------------------------------------- /lib/antlr-runtime-3.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/macan/PL-SQL2Python/HEAD/lib/antlr-runtime-3.2.jar -------------------------------------------------------------------------------- /run_antlrworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | java -jar -Xms256M -Xmx720M -XX:+UseParallelGC -XX:MinHeapFreeRatio=40 -XX:ParallelGCThreads=2 ./lib/antlrworks-1.4.jar pl2py.java 4 | -------------------------------------------------------------------------------- /input/test1.sql: -------------------------------------------------------------------------------- 1 | create or replace procedure output_date is 2 | 3 |   begin 4 | 5 |   dbms_output.put_line(sysdate); 6 | 7 |   end output_date; 8 | 9 |   create or replace procedure get_username(v_id in number,v_username out varchar2) 10 | 11 |   as 12 | 13 |   begin 14 | 15 |   select username into v_username from tab_user where id = v_id; 16 | 17 |   exception 18 | 19 |   when no_data_found then 20 | 21 |   raise_application_error(-20001,'ID不存在!'); 22 | 23 |   end get_username; -------------------------------------------------------------------------------- /lib/tdwpl: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "x$TDWPL_HOME" == "x" ]; then 4 | TDWPL_HOME=. 5 | fi 6 | 7 | PY_VERSION=`/usr/bin/env python -V 2>&1 | awk '{print $2}' | sed -e 's/\.//g'` 8 | PYV=`/usr/bin/env python -V 2>&1` 9 | 10 | if [ $PY_VERSION -gt 240 ]; then 11 | echo "Python version is OK." 12 | else 13 | echo "The TDW/PL lib and tool only works in Python 2.4.* and higher version" 14 | echo "Your version is ${PYV}" 15 | exit 16 | fi 17 | 18 | /usr/bin/env python ${TDWPL_HOME}/tdwpl.py $* 19 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | HOME = $(shell pwd) 2 | 3 | CP = $(HOME)/lib/antlr-3.2.jar:$(HOME)/lib/antlr-runtime-3.2.jar:$(HOME)/lib/antlrworks-1.4.jar 4 | 5 | all : 6 | CLASSPATH=$(CP) javac -d build output/*.java 7 | CLASSPATH=$(CP) javac -d build ANTLRNoCaseFileStream.java 8 | cd build; jar cvf plsql.jar org/plsql/*.class 9 | CLASSPATH=$(CP):build/plsql.jar javac -d build pl2py.java 10 | #cd build; echo "Main-Class: org.pl2py.pl2py" > manifest.txt 11 | #cd build; jar cvfm pl2py.jar manifest.txt org/ABC/*.class 12 | cd build; jar cvf pl2py.jar org/pl2py/*.class plsql.jar 13 | 14 | run : 15 | cd build; CLASSPATH=$(CP):plsql.jar:pl2py.jar java org.pl2py.pl2py ../input 16 | 17 | clean : 18 | rm -rf build/* 19 | -------------------------------------------------------------------------------- /input/test2.sql: -------------------------------------------------------------------------------- 1 | create or replace package body TestPackage is 2 | procedure UpdateRecords(id_in in number, newName in varchar2, newAge in number) as 3 | begin 4 | update test set age = newAge, name = newName where id = id_in; 5 | end UpdateRecords; 6 | 7 | procedure DeleteRecords(id_in in number) as 8 | begin 9 | delete from test where id = id_in; 10 | end DeleteRecords; 11 | 12 | procedure InsertRecords(name_in in varchar2, age_in in number) as 13 | begin 14 | insert into test values (test_seq.nextval, name_in, age_in); 15 | --test_seq是一个已建的Sequence对象,请参照前面的示例 16 | end InsertRecords; 17 | end TestPackage; 18 | -------------------------------------------------------------------------------- /ANTLRNoCaseFileStream.java: -------------------------------------------------------------------------------- 1 | package org.plsql; 2 | 3 | import java.io.IOException; 4 | 5 | import org.antlr.runtime.ANTLRFileStream; 6 | import org.antlr.runtime.CharStream; 7 | 8 | public class ANTLRNoCaseFileStream extends ANTLRFileStream { 9 | 10 | public ANTLRNoCaseFileStream(String fileName) throws IOException { 11 | super(fileName, null); 12 | } 13 | 14 | public ANTLRNoCaseFileStream(String fileName, String encoding) 15 | throws IOException { 16 | super(fileName, encoding); 17 | } 18 | 19 | public int LA(int i) { 20 | if ( i==0 ) { 21 | return 0; // undefined 22 | } 23 | if ( i<0 ) { 24 | i++; // e.g., translate LA(-1) to use offset 0 25 | } 26 | if ( (p+i-1) >= n ) { 27 | return CharStream.EOF; 28 | } 29 | 30 | return Character.toLowerCase(data[p+i-1]); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | * Project description 2 | 3 | This project provides a tool to transform Oracle PL/SQL package to python package, and a runtime library to simulate Oracle internal functions. 4 | 5 | * How to use it? 6 | 7 | o2t.exe [/path/to/oracle/plsql/script] 8 | 9 | The source scripts MUST have a suffix as ".sql", and the target python scripts are outputed in the same directory. For example, "ot2.txt c:\pkg-abc.sql" would output a python file named pkg-abc.py in "c:\". 10 | 11 | * Issues 12 | 13 | Right now, there is only a windows binary transformer(from Oracle PL/SQL to HiveQL) for you to evaluate. 14 | 15 | I will add the missing runtime libs in a few days. 16 | 17 | * Updates 18 | 19 | I have add the source code for o2t transformer. 20 | 21 | PLSQL.g is the core ANTLR code to parse plsql script to python script (target for Hive environment). Use run_antlrworks.sh to generate parser code in 'output' directory. 22 | 23 | ANTLRNoCaseFileStream.java and pl2py.java are wrappers for ANTLR generated classes. 24 | 25 | * How to Compile 26 | make 27 | make run 28 | 29 | Put your plsql code in 'input' directory. After you call 'make run', the generated python scripts are in 'result' directory. 30 | 31 | Contributed it and enjoy it, thank you! 32 | 33 | * Known Issues 34 | Cursor has not been well supported yet. 35 | -------------------------------------------------------------------------------- /output/PLSQL.tokens: -------------------------------------------------------------------------------- 1 | PACKAGE=117 2 | FUNCTION=8 3 | EXTERNAL=119 4 | EXPONENT=101 5 | WHILE=89 6 | DETERMINISTIC=36 7 | VARYING=26 8 | CASE=52 9 | DOUBLEDOT=67 10 | NOT=20 11 | SUBTYPE=24 12 | SQL=102 13 | RPAREN=12 14 | CREATE=116 15 | INSERT=80 16 | USING=63 17 | RETURNING=64 18 | PROMPT=138 19 | BEGIN=41 20 | LOOP=51 21 | SAVEPOINT=83 22 | RETURN=9 23 | BODY=118 24 | RAISE=75 25 | GEQ=95 26 | GOTO=70 27 | EQ=90 28 | DBMS=48 29 | SELECT=84 30 | ISOPEN=105 31 | INTO=60 32 | ARRAY=27 33 | DIVIDE=4 34 | EXCEPTION=23 35 | SPOOL=137 36 | RBRACK=129 37 | EXIT=57 38 | RECORD=25 39 | N=132 40 | TRANSACTION=86 41 | NULL=21 42 | ELSE=53 43 | AT_SIGN=128 44 | DEFINER=122 45 | DELETE=50 46 | DOUBLEVERTBAR=99 47 | ROLLBACK=82 48 | AUTHID=120 49 | NOCOPY=15 50 | WS=134 51 | LANGUAGE=123 52 | FETCH=58 53 | OUT=14 54 | REAL_NUMBER=107 55 | PIPELINED=37 56 | SL_COMMENT=135 57 | OR=44 58 | CONSTANT=22 59 | ELSIF=72 60 | END=42 61 | FALSE=109 62 | COLLECT=62 63 | CURSOR=18 64 | OTHERS=45 65 | LBRACK=130 66 | POINT=127 67 | CURRENT_USER=121 68 | LIMIT=59 69 | EXECUTE=49 70 | INSERTING=112 71 | GTH=94 72 | NOTFOUND=106 73 | PRAGMA=74 74 | RESULT_CACHE=39 75 | TABLE=29 76 | LLABEL=77 77 | UPDATE=87 78 | FOR=65 79 | ID=7 80 | AND=69 81 | ASTERISK=100 82 | LPAREN=10 83 | LOCK=81 84 | UPDATING=113 85 | IF=71 86 | RLABEL=78 87 | ML_COMMENT=136 88 | AS=40 89 | INDEX=30 90 | ROWTYPE=35 91 | IN=13 92 | THEN=46 93 | CONTINUE=55 94 | COMMA=11 95 | IS=19 96 | QUOTED_STRING=110 97 | PLUS=98 98 | EXISTS=111 99 | DOT=33 100 | ROWCOUNT=125 101 | LIKE=96 102 | INTEGER=103 103 | BY=31 104 | VARRAY=28 105 | PARALLEL_ENABLE=38 106 | PERCENT=34 107 | DOUBLEQUOTED_STRING=126 108 | MERGE=88 109 | DEFAULT=17 110 | FORALL=66 111 | SET=85 112 | MINUS=97 113 | TRUE=108 114 | SEMI=5 115 | PROCEDURE=6 116 | NOT_EQ=91 117 | REF=32 118 | VERTBAR=131 119 | LTH=92 120 | COLON=47 121 | OPEN=73 122 | BULK_ROWCOUNT=104 123 | COMMIT=79 124 | CLOSE=54 125 | WHEN=43 126 | FOUND=124 127 | ASSIGN=16 128 | NUMBER_VALUE=133 129 | IMMEDIATE=56 130 | ARROW=115 131 | DECLARE=76 132 | DELETING=114 133 | BULK=61 134 | BETWEEN=68 135 | LEQ=93 136 | -------------------------------------------------------------------------------- /pl2py.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2010,2011 Ma Can 3 | */ 4 | 5 | package org.pl2py; 6 | 7 | import java.io.File; 8 | 9 | import org.antlr.runtime.*; 10 | import org.plsql.*; 11 | 12 | public class pl2py { 13 | 14 | public static void main(String[] args) throws Exception { 15 | if (args.length < 1) { 16 | System.out.println("Usage: pl2py path/to/file"); 17 | System.exit(0); 18 | } 19 | String dir_name = args[0]; 20 | File myDir = new File(dir_name); 21 | File[] contents = myDir.listFiles(); 22 | int sql_rowcount = 0; 23 | int todo_count = 0; 24 | int row_count = 0; 25 | 26 | for(int i = 0; i < contents.length; i++) { 27 | // Create an input character stream from standard in 28 | ANTLRNoCaseFileStream input = new ANTLRNoCaseFileStream(dir_name + '/' + contents[i].getName()); 29 | 30 | // Create an ExprLexer that feeds from that stream 31 | PLSQLLexer lexer = new PLSQLLexer(input); 32 | 33 | // Create a stream of tokens fed by the lexer 34 | CommonTokenStream tokens = new CommonTokenStream(lexer); 35 | 36 | // Create a parser that feeds off the token stream 37 | System.out.print("Transform " + contents[i].getName() + " ...\n"); 38 | File Dir = new File(dir_name + "/../result/" + contents[i].getName().split("[.]")[0]); 39 | if(!Dir.exists()) 40 | Dir.mkdirs(); 41 | System.out.println(dir_name + "/../result/" + contents[i].getName().split("[.]")[0] + "/"); 42 | PLSQLParser parser = new PLSQLParser(tokens, dir_name + "/../result/" + contents[i].getName().split("[.]")[0] + "/", contents[i].getName().replace("sql", "py")); 43 | parser.sqlplus_file(); 44 | 45 | //System.out.print("row_count: " + lexer.row_count + '\n'); 46 | //System.out.print("todo_count: " + parser.todo_count + '\n'); 47 | //System.out.print("sql_rowcount: " + parser.sql_count + '\n'); 48 | row_count += lexer.row_count; 49 | todo_count += parser.todo_count; 50 | sql_rowcount += parser.sql_count; 51 | } 52 | System.out.print("Done" + '\n'); 53 | System.out.print("sql_rowcount:" + sql_rowcount + '\n'); 54 | System.out.print("todo_count:" + todo_count + '\n'); 55 | System.out.print("row_count:" + row_count + '\n'); 56 | double tis = (1.0 - Double.parseDouble(Integer.toString(todo_count)) / (row_count - sql_rowcount)) * 100; 57 | double tes = (Double.parseDouble(Integer.toString(sql_rowcount)) / (row_count)) * 100; 58 | System.out.println("All the SQL should be revised:"); 59 | System.out.println("\t1. Static SQL should be fixed for converting the variables in VALUES, WHERE."); 60 | System.out.println("\t2. Reference to DATE should be fixed."); 61 | System.out.print("SQL should be revised is " + 62 | tes + "%\n"); 63 | System.out.print("Transform Ratio (-SQL) is " + 64 | tis + "%\n"); 65 | } 66 | } 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /lib/tdw_loader.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | ''' Copyright (c) 2010 Ma Can 3 | 4 | This is the Server-Side job loader. 5 | ''' 6 | import sys, os 7 | import getopt 8 | 9 | sys.path.append("./lib/py/") 10 | 11 | from hive_service import ThriftHive 12 | from hive_service.ttypes import HiveServerException 13 | from thrift import Thrift 14 | from thrift.transport import TSocket 15 | from thrift.transport import TTransport 16 | from thrift.protocol import TBinaryProtocol 17 | 18 | import tdw 19 | 20 | def tdw_file_checking(fname): 21 | '''Do file checking''' 22 | f = open(fname, "r") 23 | for line in f.readlines(): 24 | # Ignore the import instruction now 25 | # if 'import' in line: 26 | # raise IOError(-1, "'import' is NOT allowed in the TDW/PL code.") 27 | if 'os.kill' in line: 28 | raise IOError(-1, "'os.kill' is NOT allowed in the TDW/PL code.") 29 | if 'os.rmdir' in line: 30 | raise IOError(-1, "'os.rmdir' is NOT allowed in the TDW/PL code.") 31 | f.close() 32 | 33 | def main(argv): 34 | '''Main loader''' 35 | try: 36 | opts, args = getopt.getopt(argv, 37 | "d:f:s:a:u:p:x:j:t:", 38 | ["file=", "session=", "authid=", "user=", 39 | "passwd=", "path=", "jobid=", "dbname=", 40 | "port="]) 41 | except getopt.GetoptError: 42 | sys.exit() 43 | fname = None 44 | sid = None 45 | svid = None 46 | path = None 47 | jobid = None 48 | dbname = None 49 | port = None 50 | for opt, arg in opts: 51 | if opt in ("-f", "--file"): 52 | fname = arg 53 | elif opt in ("-s", "--session"): 54 | sid = arg 55 | elif opt in ("-a", "--authid"): 56 | svid = arg 57 | elif opt in ("-u", "--user"): 58 | user = arg 59 | elif opt in ("-p", "--passwd"): 60 | passwd = arg 61 | elif opt in ("-x", "--path"): 62 | path = arg 63 | elif opt in ("-j", "--jobid"): 64 | jobid = arg 65 | elif opt in ("-d", "--dbname"): 66 | dbname = arg 67 | elif opt in ("-t", "--port"): 68 | port = arg 69 | 70 | # Check the file 71 | try: 72 | print "Checking TDW/PL code from file '%s'" % (path + fname) 73 | tdw_file_checking(path + fname + ".py") 74 | except IOError, ie: 75 | print "PL checking error(%d) %s" % (ie.errno, ie.strerror) 76 | return 77 | 78 | # ok, we will just create another connection and attache to the created 79 | # session 80 | sys.path.append("./pl/lib/" + user) 81 | sys.path.append("./pl/lib/") 82 | sys.path.append("./pl/lib/global") 83 | print "Module : %s, sid : %s, dbname %s" % (fname, sid, dbname) 84 | module = __import__(fname) 85 | string = "ok" 86 | 87 | try: 88 | transport = TSocket.TSocket('localhost', port) 89 | transport = TTransport.TBufferedTransport(transport) 90 | protocol = TBinaryProtocol.TBinaryProtocol(transport) 91 | 92 | client = ThriftHive.Client(protocol) 93 | transport.open() 94 | 95 | res = client.audit(user, passwd, dbname) 96 | if str(res) == "": 97 | string = "failed" 98 | print "Audit: " + string 99 | if str(res) == "": 100 | sys.exit() 101 | 102 | res = client.requireSession(sid, svid) 103 | if str(res) == "": 104 | string = "failed" 105 | print "Require Session: " + sid + " " + string 106 | if str(res) == "": 107 | sys.exit() 108 | 109 | print "Session " + sid + " " + jobid 110 | res = client.setHistory(sid, int(jobid)) 111 | 112 | module.TDW_PL(tdw.TDW(client)) 113 | 114 | # detach the session and exit 115 | client.detachSession(sid, svid) 116 | if str(res) == "": 117 | string = "failed" 118 | print "Detach Session: " + sid + " " + string 119 | if str(res) == "": 120 | sys.exit() 121 | 122 | transport.close() 123 | except Thrift.TException, tx: 124 | print '%s' % (tx.message) 125 | 126 | if __name__ == '__main__': 127 | main(sys.argv[1:]) 128 | -------------------------------------------------------------------------------- /lib/tdw.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ Copyright (c) 2010 Ma Can 3 | 4 | This is the core TDW runtime library, enjoy it :) 5 | """ 6 | 7 | import sys, re 8 | 9 | from hive_service import ThriftHive 10 | from hive_service.ttypes import HiveServerException 11 | from thrift import Thrift 12 | from thrift.transport import TSocket 13 | from thrift.transport import TTransport 14 | from thrift.protocol import TBinaryProtocol 15 | 16 | from array import * 17 | 18 | def to_type(line, t): 19 | '''Type conversion''' 20 | if t == 'int': 21 | return int(line) 22 | elif t == 'bigint': 23 | return long(line) 24 | elif t == 'array': 25 | line = line.strip(" ") 26 | line = line.strip("[") 27 | line = line.rstrip(" ") 28 | line = line.rstrip("]") 29 | l = line.split(",") 30 | for i in range(0, len(l)): 31 | if l[i] == "": 32 | return array('i') 33 | else: 34 | l[i] = int(l[i]) 35 | return array('i', l) 36 | elif t == 'string': 37 | return str(line) 38 | 39 | class dynamic_type: 40 | '''Dynamic Type Support''' 41 | pass 42 | 43 | class TDW: 44 | '''This is the runtime TDW class.''' 45 | running = True 46 | 47 | def __init__(self, client=None): 48 | '''do init job''' 49 | self.cli = client 50 | 51 | def do_exit(self): 52 | '''begin to exit''' 53 | self.running = False 54 | 55 | def execute(self, query): 56 | '''Execute a SQL query and return the result LIST[0:]''' 57 | if self.running: 58 | self.cli.execute(query) 59 | return self.cli.fetchAll() 60 | else: 61 | raise IOError (-2, "Interrupted by the caller.") 62 | 63 | def execute2int(self, query): 64 | '''Execute a SQL query and return a INT result''' 65 | try: 66 | if self.running: 67 | self.cli.execute(query) 68 | else: 69 | raise IOError (-2, "Interrupted by the caller.") 70 | except KeyboardInterrupt: 71 | print "Recv KeyboardInterrupt, please wait for this SQL execution" 72 | self.do_exit() 73 | self.cli.recv_execute() 74 | 75 | try: 76 | res = self.cli.fetchAll() 77 | return int(res[0]) 78 | except TypeError, e : 79 | print "Result '%s' to INT failed %s" % (res[0], e.message) 80 | raise IOError (-3, "Result type transform to INT failed, " 81 | "TypeError.") 82 | except ValueError : 83 | print "Result '%s' to INT failed, ValueError" % res[0] 84 | raise IOError (-3, "Result type transform to INT failed, " 85 | "ValueError.") 86 | except KeyboardInterrupt: 87 | print "Recv KeyboardInterrupt, your client should be reset." 88 | self.do_exit() 89 | 90 | def execute2str(self, query): 91 | '''Execute a SQL query and return a STRING (LIST[0])''' 92 | try: 93 | if self.running: 94 | self.cli.execute(query) 95 | else: 96 | raise IOError (-2, "Interrupted by the caller.") 97 | except KeyboardInterrupt: 98 | print "Recv KeyboardInterrupt, please wait for this SQL execution" 99 | self.do_exit() 100 | self.cli.recv_execute() 101 | 102 | try: 103 | res = self.cli.fetchAll() 104 | return str(res[0]) 105 | except TypeError, e: 106 | print "Result '%s' to STRING failed %s" % (res[0], e.message) 107 | raise IOError (-3, "Result type transform to STRING failed, " 108 | "TypeError.") 109 | except ValueError : 110 | print "Result '%s' to STRING failed" % res[0] 111 | raise IOError (-3, "Result type transform to STRING failed, " 112 | "ValueError.") 113 | except KeyboardInterrupt: 114 | print "Recv KeyboardInterrupt, your client should be reset." 115 | self.do_exit() 116 | 117 | def printf(self, string, res): 118 | '''Print the result in a formated manner''' 119 | try: 120 | if (type(res) == type(str())): 121 | print string + " " + res 122 | elif (type(res) == type(list())): 123 | print "Q: '" + string + "' |=> '" + " ".join(res) + "'" 124 | elif (type(res) == type(int())): 125 | print string + " " + str(res) 126 | elif (type(res) == type(None)): 127 | print "Argument is Not A Type." 128 | except ValueError : 129 | print "printf convert STRING failed" 130 | raise IOError (-3, "printf convert STRING failed, ValueError.") 131 | 132 | def result_str(self, res): 133 | '''Convert a SQL result to a STRING''' 134 | try: 135 | __res = str(res) 136 | except: 137 | return None 138 | return __res 139 | 140 | def result_list(self, res): 141 | '''Convert a SQL result to a LIST''' 142 | try: 143 | __res = list(res) 144 | except: 145 | return None 146 | return __res 147 | 148 | def result_int(self, res): 149 | '''Convert a SQL result to a INT''' 150 | try: 151 | __res = int(res) 152 | except: 153 | return None 154 | return __res 155 | 156 | def uploadJob(self, fname): 157 | '''Upload a job file to server''' 158 | print "Tring to upload Job '%s' ..." % (fname) 159 | read_data = "" 160 | try: 161 | f = open(fname, "r") 162 | read_data = f.read() 163 | f.close() 164 | except IOError, ie: 165 | print "IOError %s" % ie 166 | return 167 | 168 | if read_data == "": 169 | print "[WARN] Read file '" + fname + "' w/ ZERO content." 170 | # ok to upload the file to hiveserver 171 | self.cli.uploadJob(read_data) 172 | 173 | def getschema(self): 174 | '''Get the Hive Schema from the server''' 175 | try: 176 | if self.running: 177 | return str(self.cli.getSchema()) 178 | else: 179 | raise IOError (-2, "Interrupted by the caller.") 180 | except KeyboardInterrupt: 181 | print "Recv KeyboardInterrupt, please wait for get schema" 182 | self.do_exit() 183 | self.cli.recv_getSchema() 184 | 185 | def getschemax(self): 186 | '''Get the SQL schema info the the Hive Scheme''' 187 | try: 188 | if self.running: 189 | schema_string = str(self.cli.getSchema()) 190 | else: 191 | raise IOError (-2, "Interrupted by the caller.") 192 | except KeyboardInterrupt: 193 | print "Recv KeyboardInterrupt, please wait for get schema" 194 | self.do_exit() 195 | self.cli.recv_getSchema() 196 | return 197 | 198 | # Parse the schema_string 199 | m = re.findall("name='[^']*", schema_string) 200 | for i in range(0, len(m)): 201 | m[i] = m[i].replace("name='", "") 202 | return m 203 | 204 | def gettypex(self): 205 | '''Get the SQL type info from the Hive Schema''' 206 | try: 207 | if self.running: 208 | schema_string = str(self.cli.getSchema()) 209 | else: 210 | raise IOError (-2, "Interrupted by the caller.") 211 | except KeyboardInterrupt: 212 | print "Recv KeyboardInterrupt, please wait for get schema" 213 | self.do_exit() 214 | self.cli.recv_getSchema() 215 | return 216 | 217 | # Parse the schema_string 218 | m = re.findall("type='[^']*", schema_string) 219 | for i in range(0, len(m)): 220 | m[i] = m[i].replace("type='", "") 221 | return m 222 | 223 | def parseschema(self, dict, sql_result): 224 | '''Parse the SQL result list to a list of lists based on the 'type' 225 | and 'schema' info in DICT''' 226 | if sql_result == "" or sql_result == None: 227 | return list() 228 | if type(sql_result) != type(list()): 229 | return list() 230 | 231 | result_list = list() 232 | column_list = dict['schema'] 233 | type_list = dict['type'] 234 | for i in range(0, len(sql_result)): 235 | if sql_result[i] == "": 236 | continue 237 | new_object = dynamic_type() 238 | sql_line = sql_result[i].split("\t") 239 | for j in range(0, len(column_list)): 240 | setattr(new_object, column_list[j], to_type(sql_line[j], 241 | type_list[j])) 242 | result_list.append(new_object) 243 | 244 | return result_list 245 | 246 | def tdw_getrowcount(self): 247 | '''Get the rowcount from server. The same as %rowcount''' 248 | try: 249 | if self.running: 250 | rc = self.cli.getrowcount() 251 | else: 252 | raise IOError (-2, "Interrupt by the caller.") 253 | except TypeError, e: 254 | print "TypeError %s" % e 255 | raise IOError (-2, "%s" % e) 256 | except KeyboardInterrupt, e: 257 | print "Recv KeyboardInterrupt, your client should be reset." 258 | self.do_exit() 259 | raise IOError (-2, "%s" % e) 260 | 261 | return long(rc) 262 | 263 | def tdw_raise(self, errno=None, strerror=None): 264 | '''Raise a TDW/PL exception (IOError actually)''' 265 | if type(errno) != type(int()): 266 | errno = -1 267 | if type(strerror) != type(str()): 268 | strerror = "TDW/PL default exception." 269 | raise IOError(errno, strerror) 270 | -------------------------------------------------------------------------------- /input/test3.sql: -------------------------------------------------------------------------------- 1 | /* Formatted on 2002/08/10 09:24 (Formatter Plus v4.7.0) */ 2 | /**************************************************************************************** 3 | Author : Venky Mangapillai 4 | Created : Mar'2002 5 | Description : Example test pcakage to test MYBOOKS_PKG package using UTPLSQL 6 | Prerequests : Run the mybooks_setup.sql 7 | ****************************************************************************************/ 8 | /* --------------------------------------------------------------------------------- 9 | This is the test package for the MYBOOKS_PKG package. 10 | The test package name should be prefix with "ut_" before the real package name" 11 | e.g "UT_MYBOOKS_PKG" is test package for "MYBOOKS_PKG" 12 | Here we are going to test the each procedure/function in MYBOOKS_PKG. 13 | MYBOOKS_PKG package contains the following methods 14 | FUNCTION sel_book_func(bookid number) return mybooks_rec; 15 | PROCEDURE sel_book_proc(bookid number, rc OUT mybooks_rec); 16 | FUNCTION sel_booknm(bookid number) return varchar2; 17 | PROCEDURE ins(bookid number, booknm varchar2,publishdt date); 18 | PROCEDURE upd(bookid number, booknm varchar2,publishdt date); 19 | PROCEDURE del(bookid number); 20 | Now we are going to test every function/procedure in MYBOOKS_PKG. Before that let's remember, 21 | all the test procedure should start with "ut_" also. But need not end with with function/procedure name. 22 | e.g you can name the test procedure as "ut_sel_book_func" or "ut_something" for procedure "sel_book_func". 23 | But it is good practice to have the procedure name as test procedure. 24 | Function/procedure can have many test procedures. e.g ut_sel_book_func can have two test procedures like 25 | ut_sel_book_func_1 and ut_sel_book_func_2. 26 | Basically the UTPLSQL tool take all the function/procedures in test packages and run one by one starting 27 | with "ut_setup" and ending with "ut_teardown" in the alphabetical order. 28 | So the test procedures are 29 | PROCEDURE ut_2_sel_book_func; 30 | PROCEDURE ut_3_sel_book_proc; 31 | PROCEDURE ut_4_sel_booknm; 32 | PROCEDURE ut_1_ins 33 | PROCEDURE ut_5_upd 34 | PROCEDURE ut_6_del 35 | plus 36 | PROCEDURE ut_setup -- to setup the test data. 37 | PROCEDURE ut_teardown -- to clean up the test data. 38 | Here I used nunber 1,2,3.. after the "ut_". This is because I wanted the INS function to go first 39 | before the DEL function. Otherwise DEL will get tested first and it will end up FAILURE. 40 | This is one way to force the order of test procedure executions. If you are not 41 | worried about the order you don't have to follow this. One more reason I needed here is because 42 | I am using the same test record. Some tester use different test records for diffrent test procedures. 43 | In that case you don't have to worry about the order. I did't the numbering for the ut_setup and ut_teardown 44 | because ut_setup always gets executed first and ut_teardown always get executed last. Even if the test case fails 45 | ut_teardown gets executed. 46 | Using these test procedures I will show how most of the assertion methods getting used. 47 | Sounds interesting. Isn't it? 48 | So lets get started writing the test package. 49 | --------------------------------------------------------------------------------------*/ 50 | -- As I mentioned earlier the test package whoud be prefixed with "ut_". 51 | CREATE OR REPLACE PACKAGE ut_mybooks_pkg 52 | IS 53 | -- Also the test procedures in the test package 54 | PROCEDURE ut_setup; 55 | PROCEDURE ut_teardown; 56 | PROCEDURE ut_2_sel_book_func; 57 | PROCEDURE ut_3_sel_book_proc; 58 | PROCEDURE ut_4_sel_booknm; 59 | PROCEDURE ut_1_ins; 60 | PROCEDURE ut_5_upd; 61 | PROCEDURE ut_6_del; 62 | END; 63 | / 64 | CREATE OR REPLACE PACKAGE BODY ut_mybooks_pkg 65 | IS -- package body 66 | -- Here is my test record. 67 | bookid INTEGER := 100; 68 | booknm VARCHAR2 (30) := 'American History-Vol1'; 69 | publishdt DATE := '05-JAN-2002'; 70 | /* -------------------------------------------------- 71 | UT_SETUP : setup the test data here. This is first 72 | procedure gets executed automatically 73 | ----------------------------------------------------- */ 74 | PROCEDURE ut_setup 75 | IS 76 | BEGIN 77 | ut_teardown; -- drop the temp tables even though it should be there. Just extract caution 78 | -- "mybooks_part" table contains test record which we are going to test. 79 | -- I am using 8i syntax. Change needed for 8.0 databases 80 | EXECUTE IMMEDIATE 'create table mybooks_part as select * from mybooks where rownum < 1'; 81 | EXECUTE IMMEDIATE 'insert into mybooks_part values (:bookid,:booknm,:publishdt)' 82 | USING bookid, booknm, publishdt; 83 | END; 84 | /* -------------------------------------------------- 85 | UT_TEARDOWN : clean you data here. This is the last 86 | procedure gets executed automatically 87 | ----------------------------------------------------- */ 88 | PROCEDURE ut_teardown 89 | IS 90 | BEGIN 91 | EXECUTE IMMEDIATE 'drop table mybooks_part'; -- Drop the temporary test table after the test 92 | DELETE FROM mybooks 93 | WHERE book_id = bookid; --Delete the test record after the test 94 | EXCEPTION 95 | WHEN OTHERS 96 | THEN 97 | NULL; -- Ignore if any errors. 98 | END; 99 | /* --------------------------------------------------------------------- 100 | FUNCTION mybooks_pkg.sel_book_func( 101 | bookid IN NUMBER, 102 | RETURN REFCURSOR 103 | Assertion methods used : EQ_REFC_TABLE, EQ_REFC_QUERY 104 | /* -------------------------------------------------------------------- */ 105 | PROCEDURE ut_2_sel_book_func 106 | IS 107 | proc_params utplsql_util.utplsql_params; 108 | BEGIN 109 | -- Register the parameters 110 | -- IMPORTANT: The position starts with 0 for functions. For procedures it starts with 1 111 | utplsql_util.reg_out_param (0, 'REFCURSOR', proc_params); 112 | utplsql_util.reg_in_param (1, 100, proc_params); 113 | -- Test the sel_book_func function. It compares the refcursor with mybooks_part table. 114 | -- Here we expect the refcursor should return the records for the bookid=1. mybooks_part table 115 | -- has bookid=1 record in it which we setup in the ut_setup procedure. 116 | -- If rows matched then it results in SUCCESS otherwise FAILURE. 117 | -- If SUCCESS then sel_book_func fuction behaves as we expected. 118 | utassert.eq_refc_table ( 119 | 'sel_book_func-1', 120 | 'mybooks_pkg.sel_book_func', 121 | proc_params, 122 | 0, 123 | 'mybooks_part' 124 | ); 125 | -- Other ways to test this 126 | utassert.eq_refc_query ( 127 | 'sel_book_func-2', 128 | 'mybooks_pkg.sel_book_func', 129 | proc_params, 130 | 0, 131 | 'select * from mybooks_part' 132 | ); 133 | END; 134 | /* --------------------------------------------------------------------- 135 | PROCEDURE mybooks_pkg.sel_book_proc( 136 | bookid IN NUMBER, 137 | mybooks_rec OUT REFCURSOR) 138 | Assertion methods used : EQ_REFC_TABLE, EQ_REFC_QUERY 139 | /* -------------------------------------------------------------------- */ 140 | PROCEDURE ut_3_sel_book_proc 141 | IS 142 | proc_params utplsql_util.utplsql_params; 143 | BEGIN 144 | -- This procedure I used this because I want to show how to handle the refcursor as OUT parameter 145 | -- Register the parameters 146 | -- IMPORTANT: The position starts with 0 for functions. For procedures it starts with 1 147 | utplsql_util.reg_in_param (1, 100, proc_params); 148 | utplsql_util.reg_out_param (2, 'REFCURSOR', proc_params); 149 | utassert.eq_refc_table ( 150 | 'sel_book_proc-1', 151 | 'mybooks_pkg.sel_book_proc', 152 | proc_params, 153 | 2, 154 | 'mybooks_part' 155 | ); 156 | -- Other ways to test this 157 | utassert.eq_refc_query ( 158 | 'sel_book_proc-2', 159 | 'mybooks_pkg.sel_book_proc', 160 | proc_params, 161 | 2, 162 | 'select * from mybooks_part' 163 | ); 164 | END; 165 | /* -------------------------------------------------- 166 | EQ : FUNCTION sel_booknm ( 167 | bookid IN NUMBER, 168 | ) RETRUN VARCHAR2 169 | Assertion methods used : EQ 170 | ----------------------------------------------------- */ 171 | PROCEDURE ut_4_sel_booknm 172 | IS 173 | BEGIN 174 | -- We expect "American History-Vol1 " from the sel_booknm(100) function. 175 | utassert.eq ('sel_booknm-1', booknm, mybooks_pkg.sel_booknm (bookid)); -- Success 176 | END; 177 | /* -------------------------------------------------- 178 | PROCEDURE ins ( 179 | bookid IN NUMBER, 180 | booknm IN VARCHAR2, 181 | publishdt DATE 182 | ) 183 | Assertion methods used : EQ , EQTABCOUNT, EQQUERYVALUE, EQQUERY, THROWS 184 | ----------------------------------------------------- */ 185 | PROCEDURE ut_1_ins 186 | IS 187 | BEGIN 188 | -- Call the INS function. 189 | mybooks_pkg.ins (bookid, booknm, publishdt); 190 | -- Check if the row inserted successfully 191 | utassert.eq ('ins-1-4', booknm, mybooks_pkg.sel_booknm (bookid)); 192 | --Other ways to check row inserted successfully and many more ways 193 | utassert.eqqueryvalue ( 194 | 'ins-2', 195 | 'select count(*) from mybooks where book_id=' || TO_CHAR (bookid), 196 | 1 197 | ); 198 | utassert.eqqueryvalue ( 199 | 'ins-3', 200 | 'select book_nm from mybooks where book_id=' || bookid, 201 | booknm 202 | ); 203 | utassert.eqquery ( 204 | 'ins-4', 205 | 'select * from mybooks where book_id=' || bookid, 206 | 'select * from mybooks_part' 207 | ); 208 | -- Lets try the THROWS assertion method here. 209 | -- If I insert the same bookid again I should get PRIMARY KEY violation error (ERRORCODE=-1 in oracle) 210 | -- Here is the I am looking for "-1". If I get "-1" then SUCCESS otherwise FAIL 211 | utassert.throws ( 212 | 'ins-5', 213 | 'mybooks_pkg.ins(' || bookid || ',''Something'',sysdate)', 214 | -1 215 | ); 216 | END; 217 | /* -------------------------------------------------- 218 | PROCEDURE upd ( 219 | bookid IN NUMBER, 220 | booknm IN VARCHAR2, 221 | publishdt DATE 222 | ) 223 | Assertion methods used : EQ 224 | ----------------------------------------------------- */ 225 | PROCEDURE ut_5_upd 226 | IS 227 | BEGIN 228 | booknm := 'American History-Vol2'; -- new values 229 | publishdt := '06-JAN-2002'; 230 | -- Call the INS function. 231 | mybooks_pkg.upd (bookid, booknm, publishdt); 232 | -- Check if the row inserted successfully 233 | utassert.eq ('ut_upd-1', booknm, mybooks_pkg.sel_booknm (bookid)); 234 | END; 235 | /* -------------------------------------------------- 236 | PROCEDURE del ( 237 | bookid IN NUMBER 238 | ) 239 | Assertion methods used : EQQUERY, THROWS 240 | ----------------------------------------------------- */ 241 | PROCEDURE ut_6_del 242 | IS 243 | ret_val VARCHAR2 (30); 244 | BEGIN 245 | -- Call the DEL function. 246 | DBMS_OUTPUT.put_line ('Id=' || TO_CHAR (bookid)); 247 | mybooks_pkg.del (bookid); 248 | -- Check if the row deleted successfully 249 | utassert.eqqueryvalue ( 250 | 'ut_del-1', 251 | 'select count(*) from mybooks where book_id=100', 252 | 0 253 | ); 254 | -- Other ways to test 255 | --utassert.throws('ut_del-2','v_dummy := mybooks_pkg.sel_booknm(100)',100); -- 100 is "NO DATA FOUND" 256 | -- here is another way 257 | BEGIN 258 | ret_val := mybooks_pkg.sel_booknm (100); 259 | EXCEPTION 260 | WHEN NO_DATA_FOUND 261 | THEN 262 | NULL; 263 | WHEN OTHERS 264 | THEN 265 | utassert.eq ('ut_del-3', 1, 2); -- Forced to fail 1<>2 266 | END; 267 | END; 268 | END; 269 | -- End of test package 270 | / 271 | CREATE PUBLIC SYNONYM ut_mybooks_pkg for ut_mybooks_pkg 272 | / 273 | GRANT execute on ut_mybooks_pkg to public 274 | / 275 | show errors 276 | /* -------------------------------------------------------------------------- 277 | This is how you will run the test packages 278 | -----------------------------------------------------------------------------*/ 279 | set SERVEROUTPUT ON size 1000000 280 | REM exec utplsql.notrc 281 | spool trc 282 | BEGIN 283 | utplsql.test ('MYBOOKS_PKG'); 284 | DBMS_OUTPUT.put_line (utplsql2.runnum); 285 | END; 286 | / 287 | REM spool off 288 | /* --------------------------------------------------------------------------- 289 | Now we are done and have wonderfull unit testing using UTPLSQL 290 | -----------------------------------------------------------------------------*/ 291 | -------------------------------------------------------------------------------- /lib/tdw_sql_lib.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2010 Ma Can 3 | roachxiang 4 | 5 | This is the TDW SQL Library. We supply the following functions 6 | for our user. 7 | """ 8 | 9 | import time 10 | import datetime 11 | import math 12 | import calendar 13 | import tdw_sql_lib 14 | 15 | # String Functions: 16 | def nvl(tdw, string, replace_with): 17 | '''Fully support Oracle NVL''' 18 | if string is None: 19 | return replace_with 20 | 21 | def nvl2(tdw, string, value_if_not_null, value_if_null): 22 | '''Fully support Oracle NVL2''' 23 | if string is None: 24 | return value_if_null 25 | else: 26 | return value_if_not_null 27 | 28 | def substr(tdw, string, start_position, leng = 65535): 29 | '''Fully support Oracle PL/SQL substr''' 30 | if string is None: 31 | return None 32 | 33 | #for PL/SQL string start with positon 1, treats 0 as 1 34 | if start_position > 0: 35 | start_position -= 1 36 | if start_position < 0: 37 | start_position += len(string) 38 | 39 | #for PL/SQL if length <= 0 ,return NULL 40 | if leng <= 0: 41 | return None 42 | elif leng > len(string): 43 | return string[start_position:] 44 | else: 45 | if leng < 65535: 46 | end_position = start_position + leng 47 | return string[start_position:end_position] 48 | else: 49 | return string[start_position:] 50 | 51 | # API Has changed from Oracle 10g (trim, ltrim, rtrim) 52 | def ltrim(tdw, old_str, ch = None): 53 | '''LTRIM is changed from Oracle''' 54 | if ch != None: 55 | return old_str.lstrip(ch) 56 | else: 57 | return old_str.lstrip() 58 | 59 | def rtrim(tdw, old_str, ch = None): 60 | '''RTRIM is changed from Oracle''' 61 | if ch != None: 62 | return old_str.rstrip(ch) 63 | else: 64 | return old_str.rstrip() 65 | 66 | def trim(tdw, old_str, ch = None): 67 | '''TRIM is changed from Oracle''' 68 | old_str = ltrim(old_str, ch) 69 | return rtrim(old_str, ch) 70 | 71 | def length(tdw, string): 72 | '''Fully support Oracle LENGTH''' 73 | if string == None or string == "": 74 | return None 75 | return len(string) 76 | 77 | def upper(tdw, string): 78 | '''Fully support Oracle UPPER''' 79 | return string.upper() 80 | 81 | def lower(tdw, string): 82 | '''Fully support Oracle LOWER''' 83 | return string.lower() 84 | 85 | def instr(tdw, srcstr, sub_str, start = 0, nth = 1): 86 | '''Fully support Oracle INSTR''' 87 | reset = 0 88 | if start < 0: 89 | start += len(srcstr) 90 | reset = 1 91 | 92 | while nth > 0: 93 | start = srcstr.find(sub_str, start) 94 | start += 1 95 | if start == 0 and reset == 1: 96 | nth += 1 97 | nth -= 1 98 | return start 99 | 100 | def replace(tdw, src, to_replace, replacement = ""): 101 | '''Fully support Oracle REPLACE''' 102 | return src.replace(to_replace, replacement) 103 | 104 | # Conversion Functions: 105 | def to_number(tdw, uinput, uformat = None): 106 | '''TO_NUMBER changed from Oracle TO_NUMBER''' 107 | try: 108 | if uinput.find('.') == -1: 109 | if uinput.isdigit() is True or uinput[0] == '+' or uinput[0] == '-': 110 | return int(uinput) 111 | else: 112 | print "Invalid number format!" 113 | return None 114 | else: 115 | return float(uinput) 116 | except ValueError, ve: 117 | print ve 118 | return None 119 | 120 | def to_char(tdw, uinput, uformat = None): 121 | '''TO_CHAR changed from Oracle TO_CHAR''' 122 | if isinstance(uinput, Dateclass): 123 | return to_char_date(uinput, uformat) 124 | else: 125 | try: 126 | if uformat == None or uformat == "": 127 | return uinput 128 | uinput = str(uinput) 129 | ret = "" 130 | i = 0 131 | j = 0 132 | has_digit = 0 133 | while i < len(uformat): 134 | if uformat[i] == '9': 135 | ret += uinput[j] 136 | i += 1 137 | j += 1 138 | elif uformat[i] == '0': 139 | if has_digit == 1: 140 | ret += uinput[j] 141 | j += 1 142 | else: 143 | ret += "0" 144 | i += 1 145 | elif uformat[i] == '.': 146 | if uinput[j] != '.': 147 | print "Value and format mismatch!" 148 | return None 149 | ret += uinput[j] 150 | i += 1 151 | j += 1 152 | has_digit = 1 153 | else: 154 | ret += uformat[i] 155 | i += 1 156 | except IndexError, ie: 157 | print ie 158 | return None 159 | 160 | return ret 161 | 162 | # Math Functions 163 | def mod(tdw, m, n): 164 | '''MOD changed from Oracle MOD''' 165 | return math.fmod(m, n) 166 | 167 | def tdw_abs(tdw, number): 168 | '''Python build-in function abs''' 169 | return abs(number) 170 | 171 | def floor(tdw, number): 172 | '''Python build-in function floor''' 173 | return math.floor(number) 174 | 175 | def ln(tdw, number): 176 | '''Python build-in function log''' 177 | return math.log(number) 178 | 179 | def acos(tdw, number): 180 | '''Python build-in function acos''' 181 | return math.acos(number) 182 | 183 | def sin(tdw, number): 184 | '''Python build-in function sin''' 185 | return math.sin(number) 186 | 187 | def sinh(tdw, number): 188 | '''Python build-in function sinh''' 189 | return math.sinh(number) 190 | 191 | def cos(tdw, number): 192 | '''Python build-in function cos''' 193 | return math.cos(number) 194 | 195 | def cosh(tdw, number): 196 | '''Python build-in function cosh''' 197 | return math.cosh(number) 198 | 199 | def tan(tdw, number): 200 | '''Python build-in function tan''' 201 | return math.tan(number) 202 | 203 | def tanh(tdw, number): 204 | '''Python build-in function tanh''' 205 | return math.tanh(number) 206 | 207 | # round function is a python built-in function! 208 | def tdw_round(tdw, number, dp = 0): 209 | '''Python build-in function round''' 210 | return round(number, dp) 211 | 212 | def power(tdw, m, n): 213 | '''Python build-in function math.pow''' 214 | return math.pow(m, n) 215 | 216 | def trunc_number(tdw, f, n = 0): 217 | '''Internal NUMBER TRUNC function''' 218 | f = float(f) 219 | ret = ('%.*f' % (n + 1, f))[:-1] 220 | if n == 0: 221 | ret = ret.replace('.', '') 222 | elif n < 0: 223 | i = int(f) 224 | j = -n 225 | while j > 0: 226 | i /= 10 227 | j -= 1 228 | j = -n 229 | while j > 0: 230 | i *= 10 231 | j -= 1 232 | ret = str(i) 233 | return ret 234 | 235 | def trunc(tdw, uinput, argv1 = 0): 236 | '''TRUNC changed from Oracle''' 237 | if isinstance(uinput, Dateclass): 238 | return trunc_date(tdw, uinput, argv1) 239 | else: 240 | return trunc_number(tdw, uinput, argv1) 241 | 242 | # Date Functions: 243 | sessiontimezone = time.timezone 244 | dbtimezone = time.timezone 245 | 246 | def tz_offset(tdw, name): 247 | '''TZ_OFFSET changed from Oracle TZ_OFFSET 248 | tz_offset('-08:00') would return '-08:00' 249 | tz_offset('US/Michigan') is NOT supported 250 | ''' 251 | if type(name) == type(str()): 252 | return name 253 | else: 254 | try: 255 | offset = long(name) / 3600 256 | ret = "" 257 | if offset < 0: 258 | ret += "+" 259 | ret += "%02d" % (-offset) 260 | else: 261 | ret += '-' 262 | ret += "%02d" % (offset) 263 | ret += ":00" 264 | return ret 265 | except ValueError, ve: 266 | print ve 267 | return None 268 | 269 | class Dateclass: 270 | """ 271 | Date type class, give the default value 272 | """ 273 | year = str(time.localtime(time.time()).tm_year) 274 | month = str(time.localtime(time.time()).tm_mon) 275 | day = '01' 276 | hour = '00' 277 | min = '00' 278 | sec = '00' 279 | subsec = 0.0 280 | 281 | def __init__(self, year = None, month = None, day = None, 282 | hour = None, min = None, sec = None, subsec = None): 283 | if year != None: 284 | self.year = str(year) 285 | if month != None: 286 | self.month = str(month) 287 | if day != None: 288 | self.day = str(day) 289 | if hour != None: 290 | self.hour = str(hour) 291 | if min != None: 292 | self.min = str(min) 293 | if sec != None: 294 | self.sec = str(sec) 295 | if subsec != None: 296 | self.subsec = float(subsec) 297 | 298 | def current(self): 299 | timetmp = time.localtime(time.time()) 300 | self.year = str(timetmp.tm_year) 301 | self.month = str(timetmp.tm_mon) 302 | self.day = str(timetmp.tm_mday) 303 | self.hour = str(timetmp.tm_hour) 304 | self.min = str(timetmp.tm_min) 305 | self.sec = str(timetmp.tm_sec) 306 | _tmp = time.time() 307 | self.subsec = _tmp - int(_tmp) 308 | return self 309 | 310 | def __sub__(self, other): 311 | '''sub two days and return the day gap''' 312 | dt = datetime.datetime(int(self.year), int(self.month), 313 | int(self.day), int(self.hour), 314 | int(self.min), int(self.sec)) 315 | dt2 = datetime.datetime(int(other.year), int(other.month), 316 | int(other.day), int(other.hour), 317 | int(other.min), int(other.sec)) 318 | dd = dt - dt2 319 | return (dd.seconds + dd.days * 86400) / 86400 320 | 321 | def __add__(self, seconds): 322 | '''add seconds to day and return the adjusted day''' 323 | dt = datetime.datetime(int(self.year), int(self.month), 324 | int(self.day), int(self.hour), 325 | int(self.min), int(self.sec)) 326 | dt += datetime.timedelta(0, seconds) 327 | # convert to Dateclass 328 | self.year = str(dt.year) 329 | self.month = str(dt.month) 330 | self.day = str(dt.day) 331 | self.hour = str(dt.hour) 332 | self.min = str(dt.minute) 333 | self.sec = str(dt.second) 334 | return self 335 | 336 | class SysdateClass(Dateclass): 337 | '''SysdateClass from Dateclass''' 338 | def __init__(self): 339 | Dateclass.__init__(self) 340 | timetmp = time.localtime(time.time()) 341 | self.year = str(timetmp.tm_year) 342 | self.month = str(timetmp.tm_mon) 343 | self.day = str(timetmp.tm_mday) 344 | self.hour = str(timetmp.tm_hour) 345 | self.min = str(timetmp.tm_min) 346 | self.sec = str(timetmp.tm_sec) 347 | 348 | sysdate = SysdateClass() 349 | systimestamp = Dateclass().current() 350 | 351 | def to_date(tdw, date_string, uformat): 352 | '''TO_DATE changed from Oracle''' 353 | if (date_string == None or date_string == "" 354 | or uformat == None or uformat == ""): 355 | print "Empty date string or format string" 356 | return None 357 | 358 | dc = Dateclass() 359 | #0:24 hours, 1:12 hours 360 | #delete '24' or '12' 361 | flag12 = 0 362 | uformat = uformat.lower() 363 | if uformat.find('hh') != -1: 364 | pos = uformat.find('24') 365 | if pos == -1: 366 | #12hours 367 | flag12 = 1 368 | pos1 = uformat.find('12') 369 | if pos1 != -1: 370 | uformat = uformat[:pos1] + uformat[pos1+2:] 371 | else: 372 | #24hours 373 | uformat = uformat[:pos] + uformat[pos+2:] 374 | 375 | #delete all spaces, ':', '-', '/' 376 | date_string = ''.join(date_string.split()) 377 | date_string = ''.join(date_string.split(':')) 378 | date_string = ''.join(date_string.split('-')) 379 | date_string = ''.join(date_string.split('/')) 380 | uformat = ''.join(uformat.split()) 381 | uformat = ''.join(uformat.split(':')) 382 | uformat = ''.join(uformat.split('-')) 383 | uformat = ''.join(uformat.split('/')) 384 | 385 | if len(date_string) > len(uformat): 386 | print 'date string not match uformat' 387 | return None 388 | 389 | #delete the duplicate,i instead of mi 390 | position = [] 391 | for i in range(0, len(uformat)): 392 | if uformat[i] not in position: 393 | position.append(uformat[i]) 394 | 395 | #parse the date 396 | i = 0 397 | while i < len(date_string): 398 | type = position[0] 399 | position = position[1:] 400 | if type == 'y': 401 | if i+4 > len(date_string): 402 | print 'date string not match format' 403 | return None 404 | 405 | dc.year = date_string[i:i+4] 406 | i += 4 407 | else: 408 | if i+2 > len(date_string): 409 | print 'date string not match format' 410 | return None 411 | if type == 'm': 412 | dc.month = date_string[i:i+2] 413 | elif type == 'd': 414 | dc.day = date_string[i:i+2] 415 | elif type == 'h': 416 | dc.hour = date_string[i:i+2] 417 | elif type == 'i': 418 | dc.min = date_string[i:i+2] 419 | elif type == 's': 420 | dc.sec = date_string[i:i+2] 421 | else: 422 | print "Can't recognize type:" + type 423 | return None 424 | 425 | i += 2 426 | 427 | #check for value 428 | if int(dc.month) > 0 and int(dc.month) <= 12: 429 | pass 430 | else: 431 | print 'wrong month value' 432 | return None 433 | 434 | right_day = 0 435 | if int(dc.month) in [1, 3, 5, 7, 8, 10, 12]: 436 | if int(dc.day) >0 and int(dc.day) <=31: 437 | right_day = 1 438 | elif int(dc.month) in [4, 6, 9, 11]: 439 | if int(dc.day) >0 and int(dc.day) <=30: 440 | right_day = 1 441 | else:#leap year 442 | if int(dc.year) %4 == 0 and int(dc.year) % 100 != 0 : 443 | if int(dc.day) >0 and int(dc.day) <=29: 444 | right_day = 1 445 | elif int(dc.year) %400 == 0: 446 | if int(dc.day) >0 and int(dc.day) <=29: 447 | right_day = 1 448 | else: 449 | if int(dc.day) >0 and int(dc.day) <=29: 450 | right_day = 1 451 | 452 | if right_day == 0: 453 | print 'wrong day value' 454 | return None 455 | 456 | if flag12 == 1 and int(dc.hour) > 12: 457 | print 'wrong hour value' 458 | return None 459 | elif flag12 == 0 and int(dc.hour) > 24: 460 | print 'wrong hour value' 461 | return None 462 | else: 463 | pass 464 | 465 | if int(dc.min) >= 0 and int(dc.min) < 60: 466 | pass 467 | else: 468 | print 'wrong minute value' 469 | return None 470 | 471 | if int(dc.sec) >= 0 and int(dc.sec) < 60: 472 | pass 473 | else: 474 | print 'wrong minute value' 475 | return None 476 | return dc 477 | 478 | def to_char_date(tdw, value, *uformat): 479 | '''Internal function TO_CHAR_DATE chagned from Oracle''' 480 | # date to char 481 | if value.__class__.__name__ == 'Dateclass': 482 | if len(uformat) == 0: 483 | uformat = 'yyyy-mm-dd' 484 | else: 485 | uformat = uformat[0].lower() 486 | 487 | result = '' 488 | i = 0 489 | try: 490 | while i < len(uformat): 491 | if uformat[i] == 'y': 492 | year_cnt = uformat.count('y') 493 | for tmp in uformat[i:i + year_cnt]: 494 | if tmp != 'y': 495 | print "Can't recognize type:" + uformat[i:i+year_cnt+1] 496 | return None 497 | result += str(value.year[-1 - year_cnt -1:]) 498 | 499 | i += year_cnt 500 | elif uformat[i] == 'm': 501 | if uformat[i+1] == 'm': 502 | result += str(value.month) 503 | elif uformat[i+1] == 'i': 504 | result += str(value.min) 505 | else: 506 | print "Can't recognize type:" + uformat[i:i+2] 507 | return None 508 | 509 | i = i + 2 510 | elif uformat[i] == 'd': 511 | if uformat[i+1] == 'd': 512 | result += str(value.day) 513 | else: 514 | print "Can't recognize type:" + uformat[i:i+2] 515 | return None 516 | 517 | i = i + 2 518 | elif uformat[i] == 'h': 519 | if uformat[i+1] == 'h': 520 | if uformat[i+2:i+4] == '12': 521 | _hour_ = int(value.hour) 522 | if _hour_ > 12: 523 | _hour_ = _hour_ - 12 524 | result += str(_hour_) 525 | i = i + 2 526 | elif uformat[i+2:i+4] == '24': 527 | i = i + 2 528 | result += str(value.hour) 529 | else: 530 | result += str(value.hour) 531 | else: 532 | print "Can't recognize type:" + uformat[i:i+2] 533 | return None 534 | 535 | i = i + 2 536 | elif uformat[i] == 's': 537 | if uformat[i+1] == 's': 538 | result += str(value.sec) 539 | else: 540 | print "Can't recognize type:" + uformat[i:i+2] 541 | return None 542 | 543 | i = i + 2 544 | elif uformat[i] == 'f': 545 | if uformat[i+1] == 'f': 546 | _tmp = "%.2f" % (value.subsec) 547 | _tmp = _tmp[_tmp.index('.') + 1:] 548 | result += str(_tmp) 549 | i = i + 2 550 | else: 551 | result += uformat[i] 552 | i = i+1 553 | except IndexError, ie: 554 | print "Invalid format string." 555 | return None 556 | 557 | return result 558 | else: 559 | if value == None: 560 | print "NoneType date?" 561 | return None 562 | 563 | if value.isdigit(): 564 | return str(value) 565 | else: 566 | print "Need Dateclass or digit" 567 | return None 568 | 569 | # 570 | def last_day(tdw, dc): 571 | '''LAST_DAY changed from Oracle. 572 | examples: 573 | >>> dc = Dateclass(2003, 3, 15) 574 | >>> last_day(dc) 575 | '2003/03/31' 576 | >>> dc = Dateclass(2003, 2, 3) 577 | >>> last_day(dc) 578 | '2003/02/28' 579 | >>> dc = Dateclass(2004, 2, 3) 580 | >>> last_day(dc) 581 | '2004/02/29' 582 | ''' 583 | if not isinstance(dc, Dateclass): 584 | print "Unsupport type, we only support class Dateclass type!" 585 | return None 586 | tc = calendar.TextCalendar() 587 | l = tc.formatmonth(int(dc.year), 588 | int(dc.month)).replace('\n', ' ').rstrip().split(' ') 589 | return (str(dc.year) + "/" + ("%02d" % int(dc.month)) + "/" + 590 | ("%02d" % int(l[-1]))) 591 | 592 | def next_day(tdw, dateclass, wd): 593 | '''NEXT_DAY changed from Oracle 594 | examples: 595 | >>> dc = Dateclass(2003, 8, 6) 596 | >>> to_char_date(next_day(dc, 'Wednesday'), 'YYYY:MM:DD') 597 | '2003:8:13' 598 | >>> to_char_date(next_day(dc, 'Sunday'), 'YYYY:MM:DD') 599 | '2003:8:10' 600 | >>> to_char_date(next_day(dc, 'Shitday'), 'YYYY:MM:DD') 601 | Invalid weekday string. Weekday string we support is: 602 | SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY 603 | NoneType date? 604 | ''' 605 | if wd.lower() == "monday": 606 | wd = 0 607 | elif wd.lower() == "tuesday": 608 | wd = 1 609 | elif wd.lower() == "wednesday": 610 | wd = 2 611 | elif wd.lower() == "thursday": 612 | wd = 3 613 | elif wd.lower() == "friday": 614 | wd = 4 615 | elif wd.lower() == "saturday": 616 | wd = 5 617 | elif wd.lower() == "sunday": 618 | wd = 6 619 | else: 620 | print "Invalid weekday string. Weekday string we support is:" 621 | print "SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY" 622 | return None 623 | 624 | if not isinstance(dateclass, Dateclass): 625 | print "Unsupport type, we only support class Dateclass type!" 626 | return None 627 | 628 | c = calendar.Calendar() 629 | l = list(c.itermonthdays2(int(dateclass.year), int(dateclass.month))) 630 | next = 0 631 | for i in range(0, len(l)): 632 | if int(l[i][0]) == 0: 633 | continue 634 | if int(l[i][0]) == int(dateclass.day): 635 | next = 1 636 | wd -= int(l[i][1]) 637 | if wd <= 0: 638 | wd += 7 639 | if next == 1 and wd > 0: 640 | wd -= 1 641 | continue 642 | if next == 1 and wd == 0: 643 | return Dateclass(dateclass.year, dateclass.month, int(l[i][0])) 644 | # next month or next year? 645 | year = 0 646 | month = 0 647 | if int(dateclass.month) + 1 > 12: 648 | year = int(dateclass.year) + 1 649 | month = int(1) 650 | else: 651 | year = int(dateclass.year) 652 | month = int(dateclass.month) + 1 653 | l = list(c.itermonthdays2(year, month)) 654 | for i in range(0, len(l)): 655 | if int(l[i][0]) == 0: 656 | continue 657 | if next == 1 and wd > 0: 658 | wd -= 1 659 | continue 660 | if next == 1 and wd == 0: 661 | return Dateclass(year, month, int(l[i][0])) 662 | 663 | return None 664 | 665 | def add_months(tdw, dc, n): 666 | '''ADD_MONTHS changed from Oracle 667 | examples: 668 | >>> dc = Dateclass(2003, 8, 31) 669 | >>> to_char_date(dc, 'yyyy:mm:dd') 670 | '2003:8:31' 671 | >>> to_char_date(add_months(dc, 3), 'yyyy:mm:dd') 672 | '2003:11:30' 673 | >>> to_char_date(add_months(dc, 3), 'yyyy:mm:dd') 674 | '2004:2:29' 675 | >>> to_char_date(add_months(dc, 3), 'yyyy:mm:dd') 676 | '2004:5:29' 677 | >>> to_char_date(add_months(dc, 3), 'yyyy:mm:dd') 678 | '2004:8:29' 679 | >>> to_char_date(add_months(dc, 3), 'yyyy:mm:dd') 680 | '2004:11:29' 681 | >>> to_char_date(add_months(dc, 3), 'yyyy:mm:dd') 682 | '2005:2:28' 683 | ''' 684 | if not isinstance(dc, Dateclass): 685 | print "Unsupported type, we only support Dateclass type!" 686 | return None 687 | new_month = int(dc.month) + int(n) 688 | if new_month <= 0: 689 | dc.year = str(int(dc.year) - 1) 690 | dc.month = str(12 + new_month) 691 | elif new_month > 12: 692 | dc.month = str(new_month - 12) 693 | dc.year = str(int(dc.year) + 1) 694 | else: 695 | dc.month = str(new_month) 696 | if int(dc.month) in [4, 6, 9, 11]: 697 | if int(dc.day) == 31: 698 | dc.day = "30" 699 | elif int(dc.month) == 2: 700 | if int(dc.day) > 29: 701 | dc.day = "29" 702 | if int(dc.year) % 100 == 0 or int(dc.year) % 4 != 0: 703 | if int(dc.year) % 400 != 0: 704 | if int(dc.day) == 29: 705 | dc.day = "28" 706 | return dc 707 | 708 | def months_between(tdw, date1, date2): 709 | '''Return the months' gap between date1 and date2 as (date1 - date2)''' 710 | if not isinstance(date1, Dateclass) or not isinstance(date2, Dateclass): 711 | print "Unsupported type, we only support Dateclass type!" 712 | return None 713 | 714 | year_gap = int(date1.year) - int(date2.year) 715 | month_gap = int(date2.month) - int(date1.month) 716 | day_gap = int(date2.day) - int(date1.day) 717 | 718 | return float(year_gap * 12 - month_gap) - float(day_gap) / 31 719 | 720 | def trunc_date(tdw, uinput, argv1): 721 | '''Internal DATE TRUNC function, chagned from Oracle TRUNC DATE 722 | >>> to_char_date(trunc_date(to_date("1998-10-12", 'yyyy-mm-dd'), 'year'), 'yyyy:mm:dd') 723 | '1998:01:01' 724 | >>> to_char_date(trunc_date(to_date("1998-10-12", 'yyyy-mm-dd'), 'Q'), 'yyyy:mm:dd') 725 | '1998:10:01' 726 | >>> to_char_date(trunc_date(to_date("1998-10-12", 'yyyy-mm-dd'), 'mm'), 'yyyy:mm:dd') 727 | '1998:10:01' 728 | ''' 729 | if not isinstance(uinput, Dateclass): 730 | print "The first argument is not a Dateclass instance." 731 | return None 732 | 733 | if argv1 == None or argv1 == "": 734 | return uinput 735 | 736 | dc = Dateclass(uinput.year) 737 | if argv1.lower() == 'year' or argv1.lower() == 'yyyy': 738 | dc.year = uinput.year 739 | dc.month = '01' 740 | return dc 741 | if argv1.lower() == 'q': 742 | dc.year = uinput.year 743 | dc.month = str(int(uinput.month) - int(uinput.month) % 3 + 1) 744 | return dc 745 | if (argv1.lower() == 'month' or argv1.lower() == 'mon' 746 | or argv1.lower() == 'mm'): 747 | dc.year = uinput.year 748 | dc.month = uinput.month 749 | return dc 750 | print "We only support the following format string:" 751 | print " year/yyyy/q/month/mon/mm" 752 | print "Other format string will be supported later:)" 753 | return None 754 | 755 | class DBMS_OUTPUT: 756 | '''Simulate the dbms_output function in Oracle''' 757 | _enable = True 758 | def __init__(self): 759 | pass 760 | def put_line(self, tdw, str_to_print): 761 | '''Write a string to the console''' 762 | if self._enable: 763 | print str_to_print 764 | def disable(self): 765 | '''Disable the output''' 766 | self._enable = False 767 | def enable(self): 768 | '''Enable the output''' 769 | self._enable = True 770 | 771 | # The following region defines the Oracle runtime variables/packages. 772 | # However, they are just a MACRO :) 773 | 774 | dbms_output = DBMS_OUTPUT() 775 | 776 | def rollback(): 777 | '''Do rollback''' 778 | return 779 | 780 | def commit(): 781 | '''Do commit''' 782 | return 783 | 784 | class DBMS_LOCK: 785 | '''Simulate the dbms_lock function in Oracle''' 786 | def __init__(self): 787 | pass 788 | def sleep(self, tdw, seconds): 789 | time.sleep(seconds) 790 | 791 | dbms_lock = DBMS_LOCK() 792 | 793 | class DBMS_SESSION: 794 | free_unused_user_memory = None 795 | '''Simulate the dbms_session function in Oracle''' 796 | def __init__(self): 797 | pass 798 | def set_nls(self, tdw, _type, _format): 799 | pass 800 | 801 | dbms_session = DBMS_SESSION() 802 | 803 | class DBMS_STATS: 804 | '''Simulate the dbms_stats function in Oracle''' 805 | def __init__(self): 806 | pass 807 | def gather_table_stats(self, tdw, ownname, tabname, partname = None, 808 | estimate_percent = None, block_sample = False, 809 | method_opt = None, degree = None, 810 | granularity = None, cascade = None, 811 | stattab = None, statid = None, statown = None, 812 | no_invalidate = None, force = None): 813 | pass 814 | 815 | dbms_stats = DBMS_STATS() 816 | 817 | class DBMS_APPLICATION_INFO: 818 | '''Simulate the dbms_application_info package in Oracle''' 819 | def __init__(self): 820 | pass 821 | def set_client_info(self, tdw, string): 822 | pass 823 | 824 | dbms_application_info = DBMS_APPLICATION_INFO() 825 | 826 | sqlcode = '''TDW/PL do NOT support SQLCODE at this moment.''' 827 | sqlerrm = '''TDW/PL do NOT support SQLERRM at this moment.''' 828 | 829 | # shadow TDW object 830 | tdw = None 831 | -------------------------------------------------------------------------------- /PLSQL.g: -------------------------------------------------------------------------------- 1 | /* 2 | Oracle PL/SQL grammar built with ANTLR v3.2 and v3.1.3. I only vouch that it works for v3.2, though. 3 | 4 | Author: Patrick Higgins 5 | License: GNU Lesser General Public License, version 2.1 or (at your option) any later version. 6 | 7 | I have used a swallow_to_semi trick to avoid parsing SQL statements and other statements that were not of value to me. 8 | The idea was that a separate parser for SQL would be created (I believe this is what Oracle itself does). 9 | 10 | Nearly all of the PL/SQL language from 11g is in this grammar, though. It works on all files in a fairly large code 11 | base. 12 | 13 | This has some limited support for parsing SQL*Plus files, which turns out to be pretty hard to work into ANTLR. 14 | 15 | It works for my usage, but I think doing it properly would mean writing a Java class to parse the SQL*Plus language 16 | (which is pretty simple and shouldn't need ANTLR) and another adapter for ANTLR which enables tracking back to the 17 | original source line numbers. This PL/SQL parser might be invoked many times for each SQL*Plus file. 18 | */ 19 | 20 | /** 21 | * Copyright (c) 2010,2011 Ma Can 22 | * 23 | * We modified this gramma file to transform Oracle PL/SQL scripts to Python for TDW project. The target code 24 | * can ONLY run in a HIVE-like runtime environment. 25 | */ 26 | 27 | grammar PLSQL; 28 | 29 | @header { 30 | package org.plsql; 31 | 32 | import java.io.File; 33 | import java.io.FileInputStream; 34 | import java.io.FileNotFoundException; 35 | import java.io.FileOutputStream; 36 | import java.io.IOException; 37 | import java.util.regex.Matcher; 38 | import java.util.regex.Pattern; 39 | import java.util.HashMap; 40 | import java.util.Iterator; 41 | import java.util.Map; 42 | import java.util.Set; 43 | import java.text.DateFormat; 44 | import java.text.SimpleDateFormat; 45 | import java.util.Date; 46 | } 47 | 48 | @members { 49 | 50 | Map map = new HashMap(); 51 | 52 | public void emitFunctionName(String fname, int lnr) 53 | { 54 | Integer i; 55 | int cnt; 56 | i = map.get(fname); 57 | if (i == null) 58 | cnt = 1; 59 | else { 60 | cnt = i.intValue() + 1; 61 | } 62 | map.put(fname, cnt); 63 | //System.out.print(getSourceName() + ":" + lnr + ":" + fname + '\n'); 64 | } 65 | Map support_set = new HashMap(); 66 | Map changed_set = new HashMap(); 67 | Map unsupport_set = new HashMap(); 68 | public void functionAPIChange() 69 | { 70 | // API Supported 71 | support_set.put("length", "support"); 72 | support_set.put("substr", "support"); 73 | support_set.put("upper", "support"); 74 | support_set.put("lower", "support"); 75 | support_set.put("instr", "support"); 76 | support_set.put("replace", "support"); 77 | support_set.put("nvl", "support"); 78 | support_set.put("nvl2", "support"); 79 | support_set.put("mod", "support"); 80 | support_set.put("abs", "support"); 81 | support_set.put("floor", "support"); 82 | support_set.put("ln", "support"); 83 | support_set.put("acos", "support"); 84 | support_set.put("sin", "support"); 85 | support_set.put("sinh", "support"); 86 | support_set.put("cos", "support"); 87 | support_set.put("cosh", "support"); 88 | support_set.put("tan", "support"); 89 | support_set.put("tanh", "support"); 90 | 91 | // API Changed 92 | changed_set.put("to_number", "changed"); 93 | changed_set.put("ltrim", "changed"); 94 | changed_set.put("rtrim", "changed"); 95 | changed_set.put("trim", "changed"); 96 | changed_set.put("to_date", "changed"); 97 | changed_set.put("to_char", "changed"); 98 | changed_set.put("tz_offset", "changed"); 99 | changed_set.put("last_day", "changed"); 100 | changed_set.put("next_day", "changed"); 101 | changed_set.put("add_months", "changed"); 102 | changed_set.put("months_between", "changed"); 103 | changed_set.put("mod", "changed"); 104 | changed_set.put("round", "changed"); 105 | changed_set.put("power", "changed"); 106 | changed_set.put("trunc", "changed"); 107 | 108 | // API Unsupported 109 | 110 | } 111 | 112 | public String getErrorHeader(RecognitionException e) { 113 | return getSourceName()+":"+e.line+":"+(e.charPositionInLine+1)+":"; 114 | } 115 | 116 | public String getErrorMessage(RecognitionException e, String[] tokenNames) { 117 | List stack = getRuleInvocationStack(e, this.getClass().getName()); 118 | String msg = null; 119 | if (e instanceof NoViableAltException) { 120 | NoViableAltException nvae = (NoViableAltException) e; 121 | msg = " no viable alt; token="+e.token+ 122 | " (decision="+nvae.decisionNumber+ 123 | " state "+nvae.stateNumber+")"+ 124 | " decision=<<"+nvae.grammarDecisionDescription+">>"; 125 | } 126 | else { 127 | msg = super.getErrorMessage(e, tokenNames); 128 | } 129 | return stack+" "+msg; 130 | } 131 | 132 | public String getTokenErrorDisplay(Token t) { 133 | return t.toString(); 134 | } 135 | 136 | public File outf = null;//the main python file 137 | public FileOutputStream fops = null; 138 | public File poutf = null;//package output, every package generate a python file 139 | public FileOutputStream pfops = null; 140 | public String output = ""; 141 | public String[] parameter_list = new String[20]; 142 | public int parameter_list_count = -1; 143 | public String[] initial_statement = new String[20]; 144 | public int initial_statement_count = -1; 145 | public String exp = ""; 146 | public int indent_count = 0; 147 | public String stat = ""; 148 | public String __par = ""; 149 | public String __sql = ""; 150 | public int sql_count = 0; 151 | public int todo_count = 0; 152 | public int create_package = 0; 153 | public String path = "";//the output file path 154 | public String filename = ""; 155 | public String[] import_package = new String[50];//import packages for package body 156 | public int import_package_count = -1; 157 | public String[] global_import_package = new String[50];//import packages for the whole files 158 | public int global_import_package_count = -1; 159 | public int global = 1;//1:global file 0:package file 160 | 161 | public int has_record_type = 0;//composite struct:record, varray, table 162 | public String[] record_define = new String[50]; 163 | public int record_define_cnt = -1; 164 | public String[] record_declare = new String[50]; 165 | public int record_declare_cnt = -1; 166 | 167 | public int has_collection_type = 0;//composite struct:record, varray, table 168 | public String[] collection_type_define = new String[50]; 169 | public int collection_type_define_cnt = -1; 170 | public String[] collection_type_declare = new String[50]; 171 | public int collection_type_declare_cnt = -1; 172 | public int collection_var_cnt = -1; 173 | public String[] collection_variables = new String[200]; 174 | 175 | public String into_exp = ""; 176 | public int has_into_exp = 0; 177 | 178 | public String last_id = ""; 179 | 180 | public String[] variables_list = new String[150]; 181 | public int variables_list_cnt = -1; 182 | public int replace_length = 0; 183 | 184 | public String[][] pkg_list = new String[200][2]; 185 | public int pkg_list_cnt = -1; 186 | String pkg_current = ""; 187 | 188 | public PLSQLParser(TokenStream input, String NewPath, String NewFileName) throws IOException { 189 | this(input, new RecognizerSharedState()); 190 | outf = new File(NewPath + "/anonymous_" + NewFileName); 191 | 192 | path = NewPath; 193 | filename = outf.getName(); 194 | 195 | if(!outf.exists()){ 196 | outf.createNewFile(); 197 | } 198 | 199 | try { 200 | fops = new FileOutputStream(outf); 201 | } catch (FileNotFoundException e) { 202 | System.out.print("File not Found"); 203 | e.printStackTrace(); 204 | } 205 | } 206 | 207 | } 208 | 209 | @lexer::header { 210 | package org.plsql; 211 | } 212 | 213 | @lexer::members { 214 | 215 | public String getErrorHeader(RecognitionException e) { 216 | return getSourceName()+":"+e.line+":"+(e.charPositionInLine+1)+":"; 217 | } 218 | 219 | // needed for things like BETWEEN 1..2 where 1. would be treated as a literal 220 | private boolean numberDotValid() { 221 | int i = 1; 222 | while (input.LA(i) >= '0' && input.LA(i) <= '9') { 223 | i++; 224 | } 225 | return input.LA(i) == '.' && input.LA(i+1) != '.'; 226 | } 227 | 228 | public int row_count = 0; 229 | } 230 | 231 | 232 | sqlplus_file 233 | @after{ 234 | functionAPIChange(); 235 | // emit all the function calls now 236 | Set set = map.entrySet(); 237 | int total_function = 0, support_function = 0, changed_function = 0, unsupport_function = 0, other = 0, total_calls = 0; 238 | 239 | Iterator it = set.iterator(); 240 | while (it.hasNext()) { 241 | Map.Entry me = (Map.Entry)it.next(); 242 | System.out.println(me.getKey() + ":" + me.getValue()); 243 | total_calls += ((Integer)me.getValue()).intValue(); 244 | total_function++; 245 | if (support_set.containsKey(me.getKey())) 246 | support_function++; 247 | else if (changed_set.containsKey(me.getKey())) 248 | changed_function++; 249 | else if (unsupport_set.containsKey(me.getKey())) 250 | unsupport_function++; 251 | else 252 | other++; 253 | } 254 | System.out.println("Total Functions: " + total_function); 255 | System.out.println("Support Functions: " + support_function); 256 | System.out.println("Change Functions: " + changed_function); 257 | System.out.println("Unsupport Functions: " + unsupport_function); 258 | System.out.println("Other Functions: " + other); 259 | double ratio = Double.parseDouble(Integer.toString(changed_function + unsupport_function + other)) / total_function * 100; 260 | System.out.println("Ratio of functions need to revise: " + (ratio) + "\%"); 261 | // reinit the dicts 262 | has_record_type = 0; 263 | record_declare_cnt = -1; 264 | record_define_cnt = -1; 265 | has_collection_type = 0; 266 | collection_type_define_cnt = -1; 267 | collection_type_declare_cnt = -1; 268 | collection_var_cnt = -1; 269 | // other operations 270 | fops.close(); 271 | FileInputStream ipfs = new FileInputStream(outf); 272 | 273 | String FileName = "tmp.py"; 274 | File writefile = new File(path + FileName); 275 | if(!writefile.exists()){ 276 | writefile.createNewFile(); 277 | } 278 | FileOutputStream opfs = new FileOutputStream(writefile); 279 | 280 | byte[] b = new byte[1024]; 281 | 282 | int x = 0; 283 | 284 | ipfs.read(b, 0, 13); 285 | opfs.write(b, 0, 13); 286 | 287 | DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); 288 | Date date = new Date(); 289 | 290 | String outs = "'''---THIS FILE IS CREATED AUTOMATICALLY @ " + dateFormat.format(date) + "---'''\n\n"; 291 | outs += "from tdw import HiveServerException\n"; 292 | outs += "from tdw import dynamic_type\n"; 293 | outs += "from tdw_sql_lib import *\n\n"; 294 | outs += "import " + filename.substring(0, filename.indexOf(".")) + "\n\n"; 295 | 296 | if(global_import_package_count != -1){ 297 | for(int i = 0; i<= global_import_package_count; i++){ 298 | outs += "import " + global_import_package[i].toLowerCase() + "\n"; 299 | } 300 | } 301 | outs += "\n"; 302 | opfs.write(outs.getBytes()); 303 | 304 | while((x = ipfs.read(b, 0, 1024)) != -1){ 305 | opfs.write(b, 0, x); 306 | } 307 | ipfs.close(); 308 | opfs.close(); 309 | 310 | outf.delete(); 311 | writefile.renameTo(outf); 312 | } 313 | : { 314 | String tmp = "# coding=gbk\n\n"; 315 | fops.write(tmp.getBytes()); 316 | } 317 | ( create_object ( DIVIDE show_errors )? DIVIDE? )+ EOF {pkg_list_cnt = -1;} 318 | ; 319 | catch[RecognitionException re] {reportError(re);recover(input,re);} 320 | catch[IOException e] {e.printStackTrace();} 321 | 322 | show_errors 323 | : kSHOW kERRORS SEMI? 324 | ; 325 | 326 | create_object 327 | : create_package { 328 | for (int i = 0; i <= pkg_list_cnt; i++) { 329 | if (pkg_current.equalsIgnoreCase(pkg_list[i][0])) { 330 | System.out.println("Package " + pkg_current + " is redefined!"); 331 | } 332 | } 333 | System.out.println("Add package " + pkg_current + " at index " + (pkg_list_cnt + 1)); 334 | pkg_list_cnt++; 335 | pkg_list[pkg_list_cnt][0] = pkg_current; 336 | pkg_list[pkg_list_cnt][1] = output; 337 | output = ""; 338 | } 339 | | create_package_body { output = "";} 340 | | create_function {fops.write(output.getBytes()); fops.write("\n\n".getBytes()); output = "";} 341 | | create_procedure {fops.write(output.getBytes()); fops.write("\n\n".getBytes()); output = "";} 342 | ; 343 | catch[RecognitionException re] {reportError(re);recover(input,re);} 344 | catch[IOException e] {e.printStackTrace();} 345 | 346 | procedure_heading : 347 | PROCEDURE ID 348 | { 349 | String tmp = $ID.getText().toLowerCase(); 350 | if(tmp.startsWith("\"")&&tmp.endsWith("\"")) 351 | tmp = tmp.substring(1, tmp.length() -1 ); 352 | 353 | output += "def " + tmp.toLowerCase() + "(tdw, ";} 354 | parameter_declarations? {output += __par; __par = "";} 355 | {output += ")";} 356 | {output += ":\n"; 357 | if(initial_statement_count >= 0) 358 | { 359 | for(int i = 0; i <= initial_statement_count; i++) 360 | { 361 | output += '\t' + initial_statement[i] + "\n"; 362 | } 363 | initial_statement_count = -1; 364 | } 365 | } 366 | ; 367 | 368 | function_heading : 369 | FUNCTION ID 370 | { 371 | String tmp = $ID.getText().toLowerCase(); 372 | if(tmp.startsWith("\"")&&tmp.endsWith("\"")) 373 | tmp = tmp.substring(1, tmp.length() -1 ); 374 | 375 | output += "def " + tmp.toLowerCase() + "(tdw, ";} 376 | parameter_declarations? {output += __par; __par = "";} 377 | {output += ")";} 378 | {output += ":\n"; 379 | if(initial_statement_count >= 0) 380 | { 381 | for(int i = 0; i <= initial_statement_count; i++) 382 | { 383 | output += '\t' + initial_statement[i] + "\n"; 384 | } 385 | initial_statement_count = -1; 386 | } 387 | } 388 | RETURN datatype 389 | ; 390 | 391 | parameter_declarations : 392 | ( LPAREN parameter_declaration ( COMMA parameter_declaration )* RPAREN) 393 | { 394 | int has_defaults = 0; 395 | for(int i = 0; i <= parameter_list_count; i++) 396 | { 397 | if (parameter_list[i].contains("= None")) 398 | has_defaults = 1; 399 | } 400 | if (has_defaults == 1) { 401 | for(int i = 0; i <= parameter_list_count; i++) 402 | { 403 | if (!parameter_list[i].contains("= None")) 404 | parameter_list[i] += " = None"; 405 | } 406 | } 407 | 408 | if(parameter_list_count >= 0) 409 | { 410 | __par += parameter_list[0]; 411 | for(int i = 1; i <= parameter_list_count; i++) 412 | { 413 | __par += ", " + parameter_list[i]; 414 | } 415 | parameter_list_count = -1; 416 | } 417 | } 418 | ; 419 | 420 | parameter_declaration 421 | @init{ 422 | String id_name = ""; 423 | int has_default = 0; 424 | } 425 | @after{ 426 | if (has_default == 0) { 427 | parameter_list_count++; 428 | parameter_list[parameter_list_count] = id_name; 429 | variables_list_cnt++; 430 | variables_list[variables_list_cnt] = id_name; 431 | } else { 432 | parameter_list_count++; 433 | parameter_list[parameter_list_count] = id_name + " = None"; 434 | variables_list_cnt++; 435 | variables_list[variables_list_cnt] = id_name; 436 | } 437 | } 438 | : 439 | ID {id_name = $ID.getText().toLowerCase();} ( IN | ( ( OUT | IN OUT ) NOCOPY? ) )? 440 | datatype ( ( ASSIGN {has_default = 1;} | DEFAULT {has_default = 1;} ) expression 441 | { 442 | if (has_default == 0) { 443 | initial_statement_count++; 444 | initial_statement[initial_statement_count] = $ID.getText().toLowerCase() + " = " + exp; 445 | exp = ""; 446 | } else { 447 | initial_statement_count++; 448 | initial_statement[initial_statement_count] = 449 | "if " + $ID.getText().toLowerCase() + " == None: " + $ID.getText().toLowerCase() + " = " + exp; 450 | exp = ""; 451 | } 452 | } 453 | )? 454 | ; 455 | 456 | declare_section 457 | @init{ 458 | String xout = output; 459 | output = ""; 460 | } 461 | @after{ 462 | output = xout; 463 | } 464 | : 465 | ( type_definition SEMI {xout += output; output = "";} 466 | | subtype_definition 467 | {int start = input.LT(1).getTokenIndex();} 468 | SEMI 469 | {int end = input.LT(-1).getTokenIndex(); 470 | int pos = end + 1; 471 | while(input.get(pos).getChannel() != 0) 472 | pos++; 473 | end = pos - 1; 474 | xout += input.toString(start, end).toLowerCase();} 475 | | cursor_definition SEMI {xout += output; output = "";} 476 | | item_declaration SEMI {xout += output; output = "";} 477 | | function_declaration_or_definition SEMI {if (create_package == 0) xout += output; output = "";} 478 | | procedure_declaration_or_definition SEMI {if (create_package == 0) xout += output; output = "";} 479 | | pragma SEMI {xout += output; output = "";} 480 | )+ 481 | ; 482 | 483 | cursor_definition 484 | @init { 485 | String tmp = ""; 486 | } 487 | @after { 488 | output += tmp + '\n'; 489 | stat = ""; 490 | } 491 | : 492 | { 493 | String v_cursor = ""; 494 | output += "\t# FIXME: CURSOR DEFINITION\n"; 495 | } 496 | CURSOR ID {v_cursor = input.LT(-1).getText().toLowerCase();} {__par = "";} parameter_declarations ? { 497 | if (__par == "") { 498 | todo_count++; 499 | } 500 | __par = ""; 501 | } IS select_statement 502 | { 503 | tmp += "\t" + v_cursor + " = ({'isopen':0, 'sql':" + __sql + "})\n"; 504 | __sql = ""; 505 | } 506 | ; 507 | 508 | item_declaration 509 | @init{ 510 | String indent = ""; 511 | for (int i = 0; i < indent_count; i++) 512 | indent += "\t"; 513 | if (create_package == 1) { 514 | indent = ""; 515 | } 516 | } 517 | @after{ 518 | exp = ""; 519 | } 520 | : ( ID 521 | {int start = input.LT(1).getTokenIndex();} 522 | datatype 523 | { 524 | int emit = 1; 525 | int end = input.LT(-1).getTokenIndex(); 526 | String datatype_string = input.toString(start, end).toLowerCase(); 527 | if( has_record_type == 1 ) 528 | { 529 | for(int i = 0; i <= record_define_cnt; i++) 530 | { 531 | if( datatype_string.equalsIgnoreCase(record_define[i])) 532 | { 533 | output += indent + $ID.getText().toLowerCase() + " = " + record_define[i] + "()\n"; 534 | record_declare_cnt++; 535 | record_declare[record_declare_cnt] = $ID.getText().toLowerCase(); 536 | emit = 0; 537 | break; 538 | } 539 | } 540 | } 541 | 542 | if( has_collection_type == 1 ) 543 | { 544 | for(int i = 0; i <= collection_type_define_cnt; i++) 545 | { 546 | if( datatype_string.equalsIgnoreCase(collection_type_define[i])) 547 | { 548 | output += indent + $ID.getText().toLowerCase() + " = " + collection_type_define[i] + "()\n"; 549 | collection_type_declare_cnt++; 550 | collection_type_declare[collection_type_declare_cnt] = $ID.getText().toLowerCase(); 551 | 552 | collection_var_cnt++; 553 | collection_variables[collection_var_cnt] = $ID.getText().toLowerCase(); 554 | emit = 0; 555 | break; 556 | } 557 | } 558 | } 559 | 560 | if( datatype_string.contains("\%") ) 561 | { 562 | String[] tmp = datatype_string.split("\%"); 563 | String class_name = ""; 564 | if( tmp[1].equalsIgnoreCase("rowtype")) 565 | { 566 | class_name = $ID.getText().toLowerCase(); 567 | output += "\n" + indent + "class " + class_name.toUpperCase() + ":\n"; 568 | output += indent + "\tpass\n"; 569 | output += indent + class_name + " = " + class_name.toUpperCase() + "()\n"; 570 | output += indent + "rowtype_sql = \"describe " + tmp[0] + "\"\n"; 571 | output += indent + "res = tdw.execute(rowtype_sql)\n"; 572 | output += indent + "for tmp in res:\n"; 573 | output += indent + "\t" + $ID.getText().toLowerCase() + ".__dict__[tmp.split()[0]] = None\n"; 574 | output += "\n"; 575 | has_collection_type = 1; 576 | collection_var_cnt++; 577 | collection_variables[collection_var_cnt] = $ID.getText().toLowerCase(); 578 | emit = 0; 579 | } else if (tmp[1].equalsIgnoreCase("type")) { 580 | output += indent + "# FIXME: \%type is not supported, you have to rewrite it!\n"; 581 | output += indent + $ID.getText().toLowerCase() + " = dynamic_type()\n"; 582 | has_collection_type = 1; 583 | collection_var_cnt++; 584 | collection_variables[collection_var_cnt] = $ID.getText().toLowerCase(); 585 | emit = 0; 586 | } 587 | } 588 | if (datatype_string.toLowerCase().contains("number")) { 589 | output += indent + $ID.getText().toLowerCase() + " = int()\n"; 590 | emit = 0; 591 | } else if (datatype_string.toLowerCase().contains("smallint")) { 592 | output += indent + $ID.getText().toLowerCase() + " = int()\n"; 593 | emit = 0; 594 | } else if (datatype_string.toLowerCase().contains("date")) { 595 | output += indent + $ID.getText().toLowerCase() + " = Dateclass()\n"; 596 | emit = 0; 597 | } 598 | } 599 | { 600 | if (emit == 1) { 601 | output += indent + $ID.getText().toLowerCase() + " = None\n"; 602 | } 603 | exp = ""; 604 | variables_list_cnt++; 605 | variables_list[variables_list_cnt] = $ID.getText().toLowerCase(); 606 | }( ( NOT NULL )? ( ASSIGN | DEFAULT ) ( expression 607 | {output += indent + $ID.getText().toLowerCase() + " = " + exp + '\n'; } 608 | | dbmsfunc_call ) )?) 609 | | constant_declaration 610 | { 611 | output += indent + "# FIXME: Constant declaration"; 612 | todo_count++; 613 | } 614 | | exception_declaration 615 | { 616 | output += indent + exp.toLowerCase() + " = None # This is an exception!\n"; 617 | exp = ""; 618 | } 619 | ; 620 | 621 | 622 | constant_declaration : 623 | ID CONSTANT datatype ( NOT NULL )? ( ASSIGN | DEFAULT ) expression 624 | { 625 | } 626 | ; 627 | 628 | exception_declaration : 629 | ID EXCEPTION { 630 | exp = $ID.getText().toLowerCase(); 631 | variables_list_cnt++; 632 | variables_list[variables_list_cnt] = $ID.getText().toLowerCase(); 633 | } 634 | ; 635 | 636 | type_definition : 637 | kTYPE ID IS ( record_type_definition[$ID.getText().toLowerCase()] | collection_type_definition[$ID.getText().toLowerCase()] | ref_cursor_type_definition ) 638 | ; 639 | 640 | subtype_definition : 641 | {int start = input.LT(1).getTokenIndex();} 642 | SUBTYPE ID IS 643 | {int end = input.LT(-1).getTokenIndex(); 644 | int pos = end + 1; 645 | while(input.get(pos).getChannel() != 0) 646 | pos++; 647 | end = pos - 1; 648 | output += input.toString(start, end).toLowerCase();} 649 | datatype 650 | {start = input.LT(1).getTokenIndex();} 651 | ( NOT NULL )? 652 | {end = input.LT(-1).getTokenIndex(); 653 | pos = end + 1; 654 | while(input.get(pos).getChannel() != 0) 655 | pos++; 656 | end = pos - 1; 657 | output += input.toString(start, end).toLowerCase();} 658 | ; 659 | 660 | record_type_definition[String classname] 661 | @init{ 662 | int __idx = 0; 663 | String init_func = ""; 664 | indent_count = 1; 665 | } 666 | @after{ 667 | output += init_func; 668 | indent_count = 1; 669 | } 670 | : 671 | { 672 | output += '\n'; 673 | for(int i = 0; i < indent_count; i++) 674 | { 675 | output += '\t'; 676 | init_func += '\t'; 677 | } 678 | output += "class " + classname + ":\n"; 679 | init_func += "\tdef __init__(self, l = None):\n"; 680 | for(int i = 0; i < indent_count; i++) 681 | { 682 | init_func += '\t'; 683 | } 684 | init_func += "\t\tif l != None:\n"; 685 | indent_count++; 686 | has_record_type = 1; 687 | record_define_cnt++; 688 | record_define[record_define_cnt] = classname; 689 | } 690 | RECORD LPAREN 691 | { 692 | for(int i = 0; i < indent_count; i++) 693 | { 694 | output += '\t'; 695 | init_func += '\t'; 696 | } 697 | init_func += '\t'; 698 | } 699 | record_field_declaration 700 | { 701 | output += exp.toLowerCase() + " = None\n"; 702 | init_func += "\tself." + exp.toLowerCase() + " = l[" + __idx + "]\n"; 703 | exp = ""; 704 | } 705 | ( COMMA 706 | { 707 | for(int i = 0; i < indent_count; i++) 708 | { 709 | output += '\t'; 710 | init_func += '\t'; 711 | } 712 | init_func += '\t'; 713 | } 714 | record_field_declaration 715 | { 716 | __idx++; 717 | output += exp.toLowerCase() + " = None\n"; 718 | init_func += "\tself." + exp.toLowerCase() + " = l[" + __idx + "]\n"; 719 | exp = ""; 720 | } 721 | )* RPAREN 722 | {init_func += '\n';} 723 | ; 724 | 725 | record_field_declaration : 726 | ID datatype {exp = $ID.getText().toLowerCase();} ( ( NOT NULL )? ( ASSIGN | DEFAULT ) expression )? 727 | ; 728 | 729 | collection_type_definition[String name] 730 | @init{ 731 | output += '\n'; 732 | output += "\tclass " + name + ":\n"; 733 | output += "\t\t_value = {}\n"; 734 | output += "\t\t_count = 0\n"; 735 | output += "\t\tdef __init__(self, *values):\n"; 736 | output += "\t\t\ti = 1\n"; 737 | output += "\t\t\tfor tmp in values:\n"; 738 | output += "\t\t\t\tself._value[i] = tmp\n"; 739 | output += "\t\t\t\tself._count += 1\n"; 740 | output += "\t\t\t\ti += 1\n"; 741 | output += "\t\t\n"; 742 | output += "\t\tdef __len__(self):\n"; 743 | output += "\t\t\treturn self._count\n"; 744 | output += "\t\t\n"; 745 | output += "\t\tdef count(self):\n"; 746 | output += "\t\t\treturn self._count\n"; 747 | output += "\t\t\n"; 748 | output += "\t\tdef __getitem__(self, key):\n"; 749 | output += "\t\t\treturn self._value[key]\n"; 750 | output += "\t\t\n"; 751 | output += "\t\tdef __setitem__(self, key, value):\n"; 752 | output += "\t\t\tself._value[key] = value\n"; 753 | output += "\n"; 754 | 755 | has_collection_type = 1; 756 | collection_type_define_cnt++; 757 | collection_type_define[collection_type_define_cnt] = name; 758 | } 759 | @after{ 760 | indent_count = 1; 761 | } 762 | : varray_type_definition 763 | | nested_table_type_definition 764 | ; 765 | 766 | varray_type_definition 767 | : ( VARYING ARRAY? | VARRAY ) LPAREN numeric_literal RPAREN kOF datatype ( NOT NULL )? 768 | ; 769 | 770 | nested_table_type_definition 771 | : TABLE kOF datatype ( NOT NULL )? ( INDEX BY associative_index_type )? 772 | ; 773 | 774 | associative_index_type 775 | : datatype 776 | ; 777 | 778 | ref_cursor_type_definition 779 | : 780 | {int start = input.LT(1).getTokenIndex(); 781 | output += "\n\t# FIXME: REF CURSOR TYPE DEFINITION\n"; 782 | output += "\t\"\"\"\n"; 783 | } 784 | REF CURSOR ( RETURN datatype )? 785 | {int end = input.LT(-1).getTokenIndex(); 786 | int pos = end + 1; 787 | while(input.get(pos).getChannel() != 0) 788 | pos++; 789 | end = pos - 1; 790 | String tmp = input.toString(start, end).toLowerCase(); 791 | int length = tmp.length(); 792 | 793 | output += tmp + '\n'; 794 | output += "\t\"\"\"\n"; 795 | } 796 | ; 797 | 798 | 799 | datatype 800 | : ( REF )? ID ( DOT ID )? ( LPAREN numeric_literal ( COMMA numeric_literal )* RPAREN | PERCENT ( kTYPE | ROWTYPE ) )? 801 | ; 802 | 803 | function_declaration_or_definition 804 | @init{ 805 | int saved_cp = create_package; 806 | create_package = 0; 807 | indent_count = 1; 808 | } 809 | @after{ 810 | variables_list_cnt = -1; 811 | create_package = saved_cp; 812 | }: 813 | function_heading 814 | ( DETERMINISTIC | PIPELINED | PARALLEL_ENABLE | RESULT_CACHE )* 815 | ( ( IS | AS ) declare_section? body 816 | { 817 | 818 | for(int i = 0; i <= variables_list_cnt; i++ ) 819 | { 820 | String reg = "(?i)" + variables_list[i]; 821 | String repl = variables_list[i].toLowerCase(); 822 | //output = output.replaceAll(reg, repl); 823 | } 824 | 825 | pfops.write(output.getBytes()); pfops.write("\n\n".getBytes()); output = ""; 826 | if( has_record_type == 1 ) 827 | { 828 | record_define_cnt = -1; 829 | record_declare_cnt = -1; 830 | has_record_type = 0; 831 | } 832 | 833 | if( has_collection_type == 1) 834 | { 835 | collection_type_define_cnt = -1; 836 | collection_type_declare_cnt = -1; 837 | //collection_var_cnt = -1; 838 | has_collection_type = 0; 839 | } 840 | } 841 | )? 842 | ; 843 | catch[RecognitionException re] {reportError(re);recover(input,re);} 844 | catch[IOException e] {e.printStackTrace();} 845 | 846 | procedure_declaration_or_definition 847 | @init{ 848 | int saved_cp = create_package; 849 | create_package = 0; 850 | indent_count = 1; 851 | } 852 | @after{ 853 | variables_list_cnt = -1; 854 | create_package = saved_cp; 855 | }: 856 | procedure_heading 857 | ( ( IS | AS ) declare_section? body 858 | { 859 | for(int i = 0; i <= variables_list_cnt; i++ ) 860 | { 861 | String reg = "(?i)" + variables_list[i]; 862 | String repl = variables_list[i].toLowerCase(); 863 | //output = output.replaceAll(reg, repl); 864 | } 865 | 866 | pfops.write(output.getBytes()); pfops.write("\n\n".getBytes()); output = ""; 867 | if( has_record_type == 1 ) 868 | { 869 | record_define_cnt = -1; 870 | record_declare_cnt = -1; 871 | has_record_type = 0; 872 | } 873 | 874 | if( has_collection_type == 1 ) 875 | { 876 | collection_type_define_cnt = -1; 877 | collection_type_declare_cnt = -1; 878 | //collection_var_cnt = -1; 879 | has_collection_type = 0; 880 | } 881 | } 882 | )? 883 | ; 884 | catch[RecognitionException re] {reportError(re);recover(input,re);} 885 | catch[IOException e] {e.printStackTrace();} 886 | 887 | body 888 | @init{ 889 | indent_count = 2; 890 | int has_exception_handler = 0; 891 | } : 892 | BEGIN { 893 | output += "\t# BEGIN a BODY\n"; 894 | output += "\ttry:\n"; 895 | } statement { 896 | if(!stat.equals("")) { 897 | output += stat; 898 | stat = ""; 899 | } 900 | } 901 | SEMI ( statement 902 | { 903 | if(!stat.equals("")) { 904 | output += stat; 905 | stat = ""; 906 | } 907 | } SEMI | pragma SEMI )* 908 | ({ 909 | stat = ""; 910 | } 911 | EXCEPTION {has_exception_handler = 1;} exception_handler+ 912 | )? END { 913 | if (has_exception_handler == 0) { 914 | output += "\texcept HiveServerException, hse:\n"; 915 | output += "\t\tprint hse\n"; 916 | } 917 | } ID? 918 | ; 919 | 920 | exception_handler: 921 | {int start = input.LT(1).getTokenIndex();} 922 | WHEN ( qual_id ( OR qual_id )* { 923 | for (int i = 0; i < indent_count - 1; i++) { 924 | output += "\t"; 925 | } 926 | output += "except HiveServerException, hse:\n"; 927 | } | OTHERS { 928 | for (int i = 0; i < indent_count - 1; i++) { 929 | output += "\t"; 930 | } 931 | output += "except:\n";} ) THEN 932 | { 933 | 934 | } 935 | ( statement SEMI )+ 936 | { 937 | output += stat; 938 | stat = ""; 939 | } 940 | ; 941 | 942 | statement : 943 | label* 944 | ( assign_or_call_statement 945 | | case_statement 946 | | close_statement 947 | | continue_statement 948 | | basic_loop_statement 949 | | execute_immediate_statement 950 | | exit_statement 951 | | fetch_statement 952 | | for_loop_statement 953 | | forall_statement 954 | | goto_statement 955 | | if_statement 956 | | null_statement 957 | | open_statement 958 | | plsql_block 959 | | raise_statement 960 | | return_statement 961 | | sql_statement 962 | | while_loop_statement 963 | | dbmsfunc_call 964 | ) 965 | ; 966 | 967 | lvalue 968 | @init{ 969 | String previous_id = ""; 970 | last_id = ""; 971 | int found = 0; 972 | } 973 | : 974 | {int start = input.LT(1).getTokenIndex(); 975 | int end = 0;} 976 | call_lvalue {previous_id = last_id;} ( DOT {end = input.LT(-1).getTokenIndex(); stat += ".";} call_lvalue )* 977 | { 978 | if (has_collection_type == 1) { 979 | for(int i = 0; i <= collection_var_cnt; i++) { 980 | if (previous_id.contains(collection_variables[i].toLowerCase())) { 981 | found = 1; 982 | break; 983 | } 984 | } 985 | } 986 | if (found == 0) { 987 | if(global == 1) 988 | { 989 | if(end != 0){ 990 | String tmp = input.toString(start, end - 1); 991 | global_import_package_count++; 992 | int i = 0; 993 | 994 | if(!tmp.contains("dbms")&&!tmp.contains("DBMS")) 995 | { 996 | for(i = 0; i < global_import_package_count; i++) 997 | { 998 | if(global_import_package[i].equalsIgnoreCase(tmp)) 999 | break; 1000 | } 1001 | if(i == global_import_package_count) 1002 | global_import_package[i] = tmp; 1003 | else 1004 | global_import_package_count--; 1005 | } 1006 | else 1007 | global_import_package_count--; 1008 | } 1009 | } 1010 | else 1011 | { 1012 | if(end != 0){ 1013 | String tmp = input.toString(start, end - 1); 1014 | import_package_count++; 1015 | int i = 0; 1016 | 1017 | if(!tmp.contains("dbms")&&!tmp.contains("DBMS")) 1018 | { 1019 | for(i = 0; i < import_package_count; i++) 1020 | { 1021 | if(import_package[i].equalsIgnoreCase(tmp)) 1022 | break; 1023 | } 1024 | if(i == import_package_count) 1025 | import_package[i] = tmp; 1026 | else 1027 | import_package_count--; 1028 | } 1029 | else 1030 | import_package_count--; 1031 | } 1032 | } 1033 | } 1034 | } 1035 | ; 1036 | 1037 | assign_or_call_statement 1038 | @init{ 1039 | for(int i = 0; i < indent_count; i++) 1040 | { 1041 | stat += '\t'; 1042 | } 1043 | } 1044 | @after{ 1045 | stat += '\n'; 1046 | } 1047 | : 1048 | {int start = input.LT(1).getTokenIndex();} 1049 | lvalue 1050 | {int end = input.LT(-1).getTokenIndex(); 1051 | String lvalue_string = input.toString(start, end).toLowerCase(); 1052 | } 1053 | ( 1054 | DOT 1055 | {stat += '.';} 1056 | delete_call | 1057 | ASSIGN 1058 | (expression 1059 | { 1060 | if(lvalue_string.contains("(")) 1061 | { 1062 | if( has_collection_type == 1 ) { 1063 | for(int i = 0; i <= collection_var_cnt; i++) 1064 | { 1065 | if(stat.toLowerCase().contains(collection_variables[i].toLowerCase())) 1066 | { 1067 | String tmp1 = lvalue_string.toLowerCase().replace("(", "(tdw, "); 1068 | String tmp2 = tmp1.replace("(tdw, ", "["); 1069 | tmp2 = tmp2.replace(")", "]"); 1070 | stat = stat.replace(tmp1, tmp2); 1071 | break; 1072 | } 1073 | } 1074 | } else { 1075 | String tmp1 = lvalue_string.replace("(", "["); 1076 | tmp1 = tmp1.replace(")", "]"); 1077 | stat = stat.replace(lvalue_string, tmp1); 1078 | } 1079 | } 1080 | 1081 | if( (has_record_type == 1) && exp.equalsIgnoreCase("none ") ) 1082 | { 1083 | int i = 0; 1084 | int found = 0; 1085 | for(i = 0; i <= record_declare_cnt; i++) 1086 | { 1087 | if( lvalue_string.equalsIgnoreCase(record_declare[i])) 1088 | { 1089 | stat += " = " + lvalue_string + ".__class__()"; 1090 | exp = ""; 1091 | found = 1; 1092 | break; 1093 | } 1094 | } 1095 | 1096 | if( found == 0 ) 1097 | stat += " = " + exp; exp = ""; 1098 | } 1099 | else 1100 | { 1101 | stat += " = " + exp; exp = ""; 1102 | } 1103 | }| dbmsfunc_call ))? 1104 | ; 1105 | 1106 | call 1107 | @init{ 1108 | String saved_last_id = ""; 1109 | int bracket = 0; 1110 | } 1111 | @after{ 1112 | if (saved_last_id.length() > 0) 1113 | last_id = saved_last_id; 1114 | } 1115 | : COLON? {if($COLON != null) exp += ":";} ID { 1116 | String tmp = $ID.getText().toLowerCase(); 1117 | if (tmp.toLowerCase().equals("round")) 1118 | tmp = tmp.toLowerCase().replace("round", "tdw_round"); 1119 | else if (tmp.toLowerCase().equals("abs")) 1120 | tmp = tmp.toLowerCase().replace("abs", "tdw_abs"); 1121 | exp += tmp; 1122 | last_id = $ID.getText().toLowerCase(); 1123 | } 1124 | ( LPAREN { 1125 | saved_last_id = last_id; 1126 | int found = 0; 1127 | // check the collection 1128 | if( has_collection_type == 1 ) 1129 | { 1130 | for(int i = 0; i <= collection_var_cnt; i++) 1131 | { 1132 | if($ID.getText().toLowerCase().contains(collection_variables[i].toLowerCase())) 1133 | { 1134 | exp += "["; 1135 | bracket = 1; 1136 | found = 1; 1137 | break; 1138 | } 1139 | } 1140 | } 1141 | if (found == 0) { 1142 | exp += "(tdw, "; 1143 | } 1144 | // ok, we should mark the to_data() call as TODO 1145 | emitFunctionName(tmp.toLowerCase(), $ID.getLine()); 1146 | } 1147 | ( parameter 1148 | { 1149 | } 1150 | ( COMMA {exp += ", ";} (parameter 1151 | { 1152 | } 1153 | |dbmsfunc_call))* )? RPAREN {if (bracket == 0) exp += ")"; else exp += "]";})? 1154 | ; 1155 | 1156 | call_lvalue 1157 | : 1158 | COLON? ID 1159 | { 1160 | if($ID.getText().equalsIgnoreCase("dbms_stats")) 1161 | stat += ""; 1162 | stat += $ID.getText().toLowerCase(); 1163 | last_id = $ID.getText().toLowerCase(); 1164 | } 1165 | ( LPAREN {stat += "(tdw, ";} ( parameter {stat += exp ;exp = "";} ( COMMA {stat += ", ";} (parameter {stat += exp ;exp = "";}|dbmsfunc_call))* )? RPAREN {stat += ")";})? 1166 | ; 1167 | 1168 | dbmsfunc_call 1169 | : t1=DBMS DOT ( ID | EXECUTE) (LPAREN ( parameter (COMMA (parameter |dbmsfunc_call))* )? RPAREN)* 1170 | ; 1171 | 1172 | delete_call 1173 | : DELETE ( LPAREN parameter? RPAREN )? 1174 | ; 1175 | 1176 | basic_loop_statement 1177 | @init{ 1178 | stat += "\n"; 1179 | for(int i = 0; i < indent_count; i++) 1180 | { 1181 | stat += '\t'; 1182 | } 1183 | stat += "idx = 0\n"; 1184 | for(int i = 0; i < indent_count; i++) 1185 | { 1186 | stat += '\t'; 1187 | } 1188 | String tmp = ""; 1189 | } 1190 | @after{ 1191 | stat += '\n'; 1192 | } 1193 | : 1194 | LOOP {stat += "while True:\n";} 1195 | ({indent_count++;} statement {indent_count--;} SEMI )+ END LOOP label_name? 1196 | ; 1197 | 1198 | case_statement 1199 | @init{ 1200 | for(int i = 0; i < indent_count; i++) 1201 | { 1202 | stat += '\t'; 1203 | } 1204 | } 1205 | @after{ 1206 | stat += '\n'; 1207 | } 1208 | : 1209 | CASE expression? 1210 | {String variable = exp; exp = ""; 1211 | int flag = 0; 1212 | } 1213 | ( WHEN expression THEN 1214 | {if(flag == 0) 1215 | { 1216 | stat += "if " + variable + " == " + exp + ":\n"; 1217 | exp = ""; 1218 | flag = 1; 1219 | } 1220 | else 1221 | { 1222 | for(int i = 0; i < indent_count; i++) 1223 | { 1224 | stat += '\t'; 1225 | } 1226 | stat += "elif " + variable + " == " + exp + ":\n"; 1227 | exp = ""; 1228 | } 1229 | } 1230 | ({indent_count++;} statement {indent_count--;} SEMI )+ )+ 1231 | ( ELSE 1232 | { 1233 | for(int i = 0; i < indent_count; i++) 1234 | { 1235 | stat += '\t'; 1236 | } 1237 | stat += "else:\n"; 1238 | } 1239 | {indent_count++;} statement SEMI {indent_count--;})? END CASE 1240 | label_name? 1241 | ; 1242 | 1243 | close_statement 1244 | @init{ 1245 | for(int i = 0; i < indent_count; i++) 1246 | { 1247 | stat += '\t'; 1248 | } 1249 | } 1250 | @after{ 1251 | stat += '\n'; 1252 | } 1253 | : 1254 | {int start = input.LT(1).getTokenIndex(); 1255 | stat += "#FIXME: CURSOR CLOSE STATEMENT\n"; 1256 | for(int i = 0; i < indent_count; i++) 1257 | { 1258 | stat += '\t'; 1259 | } 1260 | } 1261 | CLOSE ID ( DOT ID )? 1262 | { 1263 | stat += "pass"; 1264 | } 1265 | ; 1266 | 1267 | continue_statement 1268 | @init{ 1269 | for(int i = 0; i < indent_count; i++) 1270 | { 1271 | stat += '\t'; 1272 | } 1273 | String tmp = ""; 1274 | } 1275 | @after{ 1276 | stat += '\n'; 1277 | } 1278 | : 1279 | CONTINUE ( lbl=ID )? ( WHEN expression )? 1280 | { 1281 | if(exp.equals("")) 1282 | { 1283 | stat += "continue"; 1284 | } 1285 | else 1286 | { 1287 | stat += "if " + exp + ":\n"; 1288 | exp = ""; 1289 | for(int i = 0; i < indent_count; i++) 1290 | { 1291 | stat += '\t'; 1292 | } 1293 | stat += "\tcontinue\n"; 1294 | } 1295 | } 1296 | ; 1297 | 1298 | execute_immediate_statement 1299 | @init{ 1300 | for(int i = 0; i < indent_count; i++) 1301 | { 1302 | stat += '\t'; 1303 | } 1304 | String tmp = ""; 1305 | } 1306 | @after{ 1307 | stat += '\n'; 1308 | exp = ""; 1309 | } 1310 | : 1311 | EXECUTE IMMEDIATE expression 1312 | {tmp = exp; exp = ""; 1313 | stat += "__line = tdw.execute(" + tmp.toLowerCase() + ")\n"; 1314 | }( 1315 | ( into_clause 1316 | 1317 | | bulk_collect_into_clause) using_clause? 1318 | | using_clause dynamic_returning_clause? 1319 | | dynamic_returning_clause 1320 | )? 1321 | ; 1322 | 1323 | exit_statement 1324 | @init{ 1325 | for(int i = 0; i < indent_count; i++) 1326 | { 1327 | stat += '\t'; 1328 | } 1329 | String tmp = ""; 1330 | exp = ""; 1331 | } 1332 | @after{ 1333 | stat += '\n'; 1334 | } 1335 | : 1336 | EXIT ( lbl=ID )? ( WHEN expression)? 1337 | { 1338 | if(exp.equals("")) 1339 | { 1340 | stat += "break"; 1341 | } else if (exp.matches(".*\% *NOTFOUND")) { 1342 | stat += "if " + exp.substring(0, exp.indexOf("\%")) + " == \"\":\n"; 1343 | exp = ""; 1344 | for(int i = 0; i < indent_count; i++) 1345 | { 1346 | stat += '\t'; 1347 | } 1348 | stat += "\tbreak\n"; 1349 | } else { 1350 | stat += "if " + exp + ":\n"; 1351 | exp = ""; 1352 | for(int i = 0; i < indent_count; i++) 1353 | { 1354 | stat += '\t'; 1355 | } 1356 | stat += "\tbreak\n"; 1357 | } 1358 | } 1359 | ; 1360 | 1361 | fetch_statement 1362 | @init{ 1363 | String v_cursor = ""; 1364 | int saved_ic = indent_count; 1365 | for(int i = 0; i < indent_count; i++) 1366 | { 1367 | stat += '\t'; 1368 | } 1369 | } 1370 | @after{ 1371 | for(int i = 0; i < saved_ic; i++) 1372 | { 1373 | stat += '\t'; 1374 | } 1375 | stat += "except TypeError, te:\n"; 1376 | for(int i = 0; i < indent_count; i++) 1377 | { 1378 | stat += '\t'; 1379 | } 1380 | stat += v_cursor + " = \"\"\n"; 1381 | for(int i = 0; i < saved_ic; i++) 1382 | { 1383 | stat += '\t'; 1384 | } 1385 | stat += "except IndexError, ie:\n"; 1386 | for(int i = 0; i < indent_count; i++) 1387 | { 1388 | stat += '\t'; 1389 | } 1390 | stat += v_cursor + " = \"\"\n"; 1391 | stat += '\n'; 1392 | indent_count = saved_ic; 1393 | } 1394 | : 1395 | {int start = input.LT(1).getTokenIndex(); 1396 | stat += "# FIXME: FETCH STATEMENT\n"; 1397 | for(int i = 0; i < indent_count; i++) 1398 | { 1399 | stat += '\t'; 1400 | } 1401 | stat += "try:\n"; 1402 | indent_count++; 1403 | for(int i = 0; i < indent_count; i++) 1404 | { 1405 | stat += '\t'; 1406 | } 1407 | } 1408 | FETCH qual_id 1409 | { 1410 | v_cursor = input.LT(-1).getText().toLowerCase(); 1411 | stat += "__line = " + v_cursor + "['result'][0]\n"; 1412 | for(int i = 0; i < indent_count; i++) 1413 | { 1414 | stat += '\t'; 1415 | } 1416 | stat += "__line = __line.split(\"\\t\")\n"; 1417 | } 1418 | ( into_clause | bulk_collect_into_clause ( LIMIT numeric_expression )? ) 1419 | { 1420 | for (int i = 0; i < indent_count; i++) { 1421 | stat += '\t'; 1422 | } 1423 | stat += "__TMP__ = " + v_cursor + "['result'].pop(0)\n"; 1424 | } 1425 | ; 1426 | 1427 | into_clause 1428 | @init{ 1429 | int __idx = 0; 1430 | String tmp = "", saved = stat; 1431 | stat = ""; 1432 | for(int i = 0; i < indent_count; i++) 1433 | { 1434 | tmp += '\t'; 1435 | } 1436 | } 1437 | @after{ 1438 | if (__idx == 0) 1439 | tmp += ")\n"; 1440 | stat = saved + tmp; 1441 | } 1442 | : 1443 | INTO lvalue { 1444 | if( has_collection_type == 1 ) 1445 | { 1446 | for(int i = 0; i <= collection_var_cnt; i++) 1447 | { 1448 | if(stat.toLowerCase().contains(collection_variables[i].toLowerCase())) 1449 | { 1450 | stat = stat.replace("(", "["); 1451 | stat = stat.replace(")", "]"); 1452 | break; 1453 | } 1454 | } 1455 | } 1456 | tmp += stat + " = " + stat +".__class__(__line"; 1457 | stat = ""; 1458 | } 1459 | ( COMMA lvalue { 1460 | if( has_collection_type == 1 ) 1461 | { 1462 | for(int i = 0; i <= collection_var_cnt; i++) 1463 | { 1464 | if(stat.toLowerCase().contains(collection_variables[i].toLowerCase())) 1465 | { 1466 | stat = stat.replace("(", "["); 1467 | stat = stat.replace(")", "]"); 1468 | break; 1469 | } 1470 | } 1471 | } 1472 | if (__idx == 0) 1473 | tmp += "[0])\n"; 1474 | for(int i = 0; i < indent_count; i++) 1475 | { 1476 | tmp += '\t'; 1477 | } 1478 | __idx++; 1479 | tmp += stat + " = " + stat + ".__class__(__line[" + __idx + "])\n"; 1480 | stat = ""; 1481 | } )* 1482 | ; 1483 | 1484 | bulk_collect_into_clause 1485 | @init{ 1486 | int __idx = 0; 1487 | String tmp = "", saved = stat; 1488 | stat = ""; 1489 | for(int i = 0; i < indent_count; i++) 1490 | { 1491 | tmp += '\t'; 1492 | } 1493 | } 1494 | @after{ 1495 | if (__idx == 0) 1496 | tmp += ")\n"; 1497 | stat = saved + tmp; 1498 | } 1499 | : 1500 | BULK COLLECT INTO lvalue { 1501 | if( has_collection_type == 1 ) 1502 | { 1503 | for(int i = 0; i <= collection_var_cnt; i++) 1504 | { 1505 | if(stat.toLowerCase().contains(collection_variables[i].toLowerCase())) 1506 | { 1507 | stat = stat.replace("(", "["); 1508 | stat = stat.replace(")", "]"); 1509 | break; 1510 | } 1511 | } 1512 | } 1513 | tmp += stat + " = " + stat +".__class__(__line"; 1514 | stat = ""; 1515 | }( COMMA lvalue { 1516 | if( has_collection_type == 1 ) 1517 | { 1518 | for(int i = 0; i <= collection_var_cnt; i++) 1519 | { 1520 | if(stat.toLowerCase().contains(collection_variables[i].toLowerCase())) 1521 | { 1522 | stat = stat.replace("(", "["); 1523 | stat = stat.replace(")", "]"); 1524 | break; 1525 | } 1526 | } 1527 | } 1528 | if (__idx == 0) 1529 | tmp += "[0])\n"; 1530 | for(int i = 0; i < indent_count; i++) 1531 | { 1532 | tmp += '\t'; 1533 | } 1534 | __idx++; 1535 | tmp += stat + " = " + stat + ".__class__(__line[" + __idx + "])\n"; 1536 | stat = ""; 1537 | })* 1538 | ; 1539 | 1540 | using_clause : 1541 | USING param_modifiers? expression ( COMMA param_modifiers? expression )* 1542 | ; 1543 | 1544 | param_modifiers 1545 | : IN OUT? | OUT 1546 | ; 1547 | 1548 | dynamic_returning_clause : 1549 | ( RETURNING | RETURN ) ( into_clause | bulk_collect_into_clause ) 1550 | ; 1551 | 1552 | for_loop_statement 1553 | @init{ 1554 | stat += '\n'; 1555 | for(int i = 0; i < indent_count; i++) 1556 | { 1557 | stat += '\t'; 1558 | } 1559 | } 1560 | @after{ 1561 | stat += '\n'; 1562 | }: 1563 | FOR ID IN 1564 | {int start = input.LT(1).getTokenIndex();} 1565 | ( ~(LOOP) )+ 1566 | {int end = input.LT(-1).getTokenIndex(); 1567 | int pos = end + 1; 1568 | while(input.get(pos).getChannel() != 0) 1569 | pos++; 1570 | end = pos - 1; 1571 | String tmp = input.toString(start, end); 1572 | if(tmp.toUpperCase().contains("SELECT")) { 1573 | has_collection_type = 1; 1574 | collection_var_cnt++; 1575 | collection_variables[collection_var_cnt] = $ID.getText().toLowerCase(); 1576 | stat += "# FIXME: this is a SQL loop block, you have to check it!\n"; 1577 | todo_count++; 1578 | tmp = tmp.replaceAll("\n", " "); 1579 | tmp = tmp.trim(); 1580 | if (1 == 0) { 1581 | stat += "sqlfor = \"\"\"" + tmp + "\"\"\"\n"; 1582 | for(int i = 0; i < indent_count; i++) 1583 | { 1584 | stat += '\t'; 1585 | } 1586 | stat += "sqlresult = tdw.execute(sqlfor)\n"; 1587 | for(int i = 0; i < indent_count; i++) 1588 | { 1589 | stat += '\t'; 1590 | } 1591 | stat += "for " + $ID.getText().toLowerCase() + " in sqlresult:\n"; 1592 | } else { 1593 | // Is this a cursor variable? 1594 | for (int i = 0; i < indent_count; i++) { 1595 | stat += '\t'; 1596 | } 1597 | stat += "# NOTE: implicit for-loop cursor\n"; 1598 | for (int i = 0; i < indent_count; i++) { 1599 | stat += '\t'; 1600 | } 1601 | stat += "__TMP__ = dict()\n"; 1602 | for (int i = 0; i < indent_count; i++) { 1603 | stat += '\t'; 1604 | } 1605 | stat += "__TMP__['sql'] = '''" + tmp + "'''\n"; 1606 | for (int i = 0; i < indent_count; i++) { 1607 | stat += '\t'; 1608 | } 1609 | stat += "__TMP__['isopen'] = 1\n"; 1610 | for (int i = 0; i < indent_count; i++) { 1611 | stat += '\t'; 1612 | } 1613 | stat += "__sql_result = tdw.execute(__TMP__['sql'])\n"; 1614 | for (int i = 0; i < indent_count; i++) { 1615 | stat += '\t'; 1616 | } 1617 | stat += "# __sql_result is a Python List\n"; 1618 | for (int i = 0; i < indent_count; i++) { 1619 | stat += '\t'; 1620 | } 1621 | stat += "__TMP__['schema'] = tdw.getschemax()\n"; 1622 | for (int i = 0; i < indent_count; i++) { 1623 | stat += '\t'; 1624 | } 1625 | stat += "# 'schema' is a Python list (col0 => col_name, ...)\n"; 1626 | for (int i = 0; i < indent_count; i++) { 1627 | stat += '\t'; 1628 | } 1629 | stat += "__TMP__['type'] = tdw.gettypex()\n"; 1630 | for (int i = 0; i < indent_count; i++) { 1631 | stat += '\t'; 1632 | } 1633 | stat += "# 'type' is a Python list (col0 => col_type, ...)\n"; 1634 | for (int i = 0; i < indent_count; i++) { 1635 | stat += '\t'; 1636 | } 1637 | stat += "# Convert result list to Python Class Object w/ schema: .col_name=AAA ...\n"; 1638 | for (int i = 0; i < indent_count; i++) { 1639 | stat += '\t'; 1640 | } 1641 | stat += "__TMP__['result'] = tdw.parseschema(__TMP__, __sql_result)\n\n"; 1642 | for (int i = 0; i < indent_count; i++) { 1643 | stat += '\t'; 1644 | } 1645 | stat += "for " + $ID.getText().toLowerCase() + " in __TMP__['result'] :\n"; 1646 | } 1647 | } else { 1648 | tmp = input.toString(start, end).toLowerCase(); 1649 | if(tmp.contains("..")) { 1650 | if(tmp.contains("reverse")) { 1651 | tmp = tmp.toLowerCase(); 1652 | tmp = tmp.trim(); 1653 | tmp = tmp.substring(7, tmp.length()); 1654 | String[] sArray = tmp.split("\\.\\."); 1655 | if(sArray[1].contains(".count")) 1656 | { 1657 | String[] sArray1 = sArray[1].split("\\."); 1658 | tmp = "reversed(range(" + sArray[0] + ", len(" + sArray1[0] + ") + 1))"; 1659 | } 1660 | else 1661 | { 1662 | tmp = "reversed(range(" + sArray[0] + ", " + sArray[1] + "))"; 1663 | } 1664 | } else { 1665 | tmp = tmp.toLowerCase(); 1666 | tmp = tmp.replaceAll("\n", " "); 1667 | tmp = tmp.trim(); 1668 | String[] sArray = tmp.split("\\.\\."); 1669 | if(sArray[1].contains(".count")) 1670 | { 1671 | String[] sArray1 = sArray[1].split("\\."); 1672 | tmp = "range(" + sArray[0] + ", len(" + sArray1[0] + ") + 1)"; 1673 | } else if (sArray[1].contains("length(")) { 1674 | tmp = "range(" + sArray[0] + ", " + sArray[1].replace("length(", "length(tdw, ") + ")"; 1675 | } else 1676 | { 1677 | tmp = "range(" + sArray[0] + ", " + sArray[1] + ")"; 1678 | } 1679 | } 1680 | stat += "for " + $ID.getText().toLowerCase() + " in " + tmp + ":\n"; 1681 | } else { 1682 | // Is this a cursor variable? 1683 | // Then, put the $ID.getText() in to the varlist 1684 | has_collection_type = 1; 1685 | collection_var_cnt++; 1686 | collection_variables[collection_var_cnt] = $ID.getText().toLowerCase(); 1687 | if (tmp.contains("(")) { 1688 | stat += "# FIXME: for-loop cursor with a variable arguments!\n"; 1689 | } else { 1690 | stat += "# NOTE: for-loop cursor\n"; 1691 | } 1692 | for (int i = 0; i < indent_count; i++) { 1693 | stat += '\t'; 1694 | } 1695 | stat += tmp + "['isopen'] = 1\n"; 1696 | for (int i = 0; i < indent_count; i++) { 1697 | stat += '\t'; 1698 | } 1699 | stat += "__sql_result = tdw.execute(" + tmp.toLowerCase() + "['sql'])\n"; 1700 | for (int i = 0; i < indent_count; i++) { 1701 | stat += '\t'; 1702 | } 1703 | stat += "# __sql_result is a Python List\n"; 1704 | for (int i = 0; i < indent_count; i++) { 1705 | stat += '\t'; 1706 | } 1707 | stat += tmp + "['schema'] = tdw.getschemax()\n"; 1708 | for (int i = 0; i < indent_count; i++) { 1709 | stat += '\t'; 1710 | } 1711 | stat += "# 'schema' is a Python list (col0 => col_name, ...)\n"; 1712 | for (int i = 0; i < indent_count; i++) { 1713 | stat += '\t'; 1714 | } 1715 | stat += tmp + "['type'] = tdw.gettypex()\n"; 1716 | for (int i = 0; i < indent_count; i++) { 1717 | stat += '\t'; 1718 | } 1719 | stat += "# 'type' is a Python list (col0 => col_type, ...)\n"; 1720 | for (int i = 0; i < indent_count; i++) { 1721 | stat += '\t'; 1722 | } 1723 | stat += "# Convert result list to Python Class Object w/ schema: .col_name=AAA ...\n"; 1724 | for (int i = 0; i < indent_count; i++) { 1725 | stat += '\t'; 1726 | } 1727 | stat += tmp + "['result'] = tdw.parseschema(" + tmp + ", __sql_result)\n\n"; 1728 | for (int i = 0; i < indent_count; i++) { 1729 | stat += '\t'; 1730 | } 1731 | stat += "for " + $ID.getText().toLowerCase() + " in " + tmp + "['result'] :\n"; 1732 | } 1733 | } 1734 | } 1735 | LOOP ( { 1736 | indent_count++; 1737 | } statement {indent_count--;} SEMI )+ END LOOP 1738 | label_name? 1739 | ; 1740 | 1741 | forall_statement 1742 | @init{ 1743 | for(int i = 0; i < indent_count; i++) 1744 | { 1745 | stat += '\t'; 1746 | } 1747 | } 1748 | @after{ 1749 | stat += '\n'; 1750 | } 1751 | : 1752 | FORALL ID IN 1753 | {int start = input.LT(1).getTokenIndex();} 1754 | bounds_clause 1755 | {int end = input.LT(-1).getTokenIndex(); 1756 | int pos = end + 1; 1757 | while(input.get(pos).getChannel() != 0) 1758 | pos++; 1759 | end = pos - 1; 1760 | String tmp = input.toString(start, end).toLowerCase(); 1761 | if(tmp.contains("..")) 1762 | { 1763 | String[] sArray = tmp.split("\\.\\."); 1764 | tmp = "range(" + sArray[0] + ", " + sArray[1] + ")"; 1765 | tmp = tmp.replace("\n", ""); 1766 | } 1767 | stat += "for " + $ID.getText().toLowerCase() + " in " + tmp + " :\n"; 1768 | } 1769 | {indent_count++;} 1770 | sql_statement 1771 | { indent_count--;} 1772 | ( kSAVE kEXCEPTIONS )? 1773 | ; 1774 | 1775 | bounds_clause 1776 | : numeric_expression {exp = "";} DOUBLEDOT numeric_expression {exp = "";} 1777 | | kINDICES kOF atom ( BETWEEN numeric_expression {exp = "";} AND numeric_expression {exp = "";} )? 1778 | | kVALUES kOF atom 1779 | ; 1780 | 1781 | goto_statement : 1782 | GOTO ID 1783 | { 1784 | // or GOTO lable_name 1785 | for(int i = 0; i < indent_count; i++) 1786 | { 1787 | stat += '\t'; 1788 | } 1789 | stat += "# FIXME: goto statement is not supported. Please fix it!\n"; 1790 | for(int i = 0; i < indent_count; i++) 1791 | { 1792 | stat += '\t'; 1793 | } 1794 | stat += "# goto " + $ID.getText().toLowerCase() + "\n"; 1795 | for(int i = 0; i < indent_count; i++) 1796 | { 1797 | stat += '\t'; 1798 | } 1799 | stat += "pass\n"; 1800 | } 1801 | ; 1802 | 1803 | if_statement 1804 | @init{ 1805 | for(int i = 0; i < indent_count; i++) 1806 | { 1807 | stat += '\t'; 1808 | } 1809 | } 1810 | @after{ 1811 | stat += '\n'; 1812 | }: 1813 | IF expression THEN 1814 | { 1815 | stat += "if " + exp + ":\n"; exp = "";} 1816 | ( {indent_count++;} statement {indent_count--;} SEMI )+ 1817 | ( ELSIF expression THEN 1818 | { 1819 | for(int i = 0; i < indent_count; i++) 1820 | { 1821 | stat += '\t'; 1822 | } 1823 | stat += "elif " + exp + ":\n"; exp = "";} 1824 | ( {indent_count++;} statement {indent_count--;} SEMI )+ )* 1825 | ( ELSE 1826 | { 1827 | for(int i = 0; i < indent_count; i++) 1828 | { 1829 | stat += '\t'; 1830 | } 1831 | stat += "else " + ":\n"; exp = "";} 1832 | ( {indent_count++;} statement {indent_count--;} SEMI )+ )? 1833 | END IF 1834 | ; 1835 | 1836 | null_statement 1837 | @init{ 1838 | for(int i = 0; i < indent_count; i++) 1839 | { 1840 | stat += '\t'; 1841 | } 1842 | } 1843 | @after{ 1844 | stat += '\n'; 1845 | } 1846 | : 1847 | NULL {stat += "None";} 1848 | ; 1849 | 1850 | open_statement 1851 | @init{ 1852 | int is_static = 1; 1853 | stat += '\n'; 1854 | String cursor_name = ""; 1855 | for(int i = 0; i < indent_count; i++) 1856 | { 1857 | stat += '\t'; 1858 | } 1859 | } 1860 | @after{ 1861 | stat += '\n'; 1862 | } 1863 | : 1864 | {int start = input.LT(1).getTokenIndex(); 1865 | stat += "# FIXME: CURSOR OPEN STATEMENT\n"; 1866 | for(int i = 0; i < indent_count; i++) 1867 | { 1868 | stat += '\t'; 1869 | } 1870 | } 1871 | OPEN ID {cursor_name = input.LT(-1).getText().toLowerCase(); stat += cursor_name + " = ({'isopen':1, 'result':";} ( DOT ID )* call_args? 1872 | ( FOR (select_statement {is_static =0; stat += "tdw.execute(" + __sql + ")"; __sql = "";}| ID { 1873 | is_static = 0; 1874 | stat += "tdw.execute(" + input.LT(-1).getText().toLowerCase() + ")"; 1875 | } ) )? { 1876 | if (is_static == 1) { 1877 | stat += "tdw.execute(" + cursor_name + "['sql'])"; 1878 | } 1879 | stat += "})\n"; 1880 | } 1881 | ; 1882 | 1883 | pragma : 1884 | PRAGMA swallow_to_semi 1885 | ; 1886 | 1887 | raise_statement 1888 | @after{ 1889 | stat += ");\n"; 1890 | }: 1891 | RAISE { 1892 | for(int i = 0; i < indent_count; i++) 1893 | { 1894 | stat += '\t'; 1895 | } 1896 | stat += "tdw.tdw_raise(-22, "; 1897 | } 1898 | ( ID {stat += input.LT(-1).getText().toLowerCase();} ( DOT {stat += "."; } ID { 1899 | stat += input.LT(-1).getText().toLowerCase(); 1900 | } )* )? 1901 | ; 1902 | 1903 | return_statement 1904 | @init{ 1905 | for(int i = 0; i < indent_count; i++) 1906 | { 1907 | stat += '\t'; 1908 | } 1909 | } 1910 | @after{ 1911 | stat += '\n'; 1912 | } 1913 | : 1914 | RETURN {stat += "return ";} expression? 1915 | {if(!exp.equals("")) 1916 | { 1917 | stat += exp; 1918 | exp = ""; 1919 | } 1920 | } 1921 | ; 1922 | 1923 | plsql_block 1924 | @init{ 1925 | int saved_cp = create_package; 1926 | create_package = 0; 1927 | } 1928 | @after{ 1929 | create_package = saved_cp; 1930 | } 1931 | : 1932 | ( DECLARE declare_section )? body_block 1933 | ; 1934 | 1935 | body_block 1936 | @init{ 1937 | indent_count++; 1938 | int has_exception_handler = 0; 1939 | } 1940 | @after{ 1941 | indent_count--; 1942 | } 1943 | : 1944 | BEGIN { 1945 | for (int i = 0; i < indent_count-1; i++) { 1946 | stat += "\t"; 1947 | } 1948 | stat += "# BEGIN a BODY AGAIN\n"; 1949 | for (int i = 0; i < indent_count-1; i++) { 1950 | stat += "\t"; 1951 | } 1952 | stat += "try:\n"; 1953 | } 1954 | statement { 1955 | if (!stat.equals("")) { 1956 | output += stat; 1957 | stat = ""; 1958 | } 1959 | } 1960 | SEMI ( statement { 1961 | if (!stat.equals("")) { 1962 | output += stat; 1963 | stat = ""; 1964 | } 1965 | } 1966 | SEMI | pragma SEMI )* 1967 | ( 1968 | { 1969 | stat = ""; 1970 | } 1971 | EXCEPTION {has_exception_handler = 1;} exception_handler+ 1972 | )? END { 1973 | if (has_exception_handler == 0) { 1974 | for (int i = 0; i < indent_count - 1; i++) { 1975 | stat += "\t"; 1976 | } 1977 | stat += "except HiveServerException, hse:\n"; 1978 | for (int i = 0; i < indent_count; i++) { 1979 | stat += "\t"; 1980 | } 1981 | 1982 | stat += "print hse\n"; 1983 | } 1984 | }ID? 1985 | ; 1986 | 1987 | label : 1988 | LLABEL ID RLABEL 1989 | { 1990 | for (int i = 0; i < indent_count; i++) { 1991 | stat += "\t"; 1992 | } 1993 | stat += "# FIXME: there is no goto statement in python. Please fix it!\n"; 1994 | for (int i = 0; i < indent_count; i++) { 1995 | stat += "\t"; 1996 | } 1997 | stat += "# <<" + $ID.getText().toLowerCase() + ">>\n"; 1998 | } 1999 | ; 2000 | 2001 | qual_id : 2002 | COLON? ID ( DOT COLON? ID )* 2003 | ; 2004 | 2005 | sql_statement 2006 | : commit_statement 2007 | | delete_statement 2008 | | insert_statement 2009 | | lock_table_statement 2010 | | rollback_statement 2011 | | savepoint_statement 2012 | | select_statement 2013 | | set_transaction_statement 2014 | | update_statement 2015 | | merge_statement 2016 | ; 2017 | 2018 | commit_statement 2019 | @init{ 2020 | for(int i = 0; i < indent_count; i++) 2021 | { 2022 | stat += '\t'; 2023 | } 2024 | } 2025 | @after{ 2026 | stat += '\n'; 2027 | } 2028 | : 2029 | COMMIT swallow_to_semi? 2030 | { 2031 | stat += "commit()"; 2032 | } 2033 | ; 2034 | 2035 | delete_statement 2036 | @init{ 2037 | for(int i = 0; i < indent_count; i++) 2038 | { 2039 | stat += '\t'; 2040 | } 2041 | } 2042 | @after{ 2043 | stat += '\n'; 2044 | } 2045 | : 2046 | {int start = input.LT(1).getTokenIndex();} 2047 | DELETE swallow_to_semi 2048 | {int end = input.LT(-1).getTokenIndex(); 2049 | String tmp = input.toString(start, end); 2050 | int length = tmp.length(); 2051 | 2052 | for(int i = 0; i < length; i++) 2053 | if(tmp.charAt(i) == '\n') 2054 | sql_count++; 2055 | stat += "sql_select = \"\"\"" + tmp + "\"\"\"\n"; 2056 | for(int i = 0; i < indent_count; i++) 2057 | { 2058 | stat += '\t'; 2059 | } 2060 | stat += "tdw.execute(sql_select)\n"; 2061 | } 2062 | ; 2063 | 2064 | insert_statement 2065 | @init{ 2066 | for(int i = 0; i < indent_count; i++) 2067 | { 2068 | stat += '\t'; 2069 | } 2070 | } 2071 | @after{ 2072 | stat += '\n'; 2073 | } 2074 | : 2075 | {int start = input.LT(1).getTokenIndex();} 2076 | INSERT swallow_to_semi 2077 | {int end = input.LT(-1).getTokenIndex(); 2078 | String tmp = input.toString(start, end); 2079 | int length = tmp.length(); 2080 | for(int i = 0; i < length; i++) 2081 | if(tmp.charAt(i) == '\n') 2082 | sql_count++; 2083 | stat += "sql_select = \"\"\"" + tmp + "\"\"\"\n"; 2084 | for(int i = 0; i < indent_count; i++) 2085 | { 2086 | stat += '\t'; 2087 | } 2088 | stat += "tdw.execute(sql_select)\n"; 2089 | } 2090 | ; 2091 | 2092 | lock_table_statement : 2093 | LOCK TABLE swallow_to_semi 2094 | ; 2095 | 2096 | rollback_statement 2097 | @init{ 2098 | for(int i = 0; i < indent_count; i++) 2099 | { 2100 | stat += '\t'; 2101 | } 2102 | } 2103 | @after{ 2104 | stat += '\n'; 2105 | } 2106 | : 2107 | ROLLBACK swallow_to_semi? 2108 | { 2109 | stat += "rollback()"; 2110 | } 2111 | ; 2112 | 2113 | savepoint_statement 2114 | @init{ 2115 | for(int i = 0; i < indent_count; i++) 2116 | { 2117 | stat += '\t'; 2118 | } 2119 | } 2120 | @after{ 2121 | stat += '\n'; 2122 | } 2123 | : 2124 | {int start = input.LT(1).getTokenIndex();} 2125 | SAVEPOINT ID 2126 | {int end = input.LT(-1).getTokenIndex(); 2127 | int pos = end + 1; 2128 | while(input.get(pos).getChannel() != 0) 2129 | pos++; 2130 | end = pos - 1; 2131 | stat += input.toString(start, end);} 2132 | ; 2133 | 2134 | select_statement 2135 | @init{ 2136 | for(int i = 0; i < indent_count; i++) 2137 | { 2138 | stat += '\t'; 2139 | } 2140 | } 2141 | @after{ 2142 | stat += '\n'; 2143 | } 2144 | : 2145 | {int start = input.LT(1).getTokenIndex();} 2146 | SELECT swallow_to_semi 2147 | {int end = input.LT(-1).getTokenIndex(); 2148 | String tmp = input.toString(start, end); 2149 | int length = tmp.length(); 2150 | 2151 | for(int i = 0; i < length; i++) 2152 | if(tmp.charAt(i) == '\n') 2153 | sql_count++; 2154 | stat += "sql_select = \"\"\"" + tmp + "\"\"\"\n"; 2155 | __sql = "\"\"\"" + tmp + "\"\"\""; 2156 | for(int i = 0; i < indent_count; i++) 2157 | { 2158 | stat += '\t'; 2159 | } 2160 | 2161 | if(tmp.toLowerCase().contains("into")) 2162 | { 2163 | int begin_pos = tmp.toLowerCase().indexOf("into"); 2164 | int end_pos = tmp.toLowerCase().indexOf("from", begin_pos); 2165 | 2166 | if(begin_pos > tmp.length() || begin_pos < 0 || end_pos > tmp.length() || end_pos <0 ) 2167 | { 2168 | System.out.print(tmp); 2169 | stat += "tdw.execute(sql_select)\n"; 2170 | } 2171 | else 2172 | { 2173 | String into_exp = tmp.substring(begin_pos + 4, end_pos - 1); 2174 | if (into_exp.contains("--")) 2175 | into_exp = into_exp.substring(0, into_exp.indexOf("--")); 2176 | else if (into_exp.contains("/*")) { 2177 | into_exp = into_exp.replaceAll("/\\*.*\\*/", ""); 2178 | } 2179 | into_exp = into_exp.trim().toLowerCase(); 2180 | Pattern p = Pattern.compile("\\s*|\t|\r|\n"); 2181 | Matcher m = p.matcher(into_exp); 2182 | into_exp = m.replaceAll(""); 2183 | into_exp = into_exp.replace("(", "["); 2184 | into_exp = into_exp.replace(")", "]"); 2185 | into_exp = into_exp.replace(",", ", "); 2186 | 2187 | stat += '(' + into_exp + ") = tdw.execute(sql_select)\n"; 2188 | } 2189 | } 2190 | else 2191 | stat += "tdw.execute(sql_select)\n"; 2192 | 2193 | } 2194 | ; 2195 | catch[StringIndexOutOfBoundsException e] {e.getMessage();} 2196 | 2197 | set_transaction_statement : 2198 | SET TRANSACTION swallow_to_semi 2199 | ; 2200 | 2201 | update_statement 2202 | @init{ 2203 | for(int i = 0; i < indent_count; i++) 2204 | { 2205 | stat += '\t'; 2206 | } 2207 | } 2208 | @after{ 2209 | stat += '\n'; 2210 | } 2211 | : 2212 | {int start = input.LT(1).getTokenIndex();} 2213 | UPDATE swallow_to_semi 2214 | {int end = input.LT(-1).getTokenIndex(); 2215 | String tmp = input.toString(start, end); 2216 | int length = tmp.length(); 2217 | 2218 | for(int i = 0; i < length; i++) 2219 | if(tmp.charAt(i) == '\n') 2220 | sql_count++; 2221 | stat += "sql_select = \"\"\"" + tmp + "\"\"\"\n"; 2222 | for(int i = 0; i < indent_count; i++) 2223 | { 2224 | stat += '\t'; 2225 | } 2226 | stat += "tdw.execute(sql_select)\n"; 2227 | } 2228 | ; 2229 | 2230 | merge_statement 2231 | @init{ 2232 | for(int i = 0; i < indent_count; i++) 2233 | { 2234 | stat += '\t'; 2235 | } 2236 | } 2237 | @after{ 2238 | stat += '\n'; 2239 | } 2240 | : 2241 | {int start = input.LT(1).getTokenIndex();} 2242 | MERGE swallow_to_semi 2243 | {int end = input.LT(-1).getTokenIndex(); 2244 | String tmp = input.toString(start, end); 2245 | int length = tmp.length(); 2246 | 2247 | for(int i = 0; i < length; i++) 2248 | if(tmp.charAt(i) == '\n') 2249 | sql_count++; 2250 | stat += "sql_select = \"\"\"" + tmp + "\"\"\"\n"; 2251 | for(int i = 0; i < indent_count; i++) 2252 | { 2253 | stat += '\t'; 2254 | } 2255 | stat += "tdw.execute(sql_select)\n"; 2256 | } 2257 | ; 2258 | 2259 | swallow_to_semi : 2260 | ~( SEMI )+ 2261 | ; 2262 | 2263 | while_loop_statement 2264 | @init{ 2265 | for(int i = 0; i < indent_count; i++) 2266 | { 2267 | stat += '\t'; 2268 | } 2269 | } 2270 | @after{ 2271 | stat += '\n'; 2272 | } 2273 | : 2274 | WHILE expression LOOP 2275 | { 2276 | stat += "while " + exp + ":\n"; 2277 | exp = "";} 2278 | ( {indent_count++;} statement {indent_count--;} SEMI )+ END LOOP label_name? 2279 | ; 2280 | 2281 | match_parens 2282 | : ( options {greedy=false;} : ~( RPAREN | LPAREN | SEMI | AS | IS | IN | OUT ) )* 2283 | | RPAREN match_parens LPAREN 2284 | ; 2285 | 2286 | label_name: 2287 | ID 2288 | ; 2289 | 2290 | expression 2291 | @after{ 2292 | } 2293 | : or_expr 2294 | ; 2295 | 2296 | or_expr 2297 | : and_expr ( OR { exp += " or ";} and_expr )* 2298 | ; 2299 | 2300 | and_expr 2301 | : not_expr ( AND { exp += " and ";} not_expr )* 2302 | ; 2303 | 2304 | not_expr 2305 | : NOT? { if($NOT != null) exp += " not ";} compare_expr 2306 | ; 2307 | 2308 | compare_expr 2309 | : is_null_expr ( 2310 | ( EQ {exp += " == ";} | NOT_EQ {exp += " != ";}| LTH {exp += " < ";}| LEQ {exp += " <= ";}| GTH {exp += " > ";}| GEQ {exp += " >= ";}) 2311 | is_null_expr )? 2312 | ; 2313 | 2314 | is_null_expr 2315 | : like_expr ( IS {exp += " is ";} NOT? { if($NOT != null) exp += " not ";} NULL { exp += " None ";})? 2316 | ; 2317 | 2318 | like_expr 2319 | : between_expr ( 2320 | NOT? { if($NOT != null) exp += " not ";} LIKE { exp += " == ";} 2321 | between_expr )? 2322 | ; 2323 | 2324 | between_expr 2325 | : in_expr ( NOT? { if($NOT != null) exp += " not ";} BETWEEN { exp += " between ";} 2326 | in_expr AND {exp += "and";} in_expr )? 2327 | ; 2328 | 2329 | in_expr 2330 | : add_expr ( NOT? { if($NOT != null) exp += " not ";} IN LPAREN {exp += " in (";} add_expr 2331 | ( COMMA {exp += ", ";} add_expr )* RPAREN {exp += ") ";})? 2332 | ; 2333 | 2334 | numeric_expression 2335 | : add_expr 2336 | ; 2337 | 2338 | add_expr 2339 | @init{ 2340 | int double_vertbar = 0; 2341 | int pos = 0; 2342 | String saved = exp; 2343 | exp = ""; 2344 | } 2345 | @after { 2346 | exp = saved + exp; 2347 | } 2348 | : mul_expr 2349 | ( 2350 | ( MINUS {exp += " - ";} 2351 | | PLUS {exp += " + ";} 2352 | | DOUBLEVERTBAR { exp += " || "; pos = exp.lastIndexOf("||");double_vertbar = 1;} 2353 | ) 2354 | mul_expr 2355 | { 2356 | if(double_vertbar == 1) 2357 | { 2358 | String tmp1 = ""; 2359 | String tmp = ""; 2360 | if(exp.substring(0, pos - 1).contains("==")) 2361 | { 2362 | int i = exp.lastIndexOf("=="); 2363 | tmp1 = exp.substring(0, i + 2); 2364 | tmp = exp.substring(i+2, pos - 1).trim(); 2365 | } 2366 | else 2367 | { 2368 | tmp = exp.substring(0, pos - 1).trim(); 2369 | tmp1 = ""; 2370 | } 2371 | if(tmp.startsWith("\"\"\"")||tmp.startsWith("str(")) 2372 | tmp1 += tmp; 2373 | else 2374 | tmp1 += "str(" + tmp + ")"; 2375 | tmp = exp.substring(pos + 2, exp.length()).trim(); 2376 | if(tmp.startsWith("\"\"\"")||tmp.startsWith("str(")) 2377 | tmp1 += " + " + tmp; 2378 | else 2379 | tmp1 += " + str(" + tmp + ")"; 2380 | 2381 | exp = tmp1; 2382 | double_vertbar = 0; 2383 | } 2384 | } 2385 | )* 2386 | ; 2387 | 2388 | mul_expr 2389 | : unary_sign_expr ( 2390 | ( ASTERISK {exp += " * ";}| DIVIDE {exp += " / ";} | kMOD {exp += " \% ";} ) 2391 | unary_sign_expr )* 2392 | ; 2393 | 2394 | unary_sign_expr 2395 | : 2396 | ( MINUS {exp += " - ";} | PLUS {exp += " + ";})? 2397 | exponent_expr 2398 | ; 2399 | 2400 | exponent_expr 2401 | : atom ( EXPONENT {exp += " ** ";} atom )? 2402 | ; 2403 | 2404 | atom 2405 | @init{ 2406 | String saved = exp; 2407 | exp = ""; 2408 | } 2409 | @after{ 2410 | exp = saved + exp; 2411 | } 2412 | : variable_or_function_call ( 2413 | PERCENT {exp += " \% ";} attribute { 2414 | if (exp.toLowerCase().contains("rowcount")) { 2415 | exp = "tdw.getrowcount()"; 2416 | } else if (exp.toLowerCase().contains("isopen")) { 2417 | String var = exp.substring(0, exp.indexOf("\%")); 2418 | exp = var + "['isopen']"; 2419 | } else if (exp.toLowerCase().contains("notfound")) { 2420 | String var = exp.substring(0, exp.indexOf("\%")); 2421 | exp = var + "== \"\""; 2422 | } else if (exp.toLowerCase().contains("found")) { 2423 | String var = exp.substring(0, exp.indexOf("\%")); 2424 | exp = var + "!= \"\""; 2425 | } 2426 | } )? 2427 | | 2428 | {int start = input.LT(1).getTokenIndex();} 2429 | SQL PERCENT 2430 | {int end = input.LT(-1).getTokenIndex(); 2431 | int pos = end + 1; 2432 | while(input.get(pos).getChannel() != 0) 2433 | pos++; 2434 | end = pos - 1; 2435 | exp += input.toString(start, end).toLowerCase();} 2436 | attribute { 2437 | if (exp.toLowerCase().contains("rowcount")) { 2438 | exp = "tdw.getrowcount()"; 2439 | } 2440 | } 2441 | | string_literal 2442 | | numeric_atom 2443 | | boolean_atom 2444 | | NULL{exp += "None ";} 2445 | | 2446 | LPAREN {exp += "( ";} 2447 | expression 2448 | RPAREN {exp += " )";} 2449 | | LPAREN dbmsfunc_call ( EQ | NOT_EQ | LTH | LEQ | GTH | GEQ ) INTEGER RPAREN 2450 | ; 2451 | 2452 | variable_or_function_call 2453 | @init{ 2454 | String previous_id = ""; 2455 | String saved_exp = ""; 2456 | int found = 0; 2457 | int suspect = 1; 2458 | int replaced = 0; 2459 | last_id = ""; 2460 | } 2461 | : call {previous_id = last_id; saved_exp = exp;} ( DOT { 2462 | if (has_collection_type == 1) { 2463 | for(int i = 0; i <= collection_var_cnt; i++) { 2464 | if (previous_id.toLowerCase().contains(collection_variables[i].toLowerCase())) { 2465 | found = 1; 2466 | break; 2467 | } 2468 | } 2469 | } 2470 | if (found == 0) { 2471 | if (global == 0) { 2472 | import_package_count++; 2473 | int i = 0; 2474 | 2475 | if(!exp.contains("dbms")&&!exp.contains("DBMS")) 2476 | { 2477 | for(i = 0; i < import_package_count; i++) 2478 | { 2479 | if(import_package[i].equalsIgnoreCase(exp)) 2480 | break; 2481 | } 2482 | if(i == import_package_count) 2483 | import_package[i] = exp; 2484 | else 2485 | import_package_count--; 2486 | } 2487 | } else { 2488 | global_import_package_count++; 2489 | int i = 0; 2490 | 2491 | if(!exp.contains("dbms")&&!exp.contains("DBMS")) 2492 | { 2493 | for(i = 0; i < global_import_package_count; i++) 2494 | { 2495 | if(global_import_package[i].equalsIgnoreCase(exp)) 2496 | break; 2497 | } 2498 | if(i == global_import_package_count) 2499 | global_import_package[i] = exp; 2500 | else 2501 | global_import_package_count--; 2502 | } 2503 | } 2504 | } 2505 | suspect = 0; 2506 | saved_exp += '.'; 2507 | exp = ""; 2508 | } call { 2509 | if (has_collection_type == 1) { 2510 | for(int i = 0; i <= collection_var_cnt; i++) { 2511 | if (previous_id.contains(collection_variables[i].toLowerCase())) { 2512 | exp = exp.replace("(tdw, ", "("); 2513 | suspect = 0; 2514 | break; 2515 | } 2516 | } 2517 | } 2518 | saved_exp += exp; 2519 | previous_id = last_id; 2520 | })* {exp = saved_exp;} ( DOT {exp += '.'; suspect = 0;} delete_call )? 2521 | { 2522 | 2523 | if (replaced == 0) { 2524 | //exp = exp.toLowerCase(); 2525 | } 2526 | exp = exp.replace("[tdw, ", "["); 2527 | } 2528 | ; 2529 | 2530 | attribute : 2531 | {int start = input.LT(1).getTokenIndex();} 2532 | BULK_ROWCOUNT LPAREN 2533 | {int end = input.LT(-1).getTokenIndex(); 2534 | int pos = end + 1; 2535 | while(input.get(pos).getChannel() != 0) 2536 | pos++; 2537 | end = pos - 1; 2538 | exp += input.toString(start, end).toLowerCase();} 2539 | expression 2540 | {start = input.LT(1).getTokenIndex();} 2541 | RPAREN 2542 | {end = input.LT(-1).getTokenIndex(); 2543 | pos = end + 1; 2544 | while(input.get(pos).getChannel() != 0) 2545 | pos++; 2546 | end = pos - 1; 2547 | exp += input.toString(start, end).toLowerCase();} 2548 | | 2549 | {int start = input.LT(1).getTokenIndex();} 2550 | kFOUND 2551 | {int end = input.LT(-1).getTokenIndex(); 2552 | int pos = end + 1; 2553 | while(input.get(pos).getChannel() != 0) 2554 | pos++; 2555 | end = pos - 1; 2556 | exp += input.toString(start, end).toLowerCase();} 2557 | | 2558 | {int start = input.LT(1).getTokenIndex();} 2559 | ISOPEN 2560 | {int end = input.LT(-1).getTokenIndex(); 2561 | int pos = end + 1; 2562 | while(input.get(pos).getChannel() != 0) 2563 | pos++; 2564 | end = pos - 1; 2565 | exp += input.toString(start, end).toLowerCase();} 2566 | | 2567 | {int start = input.LT(1).getTokenIndex();} 2568 | NOTFOUND 2569 | {int end = input.LT(-1).getTokenIndex(); 2570 | int pos = end + 1; 2571 | while(input.get(pos).getChannel() != 0) 2572 | pos++; 2573 | end = pos - 1; 2574 | exp += input.toString(start, end).toUpperCase();} 2575 | | 2576 | {int start = input.LT(1).getTokenIndex();} 2577 | kROWCOUNT 2578 | {int end = input.LT(-1).getTokenIndex(); 2579 | int pos = end + 1; 2580 | while(input.get(pos).getChannel() != 0) 2581 | pos++; 2582 | end = pos - 1; 2583 | exp += input.toString(start, end).toLowerCase();} 2584 | ; 2585 | 2586 | call_args 2587 | : 2588 | LPAREN ( parameter ( COMMA parameter )* )? RPAREN 2589 | ; 2590 | 2591 | boolean_atom 2592 | : boolean_literal 2593 | | collection_exists 2594 | | conditional_predicate 2595 | ; 2596 | 2597 | numeric_atom 2598 | : numeric_literal 2599 | ; 2600 | 2601 | numeric_literal 2602 | : INTEGER {exp += $INTEGER.getText();} 2603 | | REAL_NUMBER {exp += $REAL_NUMBER.getText();} 2604 | ; 2605 | 2606 | boolean_literal 2607 | : TRUE {exp += "True";}| FALSE {exp += "False";} 2608 | ; 2609 | 2610 | string_literal 2611 | : 2612 | {int start = input.LT(1).getTokenIndex();} 2613 | QUOTED_STRING 2614 | {int end = input.LT(-1).getTokenIndex(); 2615 | String tmp = input.toString(start, end); 2616 | int length = tmp.length(); 2617 | 2618 | for(int i = 0; i < length; i++) 2619 | if(tmp.charAt(i) == '\n') { 2620 | sql_count++; 2621 | } 2622 | exp += tmp.replace("\'", "\"\"\""); 2623 | } 2624 | ; 2625 | 2626 | collection_exists 2627 | : ID DOT EXISTS LPAREN expression RPAREN 2628 | ; 2629 | 2630 | conditional_predicate 2631 | : INSERTING 2632 | | UPDATING ( LPAREN QUOTED_STRING RPAREN )? 2633 | | DELETING 2634 | ; 2635 | 2636 | parameter 2637 | @init{ 2638 | int has_arrow = 0; 2639 | } 2640 | : 2641 | ( ID ARROW {has_arrow = 1; exp += "'" + $ID.getText().toLowerCase() + " => ";})? 2642 | expression 2643 | {if (has_arrow == 1) {exp += "'";}} 2644 | ; 2645 | 2646 | index 2647 | : expression 2648 | ; 2649 | 2650 | create_package 2651 | @init{ 2652 | create_package = 1; 2653 | } 2654 | @after{ 2655 | pkg_current = $package_name.getText().toLowerCase(); 2656 | } 2657 | : 2658 | CREATE 2659 | ( OR kREPLACE )? PACKAGE ( schema_name=ID DOT )? package_name=ID 2660 | ( invoker_rights_clause )? 2661 | ( IS | AS ) 2662 | ( {indent_count = 1;} declare_section )? {create_package = 0;} 2663 | END ( ID )? SEMI 2664 | ; 2665 | 2666 | create_package_body 2667 | @init{ 2668 | String saved_output = ""; 2669 | indent_count = 1; 2670 | } 2671 | : 2672 | CREATE ( OR kREPLACE )? PACKAGE BODY ( schema_name=ID DOT )? package_name=ID 2673 | { 2674 | global = 0; 2675 | String FileName = $package_name.getText().toLowerCase() + ".py"; 2676 | 2677 | poutf = new File(path + FileName); 2678 | 2679 | if(!poutf.exists()){ 2680 | poutf.createNewFile(); 2681 | } 2682 | 2683 | try { 2684 | pfops = new FileOutputStream(poutf); 2685 | 2686 | String tmp = "# coding=gbk\n\n"; 2687 | pfops.write(tmp.getBytes()); 2688 | } catch (FileNotFoundException e) { 2689 | System.out.print("File not Found"); 2690 | e.printStackTrace(); 2691 | } 2692 | } 2693 | ( IS | AS ) ( {create_package = 1;} declare_section)? {create_package = 0; saved_output = output; output = "";} 2694 | ( initialize_section=body | END ( package_name2=ID )? ) SEMI 2695 | { 2696 | pfops.close(); 2697 | 2698 | File readfile = new File(path + FileName); 2699 | FileInputStream ipfs = new FileInputStream(readfile); 2700 | 2701 | FileName = $package_name.getText().toLowerCase() + "_tmp.py"; 2702 | File writefile = new File(path + FileName); 2703 | if(!writefile.exists()){ 2704 | writefile.createNewFile(); 2705 | } 2706 | FileOutputStream opfs = new FileOutputStream(writefile); 2707 | 2708 | byte[] b = new byte[1024]; 2709 | 2710 | int x = 0; 2711 | 2712 | ipfs.read(b, 0, 13); 2713 | opfs.write(b, 0, 13); 2714 | 2715 | if(import_package_count != -1){ 2716 | String outs = ""; 2717 | 2718 | for(int i = 0; i<= import_package_count; i++){ 2719 | outs = "import " + import_package[i].toLowerCase() + "\n"; 2720 | opfs.write(outs.getBytes()); 2721 | } 2722 | } 2723 | 2724 | String outs = "'''---THIS FILE IS CREATED AUTOMATICALLY---'''\n\n"; 2725 | outs += "from tdw import HiveServerException\n"; 2726 | outs += "from tdw import dynamic_type\n"; 2727 | outs += "from tdw_sql_lib import *\n\n"; 2728 | //outs += "import " + filename.substring(0, filename.indexOf(".")) + "\n\n"; 2729 | //outs += "from " + filename.substring(0, filename.indexOf(".")) + " import *\n\n"; 2730 | 2731 | int i; 2732 | for (i = 0; i <= pkg_list_cnt; i++) { 2733 | if (pkg_list[i][0].equalsIgnoreCase($package_name.getText().toLowerCase())) { 2734 | outs += pkg_list[i][1]; 2735 | break; 2736 | } 2737 | } 2738 | System.out.println("Write package " + $package_name.getText() + " and check pkg_list @" + i); 2739 | 2740 | opfs.write(outs.getBytes()); 2741 | opfs.write(saved_output.getBytes()); 2742 | if (output.length() > 0 && !output.contains("def ")) { 2743 | output = output.replaceAll("^\t", ""); 2744 | output = output.replaceAll("\n\t", "\n"); 2745 | opfs.write(output.getBytes()); 2746 | } else 2747 | opfs.write(output.getBytes()); 2748 | 2749 | while((x = ipfs.read(b, 0, 1024)) != -1){ 2750 | opfs.write(b, 0, x); 2751 | } 2752 | ipfs.close(); 2753 | opfs.close(); 2754 | 2755 | readfile.delete(); 2756 | writefile.renameTo(readfile); 2757 | global = 1; 2758 | } 2759 | ; 2760 | catch[RecognitionException re] {reportError(re);recover(input,re);} 2761 | catch[IOException e] {e.printStackTrace();} 2762 | 2763 | 2764 | create_procedure 2765 | @init{ 2766 | if( has_record_type == 1 ) 2767 | { 2768 | record_define_cnt = -1; 2769 | record_declare_cnt = -1; 2770 | has_record_type = 0; 2771 | } 2772 | 2773 | if( has_collection_type == 1 ) 2774 | { 2775 | collection_type_define_cnt = -1; 2776 | collection_type_declare_cnt = -1; 2777 | //collection_var_cnt = -1; 2778 | has_collection_type = 0; 2779 | } 2780 | 2781 | variables_list_cnt = -1; 2782 | indent_count = 1; 2783 | }: 2784 | CREATE ( OR kREPLACE )? PROCEDURE ( schema_name=ID DOT )? procedure_name=ID 2785 | { 2786 | String tmp = $procedure_name.getText(); 2787 | if(tmp.startsWith("\"")&&tmp.endsWith("\"")) 2788 | tmp = tmp.substring(1, tmp.length() -1 ); 2789 | 2790 | output += "def " + tmp.toLowerCase() + "(tdw, ";} 2791 | ( LPAREN parameter_declaration ( COMMA parameter_declaration)* RPAREN 2792 | { 2793 | int has_defaults = 0; 2794 | for(int i = 0; i <= parameter_list_count; i++) 2795 | { 2796 | if (parameter_list[i].contains("= None")) 2797 | has_defaults = 1; 2798 | } 2799 | if (has_defaults == 1) { 2800 | for(int i = 0; i <= parameter_list_count; i++) 2801 | { 2802 | if (!parameter_list[i].contains("= None")) 2803 | parameter_list[i] += " = None"; 2804 | } 2805 | } 2806 | 2807 | if(parameter_list_count >= 0) 2808 | { 2809 | output += parameter_list[0]; 2810 | for(int i = 1; i <= parameter_list_count; i++) 2811 | { 2812 | output += ", " + parameter_list[i]; 2813 | } 2814 | parameter_list_count = -1; 2815 | } 2816 | } 2817 | )? 2818 | {output += ")";} 2819 | {output += ":\n"; 2820 | if(initial_statement_count >= 0) 2821 | { 2822 | for(int i = 0; i <= initial_statement_count; i++) 2823 | { 2824 | output += '\t' + initial_statement[i] + "\n"; 2825 | } 2826 | initial_statement_count = -1; 2827 | } 2828 | } 2829 | invoker_rights_clause? 2830 | ( IS | AS ) 2831 | ( {indent_count = 1;} declare_section? body 2832 | | call_spec 2833 | | EXTERNAL 2834 | ) 2835 | { 2836 | for(int i = 0; i <= variables_list_cnt; i++ ) 2837 | { 2838 | String reg = "(?i)" + variables_list[i]; 2839 | String repl = variables_list[i].toLowerCase(); 2840 | //output = output.replaceAll(reg, repl); 2841 | } 2842 | } 2843 | SEMI 2844 | ; 2845 | 2846 | create_function 2847 | @after{ 2848 | if( has_record_type == 1 ) 2849 | { 2850 | record_define_cnt = -1; 2851 | record_declare_cnt = -1; 2852 | has_record_type = 0; 2853 | } 2854 | 2855 | if( has_collection_type == 1 ) 2856 | { 2857 | collection_type_define_cnt = -1; 2858 | collection_type_declare_cnt = -1; 2859 | //collection_var_cnt = -1; 2860 | has_collection_type = 0; 2861 | } 2862 | 2863 | variables_list_cnt = -1; 2864 | }: 2865 | CREATE ( OR kREPLACE )? FUNCTION ( schema_name=ID DOT )? function_name=ID 2866 | { 2867 | String tmp = $function_name.getText(); 2868 | if(tmp.startsWith("\"")&&tmp.endsWith("\"")) 2869 | tmp = tmp.substring(1, tmp.length() -1 ); 2870 | 2871 | output += "def " + tmp.toLowerCase() + "(tdw, ";} 2872 | ( LPAREN parameter_declaration ( COMMA parameter_declaration )* RPAREN 2873 | { 2874 | int has_defaults = 0; 2875 | for(int i = 0; i <= parameter_list_count; i++) 2876 | { 2877 | if (parameter_list[i].contains("= None")) 2878 | has_defaults = 1; 2879 | } 2880 | if (has_defaults == 1) { 2881 | for(int i = 0; i <= parameter_list_count; i++) 2882 | { 2883 | if (!parameter_list[i].contains("= None")) 2884 | parameter_list[i] += " = None"; 2885 | } 2886 | } 2887 | if(parameter_list_count >= 0) 2888 | { 2889 | output += parameter_list[0]; 2890 | for(int i = 1; i <= parameter_list_count; i++) 2891 | { 2892 | output += ", " + parameter_list[i]; 2893 | } 2894 | parameter_list_count = -1; 2895 | } 2896 | } 2897 | )? 2898 | {output += ")";} 2899 | {output += ":\n"; 2900 | if(initial_statement_count >= 0) 2901 | { 2902 | for(int i = 0; i <= initial_statement_count; i++) 2903 | { 2904 | output += '\t' + initial_statement[i] + "\n"; 2905 | } 2906 | initial_statement_count = -1; 2907 | } 2908 | } 2909 | RETURN datatype 2910 | invoker_rights_clause? 2911 | ( IS | AS ) 2912 | ( {indent_count = 1;} declare_section? body 2913 | | call_spec 2914 | | EXTERNAL 2915 | ) 2916 | { 2917 | for(int i = 0; i <= variables_list_cnt; i++ ) 2918 | { 2919 | String reg = "(?i)" + variables_list[i]; 2920 | String repl = variables_list[i].toLowerCase(); 2921 | //output = output.replaceAll(reg, repl); 2922 | } 2923 | } 2924 | SEMI 2925 | ; 2926 | 2927 | invoker_rights_clause : 2928 | AUTHID ( CURRENT_USER | DEFINER ) 2929 | ; 2930 | 2931 | call_spec 2932 | : LANGUAGE swallow_to_semi 2933 | ; 2934 | 2935 | kERRORS : {input.LT(1).getText().length() >= 3 && "errors".startsWith(input.LT(1).getText().toLowerCase())}? ID; 2936 | kEXCEPTIONS : {input.LT(1).getText().equalsIgnoreCase("exceptions")}? ID; 2937 | //kFOUND : {input.LT(1).getText().equalsIgnoreCase("found")}? ID; 2938 | kFOUND : FOUND; 2939 | FOUND : 'found'; 2940 | 2941 | kINDICES : {input.LT(1).getText().equalsIgnoreCase("indices")}? ID; 2942 | kMOD : {input.LT(1).getText().equalsIgnoreCase("mod")}? ID; 2943 | kNAME : {input.LT(1).getText().equalsIgnoreCase("name")}? ID; 2944 | kOF : {input.LT(1).getText().equalsIgnoreCase("of")}? ID; 2945 | kREPLACE : {input.LT(1).getText().equalsIgnoreCase("replace")}? ID; 2946 | kROWCOUNT : ROWCOUNT; 2947 | ROWCOUNT : 'rowcount'; 2948 | 2949 | kSAVE : {input.LT(1).getText().equalsIgnoreCase("save")}? ID; 2950 | kSHOW : {input.LT(1).getText().equalsIgnoreCase("show")}? ID; 2951 | kTYPE : {input.LT(1).getText().equalsIgnoreCase("type")}? ID; 2952 | kVALUES : {input.LT(1).getText().equalsIgnoreCase("values")}? ID; 2953 | 2954 | AND : 'and' ; 2955 | ARRAY : 'array' ; 2956 | AS : 'as' ; 2957 | AUTHID: 'authid'; 2958 | BETWEEN : 'between' ; 2959 | BODY : 'body'; 2960 | BULK: 'bulk'; 2961 | BULK_ROWCOUNT: 'bulk_rowcount'; 2962 | BY : 'by'; 2963 | CASE: 'case'; 2964 | CREATE: 'create'; 2965 | COLLECT: 'collect'; 2966 | COMMIT : 'commit'; 2967 | CURRENT_USER: 'current_user'; 2968 | DBMS : 'dbms_sql'; 2969 | DEFAULT : 'default' ; 2970 | DEFINER: 'definer'; 2971 | DELETE : 'delete'; 2972 | ELSE : 'else' ; 2973 | ELSIF : 'elsif'; 2974 | EXTERNAL: 'external'; 2975 | FALSE : 'false'; 2976 | FETCH : 'fetch'; 2977 | FOR : 'for' ; 2978 | FORALL : 'forall' ; 2979 | GOTO : 'goto'; 2980 | IF : 'if'; 2981 | IN : 'in' ; 2982 | INDEX : 'index' ; 2983 | INSERT : 'insert'; 2984 | INTO : 'into'; 2985 | IS : 'is' ; 2986 | LANGUAGE: 'language'; 2987 | LIKE : 'like' ; 2988 | LIMIT : 'limit' ; 2989 | LOCK : 'lock'; 2990 | NOT : 'not' ; 2991 | NOTFOUND: 'notfound'; 2992 | NULL : 'null' ; 2993 | OPEN : 'open'; 2994 | OR : 'or' ; 2995 | PACKAGE: 'package'; 2996 | RAISE : 'raise'; 2997 | ROLLBACK: 'rollback'; 2998 | SAVEPOINT : 'savepoint'; 2999 | SELECT : 'select'; 3000 | SET : 'set'; 3001 | SQL : 'sql'; 3002 | TABLE : 'table'; 3003 | TRANSACTION : 'transaction'; 3004 | TRUE : 'true'; 3005 | THEN : 'then' ; 3006 | UPDATE : 'update'; 3007 | WHILE : 'while'; 3008 | INSERTING 3009 | : 'inserting'; 3010 | UPDATING: 'updating'; 3011 | DELETING: 'deleting'; 3012 | ISOPEN : 'isopen'; 3013 | EXISTS : 'exists'; 3014 | 3015 | BEGIN : 'begin' ; 3016 | CLOSE : 'close'; 3017 | CONSTANT : 'constant' ; 3018 | CONTINUE: 'continue'; 3019 | CURSOR : 'cursor' ; 3020 | DECLARE : 'declare' ; 3021 | DETERMINISTIC : 'deterministic' ; 3022 | END : 'end' ; 3023 | EXCEPTION : 'exception' ; 3024 | EXECUTE : 'execute'; 3025 | EXIT : 'exit'; 3026 | FUNCTION : 'function' ; 3027 | IMMEDIATE : 'immediate'; 3028 | LOOP : 'loop'; 3029 | MERGE : 'merge'; 3030 | NOCOPY : 'nocopy' ; 3031 | OTHERS : 'others' ; 3032 | OUT : 'out' ; 3033 | PARALLEL_ENABLE : 'parallel_enable'; 3034 | PIPELINED : 'pipelined' ; 3035 | PRAGMA : 'pragma' ; 3036 | PROCEDURE : 'procedure' ; 3037 | RECORD : 'record' ; 3038 | REF : 'ref' ; 3039 | RESULT_CACHE : 'result_cache' ; 3040 | RETURN : 'return' ; 3041 | RETURNING : 'returning' ; 3042 | ROWTYPE : 'rowtype'; 3043 | SUBTYPE : 'subtype' ; 3044 | USING: 'using' ; 3045 | VARRAY : 'varray' ; 3046 | VARYING : 'varying' ; 3047 | WHEN : 'when' ; 3048 | 3049 | QUOTED_STRING 3050 | : ( 'n' )? '\'' ( '\'\'' | ~('\'') )* '\'' 3051 | ; 3052 | 3053 | ID 3054 | : ( 'a' .. 'z' ) 3055 | ( 'a' .. 'z' | '0' .. '9' | '_' | '$' | '#' )* 3056 | | DOUBLEQUOTED_STRING 3057 | | ('\uB0A1' .. '\uF7FE') 3058 | | ('\u4E00' .. '\u9FA5') 3059 | | ('\uF900' .. '\uFA2D') 3060 | ; 3061 | SEMI 3062 | : ';' 3063 | ; 3064 | COLON 3065 | : ':' 3066 | ; 3067 | DOUBLEDOT 3068 | : POINT POINT 3069 | ; 3070 | DOT 3071 | : POINT 3072 | ; 3073 | fragment 3074 | POINT 3075 | : '.' 3076 | ; 3077 | COMMA 3078 | : (',')|('\uFF0C') 3079 | ; 3080 | EXPONENT 3081 | : '**' 3082 | ; 3083 | ASTERISK 3084 | : '*' 3085 | ; 3086 | AT_SIGN 3087 | : '@' 3088 | ; 3089 | RPAREN 3090 | : ')'|'\uFF09' 3091 | ; 3092 | LPAREN 3093 | : '('|'\uFF08' 3094 | ; 3095 | RBRACK 3096 | : ']' 3097 | ; 3098 | LBRACK 3099 | : '[' 3100 | ; 3101 | PLUS 3102 | : '+' 3103 | ; 3104 | MINUS 3105 | : '-' 3106 | ; 3107 | DIVIDE 3108 | : '/' 3109 | ; 3110 | EQ 3111 | : '=' 3112 | ; 3113 | PERCENT 3114 | : '%' 3115 | ; 3116 | LLABEL 3117 | : '<<' 3118 | ; 3119 | RLABEL 3120 | : '>>' 3121 | ; 3122 | ASSIGN 3123 | : ':=' 3124 | ; 3125 | ARROW 3126 | : '=>' 3127 | ; 3128 | VERTBAR 3129 | : '|' 3130 | ; 3131 | DOUBLEVERTBAR 3132 | : '||' 3133 | ; 3134 | NOT_EQ 3135 | : '<>' | '!=' | '~='| '^=' 3136 | ; 3137 | LTH 3138 | : '<' 3139 | ; 3140 | LEQ 3141 | : '<=' 3142 | ; 3143 | GTH 3144 | : '>' 3145 | ; 3146 | GEQ 3147 | : '>=' 3148 | ; 3149 | INTEGER 3150 | : N 3151 | ; 3152 | REAL_NUMBER 3153 | : NUMBER_VALUE ( 'e' ( PLUS | MINUS )? N )? 3154 | ; 3155 | fragment 3156 | NUMBER_VALUE 3157 | : {numberDotValid()}?=> N POINT N? 3158 | | POINT N 3159 | | N 3160 | ; 3161 | fragment 3162 | N 3163 | : '0' .. '9' ( '0' .. '9' )* 3164 | ; 3165 | fragment 3166 | DOUBLEQUOTED_STRING 3167 | : '"' ( ~('"') )* '"' 3168 | ; 3169 | WS : (' '|'\r'|'\t'|'\n' {row_count++;} |'\u3000') {$channel=HIDDEN;} 3170 | ; 3171 | SL_COMMENT 3172 | : '--' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;} 3173 | ; 3174 | ML_COMMENT 3175 | : '/*' ( options {greedy=false;} : . )* '*/' {$channel=HIDDEN;} 3176 | ; 3177 | 3178 | SPOOL : 'spool' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;} 3179 | ; 3180 | PROMPT : 'prompt' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;} 3181 | ; --------------------------------------------------------------------------------