Skip to content
This repository was archived by the owner on Jun 4, 2024. It is now read-only.

Commit fb44a22

Browse files
authored
Merge pull request #112 from SOHELAHMED7/100-timestamp-migrations-do-not-work-in-mariadb
undefined
2 parents eec3efd + a00a8da commit fb44a22

File tree

121 files changed

+3799
-344
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

121 files changed

+3799
-344
lines changed

.github/workflows/test.yml

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -21,38 +21,32 @@ jobs:
2121
fail-fast: true
2222
matrix:
2323
php-versions: ['7.1', '7.2', '7.3', '7.4']
24+
25+
# TODO use cache
2426
steps:
2527
- uses: actions/checkout@v2
2628

27-
- name: Setup PHP, with composer and extensions
28-
uses: shivammathur/setup-php@v2 #https://github.com/shivammathur/setup-php
29+
# Run every tests inside Docker container
30+
- name: Docker Compose Setup
31+
uses: ndeloof/[email protected]
2932
with:
30-
php-version: ${{ matrix.php-versions }}
31-
extensions: mbstring, intl, gd, zip, dom, pgsql
32-
tools: php-cs-fixer
33-
34-
- name: Get composer cache directory
35-
id: composercache
36-
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
33+
# version: v3.5 # defaults to 'latest'
34+
legacy: true # will also install in PATH as `docker-compose`
3735

38-
- name: Cache Composer packages
39-
id: composer-cache
40-
uses: actions/cache@v2
41-
with:
42-
path: ${{ steps.composercache.outputs.dir }}
43-
key: ${{ runner.os }}-php-${{ matrix.php-versions }}-${{ hashFiles('**/composer.json') }}
44-
restore-keys: |
45-
${{ runner.os }}-php-${{ matrix.php-versions }}
36+
- name: Clean
37+
run: make clean_all
4638

47-
- name: Install deps
48-
run: composer install --prefer-dist --no-progress --no-suggest --optimize-autoloader
39+
- name: docker-compose up
40+
run: make up
4941

50-
- name: Prepare permissions
51-
run: mkdir -p tests/tmp && chmod -R 0777 tests/tmp
42+
- name: Install Docker and composer dependencies
43+
run: make installdocker
5244

53-
- name: Unit tests
54-
run: php vendor/bin/phpunit
45+
- name: Migrate
46+
run: make migrate
5547

5648
- name: Check style
57-
run: make check-style
49+
run: make check-style-from-host
5850

51+
- name: Run tests
52+
run: make testdocker

Makefile

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ all:
77
check-style:
88
vendor/bin/php-cs-fixer fix --diff --dry-run
99

10+
check-style-from-host:
11+
docker-compose run --rm php sh -c 'vendor/bin/php-cs-fixer fix --diff --dry-run'
12+
1013
fix-style:
1114
vendor/bin/indent --tabs composer.json
1215
vendor/bin/indent --spaces .php_cs.dist
@@ -28,20 +31,40 @@ clean:
2831

2932
up:
3033
docker-compose up -d
34+
echo "Waiting for mariadb to start up..."
35+
docker-compose exec -T mysql timeout 60s sh -c "while ! (mysql -udbuser -pdbpass -h maria --execute 'SELECT 1;' > /dev/null 2>&1); do echo -n '.'; sleep 0.1 ; done; echo 'ok'" || (docker-compose ps; docker-compose logs; exit 1)
3136

3237
cli:
3338
docker-compose exec php bash
3439

3540
migrate:
36-
mkdir -p "tests/tmp/app"
37-
mkdir -p "tests/tmp/docker_app"
41+
docker-compose run --rm php sh -c 'mkdir -p "tests/tmp/app"'
42+
docker-compose run --rm php sh -c 'mkdir -p "tests/tmp/docker_app"'
3843
docker-compose run --rm php sh -c 'cd /app/tests && ./yii migrate --interactive=0'
3944

4045
installdocker:
4146
docker-compose run --rm php composer install && chmod +x tests/yii
4247

4348
testdocker:
44-
docker-compose run --rm php sh -c 'vendor/bin/phpunit tests/unit'
49+
docker-compose run --rm php sh -c 'vendor/bin/phpunit'
4550

4651
.PHONY: all check-style fix-style install test clean clean_all up cli installdocker migrate testdocker
4752

53+
54+
# Docs:
55+
56+
# outside docker
57+
# clean_all
58+
# clean (in both)
59+
# up
60+
# cli
61+
# migrate
62+
# installdocker
63+
# testdocker
64+
65+
# inside docker
66+
# check-style
67+
# fix-style
68+
# install
69+
# test
70+
# clean (in both)

README.md

