| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317 |
- using Invercargill.DataStructures;
- using InvercargillSql;
- using InvercargillSql.Orm;
- using InvercargillSql.Orm.Projections;
- using InvercargillSql.Migrations;
- using InvercargillSql.Dialects;
- /**
- * Invercargill-Sql ORM Demo Application
- *
- * This demo showcases the main features of the Invercargill-Sql ORM:
- * - Database migrations
- * - Entity mapping and CRUD operations
- * - Projection queries (simple, join, aggregate)
- */
- public int main(string[] args) {
- print("=== Invercargill-Sql ORM Demo ===\n\n");
-
- // Allow optional connection string argument
- string connection_string = args.length > 1
- ? args[1]
- : "sqlite::memory:";
-
- try {
- // Create and open database connection
- var conn = ConnectionFactory.create_and_open(connection_string);
- var dialect = new SqliteDialect();
- var session = new OrmSession(conn, dialect);
-
- // --- Running Migrations ---
- print("--- Running Migrations ---\n");
- run_migrations(conn, dialect);
-
- // --- Registering Entity Mappers ---
- print("\n--- Registering Entity Mappers ---\n");
- register_entities(session);
-
- // --- Registering Projection Definitions ---
- print("Registering projection definitions...\n");
- register_projections(session);
-
- // --- Inserting Data ---
- print("\n--- Inserting Data ---\n");
- insert_sample_data(session);
-
- // --- Querying Entities ---
- print("\n--- Querying Entities ---\n");
- demonstrate_entity_queries(session);
-
- // --- Updating Data ---
- print("\n--- Updating Data ---\n");
- demonstrate_update(session);
-
- // --- Deleting Data ---
- print("\n--- Deleting Data ---\n");
- demonstrate_delete(session);
-
- // --- Querying Projections ---
- print("\n--- Querying Projections ---\n");
- demonstrate_projection_queries(session);
-
- print("\n=== Demo Complete ===\n");
-
- conn.close();
- return 0;
-
- } catch (Error e) {
- printerr("\n=== Demo failed: %s ===\n", e.message);
- return 1;
- }
- }
- void run_migrations(Connection conn, SqlDialect dialect) throws SqlError {
- var runner = new MigrationRunner(conn, dialect);
-
- // Register migrations
- runner.register_migration(new V001_CreateUsers());
- runner.register_migration(new V002_CreateProducts());
- runner.register_migration(new V003_CreateOrders());
-
- // Run all pending migrations
- runner.migrate_to_latest();
-
- // Get applied migrations count
- var applied = runner.get_applied_migrations();
- print("Applied %d migrations\n", (int)applied.length);
- }
- void register_entities(OrmSession session) throws SqlError {
- // Register User entity using static configure_mapper method
- session.register_with_schema<User>("users", User.configure_mapper);
- print("Registered User entity\n");
-
- // Register Product entity
- session.register_with_schema<Product>("products", Product.configure_mapper);
- print("Registered Product entity\n");
-
- // Register Order entity
- session.register_with_schema<Order>("orders", Order.configure_mapper);
- print("Registered Order entity\n");
- }
- void register_projections(OrmSession session) throws ProjectionError {
- // Register projections using static configure_projection methods
- session.register_projection<UserSummary>(UserSummary.configure_projection);
- session.register_projection<OrderDetail>(OrderDetail.configure_projection);
- session.register_projection<SalesReport>(SalesReport.configure_projection);
- }
- void insert_sample_data(OrmSession session) throws SqlError {
- // Insert users
- var alice = new User();
- alice.name = "Alice";
- alice.email = "alice@example.com";
- alice.age = 30;
- alice.is_active = true;
- session.insert(alice);
- print("Inserted user: %s (ID: %lld)\n", alice.name, alice.id);
-
- var bob = new User();
- bob.name = "Bob";
- bob.email = "bob@example.com";
- bob.age = 22;
- bob.is_active = true;
- session.insert(bob);
- print("Inserted user: %s (ID: %lld)\n", bob.name, bob.id);
-
- var charlie = new User();
- charlie.name = "Charlie";
- charlie.email = "charlie@example.com";
- charlie.age = 35;
- charlie.is_active = false;
- session.insert(charlie);
- print("Inserted user: %s (ID: %lld)\n", charlie.name, charlie.id);
-
- // Insert products
- var widget = new Product();
- widget.name = "Widget";
- widget.category = "Electronics";
- widget.price = 29.99;
- widget.stock = 100;
- session.insert(widget);
- print("Inserted product: %s (ID: %lld)\n", widget.name, widget.id);
-
- var gadget = new Product();
- gadget.name = "Gadget";
- gadget.category = "Electronics";
- gadget.price = 49.99;
- gadget.stock = 50;
- session.insert(gadget);
- print("Inserted product: %s (ID: %lld)\n", gadget.name, gadget.id);
-
- var doohickey = new Product();
- doohickey.name = "Doohickey";
- doohickey.category = "Accessories";
- doohickey.price = 9.99;
- doohickey.stock = 200;
- session.insert(doohickey);
- print("Inserted product: %s (ID: %lld)\n", doohickey.name, doohickey.id);
-
- // Insert orders
- int order_count = 0;
-
- // Alice orders 2 Widgets
- var order1 = create_order(alice.id, widget.id, 2, 59.98, "completed");
- session.insert(order1);
- order_count++;
-
- // Alice orders 1 Gadget
- var order2 = create_order(alice.id, gadget.id, 1, 49.99, "completed");
- session.insert(order2);
- order_count++;
-
- // Bob orders 3 Doohickeys
- var order3 = create_order(bob.id, doohickey.id, 3, 29.97, "pending");
- session.insert(order3);
- order_count++;
-
- // Charlie orders 1 Widget and 2 Gadgets
- var order4 = create_order(charlie.id, widget.id, 1, 29.99, "completed");
- session.insert(order4);
- order_count++;
-
- var order5 = create_order(charlie.id, gadget.id, 2, 99.98, "completed");
- session.insert(order5);
- order_count++;
-
- print("Inserted %d orders\n", order_count);
- }
- Order create_order(int64 user_id, int64 product_id, int64 quantity, double total, string status) {
- var order = new Order();
- order.user_id = user_id;
- order.product_id = product_id;
- order.quantity = quantity;
- order.total = total;
- order.status = status;
- order.created_at = new DateTime.now_utc();
- return order;
- }
- void demonstrate_entity_queries(OrmSession session) throws SqlError {
- // Query all users
- var all_users = session.query<User>().materialise();
- print("All users: %d\n", (int)all_users.length);
-
- // Query users over 25
- var users_over_25 = session.query<User>()
- .where("age > 25")
- .materialise();
- print("Users over 25: %d\n", (int)users_over_25.length);
-
- // Query active users ordered by age
- var active_users = session.query<User>()
- .where("is_active == 1")
- .order_by("age")
- .materialise();
-
- print("Active users ordered by age: ");
- var first = true;
- foreach (var user in active_users) {
- if (!first) print(", ");
- print("%s(%lld)", user.name, user.age);
- first = false;
- }
- print("\n");
-
- // Query with pagination
- var paged_users = session.query<User>()
- .order_by("id")
- .limit(2)
- .offset(1)
- .materialise();
- print("Users (page 2, size 2): %d\n", (int)paged_users.length);
- }
- void demonstrate_update(OrmSession session) throws SqlError {
- // Find Alice by ID
- var alice = session.query<User>()
- .where("id == 1")
- .first();
-
- if (alice != null) {
- // Update Alice's age
- alice.age = 31;
- session.update(alice);
- print("Updated %s's age to %lld\n", alice.name, alice.age);
-
- // Verify the update
- var verified = session.query<User>()
- .where("id == 1")
- .first();
- print("Verified update: %s is now %lld\n", verified.name, verified.age);
- }
- }
- void demonstrate_delete(OrmSession session) throws SqlError {
- // Find Bob by name (using age as a proxy since string comparison in expressions may not work)
- var bob = session.query<User>()
- .where("age == 22")
- .first();
-
- if (bob != null) {
- print("Deleted user: %s\n", bob.name);
- session.delete(bob);
-
- // Verify deletion
- var remaining = session.query<User>().materialise();
- print("Remaining users: %d\n", (int)remaining.length);
- }
- }
- void demonstrate_projection_queries(OrmSession session) throws SqlError, ProjectionError {
- // Simple projection - User summaries
- print("\n--- User Summaries ---\n");
- var user_summaries = session.query_projection<UserSummary>()
- .order_by("user_name")
- .materialise();
-
- foreach (var summary in user_summaries) {
- print(" [%lld] %s <%s>\n", summary.user_id, summary.user_name, summary.email);
- }
- print("Total user summaries: %d\n", (int)user_summaries.length);
-
- // Join projection - Order details
- print("\n--- Order Details ---\n");
- var order_details = session.query_projection<OrderDetail>()
- .order_by("order_id")
- .materialise();
-
- foreach (var detail in order_details) {
- print(" [%lld] %s ordered %dx %s ($%.2f) - %s\n",
- detail.order_id, detail.user_name, detail.quantity,
- detail.product_name, detail.total, detail.status);
- }
- print("Total order details: %d\n", (int)order_details.length);
-
- // Aggregate projection - Sales by category
- print("\n--- Sales by Category ---\n");
- var sales_reports = session.query_projection<SalesReport>()
- .order_by_desc("total_revenue")
- .materialise();
-
- foreach (var report in sales_reports) {
- print(" %s: %lld orders, $%.2f revenue, $%.2f avg\n",
- report.category, report.total_orders,
- report.total_revenue, report.avg_order_value);
- }
- print("Total categories: %d\n", (int)sales_reports.length);
-
- // Projection with where clause
- print("\n--- Completed Orders ---\n");
- var completed_orders = session.query_projection<OrderDetail>()
- .where("status == 'completed'")
- .materialise();
- print("Completed orders: %d\n", (int)completed_orders.length);
- }
|