Added column casting feature for data insertion
This commit is contained in:
@@ -1,3 +1,8 @@
|
||||
## 1.19.0 [2023-09-28]
|
||||
|
||||
### Features
|
||||
1. Added column casting feature for data insertion
|
||||
|
||||
## 1.18.0 [2023-07-10]
|
||||
|
||||
### Features
|
||||
|
||||
@@ -175,6 +175,32 @@ $rows = MyTable::select(['field_one', new RawColumn('sum(field_two)', 'field_two
|
||||
|
||||
## Advanced usage
|
||||
|
||||
### Columns casting
|
||||
|
||||
Before insertion, the column will be converted to the required data type specified in the field `$casts`.
|
||||
This feature does not apply to data selection.
|
||||
The supported cast types are: `boolean`.
|
||||
|
||||
```php
|
||||
namespace App\Models\Clickhouse;
|
||||
|
||||
use PhpClickHouseLaravel\BaseModel;
|
||||
|
||||
class MyTable extends BaseModel
|
||||
{
|
||||
/**
|
||||
* The columns that should be cast.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts = ['some_bool_column' => 'boolean'];
|
||||
}
|
||||
// Then you can insert the data like this:
|
||||
MyTable::insertAssoc([
|
||||
['some_param' => 1, 'some_bool_column' => false],
|
||||
]);
|
||||
```
|
||||
|
||||
### Events
|
||||
|
||||
Events work just like an [eloquent model events](https://laravel.com/docs/9.x/eloquent#events)
|
||||
|
||||
@@ -18,7 +18,7 @@ services:
|
||||
soft: 262144
|
||||
hard: 262144
|
||||
ports:
|
||||
- "8124:8123"
|
||||
- "18123:8123"
|
||||
|
||||
clickhouse2:
|
||||
image: yandex/clickhouse-server
|
||||
|
||||
+29
-3
@@ -161,9 +161,7 @@ class BaseModel
|
||||
throw new Exception("Clickhouse does not allow update rows");
|
||||
}
|
||||
$this->exists = !static::insertAssoc([$this->getAttributes()])->isError();
|
||||
|
||||
$this->fireModelEvent('saved', false);
|
||||
|
||||
return $this->exists;
|
||||
}
|
||||
|
||||
@@ -189,6 +187,17 @@ class BaseModel
|
||||
public static function insertBulk(array $rows, array $columns = []): Statement
|
||||
{
|
||||
$instance = new static();
|
||||
if ($castsAssoc = (new static())->casts) {
|
||||
$casts = [];
|
||||
foreach ($castsAssoc as $castColumn => $castType) {
|
||||
if ($index = array_search($castColumn, $columns)) {
|
||||
$casts[$index] = $castType;
|
||||
}
|
||||
}
|
||||
foreach ($rows as &$row) {
|
||||
$row = static::castRow($row, $casts);
|
||||
}
|
||||
}
|
||||
return $instance->getThisClient()->insert($instance->getTableForInserts(), $rows, $columns);
|
||||
}
|
||||
|
||||
@@ -220,6 +229,11 @@ class BaseModel
|
||||
$row = array_replace(array_flip($keys), $row);
|
||||
}
|
||||
}
|
||||
if ($casts = (new static())->casts) {
|
||||
foreach ($rows as &$row) {
|
||||
$row = static::castRow($row, $casts);
|
||||
}
|
||||
}
|
||||
$instance = new static();
|
||||
return $instance->getThisClient()->insertAssocBulk($instance->getTableForInserts(), $rows);
|
||||
}
|
||||
@@ -236,7 +250,7 @@ class BaseModel
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare row to insert into DB, non associative array
|
||||
* Prepare row to insert into DB, non-associative array
|
||||
* Need to overwrite in nested models
|
||||
* @param array $row
|
||||
* @param array $columns
|
||||
@@ -258,6 +272,18 @@ class BaseModel
|
||||
return $row;
|
||||
}
|
||||
|
||||
protected static function castRow(array $row, array $casts): array
|
||||
{
|
||||
foreach ($casts as $index => $castType) {
|
||||
$value = $row[$index];
|
||||
if ('boolean' == $castType) {
|
||||
$value = (int)(bool)$value;
|
||||
}
|
||||
$row[$index] = $value;
|
||||
}
|
||||
return $row;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|array|RawColumn $select optional = ['*']
|
||||
* @return Builder
|
||||
|
||||
@@ -14,7 +14,11 @@ cp /src/tests/config/database.php /app/config/database.php
|
||||
cp /src/tests/config/app.php /app/config/app.php
|
||||
cp /src/tests/migrations/exampleTable.php /app/database/migrations/2022_01_01_000000_example.php
|
||||
cp /src/tests/migrations/example2Table.php /app/database/migrations/2022_01_01_000001_example.php
|
||||
cp /src/tests/migrations/example3Table.php /app/database/migrations/2022_01_01_000002_example.php
|
||||
cat /src/tests/config/.env >> /app/.env
|
||||
|
||||
# Creating test tables
|
||||
php artisan migrate
|
||||
|
||||
# Running tests
|
||||
php artisan test
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Tests;
|
||||
|
||||
use Tests\Models\Example3;
|
||||
|
||||
class CastsTest extends TestCase
|
||||
{
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
Example3::truncate();
|
||||
}
|
||||
|
||||
public function testCasts()
|
||||
{
|
||||
Example3::insertAssoc([['f_int' => 1, 'f_bool' => false]]);
|
||||
$rows = Example3::where('f_int', 1)->getRows();
|
||||
$this->assertEquals(false, $rows[0]['f_bool']);
|
||||
|
||||
Example3::truncate();
|
||||
Example3::insertBulk([[2, false]], ['f_int', 'f_bool']);
|
||||
$rows = Example3::where('f_int', 2)->getRows();
|
||||
$this->assertEquals(false, $rows[0]['f_bool']);
|
||||
|
||||
Example3::truncate();
|
||||
$one = new Example3();
|
||||
$one->f_int = 3;
|
||||
$one->f_bool = false;
|
||||
$one->save();
|
||||
$rows = Example3::where('f_int', 3)->getRows();
|
||||
$this->assertEquals(false, $rows[0]['f_bool']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Models;
|
||||
|
||||
use PhpClickHouseLaravel\BaseModel;
|
||||
|
||||
/**
|
||||
* @property bool $f_bool
|
||||
* @property int $f_int
|
||||
*/
|
||||
class Example3 extends BaseModel
|
||||
{
|
||||
protected $table = 'examples3';
|
||||
protected $casts = ['f_bool' => 'boolean'];
|
||||
}
|
||||
@@ -13,7 +13,7 @@ return new class extends \PhpClickHouseLaravel\Migration {
|
||||
{
|
||||
static::write(
|
||||
"
|
||||
CREATE TABLE examples2 (
|
||||
CREATE TABLE IF NOT EXISTS examples2 (
|
||||
created_at DateTime64 DEFAULT now64(),
|
||||
f_int Int64,
|
||||
f_int2 Int64,
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
return new class extends \PhpClickHouseLaravel\Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
static::write(
|
||||
"
|
||||
CREATE TABLE IF NOT EXISTS examples3 (
|
||||
created_at DateTime64 DEFAULT now64(),
|
||||
f_int Int64,
|
||||
f_string String,
|
||||
f_bool Bool
|
||||
)
|
||||
ENGINE = MergeTree()
|
||||
ORDER BY (f_int)
|
||||
"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
static::write('DROP TABLE examples3');
|
||||
}
|
||||
};
|
||||
@@ -10,7 +10,7 @@ return new class extends \PhpClickHouseLaravel\Migration {
|
||||
{
|
||||
static::write(
|
||||
"
|
||||
CREATE TABLE examples (
|
||||
CREATE TABLE IF NOT EXISTS examples (
|
||||
created_at DateTime64 DEFAULT now64(),
|
||||
f_int Int64,
|
||||
f_int2 Int64,
|
||||
|
||||
Reference in New Issue
Block a user