Lines changed: 141 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ On console you can run the generator with `./yii gii/api --openApiPath=@app/open
7070

7171
Run `./yii gii/api --help` for all options.
7272

73+
See [Petstore example](https://github.com/OAI/OpenAPI-Specification/blob/main/examples/v3.0/petstore.yaml) for example OpenAPI spec.
74+
7375

7476
## OpenAPI extensions
7577

@@ -114,9 +116,27 @@ Explicitly specify primary key name for table, if it is different from "id"
114116

115117
### `x-db-type`
116118

117-
Explicitly specify the database type for a column. (MUST contains only db type! (json, jsonb, uuid, varchar etc))
118-
If x-db-type sets as false, property will be processed as virtual;
119-
It will be added in model as public property, but skipped for migrations generation
119+
Explicitly specify the database type for a column. (MUST contains only real DB type! (`json`, `jsonb`, `uuid`, `varchar` etc.)).
120+
If x-db-type sets as `false`, property will be processed as virtual;
121+
It will be added in model as public property, but skipped for migrations generation.
122+
123+
Example values of `x-db-type` are:
124+
125+
- `false` (boolean false)
126+
- as string and its value can be like:
127+
- text
128+
- text[]
129+
- INTEGER PRIMARY KEY AUTO_INCREMENT
130+
- decimal(12,4)
131+
- json
132+
- varchar
133+
- VARCHAR
134+
- SMALLINT UNSIGNED ZEROFILL
135+
- MEDIUMINT(10) UNSIGNED ZEROFILL COMMENT "comment" (note the double quotes here)
136+
137+
Such values are not allowed:
138+
- `int null default null after low_price` (null and default will be handled by `nullable` and `default` keys respectively)
139+
- MEDIUMINT(10) UNSIGNED ZEROFILL NULL DEFAULT '7' COMMENT 'comment' AFTER `seti`, ADD INDEX `t` (`w`)
120140

121141
### `x-indexes`
122142
Specify table indexes
@@ -248,6 +268,97 @@ $this->update('{{%company}}', ['name' => 'No name']);
248268
$this->alterColumn('{{%company}}', 'name', $this->string(128)->notNull());
249269
```
250270

271+
### Handling of `NOT NULL` constraints
272+
273+
`NOT NULL` in DB migrations is determined by `nullable` and `required` properties of the OpenAPI schema.
274+
e.g. attribute = 'my_property'.
275+
276+
- If you define attribute neither "required" nor via "nullable", then it is by default `NULL`:
277+
278+
```yaml
279+
ExampleSchema:
280+
properties:
281+
my_property:
282+
type: string
283+
```
284+
285+
- If you define attribute in "required", then it is `NOT NULL`
286+
287+
```yaml
288+
ExampleSchema:
289+
required:
290+
- my_property
291+
properties:
292+
my_property:
293+
type: string
294+
```
295+
296+
- If you define attribute via "nullable", then it overrides "required", e.g. allow `NULL` in this case:
297+
298+
```yaml
299+
ExampleSchema:
300+
required:
301+
- my_property
302+
properties:
303+
my_property:
304+
type: string
305+
nullable: true
306+
```
307+
308+
- If you define attribute via "nullable", then it overrides "required", e.g. `NOT NULL` in this case:
309+
310+
```yaml
311+
test_table:
312+
required:
313+
properties:
314+
my_property:
315+
type: string
316+
nullable: false
317+
```
318+
319+
### Handling of `enum` (#enum, #MariaDb)
320+
It work on MariaDb.
321+
322+
```yaml
323+
test_table:
324+
properties:
325+
my_property:
326+
enum:
327+
- one
328+
- two
329+
- three
330+
```
331+
332+
### Handling of `numeric` (#numeric, #MariaDb)
333+
precision-default = 10
334+
scale-default = 2
335+
336+
- You can define attribute like "numeric(precision,scale)":
337+
```yaml
338+
test_table:
339+
properties:
340+
my_property:
341+
x-db-type: decimal(12,4)
342+
```
343+
DB-Result = decimal(12,4)
344+
345+
- You can define attribute like "numeric(precision)" with default scale-default = 2:
346+
```yaml
347+
test_table:
348+
properties:
349+
my_property:
350+
x-db-type: decimal(12)
351+
```
352+
DB-Result = decimal(12,2)
353+
354+
- You can define attribute like "numeric" with precision-default = 10 and scale-default = 2:
355+
```yaml
356+
test_table:
357+
properties:
358+
my_property:
359+
x-db-type: decimal
360+
```
361+
DB-Result = decimal(10,2)
251362

252363
## Screenshots
253364

@@ -259,6 +370,32 @@ Generated files:
259370

260371
![Gii Generated Files](doc/screenshot-files.png)
261372

373+
# Development
374+
375+
There commands are available to develop and check the tests. It can be used inside the Docker container. To enter into bash of container run `make cli` .
376+
377+
```bash
378+
./yii migrate-mysql/up
379+
./yii migrate-mysql/down 4
380+
381+
./yii migrate-maria/up
382+
./yii migrate-maria/down 4
383+
384+
./yii migrate-pgsql/up
385+
./yii migrate-pgsql/down 4
386+
```
387+
388+
To apply multiple migration with one command:
389+
390+
```bash
391+
./yii migrate-mysql/up --interactive=0 && \
392+
./yii migrate-mysql/down --interactive=0 4 && \
393+
./yii migrate-maria/up --interactive=0 && \
394+
./yii migrate-maria/down --interactive=0 4 && \
395+
./yii migrate-pgsql/up --interactive=0 && \
396+
./yii migrate-pgsql/down --interactive=0 4
397+
```
398+
262399
# Support
263400

264401
**Need help with your API project?**
@@ -268,3 +405,4 @@ Professional support, consulting as well as software development services are av
268405
https://www.cebe.cc/en/contact
269406

270407
Development of this library is sponsored by [cebe.:cloud: "Your Professional Deployment Platform"](https://cebe.cloud).
408+

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
"yiisoft/yii2-gii": "~2.0.0 | ~2.1.0 | ~2.2.0| ~2.3.0",
2525
"laminas/laminas-code": "^3.4",
2626
"insolita/yii2-fractal": "^1.0.0",
27-
"fakerphp/faker": "^1.9"
27+
"fakerphp/faker": "^1.9",
28+
"sam-it/yii2-mariadb": "^2.0"
2829
},
2930
"require-dev": {
3031
"cebe/indent": "*",

docker-compose.yml

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,19 +33,21 @@ services:
3333
MYSQL_USER: dbuser
3434
MYSQL_PASSWORD: dbpass
3535
MYSQL_DATABASE: testdb
36+
3637
maria:
37-
image: mariadb
38+
image: mariadb:10.8
3839
ports:
3940
- '23306:3306'
4041
volumes:
4142
- ./tests/tmp/maria:/var/lib/mysql:rw
4243
environment:
43-
TZ: UTC
44-
MYSQL_ALLOW_EMPTY_PASSWORD: 1
45-
MYSQL_USER: dbuser
46-
MYSQL_PASSWORD: dbpass
47-
MYSQL_DATABASE: testdb
48-
MYSQL_INITDB_SKIP_TZINFO: 1
44+
# TZ: UTC
45+
# MARIADB_ALLOW_EMPTY_PASSWORD: 1
46+
MARIADB_ROOT_PASSWORD: verysecret
47+
MARIADB_USER: dbuser
48+
MARIADB_PASSWORD: dbpass
49+
MARIADB_DATABASE: testdb
50+
# MYSQL_INITDB_SKIP_TZINFO: 1
4951
postgres:
5052
image: postgres:12
5153
ports:

src/db/ColumnSchema.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
/**
4+
* @copyright Copyright (c) 2018 Carsten Brandt <[email protected]> and contributors
5+
* @license https://github.com/cebe/yii2-openapi/blob/master/LICENSE
6+
*/
7+
8+
namespace cebe\yii2openapi\db;
9+
10+
class ColumnSchema extends \yii\db\ColumnSchema
11+
{
12+
/**
13+
* @var string|null|false
14+
* Custom DB type which contains real DB type
15+
* Contains x-db-type string if present in OpenAPI YAML/json file
16+
* @see \cebe\yii2openapi\lib\items\Attribute::$xDbType and `x-db-type` docs in README.md
17+
* Used to detect what kind of migration code for column is to be generated
18+
* e.g. `double_p double precision NULL DEFAULT NULL`
19+
* instead of
20+
* ```php
21+
* $this->createTable('{{%alldbdatatypes}}', [
22+
* ...
23+
* 'double_p' => 'double precision NULL DEFAULT NULL',
24+
* ...
25+
* ```
26+
*/
27+
public $xDbType;
28+
}

src/generator/ApiGenerator.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77

88
namespace cebe\yii2openapi\generator;
99

10+
use yii\db\mysql\Schema as MySqlSchema;
11+
use SamIT\Yii2\MariaDb\Schema as MariaDbSchema;
12+
use yii\db\pgsql\Schema as PgSqlSchema;
1013
use cebe\openapi\Reader;
1114
use cebe\openapi\spec\OpenApi;
1215
use cebe\yii2openapi\lib\Config;
@@ -502,4 +505,19 @@ protected function getOpenApiWithoutReferences():OpenApi
502505
}
503506
return $this->_openApiWithoutRef;
504507
}
508+
509+
public static function isPostgres():bool
510+
{
511+
return Yii::$app->db->schema instanceof PgSqlSchema;
512+
}
513+
514+
public static function isMysql():bool
515+
{
516+
return (Yii::$app->db->schema instanceof MySqlSchema && !static::isMariaDb());
517+
}
518+
519+
public static function isMariaDb():bool
520+
{
521+
return strpos(Yii::$app->db->schema->getServerVersion(), 'MariaDB') !== false;
522+
}
505523
}

src/lib/AttributeResolver.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,8 @@ protected function resolveProperty(PropertySchema $property, bool $isRequired):v
203203
->setDescription($property->getAttr('description', ''))
204204
->setReadOnly($property->isReadonly())
205205
->setDefault($property->guessDefault())
206+
->setXDbType($property->getAttr('x-db-type'))
207+
->setNullable($property->getProperty()->getSerializableData()->nullable ?? null)
206208
->setIsPrimary($property->isPrimaryKey());
207209
if ($property->isReference()) {
208210
if ($property->isVirtual()) {

0 commit comments

Comments
 (0)