Changeset 179:a1e884c9327b in livinglogic.python.orasql

Show
Ignore:
Timestamp:
11/06/06 17:49:46 (13 years ago)
Author:
Walter Doerwald <walter@…>
Branch:
default
Tags:
rel-1-13
Message:

Add methods itertables() and iterfks().

Fix a bug in oramerge.py: In certain branches action was uninitialized
which lead to bugs, as oramerge.py was using the action value from the
previous iteration.

Updated ipipe functionality (the the current IPython head version).

Enhanced oramerge.py output.

Files:
8 modified

Legend:

Unmodified
Added
Removed
  • NEWS.xml

    r178 r179  
     1<section><title>Changes in 1.13 (released 11/06/2006)</title> 
     2<ulist> 
     3<item>Two new methods (<method>itertables</method> and <method>iterfks</method>) 
     4have been added to <class>Connection</class>. They yields all table definitions 
     5or all foreign keys respectively.</item> 
     6<item>A new method <method>isenabled</method> has been added to 
     7<class>ForeignKey</class>.</item> 
     8<item>A <method>__str__</method> method has been added to <class>Object</class>.</item> 
     9<item>A bug in <filename>oramerge.py</filename> has been fixed: In certain 
     10situations <filename>oramerge.py</filename> used merging actions that were 
     11meant to be used for the preceeding object.</item> 
     12</ulist> 
     13</section> 
     14 
     15 
    116<section><title>Changes in 1.12.2 (released 10/18/2006)</title> 
    217<ulist> 
  • setup.py

    r178 r179  
    4747args=dict( 
    4848    name="ll-orasql", 
    49     version="1.12.2", 
     49    version="1.13", 
    5050    description="Utilities for working with cx_Oracle", 
    5151    long_description=DESCRIPTION, 
  • src/ll/orasql/__init__.py

    r178 r179  
    136136            raise AttributeError(name) 
    137137 
    138     def __xattrs__(self, mode): 
     138    def __xattrs__(self, mode="default"): 
    139139        # Return the attributes of this record. This is for interfacing with ipipe 
    140140        return [key.lower() for key in self.iterkeys()] 
     
    158158        self.count = count 
    159159 
    160     def __xattrs__(self, mode): 
     160    def __xattrs__(self, mode="default"): 
    161161        return ("type", "count") 
    162162 
     
    209209            yield (astyle.style_default, repr(self)) 
    210210 
    211     def __xiter__(self, mode): 
    212         if mode is None: 
    213             yield ipipe.XMode(self, "schema", "schema", "object types in this schema") 
    214             yield ipipe.XMode(self, "objectscreateuser", "objects (create order)", "all objects belonging to this user (in create order)") 
    215             yield ipipe.XMode(self, "objectsdropuser", "objects (drop order)", "all objects belonging to this user (in drop order)") 
    216             yield ipipe.XMode(self, "objectsflatuser", "objects (unordered)", "all objects belonging to this user (unordered)") 
    217             yield ipipe.XMode(self, "objectscreateall", "all objects (create order)", "all objects in all schemas (in create order)") 
    218             yield ipipe.XMode(self, "objectsdropall", "all objects (drop order)", "all objects in all schemas (in drop order)") 
    219             yield ipipe.XMode(self, "objectsflatall", "all objects (unordered)", "all objects in all schemas (unordered)") 
    220         elif mode == "objectscreateuser": 
    221             for item in self.iterobjects("create", "user"): 
    222                 yield item 
    223         elif mode == "objectsdropuser": 
    224             for item in self.iterobjects("drop", "user"): 
    225                 yield item 
    226         elif mode == "objectsflatuser": 
    227             for item in self.iterobjects("flat", "user"): 
    228                 yield item 
    229         elif mode == "objectscreateall": 
    230             for item in self.iterobjects("create", "all"): 
    231                 yield item 
    232         elif mode == "objectsdropall": 
    233             for item in self.iterobjects("drop", "all"): 
    234                 yield item 
    235         elif mode == "objectsflatall": 
    236             for item in self.iterobjects("flat", "all"): 
    237                 yield item 
    238         else: 
    239             for item in self.iterschema(): 
    240                 yield item 
    241  
    242211    def iterschema(self, schema="user"): 
    243212        """ 
     
    257226            if class_ is not None: 
    258227                yield _AllTypes(self, class_, schema, row.count) 
     228 
     229    def itertables(self, schema="user"): 
     230        """ 
     231        <par>Generator that yields all table definitions in the current users schema 
     232        (or all users schemas).</par> 
     233        <par><arg>schema</arg> specifies from which tables should be 
     234        yielded:</par> 
     235        <dlist> 
     236        <term><lit>"user"</lit></term><item>Only tables belonging to the current 
     237        user (and those objects these depend on) will be yielded.</item> 
     238        <term><lit>"all"</lit></term><item>All tables from all users will be 
     239        yielded.</item> 
     240        </dlist> 
     241        <par>Tables that are materialized view will be skipped in both casess.</par> 
     242        """ 
     243        if schema not in ("user", "all"): 
     244            raise UnknownSchemaError(schema) 
     245 
     246        cursor = self.cursor() 
     247 
     248        if schema == "all": 
     249            cursor.execute("select decode(owner, user, null, owner) as owner, table_name from all_tables minus select decode(owner, user, null, owner) as owner, mview_name as table_name from all_mviews") 
     250        else: 
     251            cursor.execute("select null as owner, table_name from user_tables minus select null as owner, mview_name as table_name from user_mviews") 
     252        for rec in cursor.fetchall(): 
     253            yield Table(rec.table_name, rec.owner, self) 
     254 
     255    def iterfks(self, schema="user"): 
     256        """ 
     257        <par>Generator that yields all foreign key constraints in the current users schema 
     258        (or all users schemas).</par> 
     259        <par><arg>schema</arg> specifies from which tables should be 
     260        yielded:</par> 
     261        <dlist> 
     262        <term><lit>"user"</lit></term><item>Only tables belonging to the current 
     263        user (and those objects these depend on) will be yielded.</item> 
     264        <term><lit>"all"</lit></term><item>All tables from all users will be 
     265        yielded.</item> 
     266        </dlist> 
     267        """ 
     268        if schema not in ("user", "all"): 
     269            raise UnknownSchemaError(schema) 
     270 
     271        cursor = self.cursor() 
     272 
     273        if schema == "all": 
     274            cursor.execute("select decode(owner, user, null, owner) as owner, constraint_name from all_constraints where constraint_type='R' order by owner, table_name, constraint_name") 
     275        else: 
     276            cursor.execute("select null as owner, constraint_name from user_constraints where constraint_type='R' order by table_name, constraint_name") 
     277        for rec in cursor.fetchall(): 
     278            yield ForeignKey(rec.constraint_name, rec.owner, self) 
    259279 
    260280    def iterobjects(self, mode="create", schema="user"): 
     
    615635            return "%s.%s(%r)" % (self.__class__.__module__, self.__class__.__name__, self.name) 
    616636 
     637    def __str__(self): 
     638        if self.owner is not None: 
     639            return "%s(%s, %s)" % (self.__class__.__name__, self.name, self.owner) 
     640        else: 
     641            return "%s(%s)" % (self.__class__.__name__, self.name) 
     642 
    617643    def __eq__(self, other): 
    618644        return self.__class__ is other.__class__ and self.name == other.name and self.owner == other.owner 
     
    757783        return (cls(row.object_name, row.owner, connection) for row in cursor) 
    758784 
    759     def __xiter__(self, mode): 
    760         if mode is None: 
    761             yield ipipe.XMode(self, "create", "create statement", "the SQL script to create this %s" % self.type) 
    762             yield ipipe.XMode(self, "drop", "drop statement", "the SQL script to drop this %s" % self.type) 
    763             yield ipipe.XMode(self, "referencedby", "referenced by", "other objects depending on this %s" % self.type) 
    764             yield ipipe.XMode(self, "references", "references", "other objects on which this %s depends" % self.type) 
    765             yield ipipe.XMode(self, "referencedbyall", "referenced by all", "all other objects depending on this %s" % self.type) 
    766             yield ipipe.XMode(self, "referencesall", "references all", "all other objects on which this %s depends" % self.type) 
    767         elif mode == "referencedby": 
    768             for item in self.iterreferencedby(): 
    769                 yield item 
    770         elif mode == "references": 
    771             for item in self.iterreferences(): 
    772                 yield item 
    773         elif mode == "referencedbyall": 
    774             for item in self.iterreferencedbyall(): 
    775                 yield item 
    776         elif mode == "referencesall": 
    777             for item in self.iterreferencesall(): 
    778                 yield item 
    779         elif mode == "drop": 
    780             for line in ipipe.xiter(self.dropddl()): 
    781                 yield line 
    782         else: 
    783             for line in ipipe.xiter(self.createddl()): 
    784                 yield line 
     785    def __iter__(self): 
     786        return iter(self.createddl().splitlines()) 
    785787 
    786788    def __xrepr__(self, mode): 
     
    797799 
    798800    if hasattr(ipipe, "Descriptor"): 
    799         def __xattrs__(self, mode): 
     801        def __xattrs__(self, mode="default"): 
    800802            yield "type" 
    801803            yield "name" 
     
    813815                yield "-iterreferencedbyall()" 
    814816    else: 
    815         def __xattrs__(self, mode): 
     817        def __xattrs__(self, mode="default"): 
    816818            if mode == "detail": 
    817819                return ("type", "name", "owner", "connection", "cdate()", "udate()") 
     
    874876            yield None 
    875877 
    876     def __xiter__(self, mode): 
    877         if mode is None: 
    878             yield ipipe.XMode(self, "create", "create statement", "the SQL script to create this sequence") 
    879             yield ipipe.XMode(self, "createcopy", "create statement (exact copy)", "the SQL script to create this sequence (using the current value as the start value)") 
    880             yield ipipe.XMode(self, "drop", "drop statement", "the SQL script to drop this sequence") 
    881             yield ipipe.XMode(self, "referencedby", "referenced by", "other objects depending on this %s" % self.type) 
    882             yield ipipe.XMode(self, "references", "references", "other objects on which this %s depends" % self.type) 
    883             yield ipipe.XMode(self, "referencedbyall", "referenced by all", "all other objects depending on this %s" % self.type) 
    884             yield ipipe.XMode(self, "referencesall", "references all", "all other objects on which this %s depends" % self.type) 
    885         elif mode == "referencedby": 
    886             for item in self.iterreferencedby(): 
    887                 yield item 
    888         elif mode == "references": 
    889             for item in self.iterreferences(): 
    890                 yield item 
    891         elif mode == "referencedbyall": 
    892             for item in self.iterreferencedbyall(): 
    893                 yield item 
    894         elif mode == "referencesall": 
    895             for item in self.iterreferencesall(): 
    896                 yield item 
    897         elif mode == "drop": 
    898             for line in ipipe.xiter(self.dropddl()): 
    899                 yield line 
    900         elif mode == "createcopy": 
    901             for line in ipipe.xiter(self.createddlcopy()): 
    902                 yield line 
    903         else: 
    904             for line in ipipe.xiter(self.createddl()): 
    905                 yield line 
    906  
    907     def __xattrs__(self, mode): 
     878    def __xattrs__(self, mode="default"): 
    908879        for attr in super(Sequence, self).__xattrs__(mode): 
    909880            yield attr 
     
    10771048                yield obj 
    10781049 
    1079     def __xiter__(self, mode): 
    1080         if mode is None: 
    1081             yield ipipe.XMode(self, "create", "create statement", "the SQL script to create this table") 
    1082             yield ipipe.XMode(self, "drop", "drop statement", "the SQL script to drop this table") 
    1083             yield ipipe.XMode(self, "columns", "columns", "the columns of this table") 
    1084             yield ipipe.XMode(self, "constraints", "constraints", "the constraints of this table") 
    1085             yield ipipe.XMode(self, "records", "records", "records in this table") 
    1086             yield ipipe.XMode(self, "referencedby", "referenced by", "other objects depending on this %s" % self.type) 
    1087             yield ipipe.XMode(self, "references", "references", "other objects on which this %s depends" % self.type) 
    1088             yield ipipe.XMode(self, "referencedbyall", "referenced by all", "all other objects depending on this %s" % self.type) 
    1089             yield ipipe.XMode(self, "referencesall", "references all", "all other objects on which this %s depends" % self.type) 
    1090         elif mode == "referencedby": 
    1091             for item in self.iterreferencedby(): 
    1092                 yield item 
    1093         elif mode == "references": 
    1094             for item in self.iterreferences(): 
    1095                 yield item 
    1096         elif mode == "referencedbyall": 
    1097             for item in self.iterreferencedbyall(): 
    1098                 yield item 
    1099         elif mode == "referencesall": 
    1100             for item in self.iterreferencesall(): 
    1101                 yield item 
    1102         elif mode == "drop": 
    1103             for line in ipipe.xiter(self.dropddl()): 
    1104                 yield line 
    1105         elif mode == "columns": 
    1106             for item in self.itercolumns(): 
    1107                 yield item 
    1108         elif mode == "constraints": 
    1109             for item in self.iterconstraints(): 
    1110                 yield item 
    1111         elif mode == "records": 
    1112             for item in self.iterrecords(): 
    1113                 yield item 
    1114         else: 
    1115             for line in ipipe.xiter(self.createddl()): 
    1116                 yield line 
    1117  
    11181050    if hasattr(ipipe, "Descriptor"): 
    1119         def __xattrs__(self, mode): 
     1051        def __xattrs__(self, mode="default"): 
    11201052            for attr in super(Table, self).__xattrs__(mode): 
    11211053                yield attr 
     
    11271059                yield "mview()" 
    11281060    else: 
    1129         def __xattrs__(self, mode): 
     1061        def __xattrs__(self, mode="default"): 
    11301062            for attr in super(Table, self).__xattrs__(mode): 
    11311063                yield attr 
     
    12181150        return Table(rec.table_name, self.owner, connection) 
    12191151 
    1220     def __xattrs__(self, mode): 
     1152    def __xattrs__(self, mode="default"): 
    12211153        for attr in super(PrimaryKey, self).__xattrs__(mode): 
    12221154            yield attr 
     
    13621294        return PrimaryKey(rec.r_constraint_name, rec.r_owner, connection) 
    13631295 
    1364     def __xattrs__(self, mode): 
     1296    def isenabled(self, connection=None): 
     1297        """ 
     1298        Return whether this constraint is enabled. 
     1299        """ 
     1300        (connection, cursor) = self.getcursor(connection) 
     1301        cursor.execute("select status from all_constraints where constraint_type='R' and owner=nvl(:owner, user) and constraint_name=:name", owner=self.owner, name=self.name) 
     1302        rec = cursor.fetchone() 
     1303        return rec.status == "ENABLED" 
     1304 
     1305    def __xattrs__(self, mode="default"): 
    13651306        for attr in super(ForeignKey, self).__xattrs__(mode): 
    13661307            yield attr 
     
    14341375                yield obj 
    14351376 
    1436     def __xattrs__(self, mode): 
     1377    def __xattrs__(self, mode="default"): 
    14371378        for attr in super(Index, self).__xattrs__(mode): 
    14381379            yield attr 
     
    14491390        return Table(rec.table_name, self.owner, connection) 
    14501391 
    1451     def __xattrs__(self, mode): 
     1392    def __xattrs__(self, mode="default"): 
    14521393        for attr in super(Index, self).__xattrs__(mode): 
    14531394            yield attr 
     
    15371478        return Table(rec.table_name, self.owner, connection) 
    15381479 
    1539     def __xattrs__(self, mode): 
     1480    def __xattrs__(self, mode="default"): 
    15401481        for attr in super(UniqueConstraint, self).__xattrs__(mode): 
    15411482            yield attr 
     
    16331574        cursor.execute(query) 
    16341575        return iter(cursor) 
    1635  
    1636     def __xiter__(self, mode): 
    1637         if mode is None: 
    1638             yield ipipe.XMode(self, "create", "create statement", "the SQL script to create this view") 
    1639             yield ipipe.XMode(self, "drop", "drop statement", "the SQL script to drop this view") 
    1640             yield ipipe.XMode(self, "records", "records", "records in this view") 
    1641             yield ipipe.XMode(self, "referencedby", "referenced by", "other objects depending on this %s" % self.type) 
    1642             yield ipipe.XMode(self, "references", "references", "other objects on which this %s depends" % self.type) 
    1643             yield ipipe.XMode(self, "referencedbyall", "referenced by all", "all other objects depending on this %s" % self.type) 
    1644             yield ipipe.XMode(self, "referencesall", "references all", "all other objects on which this %s depends" % self.type) 
    1645         elif mode == "referencedby": 
    1646             for item in self.iterreferencedby(): 
    1647                 yield item 
    1648         elif mode == "references": 
    1649             for item in self.iterreferences(): 
    1650                 yield item 
    1651         elif mode == "referencedbyall": 
    1652             for item in self.iterreferencedbyall(): 
    1653                 yield item 
    1654         elif mode == "referencesall": 
    1655             for item in self.iterreferencesall(): 
    1656                 yield item 
    1657         elif mode == "drop": 
    1658             for line in ipipe.xiter(self.dropddl()): 
    1659                 yield line 
    1660         elif mode == "records": 
    1661             for item in self.iterrecords(): 
    1662                 yield item 
    1663         else: 
    1664             for line in ipipe.xiter(self.createddl()): 
    1665                 yield line 
    16661576 
    16671577 
     
    21342044        return rec.comments or None 
    21352045 
    2136     def __xattrs__(self, mode): 
     2046    def __xattrs__(self, mode="default"): 
    21372047        for attr in super(Column, self).__xattrs__(mode): 
    21382048            if attr == "-createddl()": 
     
    21452055        yield "comment()" 
    21462056 
    2147     def __xiter__(self, mode): 
     2057    def __iter__(self): 
    21482058        return None 
  • src/ll/orasql/scripts/oracreate.py

    r161 r179  
    7777            else: 
    7878                msg = astyle.style_default("oracreate.py: ", cs1, " fetching #%d" % (i+1)) 
    79             msg = astyle.style_default(msg, " ", s4object(repr(obj))) 
     79            msg = astyle.style_default(msg, " ", s4object(str(obj))) 
    8080            if not keepobj: 
    8181                msg = astyle.style_default(msg, " ", s4warning("(skipped)")) 
  • src/ll/orasql/scripts/oradiff.py

    r161 r179  
    3232 
    3333def df(obj): 
    34     return s4object(repr(obj)) 
     34    return s4object(str(obj)) 
    3535 
    3636 
  • src/ll/orasql/scripts/oradrop.py

    r161 r179  
    8282        # Progress report 
    8383        if options.verbose: 
    84             msg = astyle.style_default("oradrop.py: ", cs, ": fetching #%d " % (i+1), s4object(repr(obj))) 
     84            msg = astyle.style_default("oradrop.py: ", cs, ": fetching #%d " % (i+1), s4object(str(obj))) 
    8585            if action is not None: 
    8686                msg = astyle.style_default(msg, " ", s4warning("(%s)" % action)) 
     
    9999        for (i, (obj, ddl)) in enumerate(ddls): 
    100100            if options.verbose: 
    101                 stderr.writeln("oradrop.py: ", cs, ": dropping #%d/%d " % (i+1, len(ddls)), s4object(repr(obj))) 
     101                stderr.writeln("oradrop.py: ", cs, ": dropping #%d/%d " % (i+1, len(ddls)), s4object(str(obj))) 
    102102            try: 
    103103                cursor.execute(ddl) 
  • src/ll/orasql/scripts/oramerge.py

    r173 r179  
    2626s4pos = astyle.Style.fromenv("LL_ORASQL_REPRANSI_POS", "black:black:bold") 
    2727s4connectstring = astyle.Style.fromenv("LL_ORASQL_REPRANSI_CONNECTSTRING", "yellow:black") 
     28s4connid = astyle.Style.fromenv("LL_ORASQL_REPRANSI_NOTE", "yellow:black:bold") 
     29s4action = astyle.Style.fromenv("LL_ORASQL_REPRANSI_NOTE", "magenta:black") 
    2830s4object = astyle.Style.fromenv("LL_ORASQL_REPRANSI_OBJECT", "green:black") 
    2931 
     
    3537 
    3638def df(obj): 
    37     return s4object(repr(obj)) 
    38  
    39  
    40 def comment(*msg): 
    41     return s4comment("-- ", *msg) 
     39    return s4object(str(obj)) 
     40 
     41 
     42def connid(name): 
     43    return s4connid("[%d]" % name) 
     44 
     45 
     46def showcomment(out, *texts): 
     47    out.writeln(s4comment("-- ", *texts)) 
    4248 
    4349 
     
    4652 
    4753 
    48 def showaction(out, action, obj): 
    49     out.writeln(comment(action, " ", df(obj))) 
     54def showreport(out, type, countcreate, countdrop, countcollision, countmerge, countmergeconflict): 
     55    first = True 
     56    data = (("added", countcreate), ("dropped", countdrop), ("collided", countcollision), ("merged", countmerge), ("mergeconflict", countmergeconflict)) 
     57    for (name, count) in data: 
     58        if count: 
     59            if first: 
     60                out.write(" => ") 
     61                first = False 
     62            else: 
     63                out.write("; ") 
     64            if name in ("collided", "mergeconflict"): 
     65                cls = s4error 
     66            else: 
     67                cls = s4action 
     68            if count > 1: 
     69                msg = "%d %ss %s" % (count, type, name) 
     70            else: 
     71                msg = "1 %s %s" % (type, name) 
     72            out.write(cls(msg)) 
     73    if first: 
     74        out.write(" => identical") 
     75    out.writeln() 
    5076 
    5177 
     
    89115    connection3 = orasql.connect(args[2]) 
    90116 
    91     def fetch(connection): 
     117    def fetch(connection, name): 
    92118        objects = set() 
    93119 
     
    95121            keep = ("$" not in obj.name and not obj.name.startswith("SYS_EXPORT_SCHEMA_")) or options.keepjunk 
    96122            if options.verbose: 
    97                 msg = astyle.style_default("oramerge.py: ", cs(connection), " fetching #%d " % (i+1), df(obj)) 
     123                msg = astyle.style_default("oramerge.py: ", cs(connection), connid(name), " fetching #%d " % (i+1), df(obj)) 
    98124                if not keep: 
    99125                    msg += s4error(" (skipped)") 
     
    110136            file.close() 
    111137 
    112     objects1 = fetch(connection1) 
    113     objects2 = fetch(connection2) 
    114     objects3 = fetch(connection3) 
     138    objects1 = fetch(connection1, 1) 
     139    objects2 = fetch(connection2, 2) 
     140    objects3 = fetch(connection3, 3) 
    115141 
    116142    retcode = 0 
    117143 
     144    def inmesg(flag, name): 
     145        if flag: 
     146            return astyle.style_default("in ", connid(name)) 
     147        else: 
     148            return astyle.style_default("not in ", connid(name)) 
     149 
     150    countcreate = 0 
     151    countdrop = 0 
     152    countmerge = 0 
     153    countcollision = 0 
     154    countmergeconflict = 0 
    118155    allobjects = objects1 | objects2 | objects3 
    119156    for (i, obj) in enumerate(allobjects): 
     157        action = None 
    120158        in1 = obj in objects1 
    121159        in2 = obj in objects2 
    122160        in3 = obj in objects3 
     161        if options.verbose: 
     162            stderr.write("oramerge.py: ", df(obj), " #", str(i+1), "/", str(len(allobjects)), ": ") 
     163            first = True 
     164            for (nr, flag) in enumerate((in1, in2, in3)): 
     165                if flag: 
     166                    if first: 
     167                        stderr.write("in ") 
     168                        first = False 
     169                    else: 
     170                        stderr.write("+") 
     171                    stderr.write(connid(nr+1)) 
     172        comm = s4comment("-- ", df(obj), " ") 
    123173        if in1 != in2: # ignore changes from in2 to in3, because only if something changed in the sources we have to do something 
    124174            if not in1 and in2 and not in3: # added in in2 => copy it to db3 
    125                 msg = astyle.style_default(df(obj), ": added in ", cs(connection2), " => add it to ", cs(connection3)) 
     175                if options.verbose: 
     176                    stderr.writeln(" => ", s4action("new (create it)")) 
     177                countcreate += 1 
    126178                action = "create" 
    127179            elif not in1 and in2 and in3: # added in both in2 and in3 => collision? 
    128180                if obj.createddl(connection2) != obj.createddl(connection3): 
    129                     msg = astyle.style_default(df(obj), ": added in ", cs(connection2), " and ", cs(connection3), " => ", s4error("conflict")) 
     181                    if options.verbose: 
     182                        stderr.writeln(" => ", s4error("collision")) 
     183                    countcollision += 1 
    130184                    action = "collision" 
    131185                    retcode = 2 
    132186                else: 
    133                     msg = astyle.style_default(df(obj), ": added in ", cs(connection2), " and ", cs(connection3), " and identical => keep it") 
    134                     action = None 
     187                    if options.verbose: 
     188                        stderr.writeln(" => already created (keep it)") 
    135189            elif in1 and not in2 and not in3: # removed in in2 and in3 => not needed 
    136                 msg = astyle.style_default(df(obj), ": removed in ", cs(connection2), " and ", cs(connection3), " => not needed") 
    137                 action = None 
     190                if options.verbose: 
     191                    stderr.writeln(" => removed (not needed)") 
    138192            elif in1 and not in2 and in3: # removed in in2 => remove in db3 
    139                 msg = astyle.style_default(df(obj), ": removed in ", cs(connection2), " => remove in ", cs(connection3)) 
     193                if options.verbose: 
     194                    stderr.writeln(" => ", s4action("drop it")) 
     195                countdrop += 1 
    140196                action = "drop" 
    141197            else: 
     
    147203 
    148204            if options.verbose: 
    149                 stderr.writeln("oramerge.py: diffing #%d/%d " % (i+1, len(allobjects)), df(obj)) 
     205                stderr.write(" => diffing") 
    150206 
    151207            if ddl1 != ddl2: # ignore changes between ddl2 and ddl3 here too 
     
    155211                    fields2 = set(obj.itercolumns(connection2)) 
    156212                    fields3 = set(obj.itercolumns(connection3)) 
     213                    fieldcountcreate = 0 
     214                    fieldcountdrop = 0 
     215                    fieldcountmerge = 0 
     216                    fieldcountcollision = 0 
     217                    fieldcountmergeconflict = 0 
    157218                    for field in fields1 | fields2 | fields3: 
    158                         if options.verbose: 
    159                             stderr.writeln("oramerge.py: diffing column ", df(field)) 
    160219                        in1 = field in fields1 
    161220                        in2 = field in fields2 
     
    163222                        if in1 != in2: # ignore changes between in2 and in3 here too 
    164223                            if not in1 and in2 and not in3: # added in in2 => copy it to db3 
    165                                 stdout.writeln(comment("add ", df(field))) 
     224                                fieldcountcreate += 1 
     225                                countcreate += 1 
     226                                showcomment(stdout, "add ", df(field)) 
    166227                                stdout.writeln(field.addddl(connection2)) 
    167228                            elif not in1 and in2 and in3: # added in both in2 and in3 => collision? 
    168                                 stdout.writeln(comment("conflict ", df(field))) 
     229                                fieldcountcollision += 1 
     230                                countcollision += 1 
     231                                showcomment(stdout, "collision ", df(field)) 
    169232                                stdout.writeln(conflictmarker(7*"<", "added in ", cs(connection2), " and ", cs(connection3), " with different content")) 
    170233                            elif in1 and not in2 and not in3: # removed in in2 and in3 => not needed 
    171234                                pass 
    172235                            elif in1 and not in2 and in3: # removed in in2 => remove in db3 
    173                                 stdout.writeln(comment("drop ", df(field))) 
     236                                fieldcountdrop += 1 
     237                                countdrop += 1 
     238                                showcomment(stdout, "drop ", df(field)) 
    174239                                stdout.writeln(field.dropddl(connection3)) 
    175240                        elif in1 and in2 and in3: # in all three => modify field 
     
    181246                                    ddl = field.modifyddl(connection3, connection1.cursor(), connection2.cursor()) # add changes from db1 to db2 
    182247                                except orasql.ConflictError, exc: 
    183                                     stdout.writeln(comment("conflict ", df(field))) 
     248                                    fieldcountmergeconflict += 1 
     249                                    countmergeconflict += 1 
     250                                    showcomment(stdout, "merge conflict ", df(field)) 
    184251                                    stdout.writeln(conflictmarker(7*"<", str(exc))) 
    185252                                else: 
    186                                     stdout.writeln(comment("merge ", df(field))) 
     253                                    fieldcountmerge += 1 
     254                                    countmerge += 1 
     255                                    showcomment(stdout, "merged ", df(field)) 
    187256                                    stdout.writeln(ddl) 
     257                    if options.verbose: 
     258                        showreport(stderr, "field", fieldcountcreate, fieldcountdrop, fieldcountcollision, fieldcountmerge, fieldcountmergeconflict) 
    188259                else: 
    189                     msg = astyle.style_default(df(obj), ": merge them") 
     260                    if options.verbose: 
     261                        stderr.write(" => merge them") 
    190262                    action = "merge" 
    191263            else: 
    192                 msg = astyle.style_default(df(obj), ": identical") 
    193                 action = None 
     264                if options.verbose: 
     265                    stderr.writeln(" => identical") 
     266        elif in3: 
     267            if options.verbose: 
     268                stderr.writeln(" => keep it") 
     269        else: 
     270            if options.verbose: 
     271                stderr.writeln(" => not needed") 
    194272 
    195273        if action is not None: 
    196274            if action == "collision": 
    197                 showaction(stdout, action, obj) 
     275                showcomment(stdout, "collision ", df(obj)) 
    198276                stdout.writeln(conflictmarker(7*"<", "added in ", cs(connection2), " and ", cs(connection3), " with different content")) 
    199277            elif action == "create": 
    200                 showaction(stdout, action, obj) 
     278                showcomment(stdout, "create ", df(obj)) 
    201279                stdout.writeln(obj.createddl(connection2, term=True)) 
    202280            elif action == "drop": 
    203                 showaction(stdout, action, obj) 
     281                showcomment(stdout, "drop ", df(obj)) 
    204282                stdout.writeln(obj.dropddl(connection3, term=True)) 
    205283            elif action == "merge": 
     
    241319                            data = "".join(data) 
    242320                            if diffretcode == 0: # no conflict 
     321                                showcomment(stdout, "merge ", df(obj)) 
    243322                                # Check if anything has changed 
    244323                                finalddl = data 
    245324                                # diff3 seems to append a "\n" 
    246325                                if finalddl != ddl3 and (not finalddl.endswith("\n") or finalddl[:-1] != ddl3): 
    247                                     showaction(stdout, "merge", obj) 
     326                                    if options.verbose: 
     327                                        stderr.writeln(" => ", s4action("merged")) 
    248328                                    stdout.write(finalddl) 
    249329                            elif diffretcode == 1: # conflict 
    250                                 showaction(stdout, "conflict", obj) 
     330                                showcomment(stdout, "merge conflict ", df(obj)) 
     331                                if options.verbose: 
     332                                    stderr.writeln(" => ", s4error("merge conflict")) 
    251333                                retcode = 2 
    252334                                for line in data.splitlines(): 
     
    272354                finally: 
    273355                    os.remove(filename1) 
     356    if options.verbose: 
     357        stderr.write("oramerge.py: ", cs(connection3)) 
     358        showreport(stderr, "object", countcreate, countdrop, countcollision, countmerge, countmergeconflict) 
    274359    return retcode 
    275360 
  • test/test_orasql.py

    r174 r179  
    5757    db = orasql.connect(dbname) 
    5858    list(db.iterschema()) 
     59 
     60 
     61def test_connection_itertables(): 
     62    db = orasql.connect(dbname) 
     63    list(db.itertables()) 
     64 
     65 
     66def test_connection_iterfks(): 
     67    db = orasql.connect(dbname) 
     68    list(db.iterfks()) 
    5969 
    6070