Skip to content

tpasipanodya/exposed

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Exposed


Build

GitHub License

Welcome to Exposed; a fork of the Kotlin ORM framework. In terms of behavior, this fork is identical to the main Exposed library with the exception that it allows configuring default filters (query operators) on tables. Default filters can be useful for implementing multi-tenancy & soft deletes.

Supported Databases

Visit the official Exposed page for an updated list.

Getting started

val exposedVersion: String by project
repositories {
    maven {
			name = "GitHubPackages"
			url = uri("https://maven.pkg.github.com/tpasipanodya/exposed")
			credentials {
				username = System.getenv("GITHUB_USERNAME")
				password = System.getenv("GITHUB_ACCESS_TOKEN")
			}
		}
}

dependencies {
    implementation(platform("io.taff.exposed:exposed-bom:0.10.0"))
    implementation("io.taff.exposed", "exposed-core")
    implementation("io.taff.exposed", "exposed-dao")
    implementation("io.taff.exposed", "exposed-jdbc")
}

The latest release version is 0.10.0 (pegged against org.jetbrains.exposed:exposed:0.44.1) and is available on JFrog at https://maven.pkg.github.com/tpasipanodya/exposed.

Examples

CurrentUserId = ThreadLocal<Long>()

object users : LongIdTable() {
    val name = varchar("name", length = 50) // Column<String>
}

object posts : LongIdTable() {
    val text = text("text")
    val userId = integer("user_id") references users.id

    override val defaultFilter = { Op.build { userId eq CurrentUserId.get() } }
}

fun main() {
    Database.connect(db_url)
    transaction {
        SchemaUtils.create(users, posts)
        
        val user1Id = users.insert { it[name] = "User 1" }[users.id]
        val user2Id = users.insert { it[name] = "User 2" }[users.id]

        posts.insert {
            it[userId] = user1Id
            it[text] = "foo bar"
        }
        posts.insert {
            it[userId] = user2Id
            it[text] = "lorem ipsum"
        }

        CurrentUserId.set(user1Id)
        var retrievedText = posts.selectAll().single()[posts.text]

       
        println(retrievedText == "foo bar")
        //> true

        CurrentUserId.set(user2Id)
        retrievedText = posts.selectAll().single()[posts.text]

        
        println(retrievedText == "lorem ipsum")
        //> true
        
        // Any persisted record must have an id but the following update statment 
        // applies the table's default filter, hence only the current user's post 
        // will be updated.
        val newText =  "Let's get it started in here"
        posts.update({ id.isNotNull() }) { it[text] = newText }

        posts.stripDefaultFilter()
            .orderBy(posts.userId, SortOrder.Asc)
            .selectAll()
            .map { it[posts.userId] to it[posts.text] }
            .let { allTexts -> 
                // true
                listOf(
                    user1Id to "foo bar", 
                    user2Id to newText
                ) == allTexts
            }
    }
}

Default filters are applied to all operations including deletes, joins, unions, etc. For additional examples, take a look at the official Exposed wiki.

Development

To initialize test containers and other local development fixtures:

.scripts/setup.sh

Links

  • Wiki with examples and docs.
  • Change log of improvements and bug fixes.

Feel free to submit issues and requests via Github.

License

By contributing to the Exposed project, you agree that your contributions will be licensed under Apache License, Version 2.0.