Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Table.id is not in record set #1341

Closed
BreimerR opened this issue Sep 11, 2021 · 5 comments
Closed

Table.id is not in record set #1341

BreimerR opened this issue Sep 11, 2021 · 5 comments

Comments

@BreimerR
Copy link

BreimerR commented Sep 11, 2021

What does this error mean exactly?
exposed version 0.34.1

Data Classes

data class Account(
    val id: Int,
    var name: Name
)

data class Name(
    var id: Int,
    val first: String,
    var second: String
)

DAO Class

public class Names(id: EntityID<Int>) : Entity<Int>(id) {
    public var first: String by NamesTable.first

    public var second: String by NamesTable.second

    public operator fun invoke(): Name = transaction {
        Name(
            id = this@Names.id.value,
            first = first,
            second = second
        )
    }

    public companion object : EntityClass<Int, Names>(NamesTable) {
        public fun new(name: Name): Names = transaction {
            new {
                first  = name.first
                second  = name.second
            }
        }
    }
}

public class Accounts(  id: EntityID<Int>)  :  Entity<Int>(id) {

    public var name: Names by  Names referencedOn  AccountsTable.name

    public companion object : EntityClass<Int, Accounts>(AccountsTable) {
        public fun new(account: Account): Accounts = transaction {
            new {
                name  =  Names.new(account.name)
            }
        }
    }
}

Table Class


public object NamesTable : IdTable<Int>("names_table") {
  public val first: Column<String> = varchar("first",50)

  public val second: Column<String> = varchar("second",50)

  public override val id: Column<EntityID<Int>> = integer("id").autoIncrement().entityId()

  public override val primaryKey: Table.PrimaryKey = PrimaryKey(id)
}

public object AccountsTable : IdTable<Int>("accounts_table") {
  public val name: Column<EntityID<Int>> = reference("name",NamesTable)

  public override val id: Column<EntityID<Int>> = integer("id").autoIncrement().entityId()

  public override val primaryKey: Table.PrimaryKey = PrimaryKey(id)
}

On creating a new account I get

exposed version 0.34.1
mysql-jdbc connector

Not sure yet where I'm going wrong or if it's a bug.

Inserting a Name works fine
But inserting an Account throws

AccountsTable.id is not in record set

@BreimerR
Copy link
Author

2021-09-11.20-17-15.mp4

Behaviour current solution tables look fine column registration order affecting inserts.

@Tapac
Copy link
Contributor

Tapac commented Sep 13, 2021

Oh, it was a very tricky bug! Thank you so much that you find out that columns order is matter (btw it fails only on SQLite and MySQL).

I was able to fix it in the master and will release the fix on the week.

A few things to make your code a bit less verbose - use predefined classes for IntTables and Entities (also public is a default visibility scope in Kotlin and can ba omitted):

class Names(id: EntityID<Int>) : IntEntity(id) {
    var first: String by NamesTable.first

    var second: String by NamesTable.second

    operator fun invoke(): Name = transaction {
        Name(
            id = this@Names.id.value,
            first = first,
            second = second
        )
    }

    companion object : IntEntityClass<Names>(NamesTable) {
        fun new(name: Name): Names = transaction {
            new {
                first  = name.first
                second  = name.second
            }
        }
    }
}

class Accounts(  id: EntityID<Int>)  :  IntEntity(id) {
    var name: Names by  Names referencedOn  AccountsTable.name

    companion object : IntEntityClass<Accounts>(AccountsTable) {
        public fun new(account: Account): Accounts = transaction {
            new {
                name  =  Names.new(account.name)
            }
        }
    }
}

object NamesTable : IntIdTable("names_table") {
  val first: Column<String> = varchar("first",50)
  val second: Column<String> = varchar("second",50)
}

object AccountsTable : IntIdTable("accounts_table") {
  val name: Column<EntityID<Int>> = reference("name", NamesTable)
}

Tapac added a commit that referenced this issue Sep 13, 2021
@Tapac Tapac closed this as completed Sep 13, 2021
@BreimerR
Copy link
Author

Thanks a lot. Working on a Dao and Table annotations processing thus the strict code requirements from Kotlin poet (public) :) Using the Entity to just have a unified code generation for the first phase will definitely consider using the generated ones once the code base is a bit more stable.

@Tapac
Copy link
Contributor

Tapac commented Sep 14, 2021

SchweinchenFuntik pushed a commit to SchweinchenFuntik/Exposed that referenced this issue Oct 23, 2021
@BreimerR
Copy link
Author

I created rebo to avoid having to write some of the boilerplate code. Would appreciate any review.
https://github.com/BreimerR/Rebo
Works with KSP for code generation performance. Feedback would be appreciated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants