Podchodzę do dziwnego problemu z SQLite 3. Mam stosunkowo proste zapytanie, które wymaga związanego parametru w predykatu {x0}}. Podczas wykonywania zapytania z parametrem związanym otrzymuję 0 wyników, ale uruchamiam dokładnie to samo zapytanie z wartością hardcoded, otrzymuję oczekiwaną liczbę wyników (& GT; 0).

Mam dwukrotnie sprawdzony moje zapytanie zostało przygotowane, jak oczekuję, dzwoniąc sqlite3_expanded_sql() i sprawdzając wynikowy ciąg SQL.

Moje zapytanie z parametrem związanym:

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

Wartość, którą zapewniam parametr związany:

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

I zapytanie o wartości hardcoded, które działa:

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

I wreszcie, oto wyjście z sqlite3_expanded_sql(), które dzwonię po wiązaniu mojej wartości opisanej powyżej:

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

Chyba że coś brakuje, są to identyczne stwierdzenia, ale otrzymuję zupełnie inny wynik podczas ich wykonania.

Wykonuję zapytanie za pomocą interfejsu API Sqlite C przy użyciu powiązań SWIFT i mam załadowany rozszerzenie przestrzenne (dla funkcji geometrycznych).

Sprawdzam, czy połączenie sqlite3_bind_text() z moją wartością jest SQLITE_OK. Nie ma błędu, gdy próbuję iterować nad wynikami otrzymanych wierszy, po prostu dostaję SQLITE_DONE jako pierwszy wynik, tj. Zestaw wyników jest pusty.

1
jimmy sumshugar 18 październik 2020, 19:16

1 odpowiedź

Najlepsza odpowiedź

Udało mi się to rozwiązać: musiałem przejść SQLITE_TRANSIENT jako ostatni arg Zadzwoń do sqlite3_bind_text. Wierzę, że to dlatego, że mój telefon wykonuje zapytanie było w innym zakresie, a do tego czasu wartość ciągu nie była w zakres. Mijając SQLITE_TRANSIENT, ponieważ piąty argowi instruuje sqlite, aby to zrobić własna kopia wartości.

W SWIFT W szczególności musi być ręcznie zdefiniowany jako let SQLITE_TRANSIENT = unsafeBitCast(-1, to: sqlite3_destructor_type.self) Ponieważ jest zdefiniowany z makro w plikach nagłówka SQLite (patrz: HTTPS: //www.sqlite. org / c3ref / c_static.html).

Moje połączenie, aby wiązało się wcześniej, było coś w rodzaju:

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

Ale powinno być bardziej:

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)
}

Następnie mogę przekazać moje przygotowane oświadczenie do innej funkcji do wykonania i pobierania wyników:

return loadBuildings(forStatement: stmnt)
0
old greg 18 październik 2020, 17:25