On Mon, Nov 27, 2017 at 4:02 PM,  <jens.troe...@gmail.com> wrote:
>
>
> No problem, here it is. To work with your initial code example...
>
>>>> e =
>>>> create_engine("mysql+pymysql://jens@localhost/test?charset=utf8&unix_socket=/opt/local/var/run/mysql56/mysqld.sock",
>>>> echo=True)
>>>> Base.metadata.drop_all(e)
> 2017-11-28 06:47:21,171 INFO sqlalchemy.engine.base.Engine SHOW VARIABLES
> LIKE 'sql_mode'
> 2017-11-28 06:47:21,171 INFO sqlalchemy.engine.base.Engine {}
> 2017-11-28 06:47:21,173 INFO sqlalchemy.engine.base.Engine SELECT DATABASE()
> 2017-11-28 06:47:21,173 INFO sqlalchemy.engine.base.Engine {}
> 2017-11-28 06:47:21,174 INFO sqlalchemy.engine.base.Engine show collation
> where `Charset` = 'utf8' and `Collation` = 'utf8_bin'
> 2017-11-28 06:47:21,174 INFO sqlalchemy.engine.base.Engine {}
> 2017-11-28 06:47:21,175 INFO sqlalchemy.engine.base.Engine SELECT CAST('test
> plain returns' AS CHAR(60)) AS anon_1
> 2017-11-28 06:47:21,175 INFO sqlalchemy.engine.base.Engine {}
> 2017-11-28 06:47:21,176 INFO sqlalchemy.engine.base.Engine SELECT CAST('test
> unicode returns' AS CHAR(60)) AS anon_1
> 2017-11-28 06:47:21,176 INFO sqlalchemy.engine.base.Engine {}
> 2017-11-28 06:47:21,176 INFO sqlalchemy.engine.base.Engine SELECT CAST('test
> collated returns' AS CHAR CHARACTER SET utf8) COLLATE utf8_bin AS anon_1
> 2017-11-28 06:47:21,176 INFO sqlalchemy.engine.base.Engine {}
> 2017-11-28 06:47:21,177 INFO sqlalchemy.engine.base.Engine DESCRIBE `tokens`
> 2017-11-28 06:47:21,177 INFO sqlalchemy.engine.base.Engine {}
> 2017-11-28 06:47:21,179 INFO sqlalchemy.engine.base.Engine ROLLBACK
>>>> Base.metadata.create_all(e)
> 2017-11-28 06:47:23,490 INFO sqlalchemy.engine.base.Engine DESCRIBE `tokens`
> 2017-11-28 06:47:23,490 INFO sqlalchemy.engine.base.Engine {}
> 2017-11-28 06:47:23,495 INFO sqlalchemy.engine.base.Engine ROLLBACK
> 2017-11-28 06:47:23,496 INFO sqlalchemy.engine.base.Engine
> CREATE TABLE tokens (
> id VARCHAR(50) NOT NULL,
> user_id VARCHAR(50),
> client_sig VARCHAR(50),
> PRIMARY KEY (id)
> )
> 2017-11-28 06:47:23,496 INFO sqlalchemy.engine.base.Engine {}
> 2017-11-28 06:47:23,507 INFO sqlalchemy.engine.base.Engine COMMIT
>>>> stmt = select([
> ...     literal_column("'abc'"),
> ...     literal_column("'def'"),
> ...     literal_column("'ghi'"),
> ... ]).where(
> ...     ~exists().where(and_(Token.user_id == 'def', Token.client_sig ==
> 'ghi'))
> ... )
>>>>
>>>> print(stmt)
> SELECT 'abc', 'def', 'ghi'
> WHERE NOT (EXISTS (SELECT *
> FROM tokens
> WHERE tokens.user_id = :user_id_1 AND tokens.client_sig = :client_sig_1))
>
>
>> OK I don't recall what conditions MySQL needs "FROM dual" can you share
>> with me:
>>
>> 1. the full version of MySQL

Well in standard MySQL / MariaDB fashion, they have made this as fun
as possible (well, more fun would be one database *rejects* FROM DUAL,
at least it isn't that bad):

1. MySQL 5.6 requires "FROM DUAL"

2. MySQL 5.7 does not require FROM DUAL but accepts it.

3. MariaDB 10.1 does not require FROM DUAL but accepts it.

4. MariaDB 10.2 *does* require FROM DUAL.     The two vendors have
**flip-flopped** on their preference of this issue.

Anyway, here's your dual, as is typical, to make it work completely we
need an esoteric trick to avoid quoting the "dual" word:

from sqlalchemy.sql import quoted_name
dual = table(quoted_name("dual", quote=False))

then your statement:

    stmt = select([
        literal_column("'abc'"),
        literal_column("'def'"),
        literal_column("'ghi'"),
    ]).select_from(dual).where(
        ~exists().where(and_(Token.user_id == 'def', Token.client_sig == 'ghi'))
    )





>
>
>>>> e.dialect.name, e.dialect.driver, e.dialect.server_version_info
> ('mysql', 'pymysql', (5, 6, 34))
>
>> 2. the output of "SHOW VARIABLES LIKE '%SQL_MODE%'
>>
>
> mysql> show variables like '%sql_mode%';
> +---------------+------------------------+
> | Variable_name | Value                  |
> +---------------+------------------------+
> | sql_mode      | NO_ENGINE_SUBSTITUTION |
> +---------------+------------------------+
> 1 row in set (0.00 sec)
>
>
>> 3. stack trace + error message
>
>
>>>> e.execute(
> ...     insert(Token).from_select(['id', 'user_id', 'client_sig'], stmt)
> ... )
> 2017-11-28 06:47:49,489 INFO sqlalchemy.engine.base.Engine INSERT INTO
> tokens (id, user_id, client_sig) SELECT 'abc', 'def', 'ghi'
> WHERE NOT (EXISTS (SELECT *
> FROM tokens
> WHERE tokens.user_id = %(user_id_1)s AND tokens.client_sig =
> %(client_sig_1)s))
> 2017-11-28 06:47:49,489 INFO sqlalchemy.engine.base.Engine {'client_sig_1':
> 'ghi', 'user_id_1': 'def'}
> 2017-11-28 06:47:49,491 INFO sqlalchemy.engine.base.Engine ROLLBACK
> Traceback (most recent call last):
>   File "/…/lib/python3.5/site-packages/sqlalchemy/engine/base.py", line
> 1182, in _execute_context
>     context)
>   File "/…/lib/python3.5/site-packages/sqlalchemy/engine/default.py", line
> 470, in do_execute
>     cursor.execute(statement, parameters)
>   File "/…/lib/python3.5/site-packages/pymysql/cursors.py", line 166, in
> execute
>     result = self._query(query)
>   File "/…/lib/python3.5/site-packages/pymysql/cursors.py", line 322, in
> _query
>     conn.query(q)
>   File "/…/lib/python3.5/site-packages/pymysql/connections.py", line 856, in
> query
>     self._affected_rows = self._read_query_result(unbuffered=unbuffered)
>   File "/…/lib/python3.5/site-packages/pymysql/connections.py", line 1057,
> in _read_query_result
>     result.read()
>   File "/…/lib/python3.5/site-packages/pymysql/connections.py", line 1340,
> in read
>     first_packet = self.connection._read_packet()
>   File "/…/lib/python3.5/site-packages/pymysql/connections.py", line 1014,
> in _read_packet
>     packet.check_error()
>   File "/…/lib/python3.5/site-packages/pymysql/connections.py", line 393, in
> check_error
>     err.raise_mysql_exception(self._data)
>   File "/…/lib/python3.5/site-packages/pymysql/err.py", line 107, in
> raise_mysql_exception
>     raise errorclass(errno, errval)
> pymysql.err.ProgrammingError: (1064, "You have an error in your SQL syntax;
> check the manual that corresponds to your MySQL server version for the right
> syntax to use near 'WHERE NOT (EXISTS (SELECT * \nFROM tokens \nWHERE
> tokens.user_id = 'def' AND token' at line 2")
>
> The above exception was the direct cause of the following exception:
>
> Traceback (most recent call last):
>   File "<stdin>", line 2, in <module>
>   File "/…/lib/python3.5/site-packages/sqlalchemy/engine/base.py", line
> 2064, in execute
>     return connection.execute(statement, *multiparams, **params)
>   File "/…/lib/python3.5/site-packages/sqlalchemy/engine/base.py", line 945,
> in execute
>     return meth(self, multiparams, params)
>   File "/…/lib/python3.5/site-packages/sqlalchemy/sql/elements.py", line
> 263, in _execute_on_connection
>     return connection._execute_clauseelement(self, multiparams, params)
>   File "/…/lib/python3.5/site-packages/sqlalchemy/engine/base.py", line
> 1053, in _execute_clauseelement
>     compiled_sql, distilled_params
>   File "/…/lib/python3.5/site-packages/sqlalchemy/engine/base.py", line
> 1189, in _execute_context
>     context)
>   File "/…/lib/python3.5/site-packages/sqlalchemy/engine/base.py", line
> 1402, in _handle_dbapi_exception
>     exc_info
>   File "/…/lib/python3.5/site-packages/sqlalchemy/util/compat.py", line 203,
> in raise_from_cause
>     reraise(type(exception), exception, tb=exc_tb, cause=cause)
>   File "/…/lib/python3.5/site-packages/sqlalchemy/util/compat.py", line 186,
> in reraise
>     raise value.with_traceback(tb)
>   File "/…/lib/python3.5/site-packages/sqlalchemy/engine/base.py", line
> 1182, in _execute_context
>     context)
>   File "/…/lib/python3.5/site-packages/sqlalchemy/engine/default.py", line
> 470, in do_execute
>     cursor.execute(statement, parameters)
>   File "/…/lib/python3.5/site-packages/pymysql/cursors.py", line 166, in
> execute
>     result = self._query(query)
>   File "/…/lib/python3.5/site-packages/pymysql/cursors.py", line 322, in
> _query
>     conn.query(q)
>   File "/…/lib/python3.5/site-packages/pymysql/connections.py", line 856, in
> query
>     self._affected_rows = self._read_query_result(unbuffered=unbuffered)
>   File "/…/lib/python3.5/site-packages/pymysql/connections.py", line 1057,
> in _read_query_result
>     result.read()
>   File "/…/lib/python3.5/site-packages/pymysql/connections.py", line 1340,
> in read
>     first_packet = self.connection._read_packet()
>   File "/…/lib/python3.5/site-packages/pymysql/connections.py", line 1014,
> in _read_packet
>     packet.check_error()
>   File "/…/lib/python3.5/site-packages/pymysql/connections.py", line 393, in
> check_error
>     err.raise_mysql_exception(self._data)
>   File "/…/lib/python3.5/site-packages/pymysql/err.py", line 107, in
> raise_mysql_exception
>     raise errorclass(errno, errval)
> sqlalchemy.exc.ProgrammingError: (pymysql.err.ProgrammingError) (1064, "You
> have an error in your SQL syntax; check the manual that corresponds to your
> MySQL server version for the right syntax to use near 'WHERE NOT (EXISTS
> (SELECT * \nFROM tokens \nWHERE tokens.user_id = 'def' AND token' at line
> 2") [SQL: "INSERT INTO tokens (id, user_id, client_sig) SELECT 'abc', 'def',
> 'ghi' \nWHERE NOT (EXISTS (SELECT * \nFROM tokens \nWHERE tokens.user_id =
> %(user_id_1)s AND tokens.client_sig = %(client_sig_1)s))"] [parameters:
> {'client_sig_1': 'ghi', 'user_id_1': 'def'}]
>
>  Please let me know of anything else you need from me!
> Jens
>
> --
> 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 the Google Groups
> "sqlalchemy" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to sqlalchemy+unsubscr...@googlegroups.com.
> To post to this group, send email to sqlalchemy@googlegroups.com.
> Visit this group at https://groups.google.com/group/sqlalchemy.
> For more options, visit https://groups.google.com/d/optout.

-- 
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 the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to