##### # ZFireBirdDA # # (C) Copyright 2000,2001 Phil Harris # ACN: 082 081 472 ABN: 83 082 081 472 # All Rights Reserved # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE # # Author: # Phil Harris # # Contributors: # # Robert Kellock # Yashushi Iwata # Godefroid Chapelle ##### '''ZFireBird''' __version__='0.0.3' import kinterbasdb, DateTime from Shared.DC.ZRDB.TM import TM import string, sys strsplit=string.split from string import strip, find, split from time import time failures=0 calls=0 last_call_time=time() class DB(TM): _p_oid=_p_changed=_registered=None Database_Connection=kinterbasdb.connect Database_Error=kinterbasdb.Error def __init__(self,connection): self.connection=connection self.connect() self.resetCursor() def connect(self): try: self.db.close() except: pass #--- # parse the connection string #--- if '=' in self.connection: kwargs={} for s in split(self.connection): k,v=s.split('=',1) kwargs[k]=v self.db=apply(kinterbasdb.connect,(),kwargs) else: connbits=strsplit(self.connection, ' ') db=kinterbasdb.connect(dsn=connbits[0],user=connbits[1],password=connbits[2]) self.db=db self.db.begin() def resetCursor(self): try: self.cursor.close() except: pass self.cursor=self.db.cursor() def str(self,v, StringType=type('')): if v is None: return '' r=str(v) if r[-1:]=='L' and type(v) is not StringType: r=r[:-1] return r def _finish(self, *ignored): self.db.commit() self.db.begin() def _abort(self, *ignored): self.db.rollback() self.db.begin() self.resetCursor() def tables(self, rdb=0, _care=('TABLE', 'VIEW')): r=[] a=r.append c=self.db.cursor() c.execute('''SELECT RDB$RELATION_NAME FROM RDB$RELATIONS WHERE ( NOT (RDB$RELATION_NAME STARTING WITH 'RDB$') ) ORDER BY 1''') tabs=c.fetchall() for tab in tabs: a({'TABLE_NAME': strip(str(tab[0])), 'TABLE_TYPE': 'TABLE'}) return r def columns(self, table_name): c=self.cursor try: r=c.execute('''select r.rdb$field_name field_name, t.rdb$type_name type_name, f.rdb$field_length field_length, f.rdb$field_sub_type field_sub_type, f.rdb$null_flag null_flag, rdb$field_precision field_precision, f.rdb$field_scale field_scale, f.rdb$default_source default_value from rdb$relation_fields r, rdb$types t, rdb$fields f where r.rdb$relation_name='' and f.rdb$field_name=r.rdb$field_source and t.rdb$field_name='RDB$FIELD_TYPE' and f.rdb$field_type=t.rdb$type;''' % table_name) except: self.resetCursor() return () rows=c.fetchallmap() r=[] a=r.append for row in rows: name=row['field_name'] typ=strip(row['type_name']) p=row['field_length'] scale=row['field_scale'] null_ok=row['null_flag'] is not None and 'Nullable' or '' default=row['default_value'] print "''" % typ if strip(typ)=='VARYING': typ='VARCHAR' subtyp='' if typ=='BLOB': subtyp=row['field_sub_type'] c.execute('select rdb$type_name from rdb$types where rdb$type=' ubtyp) subtyp=c.fetchall() print subtyp subtyp=strip(subtyp[0][0]) a({ 'Name': strip(name), 'Type': strip(typ), 'Precision': strip(str(p)), 'Scale': strip(str(scale)), 'Nullable': strip(str(null_ok)), 'Default': strip(str(default)), 'SubType': strip(str(subtyp)), }) return r def query(self,query_string, max_rows=9999999): global failures, calls, last_call_time calls=calls+1 desc=None result=() self._register() c=self.cursor try: for qs in filter(None, map(strip,strsplit(query_string, '\0'))): r=c.execute(qs) if r is None: if desc is not None: if c.description != desc: raise 'Query Error', ( 'Multiple select schema are not allowed') if type(result) is not ListType: result=list(result) if max_rows: for row in c.fetchmany(max_rows-len(result)): result.append(row) else: desc=c.description if desc: if max_rows==1: result=(c.fetchone(),) else: result=c.fetchmany(max_rows) failures=0 last_call_time=time() except kinterbasdb.ProgrammingError, mess: if mess[0]!=0: raise self.Database_Error(mess) self.resetCursor() except self.Database_Error,mess: raise sys.exc_type, sys.exc_value, sys.exc_traceback if desc is None: return (),() items=[] for name, type, width, ds, p, scale, null_ok in desc: if type=='NUMBER': if scale==0: type='i' else: type='n' elif type=='DATE': type='d' else: type='s' items.append({ 'name': name, 'type': type, 'width': width, 'null': null_ok, }) return items, result