Skip to content

Commit 9c4245a

Browse files
authored
Merge pull request #1271 from norberttech/feature/dbal-extractor-schema
Allow to pass schema to doctrine dbal extractors
2 parents 59e3c88 + a195e4c commit 9c4245a

File tree

19 files changed

+573
-25
lines changed

19 files changed

+573
-25
lines changed

examples/run.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@
3232
print "\nExample: {$file->getRelativePathname()}\n";
3333

3434
try {
35-
include $file->getRealPath();
35+
if ($file->getBasename() === 'code.php') {
36+
include $file->getRealPath();
37+
}
3638
} catch (Exception $e) {
3739
print "Example failed: {$e->getMessage()}\n";
3840

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use function Flow\ETL\Adapter\Doctrine\to_dbal_table_insert;
6+
use function Flow\ETL\DSL\{data_frame, from_array, overwrite};
7+
use Doctrine\DBAL\DriverManager;
8+
use Doctrine\DBAL\Schema\{Column, Table};
9+
use Doctrine\DBAL\Types\{Type, Types};
10+
11+
require __DIR__ . '/../../../autoload.php';
12+
13+
$generateOrders = require __DIR__ . '/generate_orders.php';
14+
15+
$connection = DriverManager::getConnection([
16+
'path' => __DIR__ . '/output/orders.db',
17+
'driver' => 'pdo_sqlite',
18+
]);
19+
20+
$schemaManager = $connection->createSchemaManager();
21+
22+
if ($schemaManager->tablesExist(['orders'])) {
23+
$schemaManager->dropTable('orders');
24+
}
25+
26+
$schemaManager->createTable(new Table(
27+
$table = 'orders',
28+
[
29+
new Column('order_id', Type::getType(Types::GUID), ['notnull' => true]),
30+
new Column('created_at', Type::getType(Types::DATETIME_IMMUTABLE), ['notnull' => true]),
31+
new Column('updated_at', Type::getType(Types::DATETIME_IMMUTABLE), ['notnull' => false]),
32+
new Column('discount', Type::getType(Types::FLOAT), ['notnull' => false]),
33+
new Column('email', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]),
34+
new Column('customer', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]),
35+
new Column('address', Type::getType(Types::JSON), ['notnull' => true]),
36+
new Column('notes', Type::getType(Types::JSON), ['notnull' => true]),
37+
new Column('items', Type::getType(Types::JSON), ['notnull' => true]),
38+
],
39+
));
40+
41+
data_frame()
42+
->read(from_array(generateOrders(10)))
43+
->saveMode(overwrite())
44+
->write(
45+
to_dbal_table_insert(
46+
DriverManager::getConnection([
47+
'path' => __DIR__ . '/output/orders.db',
48+
'driver' => 'pdo_sqlite',
49+
]),
50+
'orders',
51+
)
52+
)
53+
->run();
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
function generateOrders(int $count) : Generator
6+
{
7+
$faker = Faker\Factory::create();
8+
9+
$skus = [
10+
['sku' => 'SKU_0001', 'name' => 'Product 1', 'price' => $faker->randomFloat(2, 0, 500)],
11+
['sku' => 'SKU_0002', 'name' => 'Product 2', 'price' => $faker->randomFloat(2, 0, 500)],
12+
['sku' => 'SKU_0003', 'name' => 'Product 3', 'price' => $faker->randomFloat(2, 0, 500)],
13+
['sku' => 'SKU_0004', 'name' => 'Product 4', 'price' => $faker->randomFloat(2, 0, 500)],
14+
['sku' => 'SKU_0005', 'name' => 'Product 5', 'price' => $faker->randomFloat(2, 0, 500)],
15+
];
16+
17+
for ($i = 0; $i < $count; $i++) {
18+
yield [
19+
'order_id' => $faker->uuid,
20+
'created_at' => $faker->dateTimeThisYear,
21+
'updated_at' => \random_int(0, 1) === 1 ? $faker->dateTimeThisMonth : null,
22+
'discount' => \random_int(0, 1) === 1 ? $faker->randomFloat(2, 0, 50) : null,
23+
'email' => $faker->email,
24+
'customer' => $faker->firstName . ' ' . $faker->lastName,
25+
'address' => [
26+
'street' => $faker->streetAddress,
27+
'city' => $faker->city,
28+
'zip' => $faker->postcode,
29+
'country' => $faker->country,
30+
],
31+
'notes' => \array_map(
32+
static fn ($i) => $faker->sentence,
33+
\range(1, $faker->numberBetween(1, 5))
34+
),
35+
'items' => \array_map(
36+
static fn (int $index) => [
37+
'sku' => $skus[$skuIndex = $faker->numberBetween(1, 4)]['sku'],
38+
'quantity' => $faker->numberBetween(1, 10),
39+
'price' => $skus[$skuIndex]['price'],
40+
],
41+
\range(1, $faker->numberBetween(1, 4))
42+
),
43+
];
44+
}
45+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
orders.db
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use function Flow\ETL\Adapter\Doctrine\from_dbal_limit_offset;
6+
use function Flow\ETL\DSL\{data_frame, to_stream};
7+
use Doctrine\DBAL\DriverManager;
8+
use Flow\ETL\Adapter\Doctrine\{Order, OrderBy};
9+
10+
require __DIR__ . '/../../../autoload.php';
11+
12+
$connection = DriverManager::getConnection([
13+
'path' => __DIR__ . '/input/orders.db',
14+
'driver' => 'pdo_sqlite',
15+
]);
16+
17+
data_frame()
18+
->read(
19+
from_dbal_limit_offset(
20+
$connection,
21+
'orders',
22+
new OrderBy('created_at', Order::DESC),
23+
)
24+
)
25+
->collect()
26+
->write(to_stream(__DIR__ . '/output.txt', truncate: false))
27+
->run();
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
Read data from Database through Doctrine DBAL
2+
3+
The example below shows how to read from a single table using limit/offset extractor.
4+
To read data from more advanced queries, you can use one of the following extractors:
5+
6+
```php
7+
// read from a single table using limit/offset pagination
8+
from_dbal_limit_offset(
9+
$connection,
10+
'orders',
11+
new OrderBy('created_at', Order::DESC),
12+
)
13+
// read from a query using limit/offset pagination
14+
from_dbal_limit_offset_qb(
15+
$connection,
16+
$connection->createQueryBuilder()->select('*')->from('orders')
17+
);
18+
// read from a single query
19+
from_dbal_query(
20+
$connection,
21+
'SELECT * FROM orders',
22+
);
23+
// read from multiple queries each time using next parameters from the provided set
24+
from_dbal_queries(
25+
$connection,
26+
'SELECT * FROM orders LIMIT :limit OFFSET :offset',
27+
new \Flow\ETL\Adapter\Doctrine\ParametersSet(
28+
['limit' => 2, 'offset' => 0],
29+
['limit' => 2, 'offset' => 2],
30+
)
31+
);
32+
```
33+
34+
Additionally, each of them allows setting dataset schema through `$extractor->withSchema(Schema $schema)` method.
20 KB
Binary file not shown.

0 commit comments

Comments
 (0)