바인딩 된 매개 변수가있는 쿼리에 대한 Sqlite 결과 없음, 하드 코딩 된 값이있는 동일한 쿼리와 함께 작동

지미 섬 슈가 르

Sqlite 3에서 이상한 문제에 직면하고 WHERE있습니다. 조건 자에 바인딩 된 매개 변수를 사용하는 비교적 간단한 쿼리가 있습니다. 바인딩 된 매개 변수를 사용하여 쿼리를 실행하면 0 개의 결과가 표시되지만 하드 코딩 된 값으로 정확히 동일한 쿼리를 실행하면 예상 결과 수 (> 0)를 얻습니다.

sqlite3_expanded_sql()결과 SQL 문자열 을 호출 하고 검사하여 예상대로 쿼리가 준비되었는지 다시 확인했습니다 .

바인딩 된 매개 변수가있는 내 쿼리 :

SELECT
    b.name,
    Y(Transform(b.geom, 4326)) "y",
    X(Transform(b.geom, 4326)) "x"
FROM buildings b
WHERE Within(b.geom, Transform(PolygonFromText(?, 4326), 27700)) > 0

바운드 매개 변수에 제공하는 값 :

let rectWkt = """
POLYGON((
    -0.1381030196154711 51.51132617405723,
    -0.12929698038450965 51.51132617405723,
    -0.12929698038450965 51.50863378616471,
    -0.1381030196154711 51.50863378616471,
    -0.1381030196154711 51.51132617405723
))
"""

그리고 값이 하드 코딩 된 쿼리는 다음과 같이 작동합니다.

SELECT
    b.name,
    Y(Transform(b.geom, 4326)) "y",
    X(Transform(b.geom, 4326)) "x"
FROM buildings b
WHERE Within(b.geom, Transform(PolygonFromText('POLYGON((
    -0.1381030196154711 51.51132617405723,
    -0.12929698038450965 51.51132617405723,
    -0.12929698038450965 51.50863378616471,
    -0.1381030196154711 51.50863378616471,
    -0.1381030196154711 51.51132617405723
))', 4326), 27700)) > 0

마지막으로, sqlite3_expanded_sql()위에서 설명한 값을 바인딩 한 후 호출하는 의 출력은 다음 과 같습니다.

SELECT
    b.name,
    Y(Transform(b.geom, 4326)) "y",
    X(Transform(b.geom, 4326)) "x"
FROM buildings b
WHERE Within(b.geom, Transform(PolygonFromText('POLYGON((
    -0.1381030196154711 51.51132617405723,
    -0.12929698038450965 51.51132617405723,
    -0.12929698038450965 51.50863378616471,
    -0.1381030196154711 51.50863378616471,
    -0.1381030196154711 51.51132617405723
))', 4326), 27700)) > 0

내가 뭔가를 놓치고 있지 않는 한, 이것들은 동일한 문장이지만 실행하면 완전히 다른 결과를 얻습니다.

Swift 바인딩을 사용하여 sqlite c API를 사용하여 쿼리를 실행하고 있으며 Spatialite 확장을로드했습니다 (기하학적 기능 용).

sqlite3_bind_text()내 가치에 대한 호출이인지 확인합니다 SQLITE_OK. 결과 행을 반복하려고 할 때 오류가 없습니다. 단순히 SQLITE_DONE첫 번째 결과 를 얻습니다 . 결과 세트가 비어 있습니다.

지미 섬 슈가 르

나는 그것을 해결할 수 있었다. 나는 SQLITE_TRANSIENT마지막 인자로 sqlite3_bind_text. 쿼리를 실행하는 호출이 다른 범위에 있었고 그 당시에는 문자열 값이 범위에 없었기 때문이라고 생각합니다. SQLITE_TRANSIENT다섯 번째 인수로 전달하면 Sqlite가 값의 자체 복사본을 만들도록 지시합니다.

특히 Swift에서는 let SQLITE_TRANSIENT = unsafeBitCast(-1, to: sqlite3_destructor_type.self)Sqlite 헤더 파일에 매크로 로 정의되어 있기 때문에 수동으로 정의해야 합니다 ( https://www.sqlite.org/c3ref/c_static.html 참조 ).

이전에 바인딩하라는 내 전화는 다음과 같습니다.

guard
    sqlite3_bind_text(stmnt, 1, rectangleWKT, -1, nil) == SQLITE_OK
else {
    throw DatabaseError.Bind(message: errorMessage)
}

그러나 다음과 비슷해야합니다.

let SQLITE_TRANSIENT = unsafeBitCast(-1, to: sqlite3_destructor_type.self)
guard
    sqlite3_bind_text(stmnt, 1, rectangleWKT, -1, SQLITE_TRANSIENT) == SQLITE_OK
else {
    throw DatabaseError.Bind(message: errorMessage)
}

그런 다음 준비된 명령문을 다른 함수에 전달하여 결과를 실행하고 가져올 수 있습니다.

return loadBuildings(forStatement: stmnt)

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

Related 관련 기사

뜨겁다태그

보관