передача tuple для выполнения () для в sql-сервере предложения с SQLAlchemy [duplicate]

Для целей этого примера предположим, что следующий класс является объектом, подлежащим тестированию

public class Foo {
    private IMapper mapper;
    public Foo(IMapper mapper) {
        this.mapper = mapper;
    }

    public BaseDAO Bar(object obj) {
        var dao = mapper.Map(obj);
        return dao;
    }
}

, где зависимость IMapper имеет следующий контракт

public interface IMapper {
    /// 
    /// Execute a mapping from the source object to a new destination object.
    /// The source type is inferred from the source object.
    /// 
    /// Destination type to create
    /// Source object to map from
    /// Mapped destination object
    TDestination Map(object source);

    //...
}

Следующий тест демонстрирует, используя moq,

Mock IMapper Возвращаемые производные классы, где Base Expected

blockquote>
[TestClass]
public class TestClass {
    [TestMethod]
    public void _TestMethod() {
        //Arrange
        var mock = new Mock();
        var foo = new Foo(mock.Object);

        mock
            //setup the mocked function
            .Setup(_ => _.Map(It.IsAny()))
            //fake/stub what mocked function should return given provided arg
            .Returns((object arg) => {
                if (arg != null && arg is Child1)
                    return new Child1DAO();
                if (arg != null && arg is Child2)
                    return new Child2DAO();
                if (arg != null && arg is Child3)
                    return new Child3DAO();

                return null;
            });

        var child1 = new Child1();

        //Act
        var actual = foo.Bar(child1);

        //Assert
        Assert.IsNotNull(actual);
        Assert.IsInstanceOfType(actual, typeof(BaseDAO));
        Assert.IsInstanceOfType(actual, typeof(Child1DAO));
    }
}

14
задан skyler 25 January 2013 в 00:51
поделиться

2 ответа

Это необычный формат, поддерживаемый только некоторыми DBAPI, поскольку он отображает кортеж элементов как отдельных выражений SQL, включая то, что он отображает запятую и таковые между параметрами, поэтому выражение, подобное execute("select * from table where value in %s", (somelist, )), расширяется на уровень базы данных в select * from table where value in (1, 2, 3).

SQLAlchemy не ожидает этого формата - он уже выполняет некоторую проверку входящих параметров, поскольку он связан с маршрутизацией параметров в методы DBAPI execute() или executemany() , а также принимает несколько разных стилей, и результатом этого преобразования является то, что кортеж здесь сглаживается. Вы можете прокрасть свой кортеж мимо этого разбора, добавив еще один кортеж:

from sqlalchemy import create_engine

engine = create_engine("postgresql://scott:tiger@localhost/test", echo=True)

with engine.connect() as conn:
    trans = conn.begin()


    conn.execute("create table test (data integer)")
    conn.execute(
            "insert into test (data) values (%s)",
            [(1, ), (2, ), (3, ), (4, ), (5, )]
        )

    result = conn.execute(
                "select * from test where data in %s",
                (
                    ((1, 2, 3),),
                )
            )

    print result.fetchall()

Этот стиль работает только для некоторых файлов DBAPI. Быстрый тест подтверждает, что он работает для psycopg2 и MySQLdb, но не для sqlite3. Это больше связано с базовой системой, которую DBAPI использует для отправки связанных параметров в базу данных; psycopg2 и MySQLdb выполняют как интерполяцию строк Python, так и их собственное экранирование, но такие системы, как cx_oracle, будут передавать параметры по отдельности в OCI, поэтому в этом случае это не будет работать.

SQLAlchemy, конечно, предлагает в _ () при использовании конструкций выражений SQL, но это не относится к прямым строкам.

12
ответ дан zzzeek 26 August 2018 в 23:57
поделиться

Я использую SQLAlchemy 0.9.8, python 2.7, MySQL 5.X и MySQL-Python в качестве соединителя, в этом случае необходим кортеж. Мой код, указанный ниже:

id_list = [1, 2, 3, 4, 5] # in most case we have an integer list or set
s = text('SELECT id, content FROM myTable WHERE id IN :id_list')
conn = engine.connect() # get a mysql connection
rs = conn.execute(s, id_list=tuple(id_list)).fetchall()

Надеюсь, что все работает для вас.

7
ответ дан Jet Yang 26 August 2018 в 23:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: