1 module htestmain;
2 
3 import std.algorithm;
4 import std.stdio;
5 import std.string;
6 import std.conv;
7 import std.getopt;
8 import hibernated.core;
9 import std.traits;
10 
11 // Annotations of entity classes
12 @Table( "gebruiker" )
13 class User {
14     long id;
15     string name;
16     int some_field_with_underscore;
17     @ManyToMany // cannot be inferred, requires annotation
18     LazyCollection!Role roles;
19     //@ManyToOne
20     MyGroup group;
21 
22     @OneToMany
23     Address[] addresses;
24 
25     Asset[] assets;
26 
27     override string toString() {
28         return format("{id:%s, name:%s, roles:%s, group:%s}", id, name, roles, group);
29     }
30 }
31 
32 class Role {
33     int id;
34     string name;
35     @ManyToMany // w/o this annotation will be OneToMany by convention
36     LazyCollection!User users;
37 
38     override string toString() {
39         return format("{id:%s, name:%s}", id, name);
40     }
41 }
42 
43 class Address {
44     @Generated @Id int id;
45     User user;
46     string street;
47     string town;
48     string country;
49 
50     override string toString() {
51         return format("{id:%s, user:%s, street:%s, town:%s, country:%s}", id, user, street, town, country);
52     }
53 }
54 
55 class Asset {
56     @Generated @Id int id;
57     User user;
58     string name;
59 }
60 
61 @Entity
62 class MyGroup {
63     long id;
64     string name;
65     @OneToMany
66     LazyCollection!User users;
67 
68     override string toString() {
69         return format("{id:%s, name:%s}", id, name);
70     }
71 }
72 
73 void testHibernate(immutable string host, immutable ushort port, immutable string dbName, immutable string dbUser, immutable string dbPass) {
74 
75     // setup DB connection
76     version( USE_SQLITE )
77     {
78         import ddbc.drivers.sqliteddbc;
79         string[string] params;
80         DataSource ds = new ConnectionPoolDataSourceImpl(new SQLITEDriver(), "zzz.db", params);
81         Dialect dialect = new SQLiteDialect();
82     }
83     else version( USE_MYSQL )
84     {
85         import ddbc.drivers.mysqlddbc;
86         immutable string url = MySQLDriver.generateUrl(host, port, dbName);
87         string[string] params = MySQLDriver.setUserAndPassword(dbUser, dbPass);
88         DataSource ds = new ConnectionPoolDataSourceImpl(new MySQLDriver(), url, params);
89         Dialect dialect = new MySQLDialect();
90     }
91     else version( USE_PGSQL )
92     {
93         import ddbc.drivers.pgsqlddbc;
94         immutable string url = PGSQLDriver.generateUrl(host, port, dbName); // PGSQLDriver.generateUrl( "/tmp", 5432, "testdb" );
95         string[string] params;
96         params["user"] = dbUser;
97         params["password"] = dbPass;
98         params["ssl"] = "true";
99         
100         DataSource ds = new ConnectionPoolDataSourceImpl(new PGSQLDriver(), url, params);
101         Dialect dialect = new PGSQLDialect();
102     }
103 
104     // create metadata from annotations
105     writeln("Creating schema from class list");
106     EntityMetaData schema = new SchemaInfoImpl!(User, Role, Address, Asset, MyGroup);
107     //writeln("Creating schema from module list");
108     //EntityMetaData schema2 = new SchemaInfoImpl!(htestmain);
109 
110 
111     writeln("Creating session factory");
112     // create session factory
113     SessionFactory factory = new SessionFactoryImpl(schema, dialect, ds);
114     scope(exit) factory.close();
115 
116     writeln("Creating DB schema");
117     DBInfo db = factory.getDBMetaData();
118     {
119         Connection conn = ds.getConnection();
120         scope(exit) conn.close();
121         db.updateDBSchema(conn, true, true);
122     }
123 
124 
125     // create session
126     Session sess = factory.openSession();
127     scope(exit) sess.close();
128 
129     // use session to access DB
130 
131     writeln("Querying empty DB");
132     Query q = sess.createQuery("FROM User ORDER BY name");
133     User[] list = q.list!User();
134     writeln("Result size is " ~ to!string(list.length));
135 
136     // create sample data
137     writeln("Creating sample schema");
138     MyGroup grp1 = new MyGroup();
139     grp1.name = "Group-1";
140     MyGroup grp2 = new MyGroup();
141     grp2.name = "Group-2";
142     MyGroup grp3 = new MyGroup();
143     grp3.name = "Group-3";
144     //
145     Role r10 = new Role();
146     r10.name = "role10";
147     Role r11 = new Role();
148     r11.name = "role11";
149 
150     // create a user called Alex with an address and an asset
151     User u10 = new User();
152     u10.name = "Alex";
153     u10.roles = [r10, r11];
154     u10.group = grp3;
155     auto address = new Address();
156     address.street = "Some Street";
157     address.town = "Big Town";
158     address.country = "Alaska";
159     address.user = u10;
160     writefln("Saving Address: %s", address);
161     sess.save(address);
162 
163     u10.addresses = [address];
164     auto asset = new Asset();
165     asset.name = "Something Precious";
166     asset.user = u10;
167     writefln("Saving Asset: %s", asset);
168     sess.save(asset);
169     u10.assets = [asset];
170 
171     User u12 = new User();
172     u12.name = "Arjan";
173     u12.roles = [r10, r11];
174     u12.group = grp2;
175 
176     User u13 = new User();
177     u13.name = "Wessel";
178     u13.roles = [r10, r11];
179     u13.group = grp2;
180 
181     writeln("saving group 1-2-3" );
182     sess.save( grp1 );
183     sess.save( grp2 );
184     sess.save( grp3 );
185 
186     writeln("Saving Role r10: " ~ r10.name);
187     sess.save(r10);
188 
189     writeln("Saving Role r11: " ~ r11.name);
190     sess.save(r11);
191 
192     writeln("Saving User u10: " ~ u10.name);
193     sess.save(u10);
194 
195     writeln("Saving User u12: " ~ u12.name);
196     sess.save(u12);
197 
198     writeln("Saving User u13: " ~ u13.name);
199     sess.save(u13);
200 
201     writeln("Loading User");
202     // load and check data
203     auto qresult = sess.createQuery("FROM User WHERE name=:Name and some_field_with_underscore != 42").setParameter("Name", "Alex");
204     writefln( "query result: %s", qresult.listRows() );
205     User u11 = qresult.uniqueResult!User();
206     //User u11 = sess.createQuery("FROM User WHERE name=:Name and some_field_with_underscore != 42").setParameter("Name", "Alex").uniqueResult!User();
207     writefln("Checking User 11 : %s", u11);
208     assert(u11.roles.length == 2);
209     assert(u11.roles[0].name == "role10" || u11.roles.get()[0].name == "role11");
210     assert(u11.roles[1].name == "role10" || u11.roles.get()[1].name == "role11");
211     assert(u11.roles[0].users.length == 3);
212     assert(u11.roles[0].users[0] == u10);
213 
214     assert(u11.addresses.length == 1);
215     assert(u11.addresses[0].street == "Some Street");
216     assert(u11.addresses[0].town == "Big Town");
217     assert(u11.addresses[0].country == "Alaska");
218 
219     assert(u11.assets.length == 1);
220     assert(u11.assets[0].name == "Something Precious");
221 
222     // selecting all from address table should return a row that joins to the user table
223     auto allAddresses = sess.createQuery("FROM Address").list!Address();
224     assert(allAddresses.length == 1);
225     writefln("Found address : %s", allAddresses[0]);
226     assert(allAddresses[0].street == "Some Street");
227     assert(allAddresses[0].user == u11);
228 
229     // selecting all from asset table should return a row that joins to the user table
230     auto allAssets = sess.createQuery("FROM Asset").list!Asset();
231     assert(allAssets.length == 1);
232     writefln("Found asset : %s", allAssets[0]);
233     assert(allAssets[0].name == "Something Precious");
234     assert(allAssets[0].user == u11);
235 
236     // now test something else
237     writeln("Test retrieving users by group... (ManyToOne relationship)");
238     auto qUsersByGroup = sess.createQuery("FROM User WHERE group=:group_id").setParameter("group_id", grp2.id);
239     User[] usersByGroup = qUsersByGroup.list!User();
240     assert(usersByGroup.length == 2); // user 2 and user 2
241 
242     //writeln("Removing User");
243     // remove reference
244     //std.algorithm.remove(u11.roles.get(), 0);
245     //sess.update(u11);
246 
247     // remove entity
248     //sess.remove(u11);
249 }
250 
251 struct ConnectionParams
252 {
253     string host;
254 	ushort port;
255     string database;
256 	string user;
257 	string pass;
258 }
259 
260 int main(string[] args)
261 {
262     ConnectionParams par;
263     string URI;
264 
265     try
266 	{
267 		getopt(args, "host",&par.host, "port",&par.port, "database",&par.database, "user",&par.user, "password",&par.pass);
268 	}
269 	catch (GetOptException)
270 	{
271 		stderr.writefln("Could not parse args");
272 		return 1;
273 	}
274     testHibernate(par.host, par.port, par.database, par.user, par.pass);
275 
276     return 0;
277 }