-
Notifications
You must be signed in to change notification settings - Fork 31
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
BugFix: Allow non-primary-key generated fields, e.g. timestamps, coun…
…ters, etc. (#96) * Allow non-primary-key generated fields, e.g. timestamps, counters, etc. Currently, HibernateD treats `@Generated` as being inseparable from `@Id`, it is assumed that any generated field is also the primary key. However, a database table can have non-primary-key columns that are `@Generated`. For example, a database that keeps track of a timestamp, which is populated via a DB trigger or a default value, e.g. `now()`, may exist alongside a separate primary key. In order to support this kind of data, the assumption that `@Generated` implies `@Id` needs to be undone. This PR changes the core logic and also adds a basic test around generated columns to validate schema generation as well as the ability to insert and update such records. * Not sure how that change go in there. * The transaction test cleanup isn't complete apparently. * For MySQL, add a UNIQUE constraint for non-PK generated columns. * Fix syntax error in MySQL when setting UNIQUE. * Add logic to add defaults for MySQL generated non-integer types. * Make sure SqlType.BIGINT gets an autoincrement in MySQL. * Make sure generated parameters can still be manually set. * Update pgsqldialect to use a default value in schema generation when no generator exists for column type. * In pgsqldialect, autoincrement becomes the type, not an attribute. * Remove some debug output.
- Loading branch information
Showing
9 changed files
with
486 additions
and
95 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
module generatedtest; | ||
|
||
import std.datetime; | ||
|
||
import hibernated.core; | ||
|
||
import testrunner : Test; | ||
import hibernatetest : HibernateTest; | ||
|
||
// A class representing a entity with a single generated key. | ||
@Entity | ||
class Generated1 { | ||
// Generated, we can leave this off and the DB will create it. | ||
@Id @Generated | ||
int myId; | ||
|
||
string name; | ||
} | ||
|
||
// A class representing a entity with multiple generated values. | ||
@Entity | ||
class Generated2 { | ||
// Not generated, this must be set in order to save. | ||
@Id | ||
int myId; | ||
|
||
// The DB will create this value and it does not need to be set. | ||
@Generated | ||
int counter1; | ||
|
||
// The DB will create this value and it does not need to be set. | ||
@Generated | ||
DateTime counter2; | ||
|
||
string name; | ||
} | ||
|
||
class GeneratedTest : HibernateTest { | ||
override | ||
EntityMetaData buildSchema() { | ||
return new SchemaInfoImpl!(Generated1, Generated2); | ||
} | ||
|
||
@Test("generated.primary-generated") | ||
void creation1Test() { | ||
Session sess = sessionFactory.openSession(); | ||
scope (exit) sess.close(); | ||
|
||
Generated1 g1 = new Generated1(); | ||
g1.name = "Bob"; | ||
sess.save(g1); | ||
// This value should have been detected as empty, populated by the DB, and refreshed. | ||
int g1Id = g1.myId; | ||
assert(g1Id != 0); | ||
|
||
g1.name = "Barb"; | ||
sess.update(g1); | ||
// The ID should not have changed. | ||
assert(g1.myId == g1Id); | ||
} | ||
|
||
@Test("generated.mannually-set-id-generated") | ||
void manuallySetIdTest() { | ||
Session sess = sessionFactory.openSession(); | ||
scope (exit) sess.close(); | ||
|
||
Generated1 g1 = new Generated1(); | ||
g1.myId = 10; | ||
g1.name = "Bob"; | ||
sess.save(g1); | ||
// This value should have been detected as empty, populated by the DB, and refreshed. | ||
int g1Id = g1.myId; | ||
assert(g1Id == 10); | ||
|
||
g1.name = "Barb"; | ||
sess.update(g1); | ||
|
||
// Make a new session to avoid caching. | ||
sess.close(); | ||
sess = sessionFactory.openSession(); | ||
g1 = sess.get!Generated1(10); | ||
|
||
// The ID should not have been generated. | ||
assert(g1.myId == g1Id); | ||
} | ||
|
||
@Test("generated.non-primary-generated") | ||
void creation2Test() { | ||
Session sess = sessionFactory.openSession(); | ||
scope (exit) sess.close(); | ||
|
||
Generated2 g2 = new Generated2(); | ||
g2.myId = 2; | ||
g2.name = "Sam"; | ||
sess.save(g2); | ||
|
||
int g2Id = g2.myId; | ||
|
||
g2.name = "Slom"; | ||
sess.update(g2); | ||
|
||
// The ID should not have changed. | ||
assert(g2Id == g2.myId); | ||
} | ||
|
||
@Test("generated.manually-set-non-id-generated") | ||
void manuallySetNonIdTest() { | ||
Session sess = sessionFactory.openSession(); | ||
scope (exit) sess.close(); | ||
|
||
Generated2 g2 = new Generated2(); | ||
g2.myId = 3; | ||
g2.name = "Sam"; | ||
g2.counter1 = 11; | ||
sess.save(g2); | ||
|
||
int g2Id = g2.myId; | ||
|
||
g2.name = "Slom"; | ||
sess.update(g2); | ||
|
||
// Make a new session to avoid caching. | ||
sess.close(); | ||
sess = sessionFactory.openSession(); | ||
g2 = sess.get!Generated2(3); | ||
|
||
// The ID should not have changed. | ||
assert(g2Id == g2.myId); | ||
assert(g2.counter1 == 11); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.