diff --git a/src/SQLLoader.php b/src/SQLLoader.php index d83ebe8..e1b9eb1 100644 --- a/src/SQLLoader.php +++ b/src/SQLLoader.php @@ -6,6 +6,7 @@ use Illuminate\Contracts\Filesystem\Filesystem; use Illuminate\Contracts\Process\ProcessResult; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\File; use Illuminate\Support\Facades\Process; use Illuminate\Support\Facades\Schema; @@ -87,6 +88,8 @@ public function into( $columns = array_merge($columns, $this->constants); + $table = DB::connection($this->getConnection())->getQueryGrammar()->wrapTable($table); + $this->tables[] = new TableDefinition( $table, $columns, $terminatedBy, $enclosedBy, $trailing, $formatOptions, $when, $csv, $withEmbedded ); @@ -97,7 +100,7 @@ public function into( public function createColumnsFromHeaders(string $table, array $columns): array { $columns = array_map('strtolower', $columns); - $schemaColumns = collect(Schema::connection(config('sql-loader.connection'))->getColumns($table)); + $schemaColumns = collect(Schema::connection($this->getConnection())->getColumns($table)); $dates = $schemaColumns->filter(fn ($column) => in_array($column['type'], [ 'date', diff --git a/tests/Feature/ControlFileBuilderTest.php b/tests/Feature/ControlFileBuilderTest.php index ad7678e..d8d43b4 100644 --- a/tests/Feature/ControlFileBuilderTest.php +++ b/tests/Feature/ControlFileBuilderTest.php @@ -3,119 +3,121 @@ use Yajra\SQLLoader\ControlFileBuilder; use Yajra\SQLLoader\SQLLoader; -test('it can build a control file', function () { - $loader = new SQLLoader(['skip=1', 'load=2']); - $loader->inFile(__DIR__.'/../data/users.dat') - ->as('users.ctl') - ->into( - table: 'users', - columns: ['id', 'name', 'email'], - trailing: 'TRAILING NULLCOLS' - ); - - $ctl = new ControlFileBuilder($loader); - $controlFile = $ctl->build(); - - expect($controlFile)->toBeString() - ->and($controlFile)->toContain('OPTIONS(skip=1, load=2)') - ->and($controlFile)->toContain("INFILE '".__DIR__."/../data/users.dat'") - ->and($controlFile)->toContain('APPEND') - ->and($controlFile)->toContain('INTO TABLE users') - ->and($controlFile)->toContain("FIELDS TERMINATED BY ','") - ->and($controlFile)->toContain('OPTIONALLY') - ->and($controlFile)->toContain("ENCLOSED BY '\"'") - ->and($controlFile)->toContain('TRAILING NULLCOLS') - ->and($controlFile)->toContain('(') - ->and($controlFile)->toContain('id,') - ->and($controlFile)->toContain('name,') - ->and($controlFile)->toContain('email') - ->and($controlFile)->toContain(')'); -}); - -test('it can build multiple input files', function () { - $loader = new SQLLoader(['skip=1', 'load=2']); - $loader->inFile(__DIR__.'/../data/users.dat') - ->inFile(__DIR__.'/../data/roles.dat') - ->as('users.ctl') - ->into( - table: 'users', - columns: ['id', 'name', 'email'], - trailing: 'TRAILING NULLCOLS' - ); - - $ctl = new ControlFileBuilder($loader); - $controlFile = $ctl->build(); - - expect($controlFile)->toBeString() - ->and($controlFile)->toContain("INFILE '".__DIR__."/../data/users.dat'") - ->and($controlFile)->toContain("INFILE '".__DIR__."/../data/roles.dat'"); -}); - -test('it can build with bad file, discard file and discard max', function () { - $loader = new SQLLoader(['skip=1', 'load=2']); - $loader->inFile(__DIR__.'/../data/users.dat', badFile: 'users.bad', discardFile: 'users.dis', discardMax: '1') - ->as('users.ctl') - ->into( - table: 'users', - columns: ['id', 'name', 'email'], - trailing: 'TRAILING NULLCOLS' - ); - - $ctl = new ControlFileBuilder($loader); - $controlFile = $ctl->build(); - - expect($controlFile)->toBeString() - ->and($controlFile)->toContain("BADFILE 'users.bad'") - ->and($controlFile)->toContain("DISCARDFILE 'users.dis'") - ->and($controlFile)->toContain('DISCARDMAX 1'); -}); - -test('it can build table with formatting options', function () { - $loader = new SQLLoader(['skip=1', 'load=2']); - $loader->inFile(__DIR__.'/../data/users.dat') - ->as('users.ctl') - ->into( - table: 'users', - columns: ['id', 'name', 'email'], - trailing: 'TRAILING NULLCOLS', - formatOptions: [ - 'DATE_FORMAT "YYYY-MM-DD"', - 'TIMESTAMP FORMAT "YYYY-MM-DD HH24:MI:SS"', - 'TIMESTAMP WITH TIME ZONE "YYYY-MM-DD HH24:MI:SS TZH:TZM"', - 'TIMESTAMP WITH LOCAL TIME ZONE "YYYY-MM-DD HH24:MI:SS"', - ] - ); - - $ctl = new ControlFileBuilder($loader); - $controlFile = $ctl->build(); - - expect($controlFile)->toBeString() - ->and($controlFile)->toContain('DATE_FORMAT "YYYY-MM-DD"') - ->and($controlFile)->toContain('TIMESTAMP FORMAT "YYYY-MM-DD HH24:MI:SS') - ->and($controlFile)->toContain('TIMESTAMP WITH TIME ZONE "YYYY-MM-DD HH24:MI:SS TZH:TZM"') - ->and($controlFile)->toContain('TIMESTAMP WITH LOCAL TIME ZONE "YYYY-MM-DD HH24:MI:SS"'); -}); - -test('it can build using begin data', function () { - $loader = new SQLLoader(['skip=1', 'load=2']); - $loader->as('users.ctl') - ->into( - table: 'users', - columns: ['id', 'name', 'email'], - ) - ->beginData([ - ['1', 'name-1', 'email-1'], - ['2', 'name-2', 'email-2'], - ['3', 'name,-2', 'email"-2'], - ]); - - $ctl = new ControlFileBuilder($loader); - $controlFile = $ctl->build(); - - expect($controlFile)->toBeString() - ->and($controlFile)->toContain('INFILE *') - ->and($controlFile)->toContain("BEGINDATA\n") - ->and($controlFile)->toContain('1,name-1,email-1') - ->and($controlFile)->toContain('2,name-2,email-2') - ->and($controlFile)->toContain('3,"name,-2","email""-2"'); +describe('Control File Builder', function () { + test('it can build a control file', function () { + $loader = new SQLLoader(['skip=1', 'load=2']); + $loader->inFile(__DIR__.'/../data/users.dat') + ->as('users.ctl') + ->into( + table: 'users', + columns: ['id', 'name', 'email'], + trailing: 'TRAILING NULLCOLS' + ); + + $ctl = new ControlFileBuilder($loader); + $controlFile = $ctl->build(); + + expect($controlFile)->toBeString() + ->and($controlFile)->toContain('OPTIONS(skip=1, load=2)') + ->and($controlFile)->toContain("INFILE '".__DIR__."/../data/users.dat'") + ->and($controlFile)->toContain('APPEND') + ->and($controlFile)->toContain('INTO TABLE "USERS"') + ->and($controlFile)->toContain("FIELDS TERMINATED BY ','") + ->and($controlFile)->toContain('OPTIONALLY') + ->and($controlFile)->toContain("ENCLOSED BY '\"'") + ->and($controlFile)->toContain('TRAILING NULLCOLS') + ->and($controlFile)->toContain('(') + ->and($controlFile)->toContain('id,') + ->and($controlFile)->toContain('name,') + ->and($controlFile)->toContain('email') + ->and($controlFile)->toContain(')'); + }); + + test('it can build multiple input files', function () { + $loader = new SQLLoader(['skip=1', 'load=2']); + $loader->inFile(__DIR__.'/../data/users.dat') + ->inFile(__DIR__.'/../data/roles.dat') + ->as('users.ctl') + ->into( + table: 'users', + columns: ['id', 'name', 'email'], + trailing: 'TRAILING NULLCOLS' + ); + + $ctl = new ControlFileBuilder($loader); + $controlFile = $ctl->build(); + + expect($controlFile)->toBeString() + ->and($controlFile)->toContain("INFILE '".__DIR__."/../data/users.dat'") + ->and($controlFile)->toContain("INFILE '".__DIR__."/../data/roles.dat'"); + }); + + test('it can build with bad file, discard file and discard max', function () { + $loader = new SQLLoader(['skip=1', 'load=2']); + $loader->inFile(__DIR__.'/../data/users.dat', badFile: 'users.bad', discardFile: 'users.dis', discardMax: '1') + ->as('users.ctl') + ->into( + table: 'users', + columns: ['id', 'name', 'email'], + trailing: 'TRAILING NULLCOLS' + ); + + $ctl = new ControlFileBuilder($loader); + $controlFile = $ctl->build(); + + expect($controlFile)->toBeString() + ->and($controlFile)->toContain("BADFILE 'users.bad'") + ->and($controlFile)->toContain("DISCARDFILE 'users.dis'") + ->and($controlFile)->toContain('DISCARDMAX 1'); + }); + + test('it can build table with formatting options', function () { + $loader = new SQLLoader(['skip=1', 'load=2']); + $loader->inFile(__DIR__.'/../data/users.dat') + ->as('users.ctl') + ->into( + table: 'users', + columns: ['id', 'name', 'email'], + trailing: 'TRAILING NULLCOLS', + formatOptions: [ + 'DATE_FORMAT "YYYY-MM-DD"', + 'TIMESTAMP FORMAT "YYYY-MM-DD HH24:MI:SS"', + 'TIMESTAMP WITH TIME ZONE "YYYY-MM-DD HH24:MI:SS TZH:TZM"', + 'TIMESTAMP WITH LOCAL TIME ZONE "YYYY-MM-DD HH24:MI:SS"', + ] + ); + + $ctl = new ControlFileBuilder($loader); + $controlFile = $ctl->build(); + + expect($controlFile)->toBeString() + ->and($controlFile)->toContain('DATE_FORMAT "YYYY-MM-DD"') + ->and($controlFile)->toContain('TIMESTAMP FORMAT "YYYY-MM-DD HH24:MI:SS') + ->and($controlFile)->toContain('TIMESTAMP WITH TIME ZONE "YYYY-MM-DD HH24:MI:SS TZH:TZM"') + ->and($controlFile)->toContain('TIMESTAMP WITH LOCAL TIME ZONE "YYYY-MM-DD HH24:MI:SS"'); + }); + + test('it can build using begin data', function () { + $loader = new SQLLoader(['skip=1', 'load=2']); + $loader->as('users.ctl') + ->into( + table: 'users', + columns: ['id', 'name', 'email'], + ) + ->beginData([ + ['1', 'name-1', 'email-1'], + ['2', 'name-2', 'email-2'], + ['3', 'name,-2', 'email"-2'], + ]); + + $ctl = new ControlFileBuilder($loader); + $controlFile = $ctl->build(); + + expect($controlFile)->toBeString() + ->and($controlFile)->toContain('INFILE *') + ->and($controlFile)->toContain("BEGINDATA\n") + ->and($controlFile)->toContain('1,name-1,email-1') + ->and($controlFile)->toContain('2,name-2,email-2') + ->and($controlFile)->toContain('3,"name,-2","email""-2"'); + }); }); diff --git a/tests/Feature/CsvFileTest.php b/tests/Feature/CsvFileTest.php index 06c8b0e..0257f25 100644 --- a/tests/Feature/CsvFileTest.php +++ b/tests/Feature/CsvFileTest.php @@ -2,65 +2,67 @@ use Yajra\SQLLoader\CsvFile; -test('it can create a blank csv file', function () { - $file = CsvFile::blank(storage_path('test.csv')); +describe('CSV File', function () { + test('it can create a blank csv file', function () { + $file = CsvFile::blank(storage_path('test.csv')); - expect($file)->toBeString() - ->and($file)->toBe(storage_path('test.csv')) - ->and(file_exists($file))->toBeTrue(); -}); + expect($file)->toBeString() + ->and($file)->toBe(storage_path('test.csv')) + ->and(file_exists($file))->toBeTrue(); + }); -test('it can create a csv file', function () { - $file = CsvFile::create(storage_path('test.csv')); + test('it can create a csv file', function () { + $file = CsvFile::create(storage_path('test.csv')); - expect($file)->toBeString() - ->and($file)->toBe(storage_path('test.csv')) - ->and(file_exists($file))->toBeTrue(); -}); + expect($file)->toBeString() + ->and($file)->toBe(storage_path('test.csv')) + ->and(file_exists($file))->toBeTrue(); + }); -test('it can make a csv file with array content', function () { - $file = CsvFile::make(storage_path('test.csv'), 'w'); - $file->append(['id', 'name', 'email']); + test('it can make a csv file with array content', function () { + $file = CsvFile::make(storage_path('test.csv'), 'w'); + $file->append(['id', 'name', 'email']); - expect($file)->toBeInstanceOf(CsvFile::class) - ->and($file->isEmpty())->toBeFalse() - ->and($file->get())->toContain('id,name,email'.PHP_EOL); -}); + expect($file)->toBeInstanceOf(CsvFile::class) + ->and($file->isEmpty())->toBeFalse() + ->and($file->get())->toContain('id,name,email'.PHP_EOL); + }); -test('it can have a csv header', function () { - $file = CsvFile::make(storage_path('test.csv'), 'w'); - $file->headers(['id', 'name', 'email']); + test('it can have a csv header', function () { + $file = CsvFile::make(storage_path('test.csv'), 'w'); + $file->headers(['id', 'name', 'email']); - expect($file)->toBeInstanceOf(CsvFile::class) - ->and($file->isEmpty())->toBeFalse() - ->and($file->get())->toContain('id,name,email'.PHP_EOL); -}); + expect($file)->toBeInstanceOf(CsvFile::class) + ->and($file->isEmpty())->toBeFalse() + ->and($file->get())->toContain('id,name,email'.PHP_EOL); + }); -test('it can insert data using array', function () { - $file = CsvFile::make(storage_path('test.csv'), 'w'); - $file->headers(['id', 'name', 'email']); - $file->insert([ - ['1', 'John Doe', 'email@example.com'], - ['2', 'Jane Doe', 'e'], - ['3', 'Jane, Doe', '3'], - ['3', 'Jane" Doe', '3'], - ]); + test('it can insert data using array', function () { + $file = CsvFile::make(storage_path('test.csv'), 'w'); + $file->headers(['id', 'name', 'email']); + $file->insert([ + ['1', 'John Doe', 'email@example.com'], + ['2', 'Jane Doe', 'e'], + ['3', 'Jane, Doe', '3'], + ['3', 'Jane" Doe', '3'], + ]); - $content = $file->get(); + $content = $file->get(); - expect($file)->toBeInstanceOf(CsvFile::class) - ->and($file->isEmpty())->toBeFalse() - ->and($content)->toContain('1,"John Doe",email@example.com'.PHP_EOL) - ->and($content)->toContain('2,"Jane Doe",e'.PHP_EOL) - ->and($content)->toContain('3,"Jane, Doe",3'.PHP_EOL) - ->and($content)->toContain('3,"Jane"" Doe",3'.PHP_EOL); -}); + expect($file)->toBeInstanceOf(CsvFile::class) + ->and($file->isEmpty())->toBeFalse() + ->and($content)->toContain('1,"John Doe",email@example.com'.PHP_EOL) + ->and($content)->toContain('2,"Jane Doe",e'.PHP_EOL) + ->and($content)->toContain('3,"Jane, Doe",3'.PHP_EOL) + ->and($content)->toContain('3,"Jane"" Doe",3'.PHP_EOL); + }); -test('it can sanitize headers', function () { - $headers = CsvFile::make(__DIR__.'/../data/bad-header.dat', 'r')->getHeaders(); - expect($headers)->toBe([ - 'NAME', - 'EMAIL', - 'PHONE', - ]); + test('it can sanitize headers', function () { + $headers = CsvFile::make(__DIR__.'/../data/bad-header.dat', 'r')->getHeaders(); + expect($headers)->toBe([ + 'NAME', + 'EMAIL', + 'PHONE', + ]); + }); }); diff --git a/tests/Feature/SQLLoaderTest.php b/tests/Feature/SQLLoaderTest.php index 63178f1..e2338f9 100644 --- a/tests/Feature/SQLLoaderTest.php +++ b/tests/Feature/SQLLoaderTest.php @@ -6,277 +6,279 @@ use Yajra\SQLLoader\SQLLoader; use Yajra\SQLLoader\TnsBuilder; -test('it throws an error on invalid/non-existent file', function () { - $loader = new SQLLoader(['skip=1', 'load=2']); - $loader->inFile('file.dat'); -})->throws(InvalidArgumentException::class, 'File [file.dat] does not exist.'); - -test('it can create an instance and build the command', function () { - expect(SQLLoader::make())->toBeInstanceOf(SQLLoader::class); - - $file = __DIR__.'/../data/users.dat'; - - $loader = new SQLLoader(['skip=1', 'load=2']); - $loader->inFile(path: $file, badFile: 'users.bad', discardFile: 'users.dis', discardMax: '1') - ->as('users.ctl') - ->into('users', ['id', 'name', 'email']); - - expect($loader)->toBeInstanceOf(SQLLoader::class); - - $controlFile = $loader->buildControlFile(); - - expect($controlFile)->toBeString() - ->toContain('OPTIONS(skip=1, load=2)') - ->toContain("INFILE '{$file}'") - ->toContain("BADFILE 'users.bad'") - ->toContain("DISCARDFILE 'users.dis'") - ->toContain('DISCARDMAX 1') - ->toContain('APPEND') - ->toContain('INTO TABLE users') - ->toContain("FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"'") - ->toContain('(') - ->toContain(' id,') - ->toContain(' name,') - ->toContain(' email') - ->toContain(')'); -}); +describe('SQL Loader', function () { + test('it throws an error on invalid/non-existent file', function () { + $loader = new SQLLoader(['skip=1', 'load=2']); + $loader->inFile('file.dat'); + })->throws(InvalidArgumentException::class, 'File [file.dat] does not exist.'); + + test('it can create an instance and build the command', function () { + expect(SQLLoader::make())->toBeInstanceOf(SQLLoader::class); + + $file = __DIR__.'/../data/users.dat'; + + $loader = new SQLLoader(['skip=1', 'load=2']); + $loader->inFile(path: $file, badFile: 'users.bad', discardFile: 'users.dis', discardMax: '1') + ->as('users.ctl') + ->into('users', ['id', 'name', 'email']); + + expect($loader)->toBeInstanceOf(SQLLoader::class); + + $controlFile = $loader->buildControlFile(); + + expect($controlFile)->toBeString() + ->toContain('OPTIONS(skip=1, load=2)') + ->toContain("INFILE '{$file}'") + ->toContain("BADFILE 'users.bad'") + ->toContain("DISCARDFILE 'users.dis'") + ->toContain('DISCARDMAX 1') + ->toContain('APPEND') + ->toContain('INTO TABLE "USERS"') + ->toContain("FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"'") + ->toContain('(') + ->toContain(' id,') + ->toContain(' name,') + ->toContain(' email') + ->toContain(')'); + }); -test('sqlldr process is invoked', function () { - Process::fake(); + test('sqlldr process is invoked', function () { + Process::fake(); - $file = __DIR__.'/../data/users.dat'; + $file = __DIR__.'/../data/users.dat'; - $loader = new SQLLoader(['skip=1']); - $loader->inFile($file) - ->as('users.ctl') - ->into('users', ['id', 'name', 'email']) - ->execute(); + $loader = new SQLLoader(['skip=1']); + $loader->inFile($file) + ->as('users.ctl') + ->into('users', ['id', 'name', 'email']) + ->execute(); - Process::assertRan(function (PendingProcess $process, ProcessResult $result) { - $username = config('database.connections.oracle.username'); - $password = config('database.connections.oracle.password'); - $host = config('database.connections.oracle.host'); - $port = config('database.connections.oracle.port'); - $database = config('database.connections.oracle.database'); + Process::assertRan(function (PendingProcess $process, ProcessResult $result) { + $username = config('database.connections.oracle.username'); + $password = config('database.connections.oracle.password'); + $host = config('database.connections.oracle.host'); + $port = config('database.connections.oracle.port'); + $database = config('database.connections.oracle.database'); - $controlFile = storage_path('app/users.ctl'); + $controlFile = storage_path('app/users.ctl'); - return str_contains((string) $process->command, "sqlldr userid={$username}/{$password}@{$host}:{$port}/{$database} control={$controlFile}"); + return str_contains((string) $process->command, "sqlldr userid={$username}/{$password}@{$host}:{$port}/{$database} control={$controlFile}"); + }); }); -}); -test('it allows * input file', function () { - Process::fake(); + test('it allows * input file', function () { + Process::fake(); - $loader = new SQLLoader(['skip=1']); - $loader->inFile('*') - ->as('users.ctl') - ->into('users', ['id', 'name', 'email']) - ->execute(); + $loader = new SQLLoader(['skip=1']); + $loader->inFile('*') + ->as('users.ctl') + ->into('users', ['id', 'name', 'email']) + ->execute(); - Process::assertRan(function (PendingProcess $process, ProcessResult $result) { - $tns = TnsBuilder::make(); - $controlFile = storage_path('app/users.ctl'); + Process::assertRan(function (PendingProcess $process, ProcessResult $result) { + $tns = TnsBuilder::make(); + $controlFile = storage_path('app/users.ctl'); - return str_contains((string) $process->command, "sqlldr userid={$tns} control={$controlFile}"); + return str_contains((string) $process->command, "sqlldr userid={$tns} control={$controlFile}"); + }); }); -}); -test('it accepts multiple input files', function () { - Process::fake(); + test('it accepts multiple input files', function () { + Process::fake(); - $loader = new SQLLoader(['skip=1']); - $loader->inFile(__DIR__.'/../data/users.dat') - ->inFile(__DIR__.'/../data/roles.dat') - ->as('users.ctl') - ->into('users', ['id', 'name', 'email']) - ->execute(); + $loader = new SQLLoader(['skip=1']); + $loader->inFile(__DIR__.'/../data/users.dat') + ->inFile(__DIR__.'/../data/roles.dat') + ->as('users.ctl') + ->into('users', ['id', 'name', 'email']) + ->execute(); - Process::assertRan(function (PendingProcess $process, ProcessResult $result) { - $tns = TnsBuilder::make(); - $controlFile = storage_path('app/users.ctl'); + Process::assertRan(function (PendingProcess $process, ProcessResult $result) { + $tns = TnsBuilder::make(); + $controlFile = storage_path('app/users.ctl'); - return str_contains((string) $process->command, "sqlldr userid={$tns} control={$controlFile}"); + return str_contains((string) $process->command, "sqlldr userid={$tns} control={$controlFile}"); + }); }); -}); -test('it can use another database connection', function () { - Process::fake(); - - $loader = new SQLLoader(['skip=1']); - $loader->inFile(__DIR__.'/../data/users.dat') - ->as('users.ctl') - ->connection('mysql') - ->into('users', ['id', 'name', 'email']) - ->execute(); - - Process::assertRan(function (PendingProcess $process, ProcessResult $result) { - $username = config('database.connections.mysql.username'); - $password = config('database.connections.mysql.password'); - $host = config('database.connections.mysql.host'); - $port = config('database.connections.mysql.port'); - $database = config('database.connections.mysql.database'); - $controlFile = storage_path('app/users.ctl'); - - return str_contains((string) $process->command, "sqlldr userid={$username}/{$password}@{$host}:{$port}/{$database} control={$controlFile}"); + test('it can use another database connection', function () { + Process::fake(); + + $loader = new SQLLoader(['skip=1']); + $loader->inFile(__DIR__.'/../data/users.dat') + ->as('users.ctl') + ->connection('mysql') + ->into('users', ['id', 'name', 'email']) + ->execute(); + + Process::assertRan(function (PendingProcess $process, ProcessResult $result) { + $username = config('database.connections.mysql.username'); + $password = config('database.connections.mysql.password'); + $host = config('database.connections.mysql.host'); + $port = config('database.connections.mysql.port'); + $database = config('database.connections.mysql.database'); + $controlFile = storage_path('app/users.ctl'); + + return str_contains((string) $process->command, "sqlldr userid={$username}/{$password}@{$host}:{$port}/{$database} control={$controlFile}"); + }); }); -}); -test('it can detect FILLER and DATE columns', function () { - Process::fake(); - - $loader = new SQLLoader(); - $loader->inFile(__DIR__.'/../data/filler.dat') - ->as('users.ctl') - ->withHeaders() - ->into('users') - ->execute(); - - $controlFile = $loader->buildControlFile(); - - expect($controlFile)->toBeString() - ->toContain("INFILE '".__DIR__.'/../data/filler.dat') - ->toContain('INTO TABLE users') - ->toContain('FIELDS TERMINATED BY \',\' OPTIONALLY ENCLOSED BY \'"\'') - ->toContain('TRAILING NULLCOLS') - ->toContain('(') - ->toContain('"NAME",') - ->toContain('"EMAIL",') - ->toContain('"PHONE" FILLER', $controlFile) - ->toContain('"CREATED_AT" DATE') - ->toContain(')'); -}); + test('it can detect FILLER and DATE columns', function () { + Process::fake(); + + $loader = new SQLLoader(); + $loader->inFile(__DIR__.'/../data/filler.dat') + ->as('users.ctl') + ->withHeaders() + ->into('users') + ->execute(); + + $controlFile = $loader->buildControlFile(); + + expect($controlFile)->toBeString() + ->toContain("INFILE '".__DIR__.'/../data/filler.dat') + ->toContain('INTO TABLE "USERS"') + ->toContain('FIELDS TERMINATED BY \',\' OPTIONALLY ENCLOSED BY \'"\'') + ->toContain('TRAILING NULLCOLS') + ->toContain('(') + ->toContain('"NAME",') + ->toContain('"EMAIL",') + ->toContain('"PHONE" FILLER', $controlFile) + ->toContain('"CREATED_AT" DATE') + ->toContain(')'); + }); -test('it can detect BOOLEAN columns and set the default value if empty', function () { - Process::fake(); + test('it can detect BOOLEAN columns and set the default value if empty', function () { + Process::fake(); - $loader = new SQLLoader(); - $loader->inFile(__DIR__.'/../data/filler.dat') - ->as('users.ctl') - ->withHeaders() - ->into('users') - ->execute(); + $loader = new SQLLoader(); + $loader->inFile(__DIR__.'/../data/filler.dat') + ->as('users.ctl') + ->withHeaders() + ->into('users') + ->execute(); - $controlFile = $loader->buildControlFile(); + $controlFile = $loader->buildControlFile(); - expect($controlFile)->toBeString() - ->toContain('"NAME"') - ->toContain('"EMAIL"') - ->toContain('"PHONE" FILLER') - ->toContain('"CREATED_AT" DATE') - ->toContain('"IS_ACTIVE" "DECODE(:is_active, \'\', \'1\', :is_active)"'); -}); + expect($controlFile)->toBeString() + ->toContain('"NAME"') + ->toContain('"EMAIL"') + ->toContain('"PHONE" FILLER') + ->toContain('"CREATED_AT" DATE') + ->toContain('"IS_ACTIVE" "DECODE(:is_active, \'\', \'1\', :is_active)"'); + }); -test('it can detect BOOLEAN columns and set the default value to 0 if no default was defined', function () { - Process::fake(); + test('it can detect BOOLEAN columns and set the default value to 0 if no default was defined', function () { + Process::fake(); - $loader = new SQLLoader(); - $loader->inFile(__DIR__.'/../data/filler.dat') - ->as('users.ctl') - ->withHeaders() - ->into('users_bool_no_default') - ->execute(); + $loader = new SQLLoader(); + $loader->inFile(__DIR__.'/../data/filler.dat') + ->as('users.ctl') + ->withHeaders() + ->into('users_bool_no_default') + ->execute(); - $controlFile = $loader->buildControlFile(); + $controlFile = $loader->buildControlFile(); - expect($controlFile)->toBeString() - ->toContain('"NAME"') - ->toContain('"EMAIL"') - ->toContain('"PHONE" FILLER') - ->toContain('"CREATED_AT" DATE') - ->toContain('"IS_ACTIVE" "DECODE(:is_active, \'\', \'0\', :is_active)"'); -}); + expect($controlFile)->toBeString() + ->toContain('"NAME"') + ->toContain('"EMAIL"') + ->toContain('"PHONE" FILLER') + ->toContain('"CREATED_AT" DATE') + ->toContain('"IS_ACTIVE" "DECODE(:is_active, \'\', \'0\', :is_active)"'); + }); -test('it accepts withHeader on input file with wildcard', function () { - Process::fake(); - - $loader = new SQLLoader(); - $path = __DIR__.'/../data/wildcard/*.dat'; - $loader->inFile($path) - ->as('users.ctl') - ->withHeaders() - ->into('users') - ->execute(); - - $controlFile = $loader->buildControlFile(); - - expect($controlFile)->toBeString() - ->toContain("INFILE '{$path}'") - ->toContain('INTO TABLE users') - ->toContain('FIELDS TERMINATED BY \',\' OPTIONALLY ENCLOSED BY \'"\'') - ->toContain('TRAILING NULLCOLS') - ->toContain('(') - ->toContain('"NAME",') - ->toContain('"EMAIL"') - ->toContain(')'); -}); + test('it accepts withHeader on input file with wildcard', function () { + Process::fake(); + + $loader = new SQLLoader(); + $path = __DIR__.'/../data/wildcard/*.dat'; + $loader->inFile($path) + ->as('users.ctl') + ->withHeaders() + ->into('users') + ->execute(); + + $controlFile = $loader->buildControlFile(); + + expect($controlFile)->toBeString() + ->toContain("INFILE '{$path}'") + ->toContain('INTO TABLE "USERS"') + ->toContain('FIELDS TERMINATED BY \',\' OPTIONALLY ENCLOSED BY \'"\'') + ->toContain('TRAILING NULLCOLS') + ->toContain('(') + ->toContain('"NAME",') + ->toContain('"EMAIL"') + ->toContain(')'); + }); -test('it can set the default date format', function () { - Process::fake(); + test('it can set the default date format', function () { + Process::fake(); - $loader = new SQLLoader(); - $loader->inFile(__DIR__.'/../data/filler.dat') - ->as('users.ctl') - ->dateFormat('YYYY-MM-DD') - ->withHeaders() - ->into('users') - ->execute(); + $loader = new SQLLoader(); + $loader->inFile(__DIR__.'/../data/filler.dat') + ->as('users.ctl') + ->dateFormat('YYYY-MM-DD') + ->withHeaders() + ->into('users') + ->execute(); - $controlFile = $loader->buildControlFile(); + $controlFile = $loader->buildControlFile(); - expect($controlFile)->toBeString() - ->toContain("DATE FORMAT 'YYYY-MM-DD'\n") - ->toContain("TIMESTAMP FORMAT 'YYYY-MM-DD'\n") - ->toContain("TIMESTAMP WITH TIME ZONE 'YYYY-MM-DD'\n") - ->toContain("TIMESTAMP WITH LOCAL TIME ZONE 'YYYY-MM-DD'\n"); -}); + expect($controlFile)->toBeString() + ->toContain("DATE FORMAT 'YYYY-MM-DD'\n") + ->toContain("TIMESTAMP FORMAT 'YYYY-MM-DD'\n") + ->toContain("TIMESTAMP WITH TIME ZONE 'YYYY-MM-DD'\n") + ->toContain("TIMESTAMP WITH LOCAL TIME ZONE 'YYYY-MM-DD'\n"); + }); -test('it can process constants columns', function () { - Process::fake(); - - $loader = new SQLLoader(); - $loader->inFile(__DIR__.'/../data/users.dat') - ->as('users.ctl') - ->withHeaders() - ->constants([ - 'created_by CONSTANT 1', - 'created_at EXPRESSION "current_timestamp(3)"', - 'updated_by CONSTANT 1', - 'updated_at EXPRESSION "current_timestamp(3)"', - ]) - ->into('users') - ->execute(); - - $controlFile = $loader->buildControlFile(); - - expect($controlFile)->toBeString() - ->toContain("\"NAME\",\n") - ->toContain("\"EMAIL\",\n") - ->toContain("created_by CONSTANT 1,\n") - ->toContain("created_at EXPRESSION \"current_timestamp(3)\",\n") - ->toContain("updated_by CONSTANT 1,\n") - ->toContain("updated_at EXPRESSION \"current_timestamp(3)\"\n"); -}); + test('it can process constants columns', function () { + Process::fake(); + + $loader = new SQLLoader(); + $loader->inFile(__DIR__.'/../data/users.dat') + ->as('users.ctl') + ->withHeaders() + ->constants([ + 'created_by CONSTANT 1', + 'created_at EXPRESSION "current_timestamp(3)"', + 'updated_by CONSTANT 1', + 'updated_at EXPRESSION "current_timestamp(3)"', + ]) + ->into('users') + ->execute(); + + $controlFile = $loader->buildControlFile(); + + expect($controlFile)->toBeString() + ->toContain("\"NAME\",\n") + ->toContain("\"EMAIL\",\n") + ->toContain("created_by CONSTANT 1,\n") + ->toContain("created_at EXPRESSION \"current_timestamp(3)\",\n") + ->toContain("updated_by CONSTANT 1,\n") + ->toContain("updated_at EXPRESSION \"current_timestamp(3)\"\n"); + }); -test('it can set input file os file proc clause', function () { - Process::fake(); - - $loader = new SQLLoader(); - $loader->inFile(__DIR__.'/../data/users.dat', osFileProcClause: 'os file proc') - ->as('users.ctl') - ->withHeaders() - ->into('users') - ->execute(); - - $controlFile = $loader->buildControlFile(); - - expect($controlFile)->toBeString() - ->toContain("INFILE '".__DIR__."/../data/users.dat' \"os file proc\"") - ->toContain('INTO TABLE users') - ->toContain('FIELDS TERMINATED BY \',\' OPTIONALLY ENCLOSED BY \'"\'') - ->toContain('TRAILING NULLCOLS') - ->toContain('(') - ->toContain('"NAME",') - ->toContain('"EMAIL"') - ->toContain(')'); + test('it can set input file os file proc clause', function () { + Process::fake(); + + $loader = new SQLLoader(); + $loader->inFile(__DIR__.'/../data/users.dat', osFileProcClause: 'os file proc') + ->as('users.ctl') + ->withHeaders() + ->into('users') + ->execute(); + + $controlFile = $loader->buildControlFile(); + + expect($controlFile)->toBeString() + ->toContain("INFILE '".__DIR__."/../data/users.dat' \"os file proc\"") + ->toContain('INTO TABLE "USERS"') + ->toContain('FIELDS TERMINATED BY \',\' OPTIONALLY ENCLOSED BY \'"\'') + ->toContain('TRAILING NULLCOLS') + ->toContain('(') + ->toContain('"NAME",') + ->toContain('"EMAIL"') + ->toContain(')'); + }); }); diff --git a/tests/Feature/TnsBuilderTest.php b/tests/Feature/TnsBuilderTest.php index 4c3e762..c2bc8c8 100644 --- a/tests/Feature/TnsBuilderTest.php +++ b/tests/Feature/TnsBuilderTest.php @@ -4,22 +4,24 @@ use function PHPUnit\Framework\assertEquals; -test('it can generate a tns string', function () { - $username = config('database.connections.oracle.username'); - $password = config('database.connections.oracle.password'); - $host = config('database.connections.oracle.host'); - $port = config('database.connections.oracle.port'); - $database = config('database.connections.oracle.database'); +describe('TNS Builder', function () { + test('it can generate a tns string', function () { + $username = config('database.connections.oracle.username'); + $password = config('database.connections.oracle.password'); + $host = config('database.connections.oracle.host'); + $port = config('database.connections.oracle.port'); + $database = config('database.connections.oracle.database'); - assertEquals("$username/$password@$host:$port/$database", TnsBuilder::make()); -}); + assertEquals("$username/$password@$host:$port/$database", TnsBuilder::make()); + }); -test('it accepts a connection', function () { - $username = config('database.connections.mysql.username'); - $password = config('database.connections.mysql.password'); - $host = config('database.connections.mysql.host'); - $port = config('database.connections.mysql.port'); - $database = config('database.connections.mysql.database'); + test('it accepts a connection', function () { + $username = config('database.connections.mysql.username'); + $password = config('database.connections.mysql.password'); + $host = config('database.connections.mysql.host'); + $port = config('database.connections.mysql.port'); + $database = config('database.connections.mysql.database'); - assertEquals("$username/$password@$host:$port/$database", TnsBuilder::make('mysql')); + assertEquals("$username/$password@$host:$port/$database", TnsBuilder::make('mysql')); + }); }); diff --git a/tests/Unit/InputFileTest.php b/tests/Unit/InputFileTest.php index c1ebedd..055aab4 100644 --- a/tests/Unit/InputFileTest.php +++ b/tests/Unit/InputFileTest.php @@ -2,48 +2,51 @@ use Yajra\SQLLoader\InputFile; -test('it can build it\'s own sql string', function () { - $inputFile = new InputFile('path/to/file'); +describe('Input File', function () { - expect($inputFile->__toString())->toBe("INFILE 'path/to/file'"); -}); + test('it can build it\'s own sql string', function () { + $inputFile = new InputFile('path/to/file'); -test('it can build it\'s own sql string with bad file', function () { - $inputFile = new InputFile('path/to/file', 'path/to/badfile'); + expect($inputFile->__toString())->toBe("INFILE 'path/to/file'"); + }); - expect($inputFile->__toString())->toBe("INFILE 'path/to/file' BADFILE 'path/to/badfile'"); -}); + test('it can build it\'s own sql string with bad file', function () { + $inputFile = new InputFile('path/to/file', 'path/to/badfile'); -test('it can build it\'s own sql string with discard file', function () { - $inputFile = new InputFile('path/to/file', 'path/to/badfile', 'path/to/discardfile'); + expect($inputFile->__toString())->toBe("INFILE 'path/to/file' BADFILE 'path/to/badfile'"); + }); - expect($inputFile->__toString())->toBe("INFILE 'path/to/file' BADFILE 'path/to/badfile' DISCARDFILE 'path/to/discardfile'"); -}); + test('it can build it\'s own sql string with discard file', function () { + $inputFile = new InputFile('path/to/file', 'path/to/badfile', 'path/to/discardfile'); -test('it can build it\'s own sql string with discard max', function () { - $inputFile = new InputFile('path/to/file', 'path/to/badfile', 'path/to/discardfile', 1); + expect($inputFile->__toString())->toBe("INFILE 'path/to/file' BADFILE 'path/to/badfile' DISCARDFILE 'path/to/discardfile'"); + }); - expect($inputFile->__toString())->toBe("INFILE 'path/to/file' BADFILE 'path/to/badfile' DISCARDFILE 'path/to/discardfile' DISCARDMAX 1"); -}); + test('it can build it\'s own sql string with discard max', function () { + $inputFile = new InputFile('path/to/file', 'path/to/badfile', 'path/to/discardfile', 1); -test('it can build it\'s own sql string with discard max as string', function () { - $inputFile = new InputFile('path/to/file', 'path/to/badfile', 'path/to/discardfile', '1'); + expect($inputFile->__toString())->toBe("INFILE 'path/to/file' BADFILE 'path/to/badfile' DISCARDFILE 'path/to/discardfile' DISCARDMAX 1"); + }); - expect($inputFile->__toString())->toBe("INFILE 'path/to/file' BADFILE 'path/to/badfile' DISCARDFILE 'path/to/discardfile' DISCARDMAX 1"); -}); + test('it can build it\'s own sql string with discard max as string', function () { + $inputFile = new InputFile('path/to/file', 'path/to/badfile', 'path/to/discardfile', '1'); -test('it can build with os file proc clause', function () { - $inputFile = new InputFile('path/to/file', 'path/to/badfile', 'path/to/discardfile', '1', 'OS_FILE_PROC'); + expect($inputFile->__toString())->toBe("INFILE 'path/to/file' BADFILE 'path/to/badfile' DISCARDFILE 'path/to/discardfile' DISCARDMAX 1"); + }); - expect($inputFile->__toString())->toBe("INFILE 'path/to/file' \"OS_FILE_PROC\" BADFILE 'path/to/badfile' DISCARDFILE 'path/to/discardfile' DISCARDMAX 1"); -}); + test('it can build with os file proc clause', function () { + $inputFile = new InputFile('path/to/file', 'path/to/badfile', 'path/to/discardfile', '1', 'OS_FILE_PROC'); + + expect($inputFile->__toString())->toBe("INFILE 'path/to/file' \"OS_FILE_PROC\" BADFILE 'path/to/badfile' DISCARDFILE 'path/to/discardfile' DISCARDMAX 1"); + }); -test('it accepts wildcard in file path', function () { - $inputFile = new InputFile('path/to/chunk-*.dat'); + test('it accepts wildcard in file path', function () { + $inputFile = new InputFile('path/to/chunk-*.dat'); - expect($inputFile->__toString())->toBe("INFILE 'path/to/chunk-*.dat'"); + expect($inputFile->__toString())->toBe("INFILE 'path/to/chunk-*.dat'"); - $inputFile = new InputFile('path/to/chunk-?.dat'); + $inputFile = new InputFile('path/to/chunk-?.dat'); - expect($inputFile->__toString())->toBe("INFILE 'path/to/chunk-?.dat'"); + expect($inputFile->__toString())->toBe("INFILE 'path/to/chunk-?.dat'"); + }); }); diff --git a/tests/Unit/TableDefinitionTest.php b/tests/Unit/TableDefinitionTest.php index 99bdb2f..7f52675 100644 --- a/tests/Unit/TableDefinitionTest.php +++ b/tests/Unit/TableDefinitionTest.php @@ -4,126 +4,129 @@ use function PHPUnit\Framework\assertEquals; -test('it can build it\'s own sql string', function () { - $table = new TableDefinition( - 'users', - ['id', 'name', 'email'], - terminatedBy: ',', - enclosedBy: '"', - trailing: 'TRAILING NULLCOLS', - formatOptions: [ - 'DATE FORMAT "YYYY-MM-DD"', - ] - ); - - assertEquals( - "INTO TABLE users\nFIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"'\nDATE FORMAT \"YYYY-MM-DD\"\nTRAILING NULLCOLS\n(\n id,\n name,\n email\n)\n", - $table - ); -}); - -test('it can build it\'s own sql string without format options', function () { - $table = new TableDefinition( - 'users', - ['id', 'name', 'email'], - terminatedBy: ',', - enclosedBy: '"', - trailing: 'TRAILING NULLCOLS', - ); - - assertEquals( - "INTO TABLE users\nFIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"'\nTRAILING NULLCOLS\n(\n id,\n name,\n email\n)\n", - $table - ); -}); - -test('it can build it\'s own sql string without trailing', function () { - $table = new TableDefinition( - 'users', - ['id', 'name', 'email'], - terminatedBy: ',', - enclosedBy: '"', - ); - - assertEquals( - "INTO TABLE users\nFIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"'\n(\n id,\n name,\n email\n)\n", - $table - ); -}); - -test('it can build it\'s own sql string without enclosed by', function () { - $table = new TableDefinition( - 'users', - ['id', 'name', 'email'], - terminatedBy: ',', - ); - - assertEquals( - "INTO TABLE users\nFIELDS TERMINATED BY ','\n(\n id,\n name,\n email\n)\n", - $table - ); -}); - -test('it can build it\'s own sql string without terminated by', function () { - $table = new TableDefinition( - 'users', - ['id', 'name', 'email'], - ); - - assertEquals( - "INTO TABLE users\n(\n id,\n name,\n email\n)\n", - $table->__toString() - ); -}); - -test('it can build it\'s own sql string with empty columns', function () { - $table = new TableDefinition( - 'users', - [], - ); - - assertEquals( - "INTO TABLE users\n(\n)\n", - $table - ); -}); - -test('it can build with when clause', function () { - $table = new TableDefinition( - 'users', - ['id', 'name', 'email'], - when: 'id > 0', - ); - - assertEquals( - "INTO TABLE users\nWHEN id > 0\n(\n id,\n name,\n email\n)\n", - $table - ); -}); - -test('it can build with csv format', function () { - $table = new TableDefinition( - 'users', - ['id', 'name', 'email'], - csv: true, - ); - - assertEquals( - "INTO TABLE users\nFIELDS CSV WITH EMBEDDED\n(\n id,\n name,\n email\n)\n", - $table->__toString() - ); -}); - -test('it can build with csv format without embedded', function () { - $table = new TableDefinition( - 'users', - ['id', 'name', 'email'], - csv: true, - withEmbedded: false, - ); - - assertEquals( - "INTO TABLE users\nFIELDS CSV WITHOUT EMBEDDED\n(\n id,\n name,\n email\n)\n", - $table - ); +describe('Table Definition Builder', function () { + + test('it can build it\'s own sql string', function () { + $table = new TableDefinition( + 'users', + ['id', 'name', 'email'], + terminatedBy: ',', + enclosedBy: '"', + trailing: 'TRAILING NULLCOLS', + formatOptions: [ + 'DATE FORMAT "YYYY-MM-DD"', + ] + ); + + assertEquals( + "INTO TABLE users\nFIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"'\nDATE FORMAT \"YYYY-MM-DD\"\nTRAILING NULLCOLS\n(\n id,\n name,\n email\n)\n", + $table + ); + }); + + test('it can build it\'s own sql string without format options', function () { + $table = new TableDefinition( + 'users', + ['id', 'name', 'email'], + terminatedBy: ',', + enclosedBy: '"', + trailing: 'TRAILING NULLCOLS', + ); + + assertEquals( + "INTO TABLE users\nFIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"'\nTRAILING NULLCOLS\n(\n id,\n name,\n email\n)\n", + $table + ); + }); + + test('it can build it\'s own sql string without trailing', function () { + $table = new TableDefinition( + 'users', + ['id', 'name', 'email'], + terminatedBy: ',', + enclosedBy: '"', + ); + + assertEquals( + "INTO TABLE users\nFIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"'\n(\n id,\n name,\n email\n)\n", + $table + ); + }); + + test('it can build it\'s own sql string without enclosed by', function () { + $table = new TableDefinition( + 'users', + ['id', 'name', 'email'], + terminatedBy: ',', + ); + + assertEquals( + "INTO TABLE users\nFIELDS TERMINATED BY ','\n(\n id,\n name,\n email\n)\n", + $table + ); + }); + + test('it can build it\'s own sql string without terminated by', function () { + $table = new TableDefinition( + 'users', + ['id', 'name', 'email'], + ); + + assertEquals( + "INTO TABLE users\n(\n id,\n name,\n email\n)\n", + $table->__toString() + ); + }); + + test('it can build it\'s own sql string with empty columns', function () { + $table = new TableDefinition( + 'users', + [], + ); + + assertEquals( + "INTO TABLE users\n(\n)\n", + $table + ); + }); + + test('it can build with when clause', function () { + $table = new TableDefinition( + 'users', + ['id', 'name', 'email'], + when: 'id > 0', + ); + + assertEquals( + "INTO TABLE users\nWHEN id > 0\n(\n id,\n name,\n email\n)\n", + $table + ); + }); + + test('it can build with csv format', function () { + $table = new TableDefinition( + 'users', + ['id', 'name', 'email'], + csv: true, + ); + + assertEquals( + "INTO TABLE users\nFIELDS CSV WITH EMBEDDED\n(\n id,\n name,\n email\n)\n", + $table->__toString() + ); + }); + + test('it can build with csv format without embedded', function () { + $table = new TableDefinition( + 'users', + ['id', 'name', 'email'], + csv: true, + withEmbedded: false, + ); + + assertEquals( + "INTO TABLE users\nFIELDS CSV WITHOUT EMBEDDED\n(\n id,\n name,\n email\n)\n", + $table + ); + }); });