# Module Service - App Database ## Overview The App Database Service provides specialized database functionality for distributed applications within the Cellframe SDK. This service offers persistent data storage, query capabilities, and database management specifically designed for decentralized applications running on the Cellframe network. *Based on: `dap_chain_net_srv_app_db.h`, `dap_chain_net_srv_app_db.c`* ## Document Structure - [[#Overview|Overview]] - [[#Database Structures|Database Structures]] - [[#Database Context|Database Context - Database connection]] - [[#Query Structure|Query Structure - Query parameters]] - [[#Database Functions|Database Functions]] - [[#Database Management|Database Management Functions]] - [[#Query Operations|Query Operations Functions]] - [[#Typical Examples|Typical Examples]] ## Database Structures ### Database Context Structure Structure for managing database connections and context. ```c typedef struct dap_chain_net_srv_app_db_context { char db_name[64]; // Database name char app_name[64]; // Associated application name dap_chain_addr_t owner_addr; // Database owner address uint64_t created_timestamp; // Creation timestamp uint64_t last_access_timestamp; // Last access timestamp bool is_active; // Database status void *db_handle; // Internal database handle pthread_mutex_t access_mutex; // Thread-safe access } dap_chain_net_srv_app_db_context_t; ``` ### Query Structure Structure for database query operations. ```c typedef struct dap_chain_net_srv_app_db_query { char query_string[2048]; // SQL query string uint32_t query_type; // Query type (SELECT, INSERT, etc.) void *parameters; // Query parameters size_t param_count; // Number of parameters uint64_t timestamp; // Query timestamp uint32_t timeout_ms; // Query timeout in milliseconds } dap_chain_net_srv_app_db_query_t; ``` ### Query Result Structure Structure for query result data. ```c typedef struct dap_chain_net_srv_app_db_result { uint32_t row_count; // Number of result rows uint32_t column_count; // Number of columns char **column_names; // Column name array void **data; // Result data array size_t data_size; // Total data size bool success; // Query success status char error_message[256]; // Error message if failed } dap_chain_net_srv_app_db_result_t; ``` ## Database Functions ### Database Management #### `dap_chain_net_srv_app_db_create()` Creates a new database for an application. ```c int dap_chain_net_srv_app_db_create( dap_chain_net_t *a_net, const char *a_app_name, const char *a_db_name, dap_chain_addr_t *a_owner_addr ); ``` **Parameters:** - `a_net` (dap_chain_net_t *) - Network context - `a_app_name` (const char *) - Application name - `a_db_name` (const char *) - Database name - `a_owner_addr` (dap_chain_addr_t *) - Owner address **Returns:** - `0` - Database created successfully - `-1` - Invalid parameters - `-2` - Database already exists - `-3` - Creation failed #### `dap_chain_net_srv_app_db_connect()` Connects to an existing database. ```c dap_chain_net_srv_app_db_context_t* dap_chain_net_srv_app_db_connect( dap_chain_net_t *a_net, const char *a_app_name, const char *a_db_name ); ``` **Parameters:** - `a_net` (dap_chain_net_t *) - Network context - `a_app_name` (const char *) - Application name - `a_db_name` (const char *) - Database name **Returns:** - Pointer to database context - `NULL` if connection failed #### `dap_chain_net_srv_app_db_disconnect()` Disconnects from a database. ```c void dap_chain_net_srv_app_db_disconnect(dap_chain_net_srv_app_db_context_t *a_context); ``` **Parameters:** - `a_context` (dap_chain_net_srv_app_db_context_t *) - Database context #### `dap_chain_net_srv_app_db_delete()` Deletes a database and all its data. ```c int dap_chain_net_srv_app_db_delete( dap_chain_net_t *a_net, const char *a_app_name, const char *a_db_name ); ``` **Parameters:** - `a_net` (dap_chain_net_t *) - Network context - `a_app_name` (const char *) - Application name - `a_db_name` (const char *) - Database name **Returns:** - `0` - Database deleted successfully - `-1` - Database not found - `-2` - Deletion failed ### Query Operations #### `dap_chain_net_srv_app_db_execute()` Executes a database query. ```c dap_chain_net_srv_app_db_result_t* dap_chain_net_srv_app_db_execute( dap_chain_net_srv_app_db_context_t *a_context, dap_chain_net_srv_app_db_query_t *a_query ); ``` **Parameters:** - `a_context` (dap_chain_net_srv_app_db_context_t *) - Database context - `a_query` (dap_chain_net_srv_app_db_query_t *) - Query to execute **Returns:** - Pointer to query result - `NULL` if execution failed #### `dap_chain_net_srv_app_db_execute_simple()` Executes a simple SQL query string. ```c dap_chain_net_srv_app_db_result_t* dap_chain_net_srv_app_db_execute_simple( dap_chain_net_srv_app_db_context_t *a_context, const char *a_sql ); ``` **Parameters:** - `a_context` (dap_chain_net_srv_app_db_context_t *) - Database context - `a_sql` (const char *) - SQL query string **Returns:** - Pointer to query result - `NULL` if execution failed #### `dap_chain_net_srv_app_db_result_free()` Frees query result memory. ```c void dap_chain_net_srv_app_db_result_free(dap_chain_net_srv_app_db_result_t *a_result); ``` **Parameters:** - `a_result` (dap_chain_net_srv_app_db_result_t *) - Result to free #### `dap_chain_net_srv_app_db_begin_transaction()` Begins a database transaction. ```c int dap_chain_net_srv_app_db_begin_transaction(dap_chain_net_srv_app_db_context_t *a_context); ``` **Parameters:** - `a_context` (dap_chain_net_srv_app_db_context_t *) - Database context **Returns:** - `0` - Transaction started successfully - Non-zero - Transaction start failed #### `dap_chain_net_srv_app_db_commit_transaction()` Commits a database transaction. ```c int dap_chain_net_srv_app_db_commit_transaction(dap_chain_net_srv_app_db_context_t *a_context); ``` **Parameters:** - `a_context` (dap_chain_net_srv_app_db_context_t *) - Database context **Returns:** - `0` - Transaction committed successfully - Non-zero - Commit failed #### `dap_chain_net_srv_app_db_rollback_transaction()` Rolls back a database transaction. ```c int dap_chain_net_srv_app_db_rollback_transaction(dap_chain_net_srv_app_db_context_t *a_context); ``` **Parameters:** - `a_context` (dap_chain_net_srv_app_db_context_t *) - Database context **Returns:** - `0` - Transaction rolled back successfully - Non-zero - Rollback failed ## Typical Examples ### Database Creation and Connection Example ```c #include <dap_chain_net_srv_app_db.h> void app_database_creation_example() { log_it_info("=== App Database Creation Example ==="); // Step 1: Setup network context dap_chain_net_t *net = dap_chain_net_by_name("backbone"); if (!net) { log_it_error("✗ Network 'backbone' not found"); return; } // Step 2: Define database parameters const char *app_name = "MyDApp"; const char *db_name = "UserData"; dap_chain_addr_t owner_addr; // Initialize owner address (example) if (dap_chain_addr_from_str(&owner_addr, "mJWQjJA4iXQ7HCZkZHgmPFNv9xAA7GV9eMUTjRdBGNBuKVaZZ3qw2k") != 0) { log_it_error("✗ Invalid owner address format"); return; } log_it_info("Database Parameters:"); log_it_info(" Application: %s", app_name); log_it_info(" Database: %s", db_name); log_it_info(" Network: %s", net->pub.name); log_it_info(" Owner: %s", dap_chain_addr_to_str(&owner_addr)); // Step 3: Create database log_it_info("--- Creating Database ---"); int create_result = dap_chain_net_srv_app_db_create( net, app_name, db_name, &owner_addr ); switch (create_result) { case 0: log_it_info("✓ Database created successfully"); break; case -1: log_it_error("✗ Invalid database parameters"); return; case -2: log_it_error("✗ Database already exists"); break; case -3: log_it_error("✗ Database creation failed"); return; default: log_it_error("✗ Unknown creation error: %d", create_result); return; } // Step 4: Connect to database log_it_info("--- Connecting to Database ---"); dap_chain_net_srv_app_db_context_t *db_context = dap_chain_net_srv_app_db_connect( net, app_name, db_name ); if (db_context) { log_it_info("✓ Database connection established"); log_it_info(" Database: %s", db_context->db_name); log_it_info(" Application: %s", db_context->app_name); log_it_info(" Status: %s", db_context->is_active ? "Active" : "Inactive"); log_it_info(" Created: %lu", db_context->created_timestamp); } else { log_it_error("✗ Database connection failed"); return; } // Step 5: Create initial tables log_it_info("--- Creating Initial Schema ---"); const char *create_table_sql = "CREATE TABLE users (" "id INTEGER PRIMARY KEY AUTOINCREMENT, " "username VARCHAR(50) NOT NULL UNIQUE, " "email VARCHAR(100) NOT NULL, " "created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP" ")"; dap_chain_net_srv_app_db_result_t *create_result_data = dap_chain_net_srv_app_db_execute_simple( db_context, create_table_sql ); if (create_result_data && create_result_data->success) { log_it_info("✓ Initial table 'users' created successfully"); } else { log_it_error("✗ Table creation failed: %s", create_result_data ? create_result_data->error_message : "Unknown error"); } // Step 6: Cleanup if (create_result_data) { dap_chain_net_srv_app_db_result_free(create_result_data); } dap_chain_net_srv_app_db_disconnect(db_context); log_it_info("✓ Database connection closed"); log_it_info("App database creation example completed"); } ``` ### Database Operations Example ```c #include <dap_chain_net_srv_app_db.h> void app_database_operations_example() { log_it_info("=== App Database Operations Example ==="); // Step 1: Connect to existing database dap_chain_net_t *net = dap_chain_net_by_name("backbone"); if (!net) { log_it_error("✗ Network not found"); return; } dap_chain_net_srv_app_db_context_t *db_context = dap_chain_net_srv_app_db_connect( net, "MyDApp", "UserData" ); if (!db_context) { log_it_error("✗ Could not connect to database"); return; } log_it_info("✓ Connected to database successfully"); // Step 2: Insert data with transaction log_it_info("--- Data Insertion with Transaction ---"); int transaction_result = dap_chain_net_srv_app_db_begin_transaction(db_context); if (transaction_result != 0) { log_it_error("✗ Failed to begin transaction"); dap_chain_net_srv_app_db_disconnect(db_context); return; } log_it_info("✓ Transaction started"); // Insert multiple users const char *insert_queries[] = { "INSERT INTO users (username, email) VALUES ('alice', '[email protected]')", "INSERT INTO users (username, email) VALUES ('bob', '[email protected]')", "INSERT INTO users (username, email) VALUES ('charlie', '[email protected]')" }; bool all_inserts_successful = true; for (int i = 0; i < 3; i++) { dap_chain_net_srv_app_db_result_t *insert_result = dap_chain_net_srv_app_db_execute_simple( db_context, insert_queries[i] ); if (insert_result && insert_result->success) { log_it_info("✓ User %d inserted successfully", i + 1); } else { log_it_error("✗ User %d insertion failed: %s", i + 1, insert_result ? insert_result->error_message : "Unknown error"); all_inserts_successful = false; } if (insert_result) { dap_chain_net_srv_app_db_result_free(insert_result); } } // Commit or rollback transaction if (all_inserts_successful) { int commit_result = dap_chain_net_srv_app_db_commit_transaction(db_context); if (commit_result == 0) { log_it_info("✓ Transaction committed successfully"); } else { log_it_error("✗ Transaction commit failed"); } } else { int rollback_result = dap_chain_net_srv_app_db_rollback_transaction(db_context); if (rollback_result == 0) { log_it_info("✓ Transaction rolled back due to errors"); } else { log_it_error("✗ Transaction rollback failed"); } } // Step 3: Query data log_it_info("--- Data Query ---"); const char *select_sql = "SELECT id, username, email, created_at FROM users ORDER BY id"; dap_chain_net_srv_app_db_result_t *select_result = dap_chain_net_srv_app_db_execute_simple( db_context, select_sql ); if (select_result && select_result->success) { log_it_info("✓ Query executed successfully"); log_it_info(" Rows returned: %u", select_result->row_count); log_it_info(" Columns: %u", select_result->column_count); // Display column headers log_it_info("Query Results:"); log_it_info("╭─────┬──────────┬─────────────────────┬─────────────────────╮"); log_it_info("│ ID │ Username │ Email │ Created At │"); log_it_info("├─────┼──────────┼─────────────────────┼─────────────────────┤"); // Display data (simulated - actual implementation would iterate through results) log_it_info("│ 1 │ alice │ [email protected] │ 2024-01-01 12:00:00 │"); log_it_info("│ 2 │ bob │ [email protected] │ 2024-01-01 12:00:01 │"); log_it_info("│ 3 │ charlie │ [email protected] │ 2024-01-01 12:00:02 │"); log_it_info("╰─────┴──────────┴─────────────────────┴─────────────────────╯"); } else { log_it_error("✗ Query execution failed: %s", select_result ? select_result->error_message : "Unknown error"); } // Step 4: Advanced query with parameters log_it_info("--- Parameterized Query ---"); dap_chain_net_srv_app_db_query_t parameterized_query = { .query_string = "SELECT * FROM users WHERE username = ? AND email LIKE ?", .query_type = 1, // SELECT type .param_count = 2, .timeout_ms = 5000 }; // In a real implementation, you would set the parameters here log_it_info("Parameterized query prepared:"); log_it_info(" SQL: %s", parameterized_query.query_string); log_it_info(" Parameters: 2 (username, email pattern)"); log_it_info(" Timeout: %u ms", parameterized_query.timeout_ms); // Step 5: Cleanup if (select_result) { dap_chain_net_srv_app_db_result_free(select_result); } dap_chain_net_srv_app_db_disconnect(db_context); log_it_info("✓ Database connection closed"); log_it_info("App database operations example completed"); } ``` --- *See also: [[Modules/Module Service|Module Service]], [[Modules/Module Service - Application|Module Service - Application]], [[ETC/Services Overview|Services Overview]]*