1 /** 2 * HibernateD - Object-Relation Mapping for D programming language, with interface similar to Hibernate. 3 * 4 * Hibernate documentation can be found here: 5 * $(LINK http://hibernate.org/docs)$(BR) 6 * 7 * Source file hibernated/tests.d. 8 * 9 * This module contains unit tests for functional testing on real DB. 10 * 11 * Copyright: Copyright 2013 12 * License: $(LINK www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 13 * Author: Vadim Lopatin 14 */ 15 module hibernated.tests; 16 17 private import std.algorithm; 18 private import std.conv; 19 private import std.stdio; 20 private import std.datetime; 21 private import std.typecons; 22 private import std.exception; 23 private import std.variant; 24 25 private import ddbc.core : Connection, DataSource, Statement; 26 27 private import hibernated.core; 28 29 version(unittest) { 30 31 //@Entity 32 @Table("users") // to override table name - "users" instead of default "user" 33 class User { 34 35 //@Generated 36 long id; 37 38 string name; 39 40 // property column 41 private long _flags; 42 @Null // override NotNull which is inferred from long type 43 @property void flags(long v) { _flags = v; } 44 @property ref long flags() { return _flags; } 45 46 // getter/setter property 47 string comment; 48 // @Column -- not mandatory, will be deduced 49 @Null // override default nullability of string with @Null (instead of using String) 50 @Column(null, 1024) // override default length, autogenerate column name) 51 string getComment() { return comment; } 52 void setComment(string v) { comment = v; } 53 54 //@ManyToOne -- not mandatory, will be deduced 55 //@JoinColumn("customer_fk") 56 Customer customer; 57 58 @ManyToMany 59 LazyCollection!Role roles; 60 61 override string toString() { 62 return "id=" ~ to!string(id) ~ ", name=" ~ name ~ ", flags=" ~ to!string(flags) ~ ", comment=" ~ comment ~ ", customerId=" ~ (customer is null ? "NULL" : customer.toString()); 63 } 64 65 } 66 67 68 //@Entity 69 @Table("customers") // to override table name - "customers" instead of default "customer" 70 class Customer { 71 //@Generated 72 int id; 73 // @Column -- not mandatory, will be deduced 74 string name; 75 76 // deduced as @Embedded automatically 77 Address address; 78 79 //@ManyToOne -- not mandatory, will be deduced 80 //@JoinColumn("account_type_fk") 81 Lazy!AccountType accountType; 82 83 // @OneToMany("customer") 84 // LazyCollection!User users; 85 86 //@OneToMany("customer") -- not mandatory, will be deduced 87 private User[] _users; 88 @property User[] users() { return _users; } 89 @property void users(User[] value) { _users = value; } 90 91 this() { 92 address = new Address(); 93 } 94 override string toString() { 95 return "id=" ~ to!string(id) ~ ", name=" ~ name ~ ", address=" ~ address.toString(); 96 } 97 } 98 99 static assert(isEmbeddedObjectMember!(Customer, "address")); 100 101 @Embeddable 102 class Address { 103 hibernated.type.String zip; 104 hibernated.type.String city; 105 hibernated.type.String streetAddress; 106 @Transient // mark field with @Transient to avoid creating column for it 107 string someNonPersistentField; 108 109 override string toString() { 110 return " zip=" ~ zip ~ ", city=" ~ city ~ ", streetAddress=" ~ streetAddress; 111 } 112 } 113 114 @Entity // need to have at least one annotation to import automatically from module 115 class AccountType { 116 //@Generated 117 int id; 118 string name; 119 } 120 121 //@Entity 122 class Role { 123 //@Generated 124 int id; 125 string name; 126 @ManyToMany 127 LazyCollection!User users; 128 } 129 130 //@Entity 131 //@Table("t1") 132 class T1 { 133 //@Id 134 //@Generated 135 int id; 136 137 //@NotNull 138 @UniqueKey 139 string name; 140 141 // property column 142 private long _flags; 143 // @Column -- not mandatory, will be deduced 144 @property long flags() { return _flags; } 145 @property void flags(long v) { _flags = v; } 146 147 // getter/setter property 148 private string comment; 149 // @Column -- not mandatory, will be deduced 150 @Null 151 string getComment() { return comment; } 152 void setComment(string v) { comment = v; } 153 154 155 override string toString() { 156 return "id=" ~ to!string(id) ~ ", name=" ~ name ~ ", flags=" ~ to!string(flags) ~ ", comment=" ~ comment; 157 } 158 } 159 160 @Entity 161 static class GeneratorTest { 162 //@Generator("std.uuid.randomUUID().toString()") 163 @Generator(UUID_GENERATOR) 164 string id; 165 string name; 166 } 167 168 @Entity 169 static class TypeTest { 170 //@Generated 171 int id; 172 string string_field; 173 hibernated.type.String nullable_string_field; 174 byte byte_field; 175 short short_field; 176 int int_field; 177 long long_field; 178 ubyte ubyte_field; 179 ushort ushort_field; 180 ulong ulong_field; 181 DateTime datetime_field; 182 Date date_field; 183 TimeOfDay time_field; 184 Byte nullable_byte_field; 185 Short nullable_short_field; 186 Int nullable_int_field; 187 Long nullable_long_field; 188 Ubyte nullable_ubyte_field; 189 Ushort nullable_ushort_field; 190 Ulong nullable_ulong_field; 191 NullableDateTime nullable_datetime_field; 192 NullableDate nullable_date_field; 193 NullableTimeOfDay nullable_time_field; 194 float float_field; 195 double double_field; 196 Float nullable_float_field; 197 Double nullable_double_field; 198 byte[] byte_array_field; 199 ubyte[] ubyte_array_field; 200 } 201 202 import ddbc.drivers.mysqlddbc; 203 import ddbc.drivers.pgsqlddbc; 204 import ddbc.drivers.sqliteddbc; 205 import ddbc.common; 206 import hibernated.dialects.mysqldialect; 207 import hibernated.dialects.sqlitedialect; 208 import hibernated.dialects.pgsqldialect; 209 210 211 string[] UNIT_TEST_DROP_TABLES_SCRIPT = 212 [ 213 "DROP TABLE IF EXISTS role_users", 214 "DROP TABLE IF EXISTS account_type", 215 "DROP TABLE IF EXISTS users", 216 "DROP TABLE IF EXISTS customers", 217 "DROP TABLE IF EXISTS person", 218 "DROP TABLE IF EXISTS person_info", 219 "DROP TABLE IF EXISTS person_info2", 220 "DROP TABLE IF EXISTS role", 221 "DROP TABLE IF EXISTS generator_test", 222 ]; 223 string[] UNIT_TEST_CREATE_TABLES_SCRIPT = 224 [ 225 "CREATE TABLE IF NOT EXISTS role (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255) NOT NULL)", 226 "CREATE TABLE IF NOT EXISTS account_type (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255) NOT NULL)", 227 "CREATE TABLE IF NOT EXISTS users (id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255) NOT NULL, flags INT, comment TEXT, customer_fk BIGINT NULL)", 228 "CREATE TABLE IF NOT EXISTS customers (id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255) NOT NULL, zip varchar(20), city varchar(100), street_address varchar(255), account_type_fk int)", 229 "CREATE TABLE IF NOT EXISTS person_info (id int not null primary key AUTO_INCREMENT, flags bigint)", 230 "CREATE TABLE IF NOT EXISTS person (id int not null primary key AUTO_INCREMENT, first_name varchar(255) not null, last_name varchar(255) not null, more_info_fk int)", 231 "CREATE TABLE IF NOT EXISTS person_info2 (id int not null primary key AUTO_INCREMENT, flags bigint, person_info_fk int)", 232 "CREATE TABLE IF NOT EXISTS role_users (role_fk int not null, user_fk int not null, primary key (role_fk, user_fk), unique index(user_fk, role_fk))", 233 "CREATE TABLE IF NOT EXISTS generator_test (id varchar(64) not null primary key, name varchar(255) not null)", 234 ]; 235 string[] UNIT_TEST_FILL_TABLES_SCRIPT = 236 [ 237 "INSERT INTO role (name) VALUES ('admin')", 238 "INSERT INTO role (name) VALUES ('viewer')", 239 "INSERT INTO role (name) VALUES ('editor')", 240 "INSERT INTO account_type (name) VALUES ('Type1')", 241 "INSERT INTO account_type (name) VALUES ('Type2')", 242 "INSERT INTO customers (name, zip, account_type_fk) VALUES ('customer 1', '12345', 1)", 243 "INSERT INTO customers (name, zip) VALUES ('customer 2', '54321')", 244 "INSERT INTO customers (name, street_address, account_type_fk) VALUES ('customer 3', 'Baker Street, 24', 2)", 245 "INSERT INTO users (name, flags, comment, customer_fk) VALUES ('user 1', 11, 'comments for user 1', 1)", 246 "INSERT INTO users (name, flags, comment, customer_fk) VALUES ('user 2', 22, 'this user belongs to customer 1', 1)", 247 "INSERT INTO users (name, flags, comment, customer_fk) VALUES ('user 3', NULL, 'this user belongs to customer 2', 2)", 248 "INSERT INTO users (name, flags, comment, customer_fk) VALUES ('user 4', 44, NULL, 3)", 249 "INSERT INTO users (name, flags, comment, customer_fk) VALUES ('test user 5', 55, 'this user belongs to customer 3, too', 3)", 250 "INSERT INTO users (name, flags, comment, customer_fk) VALUES ('test user 6', 66, 'for checking of Nullable!long reading', null)", 251 "INSERT INTO person_info (id, flags) VALUES (3, 123)", 252 "INSERT INTO person_info (id, flags) VALUES (4, 234)", 253 "INSERT INTO person_info (id, flags) VALUES (5, 345)", 254 "INSERT INTO person_info2 (id, flags, person_info_fk) VALUES (10, 1, 3)", 255 "INSERT INTO person_info2 (id, flags, person_info_fk) VALUES (11, 2, 4)", 256 "INSERT INTO person (first_name, last_name, more_info_fk) VALUES ('Andrei', 'Alexandrescu', 3)", 257 "INSERT INTO person (first_name, last_name, more_info_fk) VALUES ('Walter', 'Bright', 4)", 258 "INSERT INTO person (first_name, last_name, more_info_fk) VALUES ('John', 'Smith', 5)", 259 "INSERT INTO role_users (role_fk, user_fk) VALUES (1, 1)", 260 "INSERT INTO role_users (role_fk, user_fk) VALUES (2, 1)", 261 "INSERT INTO role_users (role_fk, user_fk) VALUES (2, 2)", 262 "INSERT INTO role_users (role_fk, user_fk) VALUES (2, 3)", 263 "INSERT INTO role_users (role_fk, user_fk) VALUES (3, 2)", 264 "INSERT INTO role_users (role_fk, user_fk) VALUES (3, 3)", 265 "INSERT INTO role_users (role_fk, user_fk) VALUES (3, 5)", 266 ]; 267 268 void recreateTestSchema(bool dropTables, bool createTables, bool fillTables) { 269 DataSource connectionPool = getUnitTestDataSource(); 270 if (connectionPool is null) 271 return; // DB tests disabled 272 Connection conn = connectionPool.getConnection(); 273 scope(exit) conn.close(); 274 if (dropTables) 275 unitTestExecuteBatch(conn, UNIT_TEST_DROP_TABLES_SCRIPT); 276 if (createTables) 277 unitTestExecuteBatch(conn, UNIT_TEST_CREATE_TABLES_SCRIPT); 278 if (fillTables) 279 unitTestExecuteBatch(conn, UNIT_TEST_FILL_TABLES_SCRIPT); 280 } 281 282 immutable bool DB_TESTS_ENABLED = SQLITE_TESTS_ENABLED || MYSQL_TESTS_ENABLED || PGSQL_TESTS_ENABLED; 283 284 285 package DataSource _unitTestConnectionPool; 286 /// will return null if DB tests are disabled 287 DataSource getUnitTestDataSource() { 288 if (_unitTestConnectionPool is null) { 289 static if (SQLITE_TESTS_ENABLED) { 290 pragma(msg, "Will use SQLite for HibernateD unit tests"); 291 _unitTestConnectionPool = createUnitTestSQLITEDataSource(); 292 } else if (MYSQL_TESTS_ENABLED) { 293 pragma(msg, "Will use MySQL for HibernateD unit tests"); 294 _unitTestConnectionPool = createUnitTestMySQLDataSource(); 295 } else if (PGSQL_TESTS_ENABLED) { 296 pragma(msg, "Will use PGSQL for HibernateD unit tests"); 297 _unitTestConnectionPool = createUnitTestPGSQLDataSource(); 298 } 299 } 300 return _unitTestConnectionPool; 301 } 302 Dialect getUnitTestDialect() { 303 304 static if (SQLITE_TESTS_ENABLED) { 305 return new SQLiteDialect(); 306 } else if (MYSQL_TESTS_ENABLED) { 307 return new MySQLDialect(); 308 } else if (PGSQL_TESTS_ENABLED) { 309 return new PGSQLDialect(); 310 } else { 311 return null; // disabled 312 } 313 } 314 315 void closeUnitTestDataSource() { 316 // if (!_unitTestConnectionPool is null) { 317 // _unitTestConnectionPool.close(); 318 // _unitTestConnectionPool = null; 319 // } 320 } 321 } 322 323 324 unittest { 325 326 // Checking generated metadata 327 EntityMetaData schema = new SchemaInfoImpl!(User, Customer, AccountType, T1, TypeTest, Address, Role); 328 329 //writeln("metadata test 1"); 330 assert(schema["TypeTest"].length==29); 331 assert(schema.getEntityCount() == 7); 332 assert(schema["User"]["name"].columnName == "name"); 333 assert(schema["User"][0].columnName == "id"); 334 assert(schema["User"][2].propertyName == "flags"); 335 assert(schema["User"]["id"].generated == true); 336 assert(schema["User"]["id"].key == true); 337 assert(schema["User"]["name"].key == false); 338 assert(schema["Customer"]["id"].generated == true); 339 assert(schema["Customer"]["id"].key == true); 340 assert(schema["Customer"]["address"].embedded == true); 341 assert(schema["Customer"]["address"].referencedEntity !is null); 342 assert(schema["Customer"]["address"].referencedEntity["streetAddress"].columnName == "street_address"); 343 assert(schema["User"]["customer"].columnName !is null); 344 345 assert(!schema["User"].embeddable); // test if @Embeddable is working 346 assert(schema["Address"].embeddable); // test if @Embeddable is working 347 assert(schema["Address"].length == 3); // test if @Transient is working 348 349 assert(schema["Customer"]["users"].relation == RelationType.OneToMany); 350 assert(schema["User"]["customer"].relation == RelationType.ManyToOne); 351 assert(schema["User"]["roles"].relation == RelationType.ManyToMany); 352 assert(schema["User"]["roles"].joinTable !is null); 353 assert(schema["User"]["roles"].joinTable.tableName == "role_users"); 354 assert(schema["User"]["roles"].joinTable.column1 == "user_fk"); 355 assert(schema["User"]["roles"].joinTable.column2 == "role_fk"); 356 assert(schema["Role"]["users"].joinTable.tableName == "role_users"); 357 assert(schema["Role"]["users"].joinTable.column1 == "role_fk"); 358 assert(schema["Role"]["users"].joinTable.column2 == "user_fk"); 359 360 assert(schema["Customer"]["users"].collection); 361 362 assert(schema["User"]["id"].readFunc !is null); 363 364 assert(schema["User"]["comment"].length == 1024); 365 static assert(isGetterFunction!(__traits(getMember, User, "getComment"), "getComment")); 366 static assert(isGetterFunction!(__traits(getMember, T1, "getComment"), "getComment")); 367 static assert(hasMemberAnnotation!(User, "getComment", Null)); 368 static assert(hasMemberAnnotation!(T1, "getComment", Null)); 369 static assert(!isMainMemberForProperty!(User, "comment")); 370 static assert(isMainMemberForProperty!(User, "getComment")); 371 static assert(isMainMemberForProperty!(Customer, "users")); 372 373 assert(schema["T1"]["comment"].nullable); 374 assert(schema["User"]["comment"].nullable); 375 376 assert(schema["TypeTest"]["id"].key); 377 assert(schema["TypeTest"]["id"].key); 378 assert(!schema["TypeTest"]["string_field"].nullable); 379 assert(schema["TypeTest"]["nullable_string_field"].nullable); 380 assert(!schema["TypeTest"]["byte_field"].nullable); 381 assert(!schema["TypeTest"]["short_field"].nullable); 382 assert(!schema["TypeTest"]["int_field"].nullable); 383 assert(!schema["TypeTest"]["long_field"].nullable); 384 assert(!schema["TypeTest"]["ubyte_field"].nullable); 385 assert(!schema["TypeTest"]["ushort_field"].nullable); 386 assert(!schema["TypeTest"]["ulong_field"].nullable); 387 assert(!schema["TypeTest"]["datetime_field"].nullable); 388 assert(!schema["TypeTest"]["date_field"].nullable); 389 assert(!schema["TypeTest"]["time_field"].nullable); 390 assert(schema["TypeTest"]["nullable_byte_field"].nullable); 391 assert(schema["TypeTest"]["nullable_short_field"].nullable); 392 assert(schema["TypeTest"]["nullable_int_field"].nullable); 393 assert(schema["TypeTest"]["nullable_long_field"].nullable); 394 assert(schema["TypeTest"]["nullable_ubyte_field"].nullable); 395 assert(schema["TypeTest"]["nullable_ushort_field"].nullable); 396 assert(schema["TypeTest"]["nullable_ulong_field"].nullable); 397 assert(schema["TypeTest"]["nullable_datetime_field"].nullable); 398 assert(schema["TypeTest"]["nullable_date_field"].nullable); 399 assert(schema["TypeTest"]["nullable_time_field"].nullable); 400 assert(!schema["TypeTest"]["float_field"].nullable); 401 assert(!schema["TypeTest"]["double_field"].nullable); 402 assert(schema["TypeTest"]["nullable_float_field"].nullable); 403 assert(schema["TypeTest"]["nullable_double_field"].nullable); 404 assert(schema["TypeTest"]["byte_array_field"].nullable); 405 assert(schema["TypeTest"]["ubyte_array_field"].nullable); 406 407 auto e2 = schema.createEntity("User"); 408 assert(e2 !is null); 409 User e2user = cast(User)e2; 410 assert(e2user !is null); 411 412 413 414 415 // TODO: 416 // e2user.customer = new Customer(); 417 // e2user.customer.id = 25; 418 // e2user.customer.name = "cust25"; 419 // Variant v = schema.getPropertyValue(e2user, "customer"); 420 // assert(v.get!Customer().name == "cust25"); 421 // e2user.customer = null; 422 // //assert(schema.getPropertyValue(e2user, "customer").to!Object is null); //Variant(cast(Customer)null)); 423 // Customer c42 = new Customer(); 424 // c42.id = 42; 425 // c42.name = "customer 42"; 426 // schema.setPropertyValue(e2user, "customer", Variant(c42)); 427 // assert(e2user.customer.id == 42); 428 // //assert(schema.getPropertyValue(e2user, "customer") == 42); 429 430 Object e1 = schema.findEntity("User").createEntity(); 431 assert(e1 !is null); 432 User e1user = cast(User)e1; 433 assert(e1user !is null); 434 e1user.id = 25; 435 436 437 438 } 439 440 unittest { 441 if (DB_TESTS_ENABLED) { 442 recreateTestSchema(true, false, false); 443 444 445 //writeln("metadata test 2"); 446 447 // Checking generated metadata 448 EntityMetaData schema = new SchemaInfoImpl!(User, Customer, AccountType, T1, TypeTest, Address, Role, GeneratorTest, Person, MoreInfo, EvenMoreInfo); 449 Dialect dialect = getUnitTestDialect(); 450 451 DBInfo db = new DBInfo(dialect, schema); 452 string[] createTables = db.getCreateTableSQL(); 453 // foreach(t; createTables) 454 // writeln(t); 455 string[] createIndexes = db.getCreateIndexSQL(); 456 // foreach(t; createIndexes) 457 // writeln(t); 458 static if (SQLITE_TESTS_ENABLED) { 459 assert(db["users"].getCreateTableSQL() == "CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL, flags INT NULL, comment TEXT NULL, customer_fk INT NULL)"); 460 assert(db["customers"].getCreateTableSQL() == "CREATE TABLE customers (id INTEGER PRIMARY KEY, name TEXT NOT NULL, zip TEXT NULL, city TEXT NULL, street_address TEXT NULL, account_type_fk INT NULL)"); 461 assert(db["account_type"].getCreateTableSQL() == "CREATE TABLE account_type (id INTEGER PRIMARY KEY, name TEXT NOT NULL)"); 462 assert(db["t1"].getCreateTableSQL() == "CREATE TABLE t1 (id INTEGER PRIMARY KEY, name TEXT NOT NULL, flags INT NOT NULL, comment TEXT NULL)"); 463 assert(db["role"].getCreateTableSQL() == "CREATE TABLE role (id INTEGER PRIMARY KEY, name TEXT NOT NULL)"); 464 assert(db["generator_test"].getCreateTableSQL() == "CREATE TABLE generator_test (id TEXT NOT NULL PRIMARY KEY, name TEXT NOT NULL)"); 465 assert(db["role_users"].getCreateTableSQL() == "CREATE TABLE role_users (role_fk INT NOT NULL, user_fk INT NOT NULL, PRIMARY KEY (role_fk, user_fk), UNIQUE (user_fk, role_fk))"); 466 } else static if (MYSQL_TESTS_ENABLED) { 467 assert(db["users"].getCreateTableSQL() == "CREATE TABLE users (id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255) NOT NULL, flags BIGINT NULL, comment VARCHAR(1024) NULL, customer_fk INT NULL)"); 468 assert(db["customers"].getCreateTableSQL() == "CREATE TABLE customers (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255) NOT NULL, zip VARCHAR(255) NULL, city VARCHAR(255) NULL, street_address VARCHAR(255) NULL, account_type_fk INT NULL)"); 469 assert(db["account_type"].getCreateTableSQL() == "CREATE TABLE account_type (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255) NOT NULL)"); 470 assert(db["t1"].getCreateTableSQL() == "CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255) NOT NULL, flags BIGINT NOT NULL, comment VARCHAR(255) NULL)"); 471 assert(db["role"].getCreateTableSQL() == "CREATE TABLE role (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255) NOT NULL)"); 472 assert(db["generator_test"].getCreateTableSQL() == "CREATE TABLE generator_test (id VARCHAR(255) NOT NULL PRIMARY KEY, name VARCHAR(255) NOT NULL)"); 473 assert(db["role_users"].getCreateTableSQL() == "CREATE TABLE role_users (role_fk INT NOT NULL, user_fk BIGINT NOT NULL, PRIMARY KEY (role_fk, user_fk), UNIQUE INDEX role_users_reverse_index (user_fk, role_fk))"); 474 } else static if (PGSQL_TESTS_ENABLED) { 475 } 476 477 478 479 DataSource ds = getUnitTestDataSource(); 480 if (ds is null) 481 return; // DB tests disabled 482 SessionFactory factory = new SessionFactoryImpl(schema, dialect, ds); 483 db = factory.getDBMetaData(); 484 { 485 Connection conn = ds.getConnection(); 486 scope(exit) conn.close(); 487 db.updateDBSchema(conn, true, true); 488 recreateTestSchema(false, false, true); 489 } 490 491 492 493 494 scope(exit) factory.close(); 495 { 496 Session sess = factory.openSession(); 497 scope(exit) sess.close(); 498 499 User u1 = sess.load!User(1); 500 //writeln("Loaded value: " ~ u1.toString); 501 assert(u1.id == 1); 502 assert(u1.name == "user 1"); 503 assert(u1.customer.name == "customer 1"); 504 assert(u1.customer.accountType() !is null); 505 assert(u1.customer.accountType().name == "Type1"); 506 Role[] u1roles = u1.roles; 507 assert(u1roles.length == 2); 508 509 User u2 = sess.load!User(2); 510 assert(u2.name == "user 2"); 511 assert(u2.flags == 22); // NULL is loaded as 0 if property cannot hold nulls 512 513 User u3 = sess.get!User(3); 514 assert(u3.name == "user 3"); 515 assert(u3.flags == 0); // NULL is loaded as 0 if property cannot hold nulls 516 assert(u3.getComment() !is null); 517 assert(u3.customer.name == "customer 2"); 518 assert(u3.customer.accountType() is null); 519 520 User u4 = new User(); 521 sess.load(u4, 4); 522 assert(u4.name == "user 4"); 523 assert(u4.getComment() is null); 524 525 User u5 = new User(); 526 u5.id = 5; 527 sess.refresh(u5); 528 assert(u5.name == "test user 5"); 529 //assert(u5.customer !is null); 530 531 u5 = sess.load!User(5); 532 assert(u5.name == "test user 5"); 533 assert(u5.customer !is null); 534 assert(u5.customer.id == 3); 535 assert(u5.customer.name == "customer 3"); 536 assert(u5.customer.accountType() !is null); 537 assert(u5.customer.accountType().name == "Type2"); 538 539 User u6 = sess.load!User(6); 540 assert(u6.name == "test user 6"); 541 assert(u6.customer is null); 542 543 // 544 //writeln("loading customer 3"); 545 // testing @Embedded property 546 Customer c3 = sess.load!Customer(3); 547 assert(c3.address.zip is null); 548 assert(c3.address.streetAddress == "Baker Street, 24"); 549 c3.address.streetAddress = "Baker Street, 24/2"; 550 c3.address.zip = "55555"; 551 552 User[] c3users = c3.users; 553 //writeln(" *** customer has " ~ to!string(c3users.length) ~ " users"); 554 assert(c3users.length == 2); 555 assert(c3users[0].customer == c3); 556 assert(c3users[1].customer == c3); 557 558 //writeln("updating customer 3"); 559 sess.update(c3); 560 Customer c3_reloaded = sess.load!Customer(3); 561 assert(c3.address.streetAddress == "Baker Street, 24/2"); 562 assert(c3.address.zip == "55555"); 563 564 } 565 { 566 Session sess = factory.openSession(); 567 scope(exit) sess.close(); 568 569 570 // check Session.save() when id is filled 571 Customer c4 = new Customer(); 572 c4.id = 4; 573 c4.name = "Customer_4"; 574 sess.save(c4); 575 576 Customer c4_check = sess.load!Customer(4); 577 assert(c4.id == c4_check.id); 578 assert(c4.name == c4_check.name); 579 580 sess.remove(c4); 581 582 c4 = sess.get!Customer(4); 583 assert (c4 is null); 584 585 Customer c5 = new Customer(); 586 c5.name = "Customer_5"; 587 sess.save(c5); 588 589 // Testing generator function (uuid) 590 GeneratorTest g1 = new GeneratorTest(); 591 g1.name = "row 1"; 592 assert(g1.id is null); 593 sess.save(g1); 594 assert(g1.id !is null); 595 596 597 assertThrown!MappingException(sess.createQuery("SELECT id, name, blabla FROM User ORDER BY name")); 598 assertThrown!QuerySyntaxException(sess.createQuery("SELECT id: name FROM User ORDER BY name")); 599 600 // test multiple row query 601 Query q = sess.createQuery("FROM User ORDER BY name"); 602 User[] list = q.list!User(); 603 assert(list.length == 6); 604 assert(list[0].name == "test user 5"); 605 assert(list[1].name == "test user 6"); 606 assert(list[2].name == "user 1"); 607 // writeln("Read " ~ to!string(list.length) ~ " rows from User"); 608 // foreach(row; list) { 609 // writeln(row.toString()); 610 // } 611 Variant[][] rows = q.listRows(); 612 assert(rows.length == 6); 613 // foreach(row; rows) { 614 // writeln(row); 615 // } 616 assertThrown!HibernatedException(q.uniqueResult!User()); 617 assertThrown!HibernatedException(q.uniqueRow()); 618 619 } 620 { 621 Session sess = factory.openSession(); 622 scope(exit) sess.close(); 623 624 // test single row select 625 Query q = sess.createQuery("FROM User AS u WHERE id = :Id and (u.name like '%test%' or flags=44)"); 626 assertThrown!HibernatedException(q.list!User()); // cannot execute w/o all parameters set 627 q.setParameter("Id", Variant(6)); 628 User[] list = q.list!User(); 629 assert(list.length == 1); 630 assert(list[0].name == "test user 6"); 631 // writeln("Read " ~ to!string(list.length) ~ " rows from User"); 632 // foreach(row; list) { 633 // writeln(row.toString()); 634 // } 635 User uu = q.uniqueResult!User(); 636 assert(uu.name == "test user 6"); 637 Variant[] row = q.uniqueRow(); 638 assert(row[0] == 6L); 639 assert(row[1] == "test user 6"); 640 641 // test empty SELECT result 642 q.setParameter("Id", Variant(7)); 643 row = q.uniqueRow(); 644 assert(row is null); 645 uu = q.uniqueResult!User(); 646 assert(uu is null); 647 648 q = sess.createQuery("SELECT c.name, c.address.zip FROM Customer AS c WHERE id = :Id").setParameter("Id", Variant(1)); 649 row = q.uniqueRow(); 650 assert(row !is null); 651 assert(row[0] == "customer 1"); // name 652 assert(row[1] == "12345"); // address.zip 653 654 655 } 656 { 657 // prepare data 658 Session sess = factory.openSession(); 659 scope(exit) sess.close(); 660 661 Role r10 = new Role(); 662 r10.name = "role10"; 663 Role r11 = new Role(); 664 r11.name = "role11"; 665 Customer c10 = new Customer(); 666 c10.name = "Customer 10"; 667 User u10 = new User(); 668 u10.name = "Alex"; 669 u10.customer = c10; 670 u10.roles = [r10, r11]; 671 sess.save(r10); 672 sess.save(r11); 673 sess.save(c10); 674 sess.save(u10); 675 assert(c10.id != 0); 676 assert(u10.id != 0); 677 assert(r10.id != 0); 678 assert(r11.id != 0); 679 } 680 { 681 // check data in separate session 682 Session sess = factory.openSession(); 683 scope(exit) sess.close(); 684 User u10 = sess.createQuery("FROM User WHERE name=:Name").setParameter("Name", "Alex").uniqueResult!User(); 685 assert(u10.roles.length == 2); 686 assert(u10.roles[0].name == "role10" || u10.roles.get()[0].name == "role11"); 687 assert(u10.roles[1].name == "role10" || u10.roles.get()[1].name == "role11"); 688 assert(u10.customer.name == "Customer 10"); 689 assert(u10.customer.users.length == 1); 690 assert(u10.customer.users[0] == u10); 691 assert(u10.roles[0].users.length == 1); 692 assert(u10.roles[0].users[0] == u10); 693 // removing one role from user 694 u10.roles.get().remove(0); 695 sess.update(u10); 696 } 697 { 698 // check that only one role left 699 Session sess = factory.openSession(); 700 scope(exit) sess.close(); 701 User u10 = sess.createQuery("FROM User WHERE name=:Name").setParameter("Name", "Alex").uniqueResult!User(); 702 assert(u10.roles.length == 1); 703 assert(u10.roles[0].name == "role10" || u10.roles.get()[0].name == "role11"); 704 // remove user 705 sess.remove(u10); 706 } 707 { 708 // check that user is removed 709 Session sess = factory.openSession(); 710 scope(exit) sess.close(); 711 User u10 = sess.createQuery("FROM User WHERE name=:Name").setParameter("Name", "Alex").uniqueResult!User(); 712 assert(u10 is null); 713 } 714 } 715 } 716 717 718 version (unittest) { 719 // for testing of Embeddable 720 @Embeddable 721 class EMName { 722 string firstName; 723 string lastName; 724 } 725 726 //@Entity 727 class EMUser { 728 //@Id @Generated 729 //@Column 730 int id; 731 732 // deduced as @Embedded automatically 733 EMName userName; 734 } 735 736 // for testing of Embeddable 737 //@Entity 738 class Person { 739 //@Id 740 int id; 741 742 // @Column @NotNull 743 string firstName; 744 // @Column @NotNull 745 string lastName; 746 747 @NotNull 748 @OneToOne 749 @JoinColumn("more_info_fk") 750 MoreInfo moreInfo; 751 } 752 753 754 //@Entity 755 @Table("person_info") 756 class MoreInfo { 757 //@Id @Generated 758 int id; 759 // @Column 760 long flags; 761 @OneToOne("moreInfo") 762 Person person; 763 @OneToOne("personInfo") 764 EvenMoreInfo evenMore; 765 } 766 767 //@Entity 768 @Table("person_info2") 769 class EvenMoreInfo { 770 //@Id @Generated 771 int id; 772 //@Column 773 long flags; 774 @OneToOne 775 @JoinColumn("person_info_fk") 776 MoreInfo personInfo; 777 } 778 779 } 780 781 782 unittest { 783 static assert(hasAnnotation!(EMName, Embeddable)); 784 static assert(isEmbeddedObjectMember!(EMUser, "userName")); 785 static assert(!hasMemberAnnotation!(EMUser, "userName", OneToOne)); 786 static assert(getPropertyEmbeddedEntityName!(EMUser, "userName") == "EMName"); 787 static assert(getPropertyEmbeddedClassName!(EMUser, "userName") == "hibernated.tests.EMName"); 788 //pragma(msg, getEmbeddedPropertyDef!(EMUser, "userName")()); 789 790 // Checking generated metadata 791 EntityMetaData schema = new SchemaInfoImpl!(EMName, EMUser); 792 793 static assert(hasMemberAnnotation!(Person, "moreInfo", OneToOne)); 794 static assert(getPropertyReferencedEntityName!(Person, "moreInfo") == "MoreInfo"); 795 static assert(getPropertyReferencedClassName!(Person, "moreInfo") == "hibernated.tests.MoreInfo"); 796 //pragma(msg, getOneToOnePropertyDef!(Person, "moreInfo")); 797 //pragma(msg, getOneToOnePropertyDef!(MoreInfo, "person")); 798 //pragma(msg, "running getOneToOneReferencedPropertyName"); 799 //pragma(msg, getOneToOneReferencedPropertyName!(MoreInfo, "person")); 800 static assert(getJoinColumnName!(Person, "moreInfo") == "more_info_fk"); 801 static assert(getOneToOneReferencedPropertyName!(MoreInfo, "person") == "moreInfo"); 802 static assert(getOneToOneReferencedPropertyName!(Person, "moreInfo") is null); 803 804 //pragma(msg, "done getOneToOneReferencedPropertyName"); 805 806 // Checking generated metadata 807 //EntityMetaData schema = new SchemaInfoImpl!(Person, MoreInfo); 808 // foreach(e; schema["Person"]) { 809 // writeln("property: " ~ e.propertyName); 810 // } 811 schema = new SchemaInfoImpl!(hibernated.tests); //Person, MoreInfo, EvenMoreInfo, 812 813 { 814 815 int[Variant] map0; 816 map0[Variant(1)] = 3; 817 assert(map0[Variant(1)] == 3); 818 map0[Variant(1)]++; 819 assert(map0[Variant(1)] == 4); 820 821 //writeln("map test"); 822 PropertyLoadMap map = new PropertyLoadMap(); 823 Person ppp1 = new Person(); 824 Person ppp2 = new Person(); 825 Person ppp3 = new Person(); 826 //writeln("adding first"); 827 map.add(schema["Person"]["moreInfo"], Variant(1), ppp1); 828 //writeln("adding second"); 829 auto prop1 = schema["Person"]["moreInfo"]; 830 auto prop2 = schema["Person"]["moreInfo"]; 831 map.add(prop1, Variant(2), ppp2); 832 map.add(prop2, Variant(2), ppp3); 833 map.add(prop2, Variant(2), ppp3); 834 map.add(prop2, Variant(2), ppp3); 835 map.add(prop2, Variant(2), ppp3); 836 assert(prop1 == prop2); 837 assert(prop1.opHash() == prop2.opHash()); 838 //writeln("checking length"); 839 assert(Variant(3) == Variant(3L)); 840 assert(map.length == 1); 841 assert(map.map.length == 1); 842 assert(map.keys.length == 1); 843 assert(map.map.values.length == 1); 844 //writeln("length of moreInfo is " ~ to!string(map[prop1].length)); 845 auto m = map[prop1]; 846 assert(m == map[prop2]); 847 assert(m.map.length == 2); 848 Variant v1 = 1; 849 Variant v2 = 2; 850 //writeln("length for id 1 " ~ to!string(m[Variant(1)].length)); 851 //writeln("length for id 2 " ~ to!string(m[Variant(2)].length)); 852 assert(m.length == 2); 853 assert(m[Variant(1)].length == 1); 854 assert(m[Variant(2)].length == 2); 855 } 856 857 if (DB_TESTS_ENABLED) { 858 //recreateTestSchema(); 859 860 //writeln("metadata test 2"); 861 import hibernated.dialects.mysqldialect; 862 863 // Checking generated metadata 864 Dialect dialect = getUnitTestDialect(); 865 DataSource ds = getUnitTestDataSource(); 866 if (ds is null) 867 return; // DB tests disabled 868 SessionFactory factory = new SessionFactoryImpl(schema, dialect, ds); 869 scope(exit) factory.close(); 870 { 871 Session sess = factory.openSession(); 872 scope(exit) sess.close(); 873 874 auto p1 = sess.get!Person(1); 875 assert(p1.firstName == "Andrei"); 876 877 878 // all non-null oneToOne relations 879 auto q = sess.createQuery("FROM Person WHERE id=:Id").setParameter("Id", Variant(1)); 880 Person p2 = q.uniqueResult!Person(); 881 assert(p2.firstName == "Andrei"); 882 assert(p2.moreInfo !is null); 883 assert(p2.moreInfo.person !is null); 884 assert(p2.moreInfo.person == p2); 885 assert(p2.moreInfo.flags == 123); 886 assert(p2.moreInfo.evenMore !is null); 887 assert(p2.moreInfo.evenMore.flags == 1); 888 assert(p2.moreInfo.evenMore.personInfo !is null); 889 assert(p2.moreInfo.evenMore.personInfo == p2.moreInfo); 890 891 892 // null oneToOne relation 893 q = sess.createQuery("FROM Person WHERE id=:Id").setParameter("Id", Variant(3)); 894 p2 = q.uniqueResult!Person(); 895 assert(p2.firstName == "John"); 896 assert(p2.moreInfo !is null); 897 assert(p2.moreInfo.person !is null); 898 assert(p2.moreInfo.person == p2); 899 assert(p2.moreInfo.flags == 345); 900 assert(p2.moreInfo.evenMore is null); 901 902 } 903 904 } 905 } 906 907