'
189 | print '* ' + uname
190 | if printcode:
191 | ucode = trigger[i]['code'] or ''
192 | print '-' * len('* ' + uname)
193 | print ucode
194 | print ''
195 | print '* Stats: ' + `form.stats`
196 |
--------------------------------------------------------------------------------
/lib/iz_tools/IniParser.py:
--------------------------------------------------------------------------------
1 | # $Id$
2 | """
3 | IniParser - an extention to ConfigParser
4 | Copyright 2010 Itzchak Rehberg & IzzySoft
5 | """
6 |
7 | from ConfigParser import ConfigParser
8 | from sys import stderr
9 |
10 | class IniParser(ConfigParser):
11 | """
12 | An extension to ConfigParser, adding a getList() method to the class -
13 | plus a Default parameter to option retrieval. Using the latter, it also
14 | tries to (silently) bypass ValueError exceptions (see logMode).
15 | As for the defaults which may be passed to ConfigParser.__init__,
16 | they cannot be assigned to a specific section - so if the same keyword
17 | exists in multiple sections, those defaults are useless. To bypass this
18 | limit, you can either pass above mentioned defaults for option retrieval -
19 | or specify section specific defaults using the IniParser.setVals() method.
20 | """
21 | def __init__(self,defaults=None):
22 | """
23 | Initialize the instance
24 | @param self
25 | @param defaults A dictionary of intrinsic defaults. The keys must be
26 | strings, the values must be appropriate for %()s string
27 | interpolation. Note that `__name__' is always an intrinsic
28 | default; it's value is the section's name. These defaults are
29 | not section specific.
30 | """
31 | ConfigParser.__init__(self,defaults)
32 | self.logMode = stderr
33 |
34 | def setVals(self,vals):
35 | """
36 | Setting multiple configuration values from a passed dictionary.
37 | This can either be used to initialize the configuration with useful
38 | defaults (section specific - not global as the constructor does) -
39 | or to overwrite settings at a later point (e.g. after parsing additional
40 | command line options).
41 | @param self
42 | @param defaults dictionary with the structure defaults[section][option]=string
43 | ATTENTION: Keep in mind: Already existing options will be overwritten by
44 | values from the passed dict!
45 | """
46 | if type(vals).__name__ == 'dict':
47 | for sect in vals.iterkeys():
48 | if not self.has_section(sect):
49 | self.add_section(sect)
50 | for opt in vals[sect].iterkeys():
51 | self.set(sect,opt,vals[sect][opt])
52 |
53 | def setLogMode(self,mode):
54 | """
55 | If some errors occur (e.g. due to invalid values specified), IniParser
56 | tries to silently fix this. For example, if you try to retrieve the value
57 | 'dummy' as integer, this normally would rise an exeption - so if you
58 | passed a default value to getInt, IniParser this and only raises an
59 | exeption otherwise. Though, you might want to inform the user - which will
60 | be done if you set the logMode correspondingly
61 | @param self
62 | @param mode logMode to set: None to keep quite, 'stderr' for error output (default)
63 | """
64 | if mode in ['None','stderr']:
65 | self.logMode = mode
66 |
67 | def log(self,msg):
68 | """
69 | Print an error message to the output specified by setLogMode()
70 | @param self
71 | @param msg message to print
72 | """
73 | if self.logMode != 'None':
74 | print >>stderr, '! '+msg
75 |
76 | def get(self,sect,opt,default=None):
77 | """
78 | Get an option from the config as string
79 | @param self
80 | @param string section name
81 | @param string option name
82 | @param optional string default value (default: None)
83 | @return string value
84 | """
85 | try:
86 | if self.has_option(sect,opt):
87 | return ConfigParser.get(self,sect,opt)
88 | else:
89 | return default
90 | except ValueError:
91 | if default != None:
92 | self.log('An invalid value was specified for '+sect+'.'+opt)
93 | return default
94 | else:
95 | raise ValueError('An invalid value was specified for '+sect+'.'+opt)
96 |
97 | def getList(self,sect,opt,default=None):
98 | """
99 | Get an option from the config as list
100 | @param self
101 | @param string section name
102 | @param string option name
103 | @param optional list default value (default: None)
104 | @return list value
105 | """
106 | if self.has_option(sect,opt):
107 | return ConfigParser.get(self,sect,opt).split(' ')
108 | else:
109 | return default
110 |
111 | def getBool(self,sect,opt,default=None):
112 | """
113 | Get an option from the config as boolean value
114 | @param self
115 | @param string section name
116 | @param string option name
117 | @param optional boolean default value (default: None)
118 | @return boolean value
119 | """
120 | try:
121 | if self.has_option(sect,opt):
122 | return self.getboolean(sect,opt)
123 | else:
124 | return default
125 | except ValueError:
126 | msg = 'invalid value for '+sect+'.'+opt+' - "'+self.get(sect,opt)+'" cannot be translated into a boolean.'
127 | if default != None:
128 | self.log(msg)
129 | return default
130 | else:
131 | raise ValueError(msg)
132 |
133 | def getInt(self,sect,opt,default=None):
134 | """
135 | Get an option from the config as integer value
136 | @param self
137 | @param string section name
138 | @param string option name
139 | @param optional int default value (default: None)
140 | @return int value
141 | """
142 | try:
143 | if self.has_option(sect,opt):
144 | return self.getint(sect,opt)
145 | else:
146 | return default
147 | except ValueError:
148 | msg = 'invalid value for '+sect+'.'+opt+' - "'+self.get(sect,opt)+'" cannot be translated into an integer.'
149 | if default != None:
150 | self.log(msg)
151 | return default
152 | else:
153 | raise ValueError(msg)
154 |
155 | def getFloat(self,sect,opt,default=None):
156 | """
157 | Get an option from the config as float value
158 | @param self
159 | @param string section name
160 | @param string option name
161 | @param optional float default value (default: None)
162 | @return float value
163 | """
164 | try:
165 | if self.has_option(sect,opt):
166 | return self.getfloat(sect,opt)
167 | else:
168 | return default
169 | except ValueError:
170 | msg = 'invalid value for '+sect+'.'+opt+' - "'+self.get(sect,opt)+'" cannot be translated into a float.'
171 | if default != None:
172 | self.log(msg)
173 | return default
174 | else:
175 | raise ValueError(msg)
176 |
--------------------------------------------------------------------------------
/lib/iz_tools/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IzzySoft/HyperSQL/7d59a7e69a99b2ed2938a5c1e0f80e9a914b9121/lib/iz_tools/__init__.py
--------------------------------------------------------------------------------
/lib/iz_tools/progressbar.py:
--------------------------------------------------------------------------------
1 | """
2 | Progress bar
3 | Original Source: http://code.activestate.com/recipes/168639-progress-bar-class/
4 | Modified by: Izzy
5 | """
6 | __revision__ = '$Id$'
7 |
8 | from sys import stdout
9 | from locale import getdefaultlocale
10 | lc, encoding = getdefaultlocale()
11 | if not encoding: encoding = 'utf-8'
12 |
13 | class progressBar:
14 | """
15 | This is a simple text mode progress bar to show the percentage of completion.
16 | It is intended to take a string explaining the task running, which is
17 | displayed together with the actual progress bar.
18 | """
19 | def __init__(self, prefix='', minValue = 0, maxValue = 100, totalWidth=12, padLen=60):
20 | """
21 | Initialize the progress bar
22 | @param self
23 | @param string prefix Task running. This string should be no longer than padLen.
24 | Leaving it empty (default) will cause the bar starting at pos 0 (begin
25 | of the line). Otherwise, prefix will be right-padded by spaces, and
26 | the bar appended to its end.
27 | @param int minValue Start value (absolute number, usually 0=default)
28 | @param int maxValue End value (absolute number corresponding to 100%, default=100)
29 | @param int totalWidth Width of the *bar* (without the prefix) in characters
30 | (default: 12)
31 | @param int padLen To how many chars the prefix (if specified) should be padded
32 | """
33 | if len(prefix)>0:
34 | prefix = prefix.ljust(60)
35 | self.prefixLen = len(prefix)
36 | self.mask = prefix + '[%s]'
37 | self.pbar = self.mask # This holds the progress bar string
38 | self._old_pbar = self.pbar # for draw()
39 | self.min = minValue
40 | self.max = maxValue
41 | self.span = maxValue - minValue
42 | self.width = totalWidth
43 | self.amount = 0 # When amount == max, we are 100% done
44 | self.update(0) # Build progress bar string
45 |
46 | def update(self, newAmount = 0):
47 | """
48 | Update the actual value and re-draw the progress bar (if necessary).
49 | This updates the "current value" and calls progressbar.draw(). The value
50 | passed may be greater or less than the recent value - or even the same.
51 | @param self
52 | @param int curVal
53 | """
54 | drawMe = (newAmount != 0)
55 | if newAmount < self.min: newAmount = self.min
56 | if newAmount > self.max: newAmount = self.max
57 | self.amount = newAmount
58 |
59 | # Figure out the new percent done, round to an integer
60 | diffFromMin = float(self.amount - self.min)
61 | if self.span!=0: percentDone = (diffFromMin / float(self.span)) * 100.0
62 | else: percentDone = 0
63 | percentDone = round(percentDone)
64 | percentDone = int(percentDone)
65 |
66 | # Figure out how many hash bars the percentage should be
67 | allFull = self.width - 2
68 | numHashes = (percentDone / 100.0) * allFull
69 | numHashes = int(round(numHashes))
70 |
71 | # build a progress bar with hashes and spaces
72 | bar = '='*numHashes + ' '*(allFull-numHashes)
73 | self.pbar = self.mask % bar
74 |
75 | # figure out where to put the percentage, roughly centered
76 | percentPlace = self.prefixLen + 1 + (self.width / 2) - len(str(percentDone))
77 | percentString = str(percentDone) + "%"
78 |
79 | # slice the percentage into the bar
80 | self.pbar = self.pbar[0:int(percentPlace)] + percentString + self.pbar[int(percentPlace)+len(percentString):]
81 |
82 | # call draw() to update screen if necessary
83 | if drawMe: self.draw()
84 |
85 | def __str__(self):
86 | """ Returns the current string of the bar (incl. prefix) """
87 | return self.pbar.encode(encoding)
88 |
89 | def draw(self):
90 | """ draw progress bar - but only if it has changed """
91 | if self.pbar != self._old_pbar:
92 | self._old_pbar = self.pbar
93 | stdout.write(self.__str__() + '\r')
94 | stdout.flush()
95 |
96 |
--------------------------------------------------------------------------------
/lib/iz_tools/system.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: utf-8 -*-
3 | # $Id$
4 | """
5 | Some useful system functions which mostly mimic PHP (or Shell) equivalents
6 | """
7 |
8 | #====================================================[ Imports and Presets ]===
9 | import os # for which() and getCallingModule()
10 | import sys # for which()
11 | from subprocess import Popen,PIPE # for popen()
12 | from .typecheck import is_string, is_list # for file_put_contents (local module typecheck)
13 | from traceback import extract_stack # for getCaller()
14 |
15 | # prepare for fopen (encoding fallback)
16 | from locale import getdefaultlocale
17 | lc, encoding = getdefaultlocale()
18 | encoding = encoding or 'UTF-8'
19 | try:
20 | import codecs
21 | except:
22 | codecs = None
23 |
24 | #==============================================================[ Functions ]===
25 | #------------------------------------------------------------------[ which ]---
26 | def which(executable, path=None):
27 | """
28 | Try to find 'executable' in the directories listed in 'path' (a
29 | string listing directories separated by 'os.pathsep'; defaults to
30 | os.environ['PATH']). Mimics the shell command "which".
31 | Returns the complete filename or None if not found
32 | Original Source: http://snippets.dzone.com/posts/show/6313
33 | @param string executable to look for
34 | @param optional string path to look in
35 | @return string path/to/executable or None
36 | """
37 | if path is None:
38 | path = os.environ['PATH']
39 | paths = path.split(os.pathsep)
40 | extlist = ['']
41 | if os.name == 'os2':
42 | (base, ext) = os.path.splitext(executable)
43 | # executable files on OS/2 can have an arbitrary extension, but
44 | # .exe is automatically appended if no dot is present in the name
45 | if not ext:
46 | executable = executable + ".exe"
47 | elif sys.platform == 'win32':
48 | pathext = os.environ['PATHEXT'].lower().split(os.pathsep)
49 | (base, ext) = os.path.splitext(executable)
50 | if ext.lower() not in pathext:
51 | extlist = pathext
52 | for ext in extlist:
53 | execname = executable + ext
54 | if os.path.isfile(execname):
55 | return execname
56 | else:
57 | for p in paths:
58 | f = os.path.join(p, execname)
59 | if os.path.isfile(f):
60 | return f
61 | else:
62 | return None
63 |
64 | #------------------------------------------------------------------[ popen ]---
65 | def popen(command):
66 | """
67 | Run a command and return its output as string. Mimics he PHP function
68 | "shell_exec" - with the difference of returning a touple, so stderr is
69 | also available to evaluation.
70 | Example call: mylist, myerr = run('ls -l')
71 | @param string command
72 | @return string stdout, string stderr
73 | """
74 | p = Popen(command, shell=True,stdout=PIPE,stderr=PIPE)
75 | out = ''.join(p.stdout.readlines() )
76 | outerr = ''.join(p.stderr.readlines() )
77 | return out, outerr
78 |
79 | #-------------------------------------------------------------[ shell_exec ]---
80 | def shell_exec(command):
81 | """
82 | Run a command and return its output as string. Mimics he PHP function
83 | "shell_exec".
84 | Example call: mylist = run('ls -l')
85 | @param string command
86 | @return string stdout
87 | """
88 | out, err = popen(command)
89 | return out
90 |
91 | #------------------------------------------------------------------[ fopen ]---
92 | def fopen(filename,mode,enc=None):
93 | """
94 | Wrapper to open a file either via codecs (if possible), or simply with open()
95 | (if codecs==None). If the third parameter is not set, it tries to read the
96 | global variable "encoding" instead. If that's not set either, fallback to
97 | open()
98 | This rawly mimics the PHP function fopen() up to the mandatory parameters,
99 | but differs with the optionals.
100 | @param string filename
101 | @param string mode
102 | @param optional string encoding
103 | @return filehandle
104 | """
105 | if enc is None:
106 | try:
107 | enc = encoding
108 | except:
109 | enc = None
110 | if codecs is None:
111 | enc = None
112 | if enc is None:
113 | return open(filename,mode)
114 | else:
115 | return codecs.open(filename,mode,enc)
116 |
117 | #------------------------------------------------------[ file_get_contents ]---
118 | def file_get_contents(filename,enc=None):
119 | """
120 | Get the content of the specified file and return it as string. Mimics the
121 | PHP function with the same name up to the mandatory parameter - but differs
122 | when it comes to the optionals.
123 | @param string filename name of the file to read
124 | @param optional string enc encoding of the file (defaults to system standard
125 | evaluated via locale settings)
126 | @return string text
127 | """
128 | infile = fopen(filename,'rb',enc)
129 | text = infile.read()
130 | infile.close()
131 | return text
132 |
133 | #---------------------------------------------------------[ file_get_lines ]---
134 | def file_get_lines(filename,enc=None):
135 | """
136 | Get the content of the specified file and return it as list. To be used
137 | like the PHP function file() - except for the optional parameter(s).
138 | @param string filename name of the file to read
139 | @param optional string enc encoding of the file (defaults to system standard
140 | evaluated via locale settings)
141 | @return list text
142 | """
143 | infile = fopen(filename,'rb',enc)
144 | list = infile.readlines()
145 | infile.close()
146 | return list
147 |
148 | #------------------------------------------------------[ file_put_contents ]---
149 | def file_put_contents(filename,content,enc=None,append=False):
150 | """
151 | Write the content to the specified file. To be used like the PHP function
152 | with the same name - except for the optional parameters.
153 | @param string filename name of the file to be written
154 | @param mixed content what should be written to the file. This can be either
155 | a string or a list
156 | @param optional string enc encoding of the file (defaults to system standard
157 | evaluated via locale settings)
158 | @param optional boolean append whether content shall be appended if the file
159 | already exists. By default, an existing file will be simply replaced.
160 | """
161 | if is_string(content): pass
162 | elif is_list(content): content = '\n'.join(content)
163 | else:
164 | raise TypeError, 'Second argument to file_put_contents must be either str or list, %s given' % is_what(content)
165 | if append: mode = 'ab'
166 | else: mode = 'wb'
167 | outfile = fopen(filename,mode)
168 | outfile.write(content)
169 | bytes = outfile.tell()
170 | outfile.close()
171 | return bytes
172 |
173 | #---------------------------------------------------------------[ makeRDir ]---
174 | def makeRDir(pathname):
175 | """
176 | Create recursive directory structur, if it not exists already
177 | (similar to 'mkdir -p' on *nix)
178 | @param string pathname path/to/create
179 | """
180 | splitted = pathname.split(os.sep)
181 | temp = ""
182 | for path_element in splitted: # loop through path components, making directories as needed
183 | temp += path_element + os.sep
184 | if os.access(temp, os.F_OK) == 1:
185 | continue
186 | else:
187 | os.mkdir(temp)
188 |
189 | #--------------------------------------------------[ Caller identification ]---
190 | def getCaller(level=3):
191 | """
192 | Find out who called the holding function
193 | @param optional integer level 1 = self, 2 = caller of GetCaller, 3 = who called 2, etc.
194 | @return tuple caller (filename, line number, function name, text)
195 | """
196 | stack = extract_stack()
197 | return stack[len(stack)-level]
198 |
199 | def getCallingModule(level=4,basename=True):
200 | """
201 | Obtain the name of the calling module
202 | @param optional integer level 1 = self, 2 = caller of GetCaller, 3 = caller of getCallingModule, 4 = who called 3 (default), etc.
203 | @param optional boolean basename whether to cut-off the path (default: True)
204 | @return string name of the module (i.e. filename w/o ext)
205 | """
206 | return os.path.splitext(os.path.basename(getCaller(level)[0]))[0]
207 |
--------------------------------------------------------------------------------
/lib/iz_tools/text.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: utf-8 -*-
3 | # $Id$
4 | """
5 | Some useful functions for string / text processing
6 | """
7 |
8 | #====================================================[ Imports and Presets ]===
9 | import re # for getWordLineNo
10 |
11 | #==============================================================[ Functions ]===
12 | #--------------------------------------[ Finding lineNo with matching text ]---
13 | def getWordLineNo(text,pattern):
14 | """
15 | Finding lineNo with matching text
16 | example:
17 | getWordLineNo(text,'([^<]+)')
18 | Adapted from: http://snippets.dzone.com/posts/show/1638
19 | By: Izzy
20 | @param string text to parse
21 | @param string pattern RegExp pattern to find
22 | @return list of tuples (lineno, offset, word)
23 | """
24 | res = []
25 | for m in re.finditer(pattern, text, re.I):
26 | start = m.start()
27 | lineno = text.count('\n', 0, start) + 1
28 | offset = start - text.rfind('\n', 0, start)
29 | word = m.group(0)
30 | res.append((lineno, offset, word))
31 | return res
32 |
--------------------------------------------------------------------------------
/lib/iz_tools/typecheck.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: utf-8 -*-
3 | # $Id$
4 | """
5 | Some useful functions around types, imitating the PHP style type checking
6 | functions. Of course, adapted to the types available in Python.
7 | """
8 |
9 | #====================================================[ Imports and Presets ]===
10 | from types import *
11 |
12 | #==============================================================[ Own Types ]===
13 | class nullDict(dict):
14 | """ A dictionary without KeyErrors (returning None instead) """
15 | def __missing__(self,key):
16 | return None
17 |
18 | #==============================================================[ Functions ]===
19 | #----------------------------------------------------------[ Type checking ]---
20 | """
21 | Type checking functions have been taken from:
22 | http://code.activestate.com/recipes/305888-a-way-to-deal-with-checking-for-types/
23 | """
24 | def check_type(obj,atts=[],callables=[]):
25 | """
26 | Helper for is_mapping(), is_list(), is_str() and is_file()
27 | @param object object to check
28 | @param optional list atts attributes the object must have (default: empty list)
29 | @param optional list callables callables the object must have (default: empty list)
30 | """
31 | got_atts=True
32 | for att in atts:
33 | if not hasattr(obj,att):
34 | got_atts=False;break
35 | got_callables=True
36 | for call in callables:
37 | if not hasattr(obj,call):
38 | got_callables=False;break
39 | the_attr=getattr(obj,call)
40 | if not callable(the_attr):
41 | got_callables=False;break
42 | if got_atts and got_callables: return -1
43 | return 0
44 |
45 | def is_iter(obj):
46 | """
47 | Check whether the object is iterable
48 | @param object object to check
49 | @return int 1 if True, 0 if False, -1 if iterable but neither list, tuple, dict or file
50 | """
51 | if isinstance(obj,ListType): return 1
52 | if isinstance(obj,TupleType): return 1
53 | if isinstance(obj,DictType): return 1
54 | if isinstance(obj,FileType): return 1
55 | if hasattr(obj,'__iter__') : return -1
56 | return 0
57 |
58 | def is_gen(obj):
59 | """
60 | Is the object a generator?
61 | @param object object to check
62 | @return int 1 if True, 0 if False
63 | """
64 | if isinstance(obj,GeneratorType): return 1
65 | return 0
66 |
67 | def is_seq(obj):
68 | """
69 | Is the object a sequence?
70 | @param object object to check
71 | @return int 1 if True, 0 if False, -1 if obj[0:0] works but it's neither list nor tuple (but e.g. str)
72 | """
73 | if isinstance(obj,ListType): return 1
74 | if isinstance(obj,TupleType): return 1
75 | if is_iter(obj):
76 | try:
77 | obj[0:0]
78 | return -1
79 | except TypeError:
80 | pass
81 | return 0
82 |
83 | def is_mapping(obj):
84 | """
85 | Is the object a mapping type (e.g. dictionary)?
86 | @param object object to check
87 | @return int 1 if True, 0 if False, -1 if it's not a dict but has callables
88 | """
89 | if isinstance(obj,DictType): return 1
90 | if is_iter(obj):
91 | return check_type(obj,callables=['iteritems','has_key'])
92 | return 0
93 |
94 | def is_dict(obj):
95 | """
96 | Is it a dictionary?
97 | @param object object to check
98 | @return int 1 if True, 0 if False, -1 if it's not a dict but has callables
99 | """
100 | return is_mapping(obj)
101 |
102 | def is_list(obj):
103 | """
104 | Is the object a list?
105 | @param object object to check
106 | @return int 1 if True, 0 if False, -1 if it's not a list, but has callables append, extend, and pop
107 | """
108 | if isinstance(obj,ListType): return 1
109 | if is_seq(obj):
110 | if check_type(obj,callables=['append','extend','pop']): return -1
111 | return 0
112 |
113 | def is_str(obj):
114 | """
115 | Is the object a string?
116 | @param object object to check
117 | @return int 1 if True, 0 if False, -1 not str but has callables index, count, and replace
118 | """
119 | if isinstance(obj, basestring): return 1
120 | if is_iter(obj):
121 | if check_type(obj,callables=['index','count','replace']): return -1
122 | return 0
123 |
124 | def is_string(obj):
125 | """ alias for is_str """
126 | return is_str(obj)
127 |
128 | def is_int(obj):
129 | """
130 | Is it an integer?
131 | @param object object to check
132 | @return int 1 if True, 0 if False, -1 not str but has callables index, count, and replace
133 | """
134 | if isinstance(obj, int) : return 1
135 | return 0
136 |
137 | def is_numeric(obj):
138 | """
139 | Is it a number - i.e. an integer or float?
140 | @param object object to check
141 | @return int 1 if True, 0 if False, -1 not str but has callables index, count, and replace
142 | """
143 | try:
144 | float(obj)
145 | return 1
146 | except ValueError:
147 | pass
148 | return 0
149 |
150 | def is_file(obj):
151 | """
152 | Is the object a file?
153 | @param object object to check
154 | @return int 1 if True, 0 if False, -1 if it's not FileType but has callables read and close
155 | """
156 | if isinstance(obj,FileType): return 1
157 | if check_type(obj,callables=['read','close']): return -1
158 | return 0
159 |
160 | def is_what(obj):
161 | """
162 | Get the type of the passed object
163 | @param object object to check
164 | @return mixed string category (if we have a direct match) or list of 0/1 [iter,gen,seq,list,str,dict,file]
165 | """
166 | try:
167 | if obj.__class__.__name__: return obj.__class__.__name__
168 | except:
169 | return [ str(i) for i in (is_iter(obj),is_gen(obj),is_seq(obj),is_list(obj),is_str(obj),is_mapping(obj),is_file(obj))]
170 |
171 |
--------------------------------------------------------------------------------
/lib/parsers/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IzzySoft/HyperSQL/7d59a7e69a99b2ed2938a5c1e0f80e9a914b9121/lib/parsers/__init__.py
--------------------------------------------------------------------------------
/lib/parsers/filefinder.py:
--------------------------------------------------------------------------------
1 | """
2 | Parsing the file system
3 | """
4 | __revision__ = '$Id$'
5 |
6 | import os
7 | from hypercore.elements import FileInfo
8 |
9 | def getFileList(sdir, fileExts, skipDirs=[], ignorefile='.hsqlignore'):
10 | """
11 | Recursively scans the source directory specified for relevant files according
12 | to the file extensions passed by the second parameter, while excluding files/
13 | directories given with the third (useful to exclude '.svn' and the like) and
14 | directories containing an ignore flag file (usually '.hsqlignore')
15 | Information for matching files will be returned as a list of FileInfo objects.
16 | @param string dir directory to scan
17 | @param list fileExts file extensions to consider. Each element must be a tuple
18 | (str fileType, list extensions)
19 | @param list skipDirs files/directories to skip
20 | @return list fileInfoList list of FileInfo objects
21 | """
22 | if fileExts is None or len(fileExts)<1: return []
23 |
24 | # get a list of this directory's contents
25 | # these items are relative and not absolute
26 | names = os.listdir(sdir)
27 | fileInfoList = []
28 |
29 | # setup supported file extensions
30 | exts = []
31 | for ext in fileExts: exts += ext[1]
32 |
33 | # iterate through the file list
34 | for i in names:
35 |
36 | if i in skipDirs: # do not look in RCS/CVS/SVN/... special dirs
37 | continue
38 | if os.path.isfile( os.path.join(sdir, i, ignorefile) ):
39 | continue
40 |
41 | # convert from relative to absolute addressing
42 | # to allow recursive calls
43 | f1=os.path.join(sdir, i)
44 |
45 | # if this item is also a directory, recurse it too
46 | if os.path.isdir(f1):
47 | fileInfoList += getFileList(f1, fileExts, skipDirs)
48 |
49 | else: # file found, only add specific file extensions to the list
50 | fspl = f1.split('.')
51 | ext = fspl[len(fspl)-1]
52 | if ext in exts:
53 | temp = FileInfo()
54 | temp.fileName = f1
55 | for ftype in fileExts:
56 | if ext in ftype[1]:
57 | temp.fileType = ftype[0]
58 | break
59 | fileInfoList.append(temp)
60 | return fileInfoList
61 |
62 |
--------------------------------------------------------------------------------
/lib/progress.py:
--------------------------------------------------------------------------------
1 | """
2 | Progressbar handlers
3 |
4 | $Id$
5 | """
6 | from iz_tools.progressbar import *
7 | from hypercore.elements import metaInfo
8 | from hypercore.logger import logg
9 | pbar = progressBar() # make it global
10 |
11 | def pbarInit(prefix,start,end,logname=''):
12 | """
13 | Initialize ProgressBar
14 | @param string prefix the progress message to pass
15 | @param int start start value (usually 0)
16 | @param int end max value
17 | """
18 | logg.getLogger(logname).debug(prefix)
19 | if metaInfo.printProgress:
20 | pbar.__init__(prefix,start,end)
21 | pbar.draw()
22 |
23 | def pbarUpdate(newVal):
24 | """
25 | Update the ProgressBar
26 | @param int newVal new value (current state)
27 | """
28 | if metaInfo.printProgress:
29 | pbar.update(newVal)
30 |
31 | def pbarClose():
32 | """ At end of processing, we need a newline """
33 | if metaInfo.printProgress: print
34 |
35 |
36 | #------------------------------------------------------------------------------
37 | def printProgress(msg,logname=''):
38 | """
39 | If config(Logging.progress) evaluates to True, print which step we are performing
40 | @param string msg what to print out
41 | """
42 | logg.getLogger(logname).debug(msg)
43 | if metaInfo.printProgress:
44 | print msg
45 |
46 |
47 |
--------------------------------------------------------------------------------
/sql.keywords:
--------------------------------------------------------------------------------
1 | ABORT
2 | ABSOLUTE
3 | ACCEPT
4 | ACCESS
5 | ACTION
6 | ADA
7 | ADD
8 | ALL
9 | ALLOCATE
10 | ALTER
11 | ANALYZE
12 | AND
13 | ANY
14 | ARCHIVE
15 | ARCHIVELOG
16 | ARE
17 | ARRAY
18 | ARRAYLEN
19 | AS
20 | ASC
21 | ASSERT
22 | ASSERTION
23 | ASSIGN
24 | AT
25 | AUDIT
26 | AUTHORIZATION
27 | AUTO_INCREMENT
28 | AVG
29 | BACKUP
30 | BASE_TABLE
31 | BECOME
32 | BEGIN
33 | BETWEEN
34 | BIT
35 | BIT_LENGTH
36 | BLOB
37 | BLOCK
38 | BODY
39 | BOTH
40 | BY
41 | CACHE
42 | CANCEL
43 | CASCADE
44 | CASCADED
45 | CASE
46 | CAST
47 | CATALOG
48 | CHANGE
49 | CHAR_BASE
50 | CHARACTER_LENGTH
51 | CHAR_LENGTH
52 | CHECK
53 | CHECKPOINT
54 | CLOSE
55 | CLUSTER
56 | CLUSTERS
57 | COALESCE
58 | COBOL
59 | COLAUTH
60 | COLLATE
61 | COLLATION
62 | COLUMN
63 | COMMENT
64 | COMMIT
65 | COMPILE
66 | COMPRESS
67 | CONNECT
68 | CONNECTION
69 | CONSTANT
70 | CONSTRAINT
71 | CONSTRAINTS
72 | CONTENTS
73 | CONTINUE
74 | CONTROLFILE
75 | COPY
76 | CORRESPONDING
77 | COUNT
78 | CRASH
79 | CREATE
80 | CROSS
81 | CURRENT
82 | CURRENT_DATE
83 | CURRENT_TIME
84 | CURRENT_TIMESTAMP
85 | CURRENT_USER
86 | CURRVAL
87 | CURSOR
88 | CYCLE
89 | DATA_BASE
90 | DATABASE
91 | DATAFILE
92 | DAY
93 | DBA
94 | DEALLOCATE
95 | DEBUGOFF
96 | DEBUGON
97 | DECLARE
98 | DECODE
99 | DEFAULT
100 | DEFERRABLE
101 | DEFERRED
102 | DEFINITION
103 | DELAY
104 | DELETE
105 | DELTA
106 | DESC
107 | DESCRIBE
108 | DESCRIPTOR
109 | DIAGNOSTICS
110 | DIGITS
111 | DISABLE
112 | DISCONNECT
113 | DISMOUNT
114 | DISPOSE
115 | DISTINCT
116 | DO
117 | DOMAIN
118 | DOUBLE
119 | DROP
120 | DUMP
121 | EACH
122 | EDITIONABLE
123 | ELSE
124 | ELSIF
125 | ENABLE
126 | ENCODING
127 | END
128 | END-EXEC
129 | ENUM
130 | ENTRY
131 | ERRORS
132 | ESCAPE
133 | EVENTS
134 | EXCEPT
135 | EXCEPTION
136 | EXCEPTION_INIT
137 | EXCLUSIVE
138 | EXEC
139 | EXECUTE
140 | EXISTS
141 | EXIT
142 | EXPLAIN
143 | EXTENT
144 | EXTERNAL
145 | EXTERNALLY
146 | EXTRACT
147 | FALSE
148 | FETCH
149 | FILE
150 | FIRST
151 | FLUSH
152 | FOR
153 | FORALL
154 | FORCE
155 | FOREIGN
156 | FORM
157 | FORTRAN
158 | FOUND
159 | FREELIST
160 | FREELISTS
161 | FROM
162 | FULL
163 | FUNCTION
164 | GENERIC
165 | GET
166 | GLOBAL
167 | GO
168 | GOTO
169 | GRANT
170 | GROUP
171 | HAVING
172 | HOUR
173 | IDENTIFIED
174 | IDENTITY
175 | IF
176 | IMMEDIATE
177 | IN
178 | INCLUDE
179 | INCLUDING
180 | INCREMENTAL
181 | INDEX
182 | INDEXES
183 | INDICATOR
184 | INITIAL
185 | INITIALLY
186 | INITRANS
187 | INNER
188 | INPUT
189 | INSENSITIVE
190 | INSERT
191 | INSTANCE
192 | INTERSECT
193 | INTERVAL
194 | INTO
195 | IS
196 | ISOLATION
197 | ISOPEN
198 | JOIN
199 | KEY
200 | LANGUAGE
201 | LAST
202 | LAYER
203 | LEADING
204 | LEFT
205 | LEVEL
206 | LIKE
207 | LIMITED
208 | LINK
209 | LISTS
210 | LOCAL
211 | LOGFILE
212 | LOCK
213 | LOOP
214 | LOWER
215 | MANAGE
216 | MANUAL
217 | MATCH
218 | MAX
219 | MAXDATAFILES
220 | MAXINSTANCES
221 | MAXLOGFILES
222 | MAXLOGHISTORY
223 | MAXLOGMEMBERS
224 | MAXEXTENTS
225 | MAXTRANS
226 | MAXVALUE
227 | MIN
228 | MINEXTENTS
229 | MINUS
230 | MINUTE
231 | MINVALUE
232 | MLSLABEL
233 | MOD
234 | MODE
235 | MODIFY
236 | MODULE
237 | MONTH
238 | MOUNT
239 | NAMES
240 | NATIONAL
241 | NATURAL
242 | NEW
243 | NEXT
244 | NEXTVAL
245 | NO
246 | NOARCHIVE
247 | NOAUDIT
248 | NOCACHE
249 | NOCOMPRESS
250 | NOCYCLE
251 | NOMAXVALUE
252 | NOMINVALUE
253 | NONE
254 | NOORDER
255 | NORESETLOGS
256 | NORMAL
257 | NOSORT
258 | NOT
259 | NOTFOUND
260 | NOWAIT
261 | NULL
262 | NULLIF
263 | NUMBER_BASE
264 | NVL
265 | OCTET_LENGTH
266 | OF
267 | OFF
268 | OFFLINE
269 | OLD
270 | ON
271 | ONLINE
272 | ONLY
273 | OPEN
274 | OPTIMAL
275 | OPTION
276 | OR
277 | ORDER
278 | OTHERS
279 | OUT
280 | OUTER
281 | OUTPUT
282 | OVERLAPS
283 | OWN
284 | PACKAGE
285 | PAD
286 | PARALLEL
287 | PARTIAL
288 | PARTITION
289 | PASCAL
290 | PCTFREE
291 | PCTINCREASE
292 | PCTUSED
293 | PLAN
294 | PLI
295 | POSITION
296 | POSITIVE
297 | PRAGMA
298 | PRECISION
299 | PREPARE
300 | PRESERVE
301 | PRIMARY
302 | PRIOR
303 | PRIVATE
304 | PRIVILEGES
305 | PROCEDURE
306 | PROFILE
307 | PROMPT
308 | PUBLIC
309 | QUOTA
310 | RAISE
311 | RANGE
312 | RAW
313 | READ
314 | REAL
315 | RECORD
316 | RECOVER
317 | REFERENCES
318 | REFERENCING
319 | RELATIVE
320 | RELEASE
321 | REMR
322 | RENAME
323 | REPLACE
324 | RESETLOGS
325 | RESOURCE
326 | RESTRICT
327 | RESTRICTED
328 | RETURN
329 | REUSE
330 | REVERSE
331 | REVOKE
332 | RIGHT
333 | ROLE
334 | ROLES
335 | ROLLBACK
336 | ROW
337 | ROWID
338 | ROWLABEL
339 | ROWNUM
340 | ROWS
341 | ROWTYPE
342 | RUN
343 | SAVEPOINT
344 | SCHEMA
345 | SCN
346 | SCROLL
347 | SECOND
348 | SECTION
349 | SEGMENT
350 | SELECT
351 | SEPARATE
352 | SEQUENCE
353 | SESSION
354 | SESSION_USER
355 | SET
356 | SHOW
357 | SHARE
358 | SHARED
359 | SIZE
360 | SNAPSHOT
361 | SOME
362 | SORT
363 | SPACE
364 | SQL
365 | SQLBUF
366 | SQLCA
367 | SQLCODE
368 | SQLERRM
369 | SQLERROR
370 | SQLSTATE
371 | SQLWARNING
372 | START
373 | STATEMENT
374 | STATEMENT_ID
375 | STATISTICS
376 | STDDEV
377 | STOP
378 | STORAGE
379 | SUBSTR
380 | SUBSTRING
381 | SUBTYPE
382 | SUCCESSFUL
383 | SUM
384 | SWITCH
385 | SYNONYME
386 | SYSDATE
387 | SYSTEM
388 | SYSTEM_USER
389 | TABAUTH
390 | TABLE
391 | TABLES
392 | TABLESPACE
393 | TASK
394 | TEMPLATE
395 | TEMPORARY
396 | TERMINATE
397 | THEN
398 | THREAD
399 | TIME
400 | TIMEZONE_HOUR
401 | TIMEZONE_MINUTE
402 | TO
403 | TRACING
404 | TRAILING
405 | TRANSACTION
406 | TRANSLATION
407 | TRIGGER
408 | TRIGGERS
409 | TRIM
410 | TRUE
411 | TRUNCATE
412 | TYPE
413 | UID
414 | UNDER
415 | UNION
416 | UNIQUE
417 | UNKNOWN
418 | UNLIMITED
419 | UNSIGNED
420 | UNTIL
421 | UPDATE
422 | UPPER
423 | USAGE
424 | USE
425 | USER
426 | USING
427 | VALIDATE
428 | VALUE
429 | VALUES
430 | VARIANCE
431 | VARYING
432 | VIEW
433 | VIEWS
434 | WARNINGS
435 | WHEN
436 | WHENEVER
437 | WHERE
438 | WHILE
439 | WITH
440 | WORK
441 | WRITE
442 | WORK
443 | XOR
444 | YEAR
445 | ZONE
446 |
--------------------------------------------------------------------------------
/sql.types:
--------------------------------------------------------------------------------
1 | BIGINT
2 | BINARY_INTEGER
3 | BLOB
4 | BOOLEAN
5 | CHAR
6 | CHARACTER
7 | CLOB
8 | DATE
9 | DATETIME
10 | DEC
11 | DECIMAL
12 | DOUBLE
13 | FLOAT
14 | INT
15 | INTEGER
16 | LONG
17 | LONGBLOB
18 | LONGTEXT
19 | MEDIUMBLOB
20 | MEDIUMINT
21 | MEDIUMTEXT
22 | NCHAR
23 | NCLOB
24 | NUMBER
25 | NUMERIC
26 | NVARCHAR
27 | REAL
28 | SMALLINT
29 | TEXT
30 | TIMESTAMP
31 | TINYBLOB
32 | TINYINT
33 | TINYTEXT
34 | VARCHAR
35 | VARCHAR2
36 |
--------------------------------------------------------------------------------
/tools/gen_sequences_scripts.sql:
--------------------------------------------------------------------------------
1 | --
2 | -- there are no comments on sequences, so we simply extract the CREATE statements
3 | --
4 |
5 | SET ECHO OFF
6 | SET FEEDBACK OFF
7 | SET SERVEROUT ON
8 | SET SQLBL ON
9 | SET TERMOUT ON
10 | SET PAGES 0
11 | SET LINES 200
12 | SET SERVEROUT ON
13 |
14 | SPOOL sequences.sql
15 | SELECT 'CREATE SEQUENCE '||i.sequence_name||' START WITH '||i.min_value||' INCREMENT BY '||i.increment_by
16 | ||' MAX VALUE '||i.max_value||i.caches||i.cycles||i.orders||';' AS line
17 | FROM (
18 | SELECT sequence_name,min_value,increment_by,max_value,
19 | (CASE WHEN cache_size=0 THEN ' NOCACHE' ELSE ' CACHE '||cache_size END) AS caches,
20 | (CASE WHEN cycle_flag='Y' THEN ' CYCLE' ELSE ' NOCYCLE' END) AS cycles,
21 | (CASE WHEN order_flag='Y' THEN ' ORDER' ELSE ' NOORDER' END) AS orders
22 | FROM user_sequences
23 | ) i;
24 | SPOOL OFF
25 |
26 | EXIT;
27 |
--------------------------------------------------------------------------------
/tools/gen_table_scripts.sql:
--------------------------------------------------------------------------------
1 | /**
2 | * Extract table definitions from data dictionary
3 | * As preparation, you will need an Oracle DIRECTORY to place the created
4 | * scripts into:
5 | * DROP DIRECTORY UTLFILEDIR;
6 | * CREATE OR REPLACE DIRECTORY UTLFILEDIR AS '';
7 | * GRANT READ, WRITE ON DIRECTORY UTLFILEDIR TO ;
8 | * Replace and to match your needs. If you change the name
9 | * of the directory, you will need to do so in below script as well.
10 | */
11 |
12 | SET ECHO OFF
13 | SET FEEDBACK OFF
14 | SET SERVEROUT ON
15 | SET SQLBL ON
16 | SET TERMOUT ON
17 | SET PAGES 0
18 | SET LINES 200
19 |
20 | DECLARE
21 | cnt NUMBER; -- in case we want a range only
22 | fh UTL_FILE.FILE_TYPE;
23 | fname VARCHAR2(255);
24 | CURSOR c_tab IS
25 | SELECT table_name
26 | FROM user_tables;
27 | CURSOR c_tabcomment(tname IN VARCHAR2) IS
28 | SELECT '/** '||comments AS line
29 | FROM user_tab_comments
30 | WHERE table_name = tname;
31 | CURSOR c_colcomment(tname IN VARCHAR2) IS
32 | SELECT ' * @col '||t.data_type||' '||t.column_name||' '||c.comments AS line
33 | FROM user_tab_columns t LEFT JOIN user_col_comments c ON (t.table_name=c.table_name AND t.column_name=c.column_name)
34 | WHERE t.table_name=tname;
35 | CURSOR c_grant(tname IN VARCHAR2) IS
36 | SELECT (CASE WHEN grantable='NO' THEN 'GRANT '||privilege||' ON '||tname||' TO '||grantee||';'
37 | ELSE 'GRANT '||privilege||' ON '||tname||' TO '||grantee||' WITH GRANT OPTION;' END) AS line
38 | FROM user_tab_privs
39 | WHERE table_name=tname;
40 | BEGIN
41 | dbms_metadata.set_transform_param(dbms_metadata.session_transform,'EMIT_SCHEMA',false); -- undocumented: remove schema
42 | dbms_metadata.set_transform_param(dbms_metadata.session_transform,'CONSTRAINTS_AS_ALTER',true); -- let's have them separate
43 | dbms_metadata.set_transform_param (dbms_metadata.session_transform, 'SEGMENT_ATTRIBUTES', false); -- skip nasty defaults
44 | dbms_metadata.set_transform_param (dbms_metadata.session_transform, 'SQLTERMINATOR', true); -- end each statement with ';'
45 | dbms_metadata.set_transform_param (dbms_metadata.session_transform, 'PRETTY', true); -- not sure what gets prettier here
46 | cnt := 0;
47 | FOR rec IN c_tab LOOP
48 | cnt := cnt +1;
49 | IF cnt < 1 THEN
50 | CONTINUE;
51 | END IF;
52 | fname := lower(rec.table_name)||'.sql';
53 | fh := utl_file.fopen('UTLFILEDIR',fname,'W',32767);
54 | FOR r1 IN c_tabcomment(rec.table_name) LOOP
55 | utl_file.put_line(fh,r1.line);
56 | END LOOP;
57 | utl_file.put_line(fh,' * @table '||rec.table_name);
58 | FOR r1 IN c_colcomment(rec.table_name) LOOP
59 | utl_file.put_line(fh,r1.line);
60 | END LOOP;
61 | utl_file.put_line(fh,' */');
62 | utl_file.putf(fh,dbms_metadata.get_ddl( object_type => 'TABLE' , name => rec.table_name)||'\n');
63 | BEGIN
64 | utl_file.putf(fh,dbms_metadata.get_dependent_ddl('COMMENT',rec.table_name)||'\n');
65 | EXCEPTION
66 | WHEN OTHERS THEN NULL; -- no comments found
67 | END;
68 | FOR r1 IN c_grant(rec.table_name) LOOP
69 | utl_file.put_line(fh,r1.line);
70 | END LOOP;
71 | utl_file.fclose(fh);
72 | -- exit;
73 | END LOOP;
74 | EXCEPTION
75 | WHEN utl_file.invalid_path THEN raise_application_error(-20000, 'ERROR: Invalid PATH FOR file.');
76 | END;
77 | /
78 |
79 | EXIT;
80 |
--------------------------------------------------------------------------------
/tools/gen_view_scripts.sql:
--------------------------------------------------------------------------------
1 | /**
2 | * Extract view definitions from data dictionary
3 | * As preparation, you will need an Oracle DIRECTORY to place the created
4 | * scripts into:
5 | * DROP DIRECTORY UTLFILEDIR;
6 | * CREATE OR REPLACE DIRECTORY UTLFILEDIR AS '';
7 | * GRANT READ, WRITE ON DIRECTORY UTLFILEDIR TO ;
8 | * Replace and to match your needs. If you change the name
9 | * of the directory, you will need to do so in below script as well.
10 | */
11 |
12 | SET ECHO OFF
13 | SET FEEDBACK OFF
14 | SET SERVEROUT ON
15 | SET SQLBL ON
16 | SET TERMOUT ON
17 | SET PAGES 0
18 | SET LINES 200
19 |
20 | DECLARE
21 | cnt NUMBER; -- in case we want a range only
22 | fh UTL_FILE.FILE_TYPE;
23 | fname VARCHAR2(255);
24 | CURSOR c_tab IS
25 | SELECT view_name as table_name
26 | FROM user_views;
27 | CURSOR c_tabcomment(tname IN VARCHAR2) IS
28 | SELECT '/** '||comments AS line
29 | FROM user_tab_comments
30 | WHERE table_name = tname;
31 | CURSOR c_colcomment(tname IN VARCHAR2) IS
32 | SELECT ' * @col '||t.data_type||' '||t.column_name||' '||c.comments AS line
33 | FROM user_tab_columns t LEFT JOIN user_col_comments c ON (t.table_name=c.table_name AND t.column_name=c.column_name)
34 | WHERE t.table_name=tname;
35 | CURSOR c_grant(tname IN VARCHAR2) IS
36 | SELECT (CASE WHEN grantable='NO' THEN 'GRANT '||privilege||' ON '||tname||' TO '||grantee||';'
37 | ELSE 'GRANT '||privilege||' ON '||tname||' TO '||grantee||' WITH GRANT OPTION;' END) AS line
38 | FROM user_tab_privs
39 | WHERE table_name='EOX_ARBEITSTAGE';
40 | BEGIN
41 | dbms_metadata.set_transform_param(dbms_metadata.session_transform,'EMIT_SCHEMA',false); -- undocumented: remove schema
42 | dbms_metadata.set_transform_param(dbms_metadata.session_transform,'CONSTRAINTS_AS_ALTER',true); -- let's have them separate
43 | dbms_metadata.set_transform_param (dbms_metadata.session_transform, 'SEGMENT_ATTRIBUTES', false); -- skip nasty defaults
44 | dbms_metadata.set_transform_param (dbms_metadata.session_transform, 'SQLTERMINATOR', true); -- end each statement with ';'
45 | dbms_metadata.set_transform_param (dbms_metadata.session_transform, 'PRETTY', true); -- not sure what gets prettier here
46 | cnt := 0;
47 | FOR rec IN c_tab LOOP
48 | cnt := cnt +1;
49 | IF cnt < 1 THEN
50 | CONTINUE;
51 | END IF;
52 | fname := lower(rec.table_name)||'.sql';
53 | fh := utl_file.fopen('UTLFILEDIR',fname,'W',32767);
54 | FOR r1 IN c_tabcomment(rec.table_name) LOOP
55 | utl_file.put_line(fh,r1.line);
56 | END LOOP;
57 | utl_file.putf(fh,' * @view '||rec.table_name||'\n');
58 | FOR r1 IN c_colcomment(rec.table_name) LOOP
59 | utl_file.put_line(fh,r1.line);
60 | END LOOP;
61 | utl_file.put_line(fh,' */');
62 | utl_file.putf(fh,dbms_metadata.get_ddl( object_type => 'VIEW' , name => rec.table_name)||'\n');
63 | BEGIN
64 | utl_file.putf(fh,dbms_metadata.get_dependent_ddl('COMMENT',rec.table_name)||'\n');
65 | EXCEPTION
66 | WHEN OTHERS THEN NULL; -- no comments found
67 | END;
68 | FOR r1 IN c_grant(rec.table_name) LOOP
69 | utl_file.put_line(fh,r1.line);
70 | END LOOP;
71 | utl_file.fclose(fh);
72 | -- exit;
73 | END LOOP;
74 | EXCEPTION
75 | WHEN utl_file.invalid_path THEN raise_application_error(-20000, 'ERROR: Invalid PATH FOR file.');
76 | END;
77 | /
78 |
79 | EXIT;
80 |
--------------------------------------------------------------------------------