# Database Module New Features

This document provides an overview of the new features added to the Database module.

## Table of Contents

- [Stored Procedures and Functions](#stored-procedures-and-functions)
- [Extended Index Management](#extended-index-management)
- [Enhanced Schema Versioning](#enhanced-schema-versioning)
- [Usage Examples](#usage-examples)

## Stored Procedures and Functions

The Database module now supports defining, executing, and managing stored procedures and functions across different database systems.

### StoredProcedureDefinition

The `StoredProcedureDefinition` class provides a fluent interface for defining stored procedures:

```php
use App\Framework\Database\StoredProcedure\StoredProcedureDefinition;

$procedure = StoredProcedureDefinition::create('get_user_by_id')
    ->withParameter('user_id', 'INT')
    ->withBody('SELECT * FROM users WHERE id = user_id')
    ->returnsType('TABLE');
```

The definition can then be converted to SQL for different database systems:

```php
// Generate MySQL-specific SQL
$mysqlSql = $procedure->toSql('mysql');

// Generate PostgreSQL-specific SQL
$pgsqlSql = $procedure->toSql('pgsql');
```

### StoredProcedureManager

The `StoredProcedureManager` class provides methods for managing stored procedures:

```php
use App\Framework\Database\StoredProcedure\StoredProcedureManager;

// Create a new manager with a database connection
$manager = new StoredProcedureManager($connection);

// Create a stored procedure
$manager->createProcedure($procedure);

// Check if a procedure exists
if ($manager->procedureExists('get_user_by_id')) {
    // Execute the procedure with parameters
    $result = $manager->executeProcedure('get_user_by_id', [42]);
    
    // Process the results
    foreach ($result->fetchAll() as $row) {
        // ...
    }
}

// Execute a stored function
$value = $manager->executeFunction('calculate_order_total', [123, true]);

// Drop a procedure
$manager->dropProcedure('get_user_by_id');

// List all procedures
$procedures = $manager->listProcedures();
```

## Extended Index Management

The Database module now supports advanced index types and features across different database systems.

### AdvancedIndexDefinition

The `AdvancedIndexDefinition` class provides a fluent interface for defining advanced indexes:

```php
use App\Framework\Database\Schema\Index\AdvancedIndexDefinition;
use App\Framework\Database\Schema\Index\AdvancedIndexType;

// Create a standard index
$index = AdvancedIndexDefinition::create(
    'idx_users_email',
    ['email'],
    AdvancedIndexType::INDEX
);

// Create a partial index (only indexes rows that match a condition)
$partialIndex = AdvancedIndexDefinition::partial(
    'idx_active_users',
    ['email'],
    AdvancedIndexType::INDEX,
    'active = true'
);

// Create a functional index (indexes the result of a function)
$functionalIndex = AdvancedIndexDefinition::functional(
    'idx_lower_email',
    AdvancedIndexType::INDEX,
    ['LOWER(email)']
);

// Create a PostgreSQL GIN index (for full-text search, JSON, arrays)
$ginIndex = AdvancedIndexDefinition::gin(
    'idx_document_content',
    ['content']
);

// Create a PostgreSQL GiST index (for geometric data, ranges)
$gistIndex = AdvancedIndexDefinition::gist(
    'idx_location_position',
    ['position']
);

// Create a MySQL BTREE index with options
$btreeIndex = AdvancedIndexDefinition::btree(
    'idx_users_name',
    ['first_name', 'last_name'],
    ['fillfactor' => 70]
);
```

The index definition can then be converted to SQL for different database systems:

```php
// Generate SQL for PostgreSQL
$sql = $index->toSql('pgsql', 'users');

// Generate SQL for MySQL
$sql = $index->toSql('mysql', 'users');
```

## Enhanced Schema Versioning

The Database module now includes enhanced schema versioning capabilities, including dependency tracking and schema comparison tools.

### Schema Comparison

The schema comparison tools allow you to compare two database schemas and generate migration code to update one schema to match the other.

```php
use App\Framework\Database\Schema\Comparison\SchemaComparator;

// Create a comparator with source and target connections
$comparator = new SchemaComparator($sourceConnection, $targetConnection);

// Compare the schemas
$difference = $comparator->compare();

// Check if there are differences
if ($difference->hasDifferences()) {
    // Get a summary of the differences
    $summary = $difference->getSummary();
    
    // Get a detailed description of the differences
    $description = $difference->getDescription();
    
    // Generate migration code to update the target schema to match the source schema
    $migrationCode = $difference->generateMigrationCode('UpdateSchema');
    
    // Save the migration code to a file
    file_put_contents('database/migrations/UpdateSchema.php', $migrationCode);
}
```

### Dependent Migrations

The enhanced migration system now supports dependencies between migrations:

```php
use App\Framework\Database\ConnectionInterface;
use App\Framework\Database\Migration\AbstractDependentMigration;
use App\Framework\Database\Migration\MigrationVersion;
use App\Framework\Database\Schema\Schema;

final class CreateCommentsTable extends AbstractDependentMigration
{
    public function getVersion(): MigrationVersion
    {
        return MigrationVersion::fromString('20250805123456');
    }
    
    public function getDescription(): string
    {
        return 'Create comments table';
    }
    
    public function getDependencies(): array
    {
        // This migration depends on the CreateUsersTable and CreatePostsTable migrations
        return [
            MigrationVersion::fromString('20250805123455'), // CreateUsersTable
            MigrationVersion::fromString('20250805123454')  // CreatePostsTable
        ];
    }
    
    public function up(ConnectionInterface $connection): void
    {
        $schema = new Schema($connection);
        
        $schema->create('comments', function ($table) {
            $table->id();
            $table->text('content');
            $table->foreignId('user_id')->references('id')->on('users');
            $table->foreignId('post_id')->references('id')->on('posts');
            $table->timestamps();
        });
        
        $schema->execute();
    }
    
    public function down(ConnectionInterface $connection): void
    {
        $schema = new Schema($connection);
        $schema->dropIfExists('comments');
        $schema->execute();
    }
}
```

The migration runner will ensure that migrations are executed in the correct order based on their dependencies.

## Usage Examples

### Creating and Using a Stored Procedure

```php
use App\Framework\Database\StoredProcedure\StoredProcedureDefinition;
use App\Framework\Database\StoredProcedure\StoredProcedureManager;

// Define a stored procedure to get active users
$procedure = StoredProcedureDefinition::create('get_active_users')
    ->withParameter('min_login_count', 'INT')
    ->withBody('
        SELECT * FROM users 
        WHERE active = true AND login_count >= min_login_count
        ORDER BY last_login DESC;
    ')
    ->returnsType('TABLE');

// Create the procedure in the database
$manager = new StoredProcedureManager($connection);
$manager->createProcedure($procedure);

// Execute the procedure
$result = $manager->executeProcedure('get_active_users', [5]);

// Process the results
foreach ($result->fetchAll() as $user) {
    echo "User: {$user['name']} (Last login: {$user['last_login']})\n";
}
```

### Creating Advanced Indexes

```php
use App\Framework\Database\Schema\Index\AdvancedIndexDefinition;
use App\Framework\Database\Schema\Index\AdvancedIndexType;

// In a migration
public function up(ConnectionInterface $connection): void
{
    $schema = new Schema($connection);
    
    $schema->create('posts', function ($table) {
        $table->id();
        $table->string('title');
        $table->text('content');
        $table->boolean('published')->default(false);
        $table->timestamps();
    });
    
    $schema->execute();
    
    // Create a partial index on published posts
    $partialIndex = AdvancedIndexDefinition::partial(
        'idx_published_posts',
        ['title'],
        AdvancedIndexType::INDEX,
        'published = true'
    );
    
    // Create a functional index for case-insensitive search
    $functionalIndex = AdvancedIndexDefinition::functional(
        'idx_lower_title',
        AdvancedIndexType::INDEX,
        ['LOWER(title)']
    );
    
    // Generate and execute SQL for the current database
    $driver = $connection->getPdo()->getAttribute(\PDO::ATTR_DRIVER_NAME);
    $connection->execute($partialIndex->toSql($driver, 'posts'));
    $connection->execute($functionalIndex->toSql($driver, 'posts'));
}
```

### Comparing Schemas and Generating Migrations

```php
use App\Framework\Database\Schema\Comparison\SchemaComparator;

// Compare development and production schemas
$comparator = new SchemaComparator($devConnection, $prodConnection);
$difference = $comparator->compare();

if ($difference->hasDifferences()) {
    // Print a summary of the differences
    $summary = $difference->getSummary();
    echo "Found {$summary['total_differences']} differences:\n";
    echo "  Missing tables: {$summary['missing_tables']}\n";
    echo "  Extra tables: {$summary['extra_tables']}\n";
    echo "  Modified tables: {$summary['modified_tables']}\n";
    
    // Generate migration code
    $timestamp = date('YmdHis');
    $className = "UpdateProductionSchema{$timestamp}";
    $migrationCode = $difference->generateMigrationCode($className);
    
    // Save the migration
    $migrationPath = "database/migrations/{$className}.php";
    file_put_contents($migrationPath, $migrationCode);
    
    echo "Generated migration: {$migrationPath}\n";
}
```
