from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()from sqlalchemy import Column, Integer, String
class Contact(Base):
__tablename__ = "db_contact"
id = Column(Integer, primary_key=True)
last_name = Column(String(20), nullable=False)
first_name = Column(String(20), nullable=False)from sqlalchemy import ForeignKey
class EntityTag(Base):
__tablename__ = "db_entity_tag"
id = Column(Integer, primary_key=True)
entity_id = Column(
Integer,
ForeignKey('db_contact.id', ondelete="CASCADE"),
nullable=False,
)For example Integer(xx) says that Integer cannot have parameters and Tinyint seems not to exist.
I presume that this front-end overhead will pay back when I write more interesting scripts that use data from Civicrm. If this works then I can map the remainder of the (many) tables.
Now, how to create the equivalent SQL query?
s = Session() subquery = ( s.query(Entity_Tag.display_name) .filter( Contribution.receive_date > datetime.date(2005, 7, 1), Contribution.contact_id == Contact.id, Contact.id == Entity_Tag.entity_id, Entity_Tag.tag_id == 6, ) .subquery() ) result = ( s.query( Contact.last_name, Contact.first_name, Address.street_address, Address.city, Address.postalcode, State.name, Country.name.label("country"), ) .filter( Contact.id == Entity_Tag.entity_id, Entity_Tag.tag_id == 6, Contact.id == Address.contact_id, Address.state_province_id == State.id, Address.country_id == Country.id, Entity_Tag.display_name.notin_(subquery), ) .distinct() .all() )SELECT DISTINCT civicrm_contact.last_name AS civicrm_contact_last_name, civicrm_contact.first_name AS civicrm_contact_first_name, civicrm_address.street_address AS civicrm_address_street_address, civicrm_address.city AS civicrm_address_city, civicrm_address.postalcode AS civicrm_address_postalcode, civicrm_state_province.name AS civicrm_state_province_name, civicrm_country.name AS country
FROM civicrm_contact, civicrm_address, civicrm_state_province, civicrm_country, civicrm_entity_tag
WHERE civicrm_contact.id = civicrm_entity_tag.entity_id AND civicrm_entity_tag.tag_id = %(tag_id_1)s AND civicrm_contact.id = civicrm_address.contact_id AND civicrm_address.state_province_id = civicrm_state_province.id AND civicrm_address.country_id = civicrm_country.id AND civicrm_entity_tag.display_name NOT IN (SELECT civicrm_entity_tag.display_name
FROM civicrm_contribution
WHERE civicrm_contribution.receive_date > %(receive_date_1)s AND civicrm_contribution.contact_id = civicrm_contact.id AND civicrm_contact.id = civicrm_entity_tag.entity_id AND civicrm_entity_tag.tag_id = %(tag_id_2)s)TypeError Traceback (most recent call last) <ipython-input-6-97e6a9952682> in <module>() 7 display_name = Column(String(128, u'utf8_unicode_ci')) 8 ----> 9 class CivicrmContribution(Base): 10 __tablename__ = 'civicrm_contribution' 11 <ipython-input-6-97e6a9952682> in CivicrmContribution() 11 12 id = Column(INTEGER, primary_key=True, comment=u'Contribution ID') ---> 13 contact_id = Column(ForeignKey(u'civicrm_contact.id'), ondelete=u'CASCADE', nullable=False, index=True) 14 financial_type_id = Column(ForeignKey(u'civicrm_financial_type.id'), index=True) 15 contribution_page_id = Column(ForeignKey(u'civicrm_contribution_page.id', ondelete=u'SET NULL'), index=True) /Users/ihf/anaconda2/lib/python2.7/site-packages/sqlalchemy/sql/schema.pyc in __init__(self, *args, **kwargs) 1382 self.info = kwargs.pop("info") 1383 -> 1384 self._extra_kwargs(**kwargs) 1385 1386 def _extra_kwargs(self, **kwargs): /Users/ihf/anaconda2/lib/python2.7/site-packages/sqlalchemy/sql/schema.pyc in _extra_kwargs(self, **kwargs) 1385 1386 def _extra_kwargs(self, **kwargs): -> 1387 self._validate_dialect_kwargs(kwargs) 1388 1389 # @property /Users/ihf/anaconda2/lib/python2.7/site-packages/sqlalchemy/sql/base.pyc in _validate_dialect_kwargs(self, kwargs) 287 raise TypeError( 288 "Additional arguments should be " --> 289 "named <dialectname>_<argument>, got '%s'" % k 290 ) 291 dialect_name, arg_name = m.group(1, 2) TypeError: Additional arguments should be named <dialectname>_<argument>, got 'ondelete'
contact_id = Column(ForeignKey(u'civicrm_contact.id'), ondelete=u'CASCADE', nullable=False, index=True)
contact_id = Column(ForeignKey(u'civicrm_contact.id', ondelete=u'CASCADE'), nullable=False, index=True)
NameError Traceback (most recent call last) <ipython-input-11-60d8f90ad86b> in <module> 1 s = Session() 2 subquery = ( ----> 3 s.query(Entity_Tag.display_name) 4 .filter( 5 Contribution.receive_date > datetime.date(2005, 7, 1), NameError: name 'Entity_Tag' is not defined
InternalError: (pymysql.err.InternalError) (1115, "Unknown character set: 'utf8mb4'") (Background on this error at: http://sqlalche.me/e/2j85)
I seem to be regressing.
Weird. When I go back to just running the SQL query, I now get:
InternalError Traceback (most recent call last) ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/engine/base.py in _wrap_pool_connect(self, fn, connection) 2264 try: -> 2265 return fn() 2266 except dialect.dbapi.Error as e: ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/pool/base.py in unique_connection(self) 302 """ --> 303 return _ConnectionFairy._checkout(self) 304 ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/pool/base.py in _checkout(cls, pool, threadconns, fairy) 759 if not fairy: --> 760 fairy = _ConnectionRecord.checkout(pool) 761 ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/pool/base.py in checkout(cls, pool) 491 def checkout(cls, pool): --> 492 rec = pool._do_get() 493 try: ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/pool/impl.py in _do_get(self) 138 with util.safe_reraise(): --> 139 self._dec_overflow() 140 else: ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/util/langhelpers.py in __exit__(self, type_, value, traceback) 67 if not self.warn_only: ---> 68 compat.reraise(exc_type, exc_value, exc_tb) 69 else: ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/util/compat.py in reraise(tp, value, tb, cause) 152 raise value.with_traceback(tb) --> 153 raise value 154 ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/pool/impl.py in _do_get(self) 135 try: --> 136 return self._create_connection() 137 except: ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/pool/base.py in _create_connection(self) 307 --> 308 return _ConnectionRecord(self) 309 ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/pool/base.py in __init__(self, pool, connect) 436 if connect: --> 437 self.__connect(first_connect_check=True) 438 self.finalize_callback = deque() ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/pool/base.py in __connect(self, first_connect_check) 648 pool.dispatch --> 649 ).exec_once(self.connection, self) 650 if pool.dispatch.connect: ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/event/attr.py in exec_once(self, *args, **kw) 286 try: --> 287 self(*args, **kw) 288 finally: ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/event/attr.py in __call__(self, *args, **kw) 296 for fn in self.listeners: --> 297 fn(*args, **kw) 298 ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/engine/strategies.py in on_connect(dbapi_connection, connection_record) 188 return --> 189 do_on_connect(conn) 190 ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/dialects/mysql/mysqldb.py in on_connect(conn) 130 cursor = conn.cursor() --> 131 cursor.execute("SET NAMES %s" % charset_name) 132 cursor.close() ~/anaconda2/lib/python3.6/site-packages/pymysql/cursors.py in execute(self, query, args) 169 --> 170 result = self._query(query) 171 self._executed = query ~/anaconda2/lib/python3.6/site-packages/pymysql/cursors.py in _query(self, q) 327 self._clear_result() --> 328 conn.query(q) 329 self._do_get_result() ~/anaconda2/lib/python3.6/site-packages/pymysql/connections.py in query(self, sql, unbuffered) 516 self._execute_command(COMMAND.COM_QUERY, sql) --> 517 self._affected_rows = self._read_query_result(unbuffered=unbuffered) 518 return self._affected_rows ~/anaconda2/lib/python3.6/site-packages/pymysql/connections.py in _read_query_result(self, unbuffered) 731 result = MySQLResult(self) --> 732 result.read() 733 self._result = result ~/anaconda2/lib/python3.6/site-packages/pymysql/connections.py in read(self) 1074 try: -> 1075 first_packet = self.connection._read_packet() 1076 ~/anaconda2/lib/python3.6/site-packages/pymysql/connections.py in _read_packet(self, packet_type) 683 packet = packet_type(buff, self.encoding) --> 684 packet.check_error() 685 return packet ~/anaconda2/lib/python3.6/site-packages/pymysql/protocol.py in check_error(self) 219 if DEBUG: print("errno =", errno) --> 220 err.raise_mysql_exception(self._data) 221 ~/anaconda2/lib/python3.6/site-packages/pymysql/err.py in raise_mysql_exception(data) 108 errorclass = error_map.get(errno, InternalError) --> 109 raise errorclass(errno, errval) InternalError: (1115, "Unknown character set: 'utf8mb4'") The above exception was the direct cause of the following exception: InternalError Traceback (most recent call last) <ipython-input-7-3ed2575ebc02> in <module> ----> 1 with engine.connect() as con: 2 rs = con.execute('SELECT DISTINCT last_name, first_name,addressee_display, street_address, city, a.name, postal_code, f.name as country FROM civicrm_contact c, civicrm_entity_tag d , civicrm_address e, civicrm_state_province a, civicrm_country f WHERE c.id = d.entity_id and tag_id = 6 and c.id = e.contact_id AND state_province_id = a.id and e.country_id = f.id and display_name not in ( SELECT display_name FROM civicrm_contribution, civicrm_contact c, civicrm_entity_tag d WHERE receive_date > \'2005-07-01\' and contact_id = c.id and c.id = entity_id and tag_id = 6 )') ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/engine/base.py in connect(self, **kwargs) 2194 """ 2195 -> 2196 return self._connection_cls(self, **kwargs) 2197 2198 @util.deprecated( ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/engine/base.py in __init__(self, engine, connection, close_with_result, _branch_from, _execution_options, _dispatch, _has_events) 101 connection 102 if connection is not None --> 103 else engine.raw_connection() 104 ) 105 self.__transaction = None ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/engine/base.py in raw_connection(self, _connection) 2294 """ 2295 return self._wrap_pool_connect( -> 2296 self.pool.unique_connection, _connection 2297 ) 2298 ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/engine/base.py in _wrap_pool_connect(self, fn, connection) 2267 if connection is None: 2268 Connection._handle_dbapi_exception_noconnection( -> 2269 e, dialect, self 2270 ) 2271 else: ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/engine/base.py in _handle_dbapi_exception_noconnection(cls, e, dialect, engine) 1534 util.raise_from_cause(newraise, exc_info) 1535 elif should_wrap: -> 1536 util.raise_from_cause(sqlalchemy_exception, exc_info) 1537 else: 1538 util.reraise(*exc_info) ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/util/compat.py in raise_from_cause(exception, exc_info) 396 exc_type, exc_value, exc_tb = exc_info 397 cause = exc_value if exc_value is not exception else None --> 398 reraise(type(exception), exception, tb=exc_tb, cause=cause) 399 400 ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/util/compat.py in reraise(tp, value, tb, cause) 150 value.__cause__ = cause 151 if value.__traceback__ is not tb: --> 152 raise value.with_traceback(tb) 153 raise value 154 ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/engine/base.py in _wrap_pool_connect(self, fn, connection) 2263 dialect = self.dialect 2264 try: -> 2265 return fn() 2266 except dialect.dbapi.Error as e: 2267 if connection is None: ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/pool/base.py in unique_connection(self) 301 302 """ --> 303 return _ConnectionFairy._checkout(self) 304 305 def _create_connection(self): ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/pool/base.py in _checkout(cls, pool, threadconns, fairy) 758 def _checkout(cls, pool, threadconns=None, fairy=None): 759 if not fairy: --> 760 fairy = _ConnectionRecord.checkout(pool) 761 762 fairy._pool = pool ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/pool/base.py in checkout(cls, pool) 490 @classmethod 491 def checkout(cls, pool): --> 492 rec = pool._do_get() 493 try: 494 dbapi_connection = rec.get_connection() ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/pool/impl.py in _do_get(self) 137 except: 138 with util.safe_reraise(): --> 139 self._dec_overflow() 140 else: 141 return self._do_get() ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/util/langhelpers.py in __exit__(self, type_, value, traceback) 66 self._exc_info = None # remove potential circular references 67 if not self.warn_only: ---> 68 compat.reraise(exc_type, exc_value, exc_tb) 69 else: 70 if not compat.py3k and self._exc_info and self._exc_info[1]: ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/util/compat.py in reraise(tp, value, tb, cause) 151 if value.__traceback__ is not tb: 152 raise value.with_traceback(tb) --> 153 raise value 154 155 def u(s): ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/pool/impl.py in _do_get(self) 134 if self._inc_overflow(): 135 try: --> 136 return self._create_connection() 137 except: 138 with util.safe_reraise(): ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/pool/base.py in _create_connection(self) 306 """Called by subclasses to create a new ConnectionRecord.""" 307 --> 308 return _ConnectionRecord(self) 309 310 def _invalidate(self, connection, exception=None, _checkin=True): ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/pool/base.py in __init__(self, pool, connect) 435 self.__pool = pool 436 if connect: --> 437 self.__connect(first_connect_check=True) 438 self.finalize_callback = deque() 439 ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/pool/base.py in __connect(self, first_connect_check) 647 pool.dispatch.first_connect.for_modify( 648 pool.dispatch --> 649 ).exec_once(self.connection, self) 650 if pool.dispatch.connect: 651 pool.dispatch.connect(self.connection, self) ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/event/attr.py in exec_once(self, *args, **kw) 285 if not self._exec_once: 286 try: --> 287 self(*args, **kw) 288 finally: 289 self._exec_once = True ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/event/attr.py in __call__(self, *args, **kw) 295 fn(*args, **kw) 296 for fn in self.listeners: --> 297 fn(*args, **kw) 298 299 def __len__(self): ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/engine/strategies.py in on_connect(dbapi_connection, connection_record) 187 if conn is None: 188 return --> 189 do_on_connect(conn) 190 191 event.listen(pool, "first_connect", on_connect) ~/anaconda2/lib/python3.6/site-packages/sqlalchemy/dialects/mysql/mysqldb.py in on_connect(conn) 129 if charset_name is not None: 130 cursor = conn.cursor() --> 131 cursor.execute("SET NAMES %s" % charset_name) 132 cursor.close() 133 ~/anaconda2/lib/python3.6/site-packages/pymysql/cursors.py in execute(self, query, args) 168 query = self.mogrify(query, args) 169 --> 170 result = self._query(query) 171 self._executed = query 172 return result ~/anaconda2/lib/python3.6/site-packages/pymysql/cursors.py in _query(self, q) 326 self._last_executed = q 327 self._clear_result() --> 328 conn.query(q) 329 self._do_get_result() 330 return self.rowcount ~/anaconda2/lib/python3.6/site-packages/pymysql/connections.py in query(self, sql, unbuffered) 515 sql = sql.encode(self.encoding, 'surrogateescape') 516 self._execute_command(COMMAND.COM_QUERY, sql) --> 517 self._affected_rows = self._read_query_result(unbuffered=unbuffered) 518 return self._affected_rows 519 ~/anaconda2/lib/python3.6/site-packages/pymysql/connections.py in _read_query_result(self, unbuffered) 730 else: 731 result = MySQLResult(self) --> 732 result.read() 733 self._result = result 734 if result.server_status is not None: ~/anaconda2/lib/python3.6/site-packages/pymysql/connections.py in read(self) 1073 def read(self): 1074 try: -> 1075 first_packet = self.connection._read_packet() 1076 1077 if first_packet.is_ok_packet(): ~/anaconda2/lib/python3.6/site-packages/pymysql/connections.py in _read_packet(self, packet_type) 682 683 packet = packet_type(buff, self.encoding) --> 684 packet.check_error() 685 return packet 686 ~/anaconda2/lib/python3.6/site-packages/pymysql/protocol.py in check_error(self) 218 errno = self.read_uint16() 219 if DEBUG: print("errno =", errno) --> 220 err.raise_mysql_exception(self._data) 221 222 def dump(self): ~/anaconda2/lib/python3.6/site-packages/pymysql/err.py in raise_mysql_exception(data) 107 errval = data[3:].decode('utf-8', 'replace') 108 errorclass = error_map.get(errno, InternalError) --> 109 raise errorclass(errno, errval)
InternalError: (pymysql.err.InternalError) (1115, "Unknown character set: 'utf8mb4'") (Background on this error at: http://sqlalche.me/e/2j85)
InternalError: (pymysql.err.InternalError) (1115, "Unknown character set: 'utf8mb4'")
Since this worked before, all I can think is that I somehow updated or changed pymysql and the result is this error.
--
SQLAlchemy -
The Python SQL Toolkit and Object Relational Mapper
http://www.sqlalchemy.org/
To post example code, please provide an MCVE: Minimal, Complete, and Verifiable Example. See http://stackoverflow.com/help/mcve for a full description.
---
You received this message because you are subscribed to a topic in the Google Groups "sqlalchemy" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/sqlalchemy/xtp9Lz4VdBI/unsubscribe.
To unsubscribe from this group and all its topics, send an email to sqlalchemy+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/sqlalchemy/df9aa766-90d3-440b-8b48-18bfc47f568f%40googlegroups.com.
To unsubscribe from this group and all its topics, send an email to sqlalchemy+unsubscribe@googlegroups.com.
To unsubscribe from this group and all its topics, send an email to sqlal...@googlegroups.com.