Code Monkey home page Code Monkey logo

postgrest-kt's Introduction

Kotlin Client for PostgREST

Warning This repository is archived. Use supabase-kt instead to use Supabase in your Kotlin projects.

Kotlin JVM client for PostgREST

Java CI with Gradle Gradle Package Bintray

Installation

Maven

<dependency>
    <groupId>io.supabase</groupId>
    <artifactId>postgrest-kt</artifactId>
    <version>{version}</version>
    <type>pom</type>
</dependency>

Gradle

implementation 'io.supabase:postgrest-kt:{version}'

Usage

Initializing the client

val postgrestClient =  PostgrestDefaultClient(
    uri = URI("http://localhost:3111"),
    headers = mapOf("Authorization" to "foobar")
)

You can also pass in a custom schema using the schema parameter.

Entry points

There are two methods to start any call on the PostgresClient.

from

The from<T> function is used for querying. It takes a generic parameter to allow for auto-completion when defining column names. However, you can always use Any if you are unsure about the data type.

postgresClient.from<Any>("messages")
    .select()
    .neq("content", "abc")
    .execute()

postgresClient.from<Message>("messages")
    .select()
    .neq(Message::content, "abc")
    .execute()

// select item_id AS itemId, age from messages...
postgresClient.from<Message>("messages")
    .select("itemId:item_id,age")
    .neq(Message::content, "abc")
    .execute()

// https://postgrest.org/en/stable/api.html#embedding-top-level-filter
postgresClient.from<Message>("messages")
    .select("name,age,company(name, address, phone)")
    .neq(Message::content, "abc")
    .execute()

rpc

The rpc<T> function executes a stored procedure.

postgresClient.rpc("get_status", mapOf("foo" to "bar"))
    .execute()

Executing requests

There are three ways to execute requests and read the response.

execute

The execute method returns a PostgrestHttpResponse. The HttpResponse contains the status code, body as string and the count (if you request the count).

val response = postgresClient.from<Any>("messages")
    .select()
    .execute()

println(response.body)
println(response.status)
println(response.count)

executeAndGetSingle

The executeAndGetSingle<T> function returns T. The JSON converter is used to convert the response to the DTO.

data class Message(
    val id: Long,
    val content: String
)

val message = postgresClient.from<Message>("messages")
    .select()
    .eq(Message::id, 123L)
    .limit(1)
    .single()
    .executeAndGetSingle<Message>()

println(message.content)

You can also use this function to convert your data to a Map, rather than a separate DTO.

val message = postgresClient.from<Message>("messages")
    .select()
    .eq(Message::id, 123L)
    .limit(1)
    .single()
    .executeAndGetSingle<Map<String, Any>>()

println(message["content"])

executeAndGetList

The executeAndGetList<T> function is pretty much the same as the executeAndGetSingle<T> function, however, this functions returns a list of T.

val messages = postgresClient.from<Any>("messages")
    .select()
    .executeAndGetList<Message>()

messages.forEach { message ->
    println(messege.content)
}

CRUD

Selecting data

The select function is used for selecting data.

val response = postgresClient.from<Any>("messages")
    .select(count = Count.EXACT) // will allow accessing data AND count
    .eq("content", "foobar")
    .execute()

Inserting data

The insert function is used for inserting or upserting data.

val message = Message(
    id = 123L,
    content = "foobar"
)

val response = postgresClient.from<Message>("messages")
    .insert(message)
    .execute()

val response = postgresClient.from<Any>("messages")
    .insert(
        value = mapOf("id" to 123L, "content" to "foobar"),
        upsert = true
    )

Updating data

The update function is used for updating data.

val response = postgresClient.from<Any>("messages")
    .update(mapOf("content" to "hello"))
    .eq("id", 123L)
    .execute()

Deleting data

The delete function is used for deleting data.

val response = postgresClient.from<Any>("messages")
    .delete()
    .eq("id", 123L)
    .execute()

HTTP / (De)-Serialization

The Apache Http-Client (5.x) is used for executing HTTP calls, Jackson is used to convert responses to DTOs.

If you want to change that, you need to implement the PostgrestHttpClient and the PostgrestJsonConverter interface.

See PostgrestHttpClientApache and PostgrestsonConverterJackson.

val postgrestClient = PostgrestClient(
    httpClient = customHttpClient(),
    jsonConverter = customConverter()
)

postgrest-kt's People

Contributors

dshukertjr avatar kevcodez avatar ponytailer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

postgrest-kt's Issues

Internal Map doesn't allow url params with the same keys

  val postgrestClient = PostgrestDefaultClient(
                    uri = URI("https://......."),
                    headers = mapOf("piu" to "kjxhzfldjfglekjblcnakuefhlk")
                )

                return postgrestClient.from<Message>("table_name")
                    .select("*")
                    .ilike("key", "%hello%")
                    .gt("like", 1_000_000) // Greater than
                    .lt("like", 3_000_000) // Less than
                    .order("like", false)
                    .limit(10)
                    .execute()

"value", 1_000_000 - will never be added to the request, because internal map will rewrite it with "value", 3_000_000
Recommendation to use multi map and then build a request.

