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] 삭제
몇 마디 만하겠습니다