Написание пользовательских функций SQL для SQLite с использованием Java или Groovy? - PullRequest
4 голосов
/ 07 июля 2010

С помощью SQLite пользовательские функции SQL можно легко добавлять с помощью C api или PHP .Но возможно ли использовать Java или Groovy?

Ответы [ 3 ]

10 голосов
/ 23 апреля 2015

Поскольку вопрос касается решения в Java или Groovy, кто-то может найти здесь решение для Java (точно так же, как я)

Ниже вы можете увидеть простую функцию, которая проверяет, если указанные даты находятся в тот же день:

public class IsSameDay extends Function {

    @Override
    protected void xFunc() throws SQLException {
        if (args() != 2) {
            throw new SQLException("IsSameDay(date1,date2): Invalid argument count. Requires 2, but found " + args());
        }
        try {
            DateTime t1 = DateTime.parse(value_text(0).replace(" ", "T"));
            DateTime t2 = DateTime.parse(value_text(1).replace(" ", "T"));
            if (t1.getYear() == t2.getYear() && t1.getDayOfYear() == t2.getDayOfYear()) {
                result(1);
            } else {
                result(0);
            }
        } catch (Exception exception) {
            throw new SQLDataException("IsSameDay(date1,date2): One of Arguments is invalid: " + exception.getLocalizedMessage());
        }
    }
}

и если кому-то нужно выполнить функцию агрегирования, этот пример может оказаться полезным:

public class MyMax extends Function.Aggregate {

    private long buff = 0;

    public MyMax() {
    }

    @Override
    protected void xStep() throws SQLException {
        long current = value_long(0);
        if (current > buff) {
            buff = current;
        }

    }

    @Override
    protected void xFinal() throws SQLException {
        result(buff);
    }
}

аккумулятор работает, потому что в каждом запросе экземпляр MyMax клонируется, поэтому начальное значение можетбыть предоставлено при создании экземпляра объекта.

в конце примера, показывающего, как прикреплять функции:

Function.create(c, IsSameDay.class.getSimpleName(), new IsSameDay());
Function.create(c, MyMax.class.getSimpleName(), new MyMax());

Надеюсь, что кто-то найдет его полезным.

8 голосов
/ 08 июля 2010

Оказывается, что написать пользовательскую функцию на самом деле довольно просто, используя SQLiteJDBC . Вот пример Groovy:

@GrabConfig(systemClassLoader=true)
@Grab('org.xerial:sqlite-jdbc:3.6.16')
import org.sqlite.*
import java.sql.*

db = groovy.sql.Sql.newInstance("jdbc:sqlite::memory:","org.sqlite.JDBC")

// a distance function using the spherical law of cosines
Function.create(db.getConnection(), "distance", new Function() {
    protected void xFunc() throws SQLException {
        def lat1 = value_double(0)
        def lon1 = value_double(1)
        def lat2 = value_double(2)
        def lon2 = value_double(3)

        double theta = lon1 - lon2;
        double dist = (Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2))) + 
            (Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.cos(deg2rad(theta)))
        dist = Math.acos(dist)
        dist = rad2deg(dist)
        dist = dist * 60 * 1.1515
        dist = dist * 1.609344
        result(dist);
    }

    def deg2rad(deg) {
      deg * Math.PI / 180.0
    }

    def rad2deg(rad) {
      rad * 180.0 / Math.PI
    }
})

db.execute("CREATE TABLE city(name, lat, lon)")
db.execute("INSERT INTO city(name, lat, lon) VALUES('New York City', 40.7143, -74.0060)")
db.execute("INSERT INTO city(name, lat, lon) VALUES('San Francisco', 37.7749, -122.4194)")
db.execute("INSERT INTO city(name, lat, lon) VALUES('Paris', 48.8567, 2.3510)")
db.execute("INSERT INTO city(name, lat, lon) VALUES('Cologne', 50.9407, 6.9599)")

db.eachRow("SELECT a.name as a, b.name as b, distance(a.lat, a.lon, b.lat, b.lon) as d FROM city a, city b WHERE a.name != b.name ORDER BY d;") {
    println "Distance from ${it.a} to ${it.b}: ${it.d}km"
}
0 голосов
/ 09 февраля 2019

Я думаю, это простой способ создать пользовательскую функцию,

Class.forName("org.sqlite.JDBC");
Connection conn = DriverManager.getConnection("jdbc:sqlite:");
Function.create(conn, "myFunc", new Function() {
           protected void xFunc() {
               System.out.println("myFunc called!");
           }
       });        
conn.createStatement().execute("select myFunc();");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...