Unable to install 0.2.0 in gradle / Android Studio

Bug report

Trying to install this postgrest-kt package via gradle like this:

def supabase_version = "0.2.0" implementation "io.supabase:postgrest-kt:${supabase_version}"

Throws an error while building:

`Execution failed for task ':app:dataBindingMergeDependencyArtifactsDebug'.

Could not resolve all files for configuration ':app:debugCompileClasspath'.
Could not find io.supabase:postgrest-kt:0.2.0.
Required by:
project :app`

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

  1. Add
    // Supabase def supabase_version = "0.2.0" implementation "io.supabase:postgrest-kt:${supabase_version}"

  2. Build Project

Expected behavior

Android Studio builds successfully, and you're able to run/test the postgrest library.

Screenshots

If applicable, add screenshots to help explain your problem.

System information

MacBook Pro (Retina, 15-inch, Late 2013)
Android Studio 4.2 Beta 5
Build #AI-202.7660.26.42.7141121, built on February 11, 2021
Runtime version: 11.0.8+10-b944.6916264 x86_64
VM: OpenJDK 64-Bit Server VM by N/A
macOS 10.16
GC: G1 Young Generation, G1 Old Generation
Memory: 2048M
Cores: 8

Additional context

Great work thus far! Cant wait to use it.

Android app INSERT returns http 400

I am attempting to use this lib with a Supabase app, just on a simple table to start with and get the hang of it.
The select() queries seem to be working fine, is just insert() that is returning the error.

Calling code is like this:

{
private lateinit var app: TestApp
private var response: GoTrueTokenResponse? = null
private lateinit var client: PostgrestClient

data class SBSimpleTest(
    var id: Long? = null,
    var CreatedAt: Date? = null,
    var Name: String? = null,
    var IntNumber: Int? = null,
    var FloatAmount: Double? = null,
    var IsOK: Boolean? = null,
    var LongNumber: Long? = null,
    var SomeUuid: UUID? = null
)

@Before
fun init() {
    app = ApplicationProvider.getApplicationContext() as TestApp

    response = app.getGoTrueClient().signInWithEmail(" snip  .co", "****").also {
        client = app.obtainPostgresClientFor(it)
    }
}

@Test
fun addARecordTest() {
    val invoice = SBSimpleTest(
        id = -1L,
        CreatedAt = Date(),
        Name = "First Test",
        SomeUuid = UUID.randomUUID(),
        IsOK = true,
        IntNumber = 543,
        LongNumber = 6789L,
        FloatAmount = 34.56
    )
    val count = client.run {
        val response = from<SBSimpleTest>("SimpleTest")
            .insert(value = invoice, returning = Returning.MINIMAL)
            .execute()
        response.count
    } ?: 0L
    assertEquals(1L, count)
}

}

I added some logging to see exactly how the Http request is being formed:

10-15 16:35:14.109 10143 6126 6164 D LoggingHttpClient: uri=https://hrlbnfdxfuhzumhpqiax.supabase.co/rest/v1/SimpleTest?, method=POST
10-15 16:35:14.109 10143 6126 6164 D LoggingHttpClient: edited-uri=https://hrlbnfdxfuhzumhpqiax.supabase.co/rest/v1/SimpleTest
10-15 16:35:14.408 10143 6126 6164 D LoggingHttpClient: body: [{"id":-1,"createdAt":"2021-10-15T05:35:14.086+00:00","floatAmount":34.56,"intNumber":543,"isOK":true,"longNumber":6789,"name":"First Test","someUuid":"ed69d849-00d8-4e69-8a0f-de6f0650869b"}]
10-15 16:35:14.409 10143 6126 6164 D LoggingHttpClient: header: apikey=snip
10-15 16:35:14.409 10143 6126 6164 D LoggingHttpClient: header: Authorization=Bearer snip.F0YSI6eyJwcm92aWRlciI6ImVtYWlsIn0sInVzZXJfbWV0YWRhdGEiOnt9LCJyb2xlIjoiYXV0aGVudGljYXRlZCJ9.RHeuYYLtlAAHELei-_aPdPypt7H0-GbvUqzkJJamPgU
10-15 16:35:14.410 10143 6126 6164 D LoggingHttpClient: header: Prefer=return=minimal
10-15 16:35:14.412 10143 6126 6164 D LoggingHttpClient: header: Content-Type=application/json
10-15 16:35:14.419 root 1734 6178 E ResolverController: No valid NAT64 prefix (101, /0)
10-15 16:35:14.629 10143 6126 6164 D LoggingHttpClient: status=400, 400 Bad Request HTTP/1.1
10-15 16:35:14.795 10143 6126 6164 E TestRunner: failed: addARecordTest(co... .dbconnector.SimplePostgresTests)

Transaction commit/rollback support

I'm by no means a Postgres expert, but am needing to find out if there is/will be support for transactions?
I'm not sure if Supabase has tutorials on this? Or whether this Kotlin library will expose methods for constructing more complex INSERT syntax, with multiple tables involved?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.