Custom SQLite functions in Xamarin.iOS

前端 未结 1 1166
失恋的感觉
失恋的感觉 2021-01-16 04:19

I am working on custom function of Sqlite on Xamarin.iOS. I got answer from here : Show markers on map within a given radius (Xamarin.Android) but I am running into issue of

相关标签:
1条回答
  • 2021-01-16 04:44

    I use the popular sqlite-net (by Frank A. Krueger) and it in turn uses SQLitePCLRaw.bundle_green and SQLitePCL.raw (both by Eric Sink).

    Thus, you can use SQLitePCLRaw.ugly-based API to easily setup and access SQLite UDFs.

    A Xamarin.iOS-based SQLite User Defined Function (UDF):

    delegate void SQLiteCallback(sqlite3_context ctx, object user_data, sqlite3_value[] args);
    [MonoPInvokeCallback(typeof(SQLiteCallback))]
    static void UDFDistanceFunction(sqlite3_context ctx, object user_data, sqlite3_value[] args)
    {
        double radius = 6367;
        var lat1 = raw.sqlite3_value_double(args[0]);
        var lng1 = raw.sqlite3_value_double(args[1]);
        var lat2 = raw.sqlite3_value_double(args[2]);
        var lng2 = raw.sqlite3_value_double(args[3]);
        var result = radius * 2 * Math.Asin(Math.Min(1, Math.Sqrt((Math.Pow(Math.Sin((lat2 * (Math.PI / 180) - lat1 * (Math.PI / 180)) / 2.0), 2.0) + Math.Cos(lat1 * (Math.PI / 180)) * Math.Cos(lat2 * (Math.PI / 180)) * Math.Pow(Math.Sin((lng2 * (Math.PI / 180) - lng1 * (Math.PI / 180)) / 2.0), 2.0)))));
        raw.sqlite3_result_double(ctx, result);
    }
    

    Usage:

    Using sqlite-net-pcl to setup tables, load/update data, .....

    SQLitePCL.raw.SetProvider(new SQLitePCL.SQLite3Provider_sqlite3());
    var dbName = Path.Combine(Path.GetTempPath(), "StackOverflow.db");
    var db = new SQLiteConnection(dbName, SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create, true);
    db.CreateTable<BarLocations>();
    db.Insert(new BarLocations()
    {
        name = "FOOBAR", lat = 47.60357, lng = -122.3295
    });
    

    Using SQLitePCLRaw.ugly to create and query w/ a SQLite UDF

    SQLitePCL.raw.SetProvider(new SQLitePCL.SQLite3Provider_sqlite3());
    var dbName = Path.Combine(Path.GetTempPath(), "StackOverflow.db");
    using (sqlite3 dbRaw = ugly.open(dbName))
    {
        dbRaw.create_function("distance", 4, null, UDFDistanceFunction);
        double currentLatitude = 47.0;
        double currentLongitude = -122.0;
        var sql = $"SELECT * FROM barlocations WHERE distance('{currentLatitude.ToString()}', '{currentLongitude.ToString()}', barlocations.lat, barlocations.lng) <= 100 ;";
        var locs = dbRaw.query<BarLocations>(sql);
        foreach (var loc in locs)
        {
            Console.WriteLine(loc.name);
        }
    }
    
    0 讨论(0)
提交回复
热议问题