408 if self.repo.config.init_cnxset_pool: |
408 if self.repo.config.init_cnxset_pool: |
409 self.open_source_connections() |
409 self.open_source_connections() |
410 |
410 |
411 |
411 |
412 def init(self, activated, source_entity): |
412 def init(self, activated, source_entity): |
413 super(NativeSQLSource, self).init(activated, source_entity) |
|
414 self.init_creating(source_entity._cw.cnxset) |
|
415 try: |
413 try: |
416 # test if 'asource' column exists |
414 # test if 'asource' column exists |
417 query = self.dbhelper.sql_add_limit_offset('SELECT asource FROM entities', 1) |
415 query = self.dbhelper.sql_add_limit_offset('SELECT asource FROM entities', 1) |
418 source_entity._cw.system_sql(query) |
416 source_entity._cw.system_sql(query) |
419 except Exception as ex: |
417 except Exception as ex: |
420 self.eid_type_source = self.eid_type_source_pre_131 |
418 self.eid_type_source = self.eid_type_source_pre_131 |
|
419 super(NativeSQLSource, self).init(activated, source_entity) |
|
420 self.init_creating(source_entity._cw.cnxset) |
421 |
421 |
422 def shutdown(self): |
422 def shutdown(self): |
423 if self._eid_creation_cnx: |
423 if self._eid_creation_cnx: |
424 self._eid_creation_cnx.close() |
424 self._eid_creation_cnx.close() |
425 self._eid_creation_cnx = None |
425 self._eid_creation_cnx = None |
749 query, args, ex.args[0]) |
749 query, args, ex.args[0]) |
750 if rollback: |
750 if rollback: |
751 try: |
751 try: |
752 session.cnxset.connection(self.uri).rollback() |
752 session.cnxset.connection(self.uri).rollback() |
753 if self.repo.config.mode != 'test': |
753 if self.repo.config.mode != 'test': |
754 self.critical('transaction has been rollbacked') |
754 self.critical('transaction has been rolled back') |
755 except Exception as ex: |
755 except Exception as ex: |
756 pass |
756 pass |
757 if ex.__class__.__name__ == 'IntegrityError': |
757 if ex.__class__.__name__ == 'IntegrityError': |
758 # need string comparison because of various backends |
758 # need string comparison because of various backends |
759 for arg in ex.args: |
759 for arg in ex.args: |
760 mo = re.search('unique_cw_[^ ]+_idx', arg) |
760 # postgres, sqlserver |
|
761 mo = re.search("unique_[a-z0-9]{32}", arg) |
761 if mo is not None: |
762 if mo is not None: |
762 index_name = mo.group(0) |
763 raise UniqueTogetherError(session, cstrname=mo.group(0)) |
763 # right-chop '_idx' postfix |
764 # sqlite |
764 # (garanteed to be there, see regexp above) |
|
765 elements = index_name[:-4].split('_cw_')[1:] |
|
766 etype = elements[0] |
|
767 rtypes = elements[1:] |
|
768 raise UniqueTogetherError(etype, rtypes) |
|
769 mo = re.search('columns (.*) are not unique', arg) |
765 mo = re.search('columns (.*) are not unique', arg) |
770 if mo is not None: # sqlite in use |
766 if mo is not None: # sqlite in use |
771 # we left chop the 'cw_' prefix of attribute names |
767 # we left chop the 'cw_' prefix of attribute names |
772 rtypes = [c.strip()[3:] |
768 rtypes = [c.strip()[3:] |
773 for c in mo.group(1).split(',')] |
769 for c in mo.group(1).split(',')] |
774 etype = '???' |
770 raise UniqueTogetherError(session, rtypes=rtypes) |
775 raise UniqueTogetherError(etype, rtypes) |
|
776 raise |
771 raise |
777 return cursor |
772 return cursor |
778 |
773 |
779 def doexecmany(self, session, query, args): |
774 def doexecmany(self, session, query, args): |
780 """Execute a query. |
775 """Execute a query. |
793 self.critical("sql many: %r\n args: %s\ndbms message: %r", |
788 self.critical("sql many: %r\n args: %s\ndbms message: %r", |
794 query, args, ex.args[0]) |
789 query, args, ex.args[0]) |
795 try: |
790 try: |
796 session.cnxset.connection(self.uri).rollback() |
791 session.cnxset.connection(self.uri).rollback() |
797 if self.repo.config.mode != 'test': |
792 if self.repo.config.mode != 'test': |
798 self.critical('transaction has been rollbacked') |
793 self.critical('transaction has been rolled back') |
799 except Exception: |
794 except Exception: |
800 pass |
795 pass |
801 raise |
796 raise |
802 |
797 |
803 # short cut to method requiring advanced db helper usage ################## |
798 # short cut to method requiring advanced db helper usage ################## |
1535 tx_uuid CHAR(32) PRIMARY KEY NOT NULL, |
1530 tx_uuid CHAR(32) PRIMARY KEY NOT NULL, |
1536 tx_user INTEGER NOT NULL, |
1531 tx_user INTEGER NOT NULL, |
1537 tx_time %s NOT NULL |
1532 tx_time %s NOT NULL |
1538 );; |
1533 );; |
1539 CREATE INDEX transactions_tx_user_idx ON transactions(tx_user);; |
1534 CREATE INDEX transactions_tx_user_idx ON transactions(tx_user);; |
|
1535 CREATE INDEX transactions_tx_time_idx ON transactions(tx_time);; |
1540 |
1536 |
1541 CREATE TABLE tx_entity_actions ( |
1537 CREATE TABLE tx_entity_actions ( |
1542 tx_uuid CHAR(32) REFERENCES transactions(tx_uuid) ON DELETE CASCADE, |
1538 tx_uuid CHAR(32) REFERENCES transactions(tx_uuid) ON DELETE CASCADE, |
1543 txa_action CHAR(1) NOT NULL, |
1539 txa_action CHAR(1) NOT NULL, |
1544 txa_public %s NOT NULL, |
1540 txa_public %s NOT NULL, |
1549 );; |
1545 );; |
1550 CREATE INDEX tx_entity_actions_txa_action_idx ON tx_entity_actions(txa_action);; |
1546 CREATE INDEX tx_entity_actions_txa_action_idx ON tx_entity_actions(txa_action);; |
1551 CREATE INDEX tx_entity_actions_txa_public_idx ON tx_entity_actions(txa_public);; |
1547 CREATE INDEX tx_entity_actions_txa_public_idx ON tx_entity_actions(txa_public);; |
1552 CREATE INDEX tx_entity_actions_eid_idx ON tx_entity_actions(eid);; |
1548 CREATE INDEX tx_entity_actions_eid_idx ON tx_entity_actions(eid);; |
1553 CREATE INDEX tx_entity_actions_etype_idx ON tx_entity_actions(etype);; |
1549 CREATE INDEX tx_entity_actions_etype_idx ON tx_entity_actions(etype);; |
|
1550 CREATE INDEX tx_entity_actions_tx_uuid_idx ON tx_entity_actions(tx_uuid);; |
1554 |
1551 |
1555 CREATE TABLE tx_relation_actions ( |
1552 CREATE TABLE tx_relation_actions ( |
1556 tx_uuid CHAR(32) REFERENCES transactions(tx_uuid) ON DELETE CASCADE, |
1553 tx_uuid CHAR(32) REFERENCES transactions(tx_uuid) ON DELETE CASCADE, |
1557 txa_action CHAR(1) NOT NULL, |
1554 txa_action CHAR(1) NOT NULL, |
1558 txa_public %s NOT NULL, |
1555 txa_public %s NOT NULL, |
1563 );; |
1560 );; |
1564 CREATE INDEX tx_relation_actions_txa_action_idx ON tx_relation_actions(txa_action);; |
1561 CREATE INDEX tx_relation_actions_txa_action_idx ON tx_relation_actions(txa_action);; |
1565 CREATE INDEX tx_relation_actions_txa_public_idx ON tx_relation_actions(txa_public);; |
1562 CREATE INDEX tx_relation_actions_txa_public_idx ON tx_relation_actions(txa_public);; |
1566 CREATE INDEX tx_relation_actions_eid_from_idx ON tx_relation_actions(eid_from);; |
1563 CREATE INDEX tx_relation_actions_eid_from_idx ON tx_relation_actions(eid_from);; |
1567 CREATE INDEX tx_relation_actions_eid_to_idx ON tx_relation_actions(eid_to);; |
1564 CREATE INDEX tx_relation_actions_eid_to_idx ON tx_relation_actions(eid_to);; |
|
1565 CREATE INDEX tx_relation_actions_tx_uuid_idx ON tx_relation_actions(tx_uuid);; |
1568 """ % (helper.sql_create_sequence('entities_id_seq').replace(';', ';;'), |
1566 """ % (helper.sql_create_sequence('entities_id_seq').replace(';', ';;'), |
1569 typemap['Datetime'], typemap['Datetime'], typemap['Datetime'], |
1567 typemap['Datetime'], typemap['Datetime'], typemap['Datetime'], |
1570 typemap['Boolean'], typemap['Bytes'], typemap['Boolean']) |
1568 typemap['Boolean'], typemap['Bytes'], typemap['Boolean']) |
1571 if helper.backend_name == 'sqlite': |
1569 if helper.backend_name == 'sqlite': |
1572 # sqlite support the ON DELETE CASCADE syntax but do nothing |
1570 # sqlite support the ON DELETE CASCADE syntax but do nothing |