seeder db
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m46s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 18s
Build, Push and Deploy / deploy-staging (push) Successful in 45s
Build, Push and Deploy / deploy-production (push) Has been skipped

This commit is contained in:
2026-04-13 09:24:39 +07:00
parent 4e58905bf7
commit de510a05f1
4 changed files with 3045 additions and 1 deletions

View File

@@ -0,0 +1,201 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Log;
class InitialDataSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
$sqlPath = base_path('db/kulakposmysql.sql');
if (!File::exists($sqlPath)) {
$this->command->error("SQL file not found at: {$sqlPath}");
return;
}
$this->command->info("Starting initial data import from: {$sqlPath}");
// Disable foreign key checks for PostgreSQL
if (DB::getDriverName() === 'pgsql') {
DB::statement("SET session_replication_role = 'replica';");
} else {
DB::statement('SET FOREIGN_KEY_CHECKS=0;');
}
$handle = fopen($sqlPath, "r");
if ($handle) {
$currentTable = null;
$insertCount = 0;
$tableColumnMap = [];
while (($line = fgets($handle)) !== false) {
$line = trim($line);
// Detect CREATE TABLE statement to extract column order
if (preg_match('/^CREATE TABLE `(.+?)`/i', $line, $matches)) {
$currentTable = $matches[1];
$tableColumnMap[$currentTable] = [];
continue;
}
// If we are inside a CREATE TABLE block, look for column definitions
if ($currentTable && preg_match('/^\s*`(.+?)`/i', $line, $colMatches)) {
$tableColumnMap[$currentTable][] = $colMatches[1];
}
// End of CREATE TABLE block
if ($currentTable && strpos($line, ') ENGINE') !== false) {
$currentTable = null;
}
// Detect INSERT INTO statement
if (preg_match('/^INSERT INTO `(.+?)` VALUES\s*\((.*)\);$/i', $line, $matches)) {
$tableName = $matches[1];
$valuesStr = $matches[2];
$values = $this->parseValues($valuesStr);
$sqlColumns = $tableColumnMap[$tableName] ?? [];
try {
$data = $this->mapValuesToTable($tableName, $values, $sqlColumns);
if (!empty($data)) {
DB::table($tableName)->insert($data);
$insertCount++;
if ($insertCount % 100 === 0) {
$this->command->info("Imported {$insertCount} records...");
}
}
} catch (\Exception $e) {
$this->command->error("Error inserting into {$tableName}: " . $e->getMessage());
}
}
}
fclose($handle);
$this->command->info("Finished! Total records imported: {$insertCount}");
}
// Re-enable foreign key checks
if (DB::getDriverName() === 'pgsql') {
DB::statement("SET session_replication_role = 'origin';");
// Update sequences for PostgreSQL
$this->updatePostgresSequences();
} else {
DB::statement('SET FOREIGN_KEY_CHECKS=1;');
}
}
/**
* Update PostgreSQL sequences so they don't clash with imported IDs.
*/
private function updatePostgresSequences()
{
$this->command->info("Updating PostgreSQL sequences...");
$tables = DB::select("SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'");
foreach ($tables as $table) {
$tableName = $table->table_name;
try {
$maxId = DB::table($tableName)->max('id');
if ($maxId) {
$seqName = "{$tableName}_id_seq";
// Check if sequence exists
$seqExists = DB::select("SELECT 1 FROM pg_class WHERE relname = ?", [$seqName]);
if ($seqExists) {
DB::statement("SELECT setval(?, ?, true)", [$seqName, $maxId]);
}
}
} catch (\Exception $e) {
// Ignore if table doesn't have id column or sequence
}
}
}
/**
* Basic parser for MySQL values string: (val1, val2, ...)
*/
private function parseValues($str)
{
$values = [];
$i = 0;
$len = strlen($str);
$current = '';
$inString = false;
$stringChar = '';
while ($i < $len) {
$char = $str[$i];
if ($inString) {
if ($char === $stringChar && ($i === 0 || $str[$i - 1] !== '\\')) {
$inString = false;
$values[] = str_replace(['\\\'', '\\"'], ["'", '"'], $current);
$current = '';
} else {
$current .= $char;
}
} else {
if ($char === "'" || $char === '"') {
$inString = true;
$stringChar = $char;
} elseif ($char === ',') {
$val = trim($current);
if ($val !== '') {
$values[] = $this->castValue($val);
}
$current = '';
} else {
$current .= $char;
}
}
$i++;
}
// Last value
$val = trim($current);
if ($val !== '') {
$values[] = $this->castValue($val);
}
return $values;
}
private function castValue($val)
{
if (strtoupper($val) === 'NULL') return null;
if (is_numeric($val) && (strpos($val, '0') !== 0 || $val === '0')) {
return $val + 0; // Convert to int or float
}
return trim($val, "'\"");
}
/**
* Map numerical values to column names based on SQL dump schema and filter by DB schema.
*/
private function mapValuesToTable($table, $values, $sqlColumns)
{
if (empty($sqlColumns) || count($sqlColumns) !== count($values)) {
return []; // Can't reliably map
}
// Combine using SQL column names
$mapped = array_combine($sqlColumns, $values);
// Get actual columns in the database
static $dbColumnsCache = [];
if (!isset($dbColumnsCache[$table])) {
$dbColumnsCache[$table] = DB::getSchemaBuilder()->getColumnListing($table);
}
$dbColumns = $dbColumnsCache[$table];
// Filter out columns that don't exist in the current DB
return array_intersect_key($mapped, array_flip($dbColumns));
}
}

2842
db/kulakposmysql.sql Normal file

File diff suppressed because one or more lines are too long

View File

@@ -176,6 +176,7 @@ fi
if [ "$AUTO_MIGRATE" = "true" ] || [ "$APP_ENV" != "production" ]; then
echo "Running migrations..."
php artisan migrate --force
php artisan db:seed --class=InitialDataSeeder
fi
echo "========================================"