add postgres example instructions
This commit is contained in:
		
							
								
								
									
										73
									
								
								heromodels/examples/postgres_example/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								heromodels/examples/postgres_example/README.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,73 @@
 | 
			
		||||
# PostgreSQL Model Example
 | 
			
		||||
 | 
			
		||||
This example demonstrates the Hero Models framework's PostgreSQL integration capabilities, showcasing how to create, store, retrieve, and manage models in a PostgreSQL database.
 | 
			
		||||
 | 
			
		||||
## Quick Setup
 | 
			
		||||
 | 
			
		||||
**Automated Setup (Recommended):**
 | 
			
		||||
```bash
 | 
			
		||||
./setup.sh
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The setup script will automatically:
 | 
			
		||||
- Detect your operating system (macOS, Ubuntu/Debian, CentOS/RHEL)
 | 
			
		||||
- Install PostgreSQL if not already installed
 | 
			
		||||
- Start the PostgreSQL service
 | 
			
		||||
- Create the required database user with password
 | 
			
		||||
- Test the database connection
 | 
			
		||||
- Configure PATH (macOS only)
 | 
			
		||||
 | 
			
		||||
**Manual Setup:**
 | 
			
		||||
If you prefer to set up PostgreSQL manually, the example expects:
 | 
			
		||||
- PostgreSQL server running on `localhost:5432`
 | 
			
		||||
- Username: `postgres`
 | 
			
		||||
- Password: `test123`
 | 
			
		||||
 | 
			
		||||
## What This Example Demonstrates
 | 
			
		||||
 | 
			
		||||
### Core Features
 | 
			
		||||
1. **Model Creation** - Creating User and Comment models with the Hero Models framework
 | 
			
		||||
2. **Database Operations** - Storing, retrieving, updating, and deleting records
 | 
			
		||||
3. **Indexing** - Using username and active status indexes for efficient queries
 | 
			
		||||
4. **Relationships** - Associating comments with users
 | 
			
		||||
5. **Connection Management** - PostgreSQL connection pooling and configuration
 | 
			
		||||
 | 
			
		||||
### Specific Operations
 | 
			
		||||
- **User Management**: Create users with different attributes (username, email, active status)
 | 
			
		||||
- **Index Queries**: Retrieve users by username and filter by active status
 | 
			
		||||
- **Data Deletion**: Remove users and see the impact on queries
 | 
			
		||||
- **Comment System**: Create comments and associate them with users
 | 
			
		||||
- **Model Introspection**: Display model information and database prefixes
 | 
			
		||||
 | 
			
		||||
## Running the Example
 | 
			
		||||
 | 
			
		||||
From the heromodels root directory:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
cargo run --example postgres_model_example
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Expected Output
 | 
			
		||||
 | 
			
		||||
The example will:
 | 
			
		||||
1. Create 4 sample users with different attributes
 | 
			
		||||
2. Display all users retrieved from the database
 | 
			
		||||
3. Demonstrate index-based queries (by username and active status)
 | 
			
		||||
4. Delete a user and show the updated results
 | 
			
		||||
5. Create and associate comments with users
 | 
			
		||||
6. Display model metadata information
 | 
			
		||||
 | 
			
		||||
## Code Structure
 | 
			
		||||
 | 
			
		||||
- **Database Configuration**: Sets up PostgreSQL connection with credentials
 | 
			
		||||
- **Model Creation**: Uses fluent builder pattern for creating User and Comment instances
 | 
			
		||||
- **Database Operations**: Demonstrates CRUD operations using the Hero Models API
 | 
			
		||||
- **Index Usage**: Shows how to query using predefined indexes
 | 
			
		||||
- **Error Handling**: Proper error handling for database operations
 | 
			
		||||
 | 
			
		||||
## Key Technologies
 | 
			
		||||
 | 
			
		||||
- **Hero Models Framework**: Core ORM-like functionality
 | 
			
		||||
- **PostgreSQL**: Database backend with connection pooling
 | 
			
		||||
- **Rust**: Type-safe model definitions and operations
 | 
			
		||||
- **Serde**: JSON serialization/deserialization for database storage
 | 
			
		||||
							
								
								
									
										249
									
								
								heromodels/examples/postgres_example/example.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										249
									
								
								heromodels/examples/postgres_example/example.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,249 @@
 | 
			
		||||
use heromodels::db::postgres::Config;
 | 
			
		||||
use heromodels::db::{Collection, Db};
 | 
			
		||||
use heromodels::models::userexample::user::user_index::{is_active, username};
 | 
			
		||||
use heromodels::models::{Comment, User};
 | 
			
		||||
use heromodels_core::Model;
 | 
			
		||||
 | 
			
		||||
// Helper function to print user details
 | 
			
		||||
fn print_user_details(user: &User) {
 | 
			
		||||
    println!("\n--- User Details ---");
 | 
			
		||||
    println!("ID: {}", user.get_id());
 | 
			
		||||
    println!("Username: {}", user.username);
 | 
			
		||||
    println!("Email: {}", user.email);
 | 
			
		||||
    println!("Full Name: {}", user.full_name);
 | 
			
		||||
    println!("Active: {}", user.is_active);
 | 
			
		||||
    println!("Created At: {}", user.base_data.created_at);
 | 
			
		||||
    println!("Modified At: {}", user.base_data.modified_at);
 | 
			
		||||
    println!("Comments: {:?}", user.base_data.comments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Helper function to print comment details
 | 
			
		||||
fn print_comment_details(comment: &Comment) {
 | 
			
		||||
    println!("\n--- Comment Details ---");
 | 
			
		||||
    println!("ID: {}", comment.get_id());
 | 
			
		||||
    println!("User ID: {}", comment.user_id);
 | 
			
		||||
    println!("Content: {}", comment.content);
 | 
			
		||||
    println!("Created At: {}", comment.base_data.created_at);
 | 
			
		||||
    println!("Modified At: {}", comment.base_data.modified_at);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn main() {
 | 
			
		||||
    let db = heromodels::db::postgres::Postgres::new(
 | 
			
		||||
        Config::new()
 | 
			
		||||
            .user(Some("postgres".into()))
 | 
			
		||||
            .password(Some("test123".into()))
 | 
			
		||||
            .host(Some("localhost".into()))
 | 
			
		||||
            .port(Some(5432)),
 | 
			
		||||
    )
 | 
			
		||||
    .expect("Can connect to postgress");
 | 
			
		||||
 | 
			
		||||
    println!("Hero Models - Basic Usage Example");
 | 
			
		||||
    println!("================================");
 | 
			
		||||
 | 
			
		||||
    // Clean up any existing data to ensure consistent results
 | 
			
		||||
    println!("Cleaning up existing data...");
 | 
			
		||||
    let user_collection = db.collection::<User>().expect("can open user collection");
 | 
			
		||||
    let comment_collection = db.collection::<Comment>().expect("can open comment collection");
 | 
			
		||||
    
 | 
			
		||||
    // Clear all existing users and comments
 | 
			
		||||
    if let Ok(existing_users) = user_collection.get_all() {
 | 
			
		||||
        for user in existing_users {
 | 
			
		||||
            let _ = user_collection.delete_by_id(user.get_id());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if let Ok(existing_comments) = comment_collection.get_all() {
 | 
			
		||||
        for comment in existing_comments {
 | 
			
		||||
            let _ = comment_collection.delete_by_id(comment.get_id());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    println!("Database cleaned.\n");
 | 
			
		||||
 | 
			
		||||
    // Create users with auto-generated IDs
 | 
			
		||||
 | 
			
		||||
    // User 1
 | 
			
		||||
    let user1 = User::new()
 | 
			
		||||
        .username("johndoe")
 | 
			
		||||
        .email("john.doe@example.com")
 | 
			
		||||
        .full_name("John Doe")
 | 
			
		||||
        .is_active(false)
 | 
			
		||||
        .build();
 | 
			
		||||
 | 
			
		||||
    // User 2
 | 
			
		||||
    let user2 = User::new()
 | 
			
		||||
        .username("janesmith")
 | 
			
		||||
        .email("jane.smith@example.com")
 | 
			
		||||
        .full_name("Jane Smith")
 | 
			
		||||
        .is_active(true)
 | 
			
		||||
        .build();
 | 
			
		||||
 | 
			
		||||
    // User 3
 | 
			
		||||
    let user3 = User::new()
 | 
			
		||||
        .username("willism")
 | 
			
		||||
        .email("willis.masters@example.com")
 | 
			
		||||
        .full_name("Willis Masters")
 | 
			
		||||
        .is_active(true)
 | 
			
		||||
        .build();
 | 
			
		||||
 | 
			
		||||
    // User 4
 | 
			
		||||
    let user4 = User::new()
 | 
			
		||||
        .username("carrols")
 | 
			
		||||
        .email("carrol.smith@example.com")
 | 
			
		||||
        .full_name("Carrol Smith")
 | 
			
		||||
        .is_active(false)
 | 
			
		||||
        .build();
 | 
			
		||||
 | 
			
		||||
    // Save all users to database and get their assigned IDs and updated models
 | 
			
		||||
    let (user1_id, db_user1) = db
 | 
			
		||||
        .collection()
 | 
			
		||||
        .expect("can open user collection")
 | 
			
		||||
        .set(&user1)
 | 
			
		||||
        .expect("can set user");
 | 
			
		||||
    let (user2_id, db_user2) = db
 | 
			
		||||
        .collection()
 | 
			
		||||
        .expect("can open user collection")
 | 
			
		||||
        .set(&user2)
 | 
			
		||||
        .expect("can set user");
 | 
			
		||||
    let (user3_id, db_user3) = db
 | 
			
		||||
        .collection()
 | 
			
		||||
        .expect("can open user collection")
 | 
			
		||||
        .set(&user3)
 | 
			
		||||
        .expect("can set user");
 | 
			
		||||
    let (user4_id, db_user4) = db
 | 
			
		||||
        .collection()
 | 
			
		||||
        .expect("can open user collection")
 | 
			
		||||
        .set(&user4)
 | 
			
		||||
        .expect("can set user");
 | 
			
		||||
 | 
			
		||||
    println!("User 1 assigned ID: {user1_id}");
 | 
			
		||||
    println!("User 2 assigned ID: {user2_id}");
 | 
			
		||||
    println!("User 3 assigned ID: {user3_id}");
 | 
			
		||||
    println!("User 4 assigned ID: {user4_id}");
 | 
			
		||||
 | 
			
		||||
    // We already have the updated models from the set method, so we don't need to retrieve them again
 | 
			
		||||
 | 
			
		||||
    // Print all users retrieved from database
 | 
			
		||||
    println!("\n--- Users Retrieved from Database ---");
 | 
			
		||||
    println!("\n1. First user:");
 | 
			
		||||
    print_user_details(&db_user1);
 | 
			
		||||
 | 
			
		||||
    println!("\n2. Second user:");
 | 
			
		||||
    print_user_details(&db_user2);
 | 
			
		||||
 | 
			
		||||
    println!("\n3. Third user:");
 | 
			
		||||
    print_user_details(&db_user3);
 | 
			
		||||
 | 
			
		||||
    println!("\n4. Fourth user:");
 | 
			
		||||
    print_user_details(&db_user4);
 | 
			
		||||
 | 
			
		||||
    // Demonstrate different ways to retrieve users from the database
 | 
			
		||||
 | 
			
		||||
    // 1. Retrieve by username index
 | 
			
		||||
    println!("\n--- Retrieving Users by Different Methods ---");
 | 
			
		||||
    println!("\n1. By Username Index:");
 | 
			
		||||
    let stored_users = db
 | 
			
		||||
        .collection::<User>()
 | 
			
		||||
        .expect("can open user collection")
 | 
			
		||||
        .get::<username, _>("johndoe")
 | 
			
		||||
        .expect("can load stored user");
 | 
			
		||||
 | 
			
		||||
    assert_eq!(stored_users.len(), 1);
 | 
			
		||||
    print_user_details(&stored_users[0]);
 | 
			
		||||
 | 
			
		||||
    // 2. Retrieve by active status
 | 
			
		||||
    println!("\n2. By Active Status (Active = true):");
 | 
			
		||||
    let active_users = db
 | 
			
		||||
        .collection::<User>()
 | 
			
		||||
        .expect("can open user collection")
 | 
			
		||||
        .get::<is_active, _>(&true)
 | 
			
		||||
        .expect("can load stored users");
 | 
			
		||||
 | 
			
		||||
    assert_eq!(active_users.len(), 2);
 | 
			
		||||
    for active_user in active_users.iter() {
 | 
			
		||||
        print_user_details(active_user);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 3. Delete a user and show the updated results
 | 
			
		||||
    println!("\n3. After Deleting a User:");
 | 
			
		||||
    let user_to_delete_id = active_users[0].get_id();
 | 
			
		||||
    println!("Deleting user with ID: {user_to_delete_id}");
 | 
			
		||||
    db.collection::<User>()
 | 
			
		||||
        .expect("can open user collection")
 | 
			
		||||
        .delete_by_id(user_to_delete_id)
 | 
			
		||||
        .expect("can delete existing user");
 | 
			
		||||
 | 
			
		||||
    // Show remaining active users
 | 
			
		||||
    let active_users = db
 | 
			
		||||
        .collection::<User>()
 | 
			
		||||
        .expect("can open user collection")
 | 
			
		||||
        .get::<is_active, _>(&true)
 | 
			
		||||
        .expect("can load stored users");
 | 
			
		||||
 | 
			
		||||
    println!("   a. Remaining Active Users:");
 | 
			
		||||
    assert_eq!(active_users.len(), 1);
 | 
			
		||||
    for active_user in active_users.iter() {
 | 
			
		||||
        print_user_details(active_user);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Show inactive users
 | 
			
		||||
    let inactive_users = db
 | 
			
		||||
        .collection::<User>()
 | 
			
		||||
        .expect("can open user collection")
 | 
			
		||||
        .get::<is_active, _>(&false)
 | 
			
		||||
        .expect("can load stored users");
 | 
			
		||||
 | 
			
		||||
    println!("   b. Inactive Users:");
 | 
			
		||||
    assert_eq!(inactive_users.len(), 2);
 | 
			
		||||
    for inactive_user in inactive_users.iter() {
 | 
			
		||||
        print_user_details(inactive_user);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Delete a user based on an index for good measure
 | 
			
		||||
    db.collection::<User>()
 | 
			
		||||
        .expect("can open user collection")
 | 
			
		||||
        .delete::<username, _>("janesmith")
 | 
			
		||||
        .expect("can delete existing user");
 | 
			
		||||
 | 
			
		||||
    println!("\n--- User Model Information ---");
 | 
			
		||||
    println!("User DB Prefix: {}", User::db_prefix());
 | 
			
		||||
 | 
			
		||||
    // Demonstrate comment creation and association with a user
 | 
			
		||||
    println!("\n--- Working with Comments ---");
 | 
			
		||||
 | 
			
		||||
    // 1. Create and save a comment
 | 
			
		||||
    println!("\n1. Creating a Comment:");
 | 
			
		||||
    let comment = Comment::new()
 | 
			
		||||
        .user_id(db_user1.get_id()) // commenter's user ID
 | 
			
		||||
        .content("This is a comment on the user")
 | 
			
		||||
        .build();
 | 
			
		||||
 | 
			
		||||
    // Save the comment and get its assigned ID and updated model
 | 
			
		||||
    let (comment_id, db_comment) = db
 | 
			
		||||
        .collection()
 | 
			
		||||
        .expect("can open comment collection")
 | 
			
		||||
        .set(&comment)
 | 
			
		||||
        .expect("can set comment");
 | 
			
		||||
 | 
			
		||||
    println!("Comment assigned ID: {comment_id}");
 | 
			
		||||
 | 
			
		||||
    println!("   a. Comment Retrieved from Database:");
 | 
			
		||||
    print_comment_details(&db_comment);
 | 
			
		||||
 | 
			
		||||
    // 3. Associate the comment with a user
 | 
			
		||||
    println!("\n2. Associating Comment with User:");
 | 
			
		||||
    let mut updated_user = db_user1.clone();
 | 
			
		||||
    updated_user.base_data.add_comment(db_comment.get_id());
 | 
			
		||||
 | 
			
		||||
    // Save the updated user and get the new version
 | 
			
		||||
    let (_, user_with_comment) = db
 | 
			
		||||
        .collection::<User>()
 | 
			
		||||
        .expect("can open user collection")
 | 
			
		||||
        .set(&updated_user)
 | 
			
		||||
        .expect("can set updated user");
 | 
			
		||||
 | 
			
		||||
    println!("   a. User with Associated Comment:");
 | 
			
		||||
    print_user_details(&user_with_comment);
 | 
			
		||||
 | 
			
		||||
    println!("\n--- Model Information ---");
 | 
			
		||||
    println!("User DB Prefix: {}", User::db_prefix());
 | 
			
		||||
    println!("Comment DB Prefix: {}", Comment::db_prefix());
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										337
									
								
								heromodels/examples/postgres_example/setup.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										337
									
								
								heromodels/examples/postgres_example/setup.sh
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,337 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
# PostgreSQL Setup Script for Hero Models Example
 | 
			
		||||
# This script checks for PostgreSQL installation and sets up the required database configuration
 | 
			
		||||
 | 
			
		||||
set -e  # Exit on any error
 | 
			
		||||
 | 
			
		||||
echo "🚀 Hero Models PostgreSQL Example Setup"
 | 
			
		||||
echo "========================================"
 | 
			
		||||
 | 
			
		||||
# Colors for output
 | 
			
		||||
RED='\033[0;31m'
 | 
			
		||||
GREEN='\033[0;32m'
 | 
			
		||||
YELLOW='\033[1;33m'
 | 
			
		||||
BLUE='\033[0;34m'
 | 
			
		||||
NC='\033[0m' # No Color
 | 
			
		||||
 | 
			
		||||
# Function to print colored output
 | 
			
		||||
print_status() {
 | 
			
		||||
    echo -e "${BLUE}[INFO]${NC} $1"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
print_success() {
 | 
			
		||||
    echo -e "${GREEN}[SUCCESS]${NC} $1"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
print_warning() {
 | 
			
		||||
    echo -e "${YELLOW}[WARNING]${NC} $1"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
print_error() {
 | 
			
		||||
    echo -e "${RED}[ERROR]${NC} $1"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Detect operating system
 | 
			
		||||
detect_os() {
 | 
			
		||||
    if [[ "$OSTYPE" == "darwin"* ]]; then
 | 
			
		||||
        echo "macos"
 | 
			
		||||
    elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
 | 
			
		||||
        if command -v apt-get &> /dev/null; then
 | 
			
		||||
            echo "ubuntu"
 | 
			
		||||
        elif command -v yum &> /dev/null; then
 | 
			
		||||
            echo "centos"
 | 
			
		||||
        else
 | 
			
		||||
            echo "linux"
 | 
			
		||||
        fi
 | 
			
		||||
    else
 | 
			
		||||
        echo "unknown"
 | 
			
		||||
    fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Check if PostgreSQL is installed
 | 
			
		||||
check_postgres_installed() {
 | 
			
		||||
    # Check if PostgreSQL is in current PATH
 | 
			
		||||
    if command -v postgres &> /dev/null || command -v psql &> /dev/null; then
 | 
			
		||||
        return 0
 | 
			
		||||
    fi
 | 
			
		||||
    
 | 
			
		||||
    # Check macOS Homebrew installation location
 | 
			
		||||
    if [[ $(detect_os) == "macos" ]]; then
 | 
			
		||||
        if [[ -f "/opt/homebrew/opt/postgresql@15/bin/postgres" ]] || [[ -f "/opt/homebrew/opt/postgresql@15/bin/psql" ]]; then
 | 
			
		||||
            return 0
 | 
			
		||||
        fi
 | 
			
		||||
        # Also check Intel Mac location
 | 
			
		||||
        if [[ -f "/usr/local/opt/postgresql@15/bin/postgres" ]] || [[ -f "/usr/local/opt/postgresql@15/bin/psql" ]]; then
 | 
			
		||||
            return 0
 | 
			
		||||
        fi
 | 
			
		||||
    fi
 | 
			
		||||
    
 | 
			
		||||
    return 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Install PostgreSQL based on OS
 | 
			
		||||
install_postgres() {
 | 
			
		||||
    local os=$(detect_os)
 | 
			
		||||
    
 | 
			
		||||
    case $os in
 | 
			
		||||
        "macos")
 | 
			
		||||
            print_status "Installing PostgreSQL on macOS using Homebrew..."
 | 
			
		||||
            if ! command -v brew &> /dev/null; then
 | 
			
		||||
                print_error "Homebrew is not installed. Please install Homebrew first:"
 | 
			
		||||
                echo "  /bin/bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\""
 | 
			
		||||
                exit 1
 | 
			
		||||
            fi
 | 
			
		||||
            brew install postgresql@15
 | 
			
		||||
            print_success "PostgreSQL installed successfully"
 | 
			
		||||
            ;;
 | 
			
		||||
        "ubuntu")
 | 
			
		||||
            print_status "Installing PostgreSQL on Ubuntu/Debian..."
 | 
			
		||||
            sudo apt-get update
 | 
			
		||||
            sudo apt-get install -y postgresql postgresql-contrib
 | 
			
		||||
            print_success "PostgreSQL installed successfully"
 | 
			
		||||
            ;;
 | 
			
		||||
        "centos")
 | 
			
		||||
            print_status "Installing PostgreSQL on CentOS/RHEL..."
 | 
			
		||||
            sudo yum install -y postgresql-server postgresql-contrib
 | 
			
		||||
            sudo postgresql-setup initdb
 | 
			
		||||
            print_success "PostgreSQL installed successfully"
 | 
			
		||||
            ;;
 | 
			
		||||
        *)
 | 
			
		||||
            print_error "Unsupported operating system: $os"
 | 
			
		||||
            print_error "Please install PostgreSQL manually and run this script again"
 | 
			
		||||
            exit 1
 | 
			
		||||
            ;;
 | 
			
		||||
    esac
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Start PostgreSQL service
 | 
			
		||||
start_postgres() {
 | 
			
		||||
    local os=$(detect_os)
 | 
			
		||||
    
 | 
			
		||||
    case $os in
 | 
			
		||||
        "macos")
 | 
			
		||||
            print_status "Starting PostgreSQL service on macOS..."
 | 
			
		||||
            brew services start postgresql@15
 | 
			
		||||
            # Add PostgreSQL to PATH for this session
 | 
			
		||||
            export PATH="/opt/homebrew/opt/postgresql@15/bin:$PATH"
 | 
			
		||||
            print_success "PostgreSQL service started"
 | 
			
		||||
            ;;
 | 
			
		||||
        "ubuntu")
 | 
			
		||||
            print_status "Starting PostgreSQL service on Ubuntu/Debian..."
 | 
			
		||||
            sudo systemctl start postgresql
 | 
			
		||||
            sudo systemctl enable postgresql
 | 
			
		||||
            print_success "PostgreSQL service started and enabled"
 | 
			
		||||
            ;;
 | 
			
		||||
        "centos")
 | 
			
		||||
            print_status "Starting PostgreSQL service on CentOS/RHEL..."
 | 
			
		||||
            sudo systemctl start postgresql
 | 
			
		||||
            sudo systemctl enable postgresql
 | 
			
		||||
            print_success "PostgreSQL service started and enabled"
 | 
			
		||||
            ;;
 | 
			
		||||
    esac
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Check if PostgreSQL is running
 | 
			
		||||
check_postgres_running() {
 | 
			
		||||
    local os=$(detect_os)
 | 
			
		||||
    
 | 
			
		||||
    # Ensure PostgreSQL binaries are in PATH for macOS
 | 
			
		||||
    if [[ $os == "macos" ]]; then
 | 
			
		||||
        export PATH="/opt/homebrew/opt/postgresql@15/bin:$PATH"
 | 
			
		||||
    fi
 | 
			
		||||
    
 | 
			
		||||
    if pg_isready -h localhost -p 5432 &> /dev/null; then
 | 
			
		||||
        return 0
 | 
			
		||||
    else
 | 
			
		||||
        return 1
 | 
			
		||||
    fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Setup database user and password
 | 
			
		||||
setup_database() {
 | 
			
		||||
    print_status "Setting up database user and password..."
 | 
			
		||||
    
 | 
			
		||||
    local os=$(detect_os)
 | 
			
		||||
    
 | 
			
		||||
    # Ensure PostgreSQL binaries are in PATH for macOS
 | 
			
		||||
    if [[ $os == "macos" ]]; then
 | 
			
		||||
        export PATH="/opt/homebrew/opt/postgresql@15/bin:$PATH"
 | 
			
		||||
    fi
 | 
			
		||||
    
 | 
			
		||||
    # Create postgres user if it doesn't exist (mainly for macOS)
 | 
			
		||||
    if ! psql -U postgres -c '\q' &> /dev/null; then
 | 
			
		||||
        print_status "Creating postgres user..."
 | 
			
		||||
        if [[ $os == "macos" ]]; then
 | 
			
		||||
            createuser -s postgres 2>/dev/null || true
 | 
			
		||||
        else
 | 
			
		||||
            sudo -u postgres createuser -s postgres 2>/dev/null || true
 | 
			
		||||
        fi
 | 
			
		||||
    fi
 | 
			
		||||
    
 | 
			
		||||
    # Set password for postgres user
 | 
			
		||||
    print_status "Setting password for postgres user..."
 | 
			
		||||
    if [[ $os == "macos" ]]; then
 | 
			
		||||
        psql -U postgres -c "ALTER USER postgres PASSWORD 'test123';" 2>/dev/null || {
 | 
			
		||||
            print_warning "Could not set password directly. Trying alternative method..."
 | 
			
		||||
            createdb -U postgres postgres 2>/dev/null || true
 | 
			
		||||
            psql -U postgres -d postgres -c "ALTER USER postgres PASSWORD 'test123';" || {
 | 
			
		||||
                print_error "Failed to set password. You may need to set it manually:"
 | 
			
		||||
                echo "  psql -U postgres -c \"ALTER USER postgres PASSWORD 'test123';\""
 | 
			
		||||
                return 1
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    else
 | 
			
		||||
        sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'test123';" || {
 | 
			
		||||
            print_error "Failed to set password. You may need to set it manually:"
 | 
			
		||||
            echo "  sudo -u postgres psql -c \"ALTER USER postgres PASSWORD 'test123';\""
 | 
			
		||||
            return 1
 | 
			
		||||
        }
 | 
			
		||||
    fi
 | 
			
		||||
    
 | 
			
		||||
    print_success "Database user configured successfully"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Test database connection
 | 
			
		||||
test_connection() {
 | 
			
		||||
    print_status "Testing database connection..."
 | 
			
		||||
    
 | 
			
		||||
    local os=$(detect_os)
 | 
			
		||||
    if [[ $os == "macos" ]]; then
 | 
			
		||||
        export PATH="/opt/homebrew/opt/postgresql@15/bin:$PATH"
 | 
			
		||||
    fi
 | 
			
		||||
    
 | 
			
		||||
    if PGPASSWORD=test123 psql -h localhost -p 5432 -U postgres -d postgres -c "SELECT version();" &> /dev/null; then
 | 
			
		||||
        print_success "Database connection test successful!"
 | 
			
		||||
        return 0
 | 
			
		||||
    else
 | 
			
		||||
        print_error "Database connection test failed"
 | 
			
		||||
        return 1
 | 
			
		||||
    fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Add PATH export to shell profile (macOS only)
 | 
			
		||||
setup_path_macos() {
 | 
			
		||||
    if [[ $(detect_os) == "macos" ]]; then
 | 
			
		||||
        local shell_profile=""
 | 
			
		||||
        if [[ $SHELL == *"zsh"* ]]; then
 | 
			
		||||
            shell_profile="$HOME/.zshrc"
 | 
			
		||||
        elif [[ $SHELL == *"bash"* ]]; then
 | 
			
		||||
            shell_profile="$HOME/.bash_profile"
 | 
			
		||||
        fi
 | 
			
		||||
        
 | 
			
		||||
        if [[ -n $shell_profile ]]; then
 | 
			
		||||
            local path_export='export PATH="/opt/homebrew/opt/postgresql@15/bin:$PATH"'
 | 
			
		||||
            if ! grep -q "$path_export" "$shell_profile" 2>/dev/null; then
 | 
			
		||||
                print_status "Adding PostgreSQL to PATH in $shell_profile..."
 | 
			
		||||
                echo "" >> "$shell_profile"
 | 
			
		||||
                echo "# PostgreSQL" >> "$shell_profile"
 | 
			
		||||
                echo "$path_export" >> "$shell_profile"
 | 
			
		||||
                print_success "PostgreSQL added to PATH. Restart your terminal or run: source $shell_profile"
 | 
			
		||||
            fi
 | 
			
		||||
        fi
 | 
			
		||||
    fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Prompt user for installation
 | 
			
		||||
prompt_install() {
 | 
			
		||||
    echo ""
 | 
			
		||||
    print_warning "PostgreSQL is not installed on your system."
 | 
			
		||||
    echo ""
 | 
			
		||||
    print_status "The Hero Models example requires PostgreSQL to be installed and configured."
 | 
			
		||||
    echo ""
 | 
			
		||||
    echo "Options:"
 | 
			
		||||
    echo "  1. Let this script install PostgreSQL automatically"
 | 
			
		||||
    echo "  2. Install PostgreSQL manually and run this script again"
 | 
			
		||||
    echo ""
 | 
			
		||||
    read -p "Would you like this script to install PostgreSQL for you? (y/n): " -n 1 -r
 | 
			
		||||
    echo ""
 | 
			
		||||
    
 | 
			
		||||
    if [[ $REPLY =~ ^[Yy]$ ]]; then
 | 
			
		||||
        return 0  # User wants automatic installation
 | 
			
		||||
    else
 | 
			
		||||
        return 1  # User wants manual installation
 | 
			
		||||
    fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Main setup process
 | 
			
		||||
main() {
 | 
			
		||||
    echo ""
 | 
			
		||||
    
 | 
			
		||||
    # Check if PostgreSQL is already installed
 | 
			
		||||
    if check_postgres_installed; then
 | 
			
		||||
        print_success "PostgreSQL is already installed"
 | 
			
		||||
    else
 | 
			
		||||
        if prompt_install; then
 | 
			
		||||
            print_status "Installing PostgreSQL..."
 | 
			
		||||
            install_postgres
 | 
			
		||||
        else
 | 
			
		||||
            print_status "Please install PostgreSQL manually and run this script again."
 | 
			
		||||
            echo ""
 | 
			
		||||
            print_status "Manual installation instructions:"
 | 
			
		||||
            local os=$(detect_os)
 | 
			
		||||
            case $os in
 | 
			
		||||
                "macos")
 | 
			
		||||
                    echo "  brew install postgresql@15"
 | 
			
		||||
                    echo "  brew services start postgresql@15"
 | 
			
		||||
                    ;;
 | 
			
		||||
                "ubuntu")
 | 
			
		||||
                    echo "  sudo apt-get update"
 | 
			
		||||
                    echo "  sudo apt-get install postgresql postgresql-contrib"
 | 
			
		||||
                    echo "  sudo systemctl start postgresql"
 | 
			
		||||
                    ;;
 | 
			
		||||
                "centos")
 | 
			
		||||
                    echo "  sudo yum install postgresql-server postgresql-contrib"
 | 
			
		||||
                    echo "  sudo postgresql-setup initdb"
 | 
			
		||||
                    echo "  sudo systemctl start postgresql"
 | 
			
		||||
                    ;;
 | 
			
		||||
                *)
 | 
			
		||||
                    echo "  Please install PostgreSQL using your system's package manager"
 | 
			
		||||
                    ;;
 | 
			
		||||
            esac
 | 
			
		||||
            echo ""
 | 
			
		||||
            exit 0
 | 
			
		||||
        fi
 | 
			
		||||
    fi
 | 
			
		||||
    
 | 
			
		||||
    # Start PostgreSQL service
 | 
			
		||||
    print_status "Checking PostgreSQL service status..."
 | 
			
		||||
    if ! check_postgres_running; then
 | 
			
		||||
        print_status "PostgreSQL is not running. Starting service..."
 | 
			
		||||
        start_postgres
 | 
			
		||||
        sleep 2  # Give service time to start
 | 
			
		||||
    else
 | 
			
		||||
        print_success "PostgreSQL service is already running"
 | 
			
		||||
    fi
 | 
			
		||||
    
 | 
			
		||||
    # Setup database user and password
 | 
			
		||||
    setup_database
 | 
			
		||||
    
 | 
			
		||||
    # Test the connection
 | 
			
		||||
    if test_connection; then
 | 
			
		||||
        print_success "Setup completed successfully!"
 | 
			
		||||
    else
 | 
			
		||||
        print_error "Setup completed but connection test failed"
 | 
			
		||||
        print_error "You may need to manually configure the database"
 | 
			
		||||
        exit 1
 | 
			
		||||
    fi
 | 
			
		||||
    
 | 
			
		||||
    # Setup PATH for macOS
 | 
			
		||||
    setup_path_macos
 | 
			
		||||
    
 | 
			
		||||
    echo ""
 | 
			
		||||
    print_success "🎉 PostgreSQL setup complete!"
 | 
			
		||||
    echo ""
 | 
			
		||||
    print_status "You can now run the example with:"
 | 
			
		||||
    echo "  cargo run --example postgres_model_example"
 | 
			
		||||
    echo ""
 | 
			
		||||
    print_status "Database configuration:"
 | 
			
		||||
    echo "  Host: localhost"
 | 
			
		||||
    echo "  Port: 5432"
 | 
			
		||||
    echo "  Username: postgres"
 | 
			
		||||
    echo "  Password: test123"
 | 
			
		||||
    echo ""
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Run main function
 | 
			
		||||
main "$@"
 | 
			
		||||
		Reference in New Issue
	
	Block a user