Skip to content

Commit 4610af5

Browse files
committed
Fix invalid default value for timestamp column.
1 parent 378f6c6 commit 4610af5

File tree

7 files changed

+218
-1
lines changed

7 files changed

+218
-1
lines changed

src/AuditTable.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ public function __construct(AuditStyle $io,
9898
$this->additionalAuditColumns = $additionalAuditColumns;
9999
$this->alias = $alias;
100100
$this->skipVariable = $skipVariable;
101+
102+
$this->dataTableColumnsDatabase->makeNullable();
101103
}
102104

103105
//--------------------------------------------------------------------------------------------------------------------

src/MySql/Sql/AlterAuditTableAddColumns.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public function buildStatement(): string
6262
$code->append(sprintf('alter table `%s`.`%s`', $this->auditSchemaName, $this->tableName));
6363
foreach ($this->columns->getColumns() as $column)
6464
{
65-
$code->append(sprintf(' add `%s` %s', $column->getName(), $column->getProperty('column_type')), false);
65+
$code->append(sprintf(' add `%s` %s', $column->getName(), $column->getColumnAuditDefinition()), false);
6666
$after = $column->getProperty('after');
6767
if (isset($after))
6868
{
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace SetBased\Audit\Test\MySql\AuditCommand\AddTimestampColumn;
5+
6+
use SetBased\Audit\MySql\AuditDataLayer;
7+
use SetBased\Audit\Test\MySql\AuditCommand\AuditCommandTestCase;
8+
use SetBased\Stratum\Middle\Helper\RowSetHelper;
9+
10+
/**
11+
* Tests for running audit with a new table column.
12+
*/
13+
class AddColumnTimestampTest extends AuditCommandTestCase
14+
{
15+
//--------------------------------------------------------------------------------------------------------------------
16+
/**
17+
* @inheritdoc
18+
*/
19+
public static function setUpBeforeClass(): void
20+
{
21+
self::$dir = __DIR__;
22+
23+
parent::setUpBeforeClass();
24+
}
25+
26+
//--------------------------------------------------------------------------------------------------------------------
27+
public function test01(): void
28+
{
29+
// Run audit.
30+
$this->runAudit();
31+
32+
// TABLE1 MUST exist.
33+
$tables = AuditDataLayer::$dl->getTablesNames(self::$auditSchema);
34+
self::assertNotNull(RowSetHelper::searchInRowSet($tables, 'table_name', 'TABLE1'));
35+
36+
// TABLE1 MUST have triggers.
37+
$triggers = AuditDataLayer::$dl->getTableTriggers(self::$dataSchema, 'TABLE1');
38+
self::assertNotNull(RowSetHelper::searchInRowSet($triggers, 'trigger_name', 'trg_audit_t1_insert'));
39+
self::assertNotNull(RowSetHelper::searchInRowSet($triggers, 'trigger_name', 'trg_audit_t1_update'));
40+
self::assertNotNull(RowSetHelper::searchInRowSet($triggers, 'trigger_name', 'trg_audit_t1_delete'));
41+
42+
$actual = AuditDataLayer::$dl->getTableColumns(self::$auditSchema, 'TABLE1');
43+
44+
$expected = [['column_name' => 'audit_timestamp',
45+
'column_type' => 'timestamp',
46+
'column_default' => 'current_timestamp()',
47+
'is_nullable' => 'NO',
48+
'character_set_name' => null,
49+
'collation_name' => null],
50+
['column_name' => 'audit_statement',
51+
'column_type' => "enum('INSERT','DELETE','UPDATE')",
52+
'column_default' => 'NULL',
53+
'is_nullable' => 'NO',
54+
'character_set_name' => 'ascii',
55+
'collation_name' => 'ascii_general_ci'],
56+
['column_name' => 'audit_type',
57+
'column_type' => "enum('OLD','NEW')",
58+
'column_default' => 'NULL',
59+
'is_nullable' => 'NO',
60+
'character_set_name' => 'ascii',
61+
'collation_name' => 'ascii_general_ci'],
62+
['column_name' => 'c1',
63+
'column_type' => 'tinyint(4)',
64+
'column_default' => 'NULL',
65+
'is_nullable' => 'YES',
66+
'character_set_name' => null,
67+
'collation_name' => null],
68+
['column_name' => 'c2',
69+
'column_type' => 'smallint(6)',
70+
'column_default' => 'NULL',
71+
'is_nullable' => 'YES',
72+
'character_set_name' => null,
73+
'collation_name' => null],
74+
['column_name' => 'c5',
75+
'column_type' => 'int(11)',
76+
'column_default' => 'NULL',
77+
'is_nullable' => 'YES',
78+
'character_set_name' => null,
79+
'collation_name' => null]];
80+
81+
self::assertSame($expected, $actual);
82+
83+
// Create new columns.
84+
AuditDataLayer::$dl->executeMulti(file_get_contents(__DIR__.'/config/create_new_columns.sql'));
85+
86+
$this->runAudit();
87+
88+
// TABLE1 MUST exist.
89+
$tables = AuditDataLayer::$dl->getTablesNames(self::$auditSchema);
90+
self::assertNotNull(RowSetHelper::searchInRowSet($tables, 'table_name', 'TABLE1'));
91+
92+
// TABLE1 MUST have triggers.
93+
$triggers = AuditDataLayer::$dl->getTableTriggers(self::$dataSchema, 'TABLE1');
94+
self::assertNotNull(RowSetHelper::searchInRowSet($triggers, 'trigger_name', 'trg_audit_t1_insert'));
95+
self::assertNotNull(RowSetHelper::searchInRowSet($triggers, 'trigger_name', 'trg_audit_t1_update'));
96+
self::assertNotNull(RowSetHelper::searchInRowSet($triggers, 'trigger_name', 'trg_audit_t1_delete'));
97+
98+
// TABLE1 must have column c3.
99+
$actual = AuditDataLayer::$dl->getTableColumns(self::$auditSchema, 'TABLE1');
100+
101+
$expected = [['column_name' => 'audit_timestamp',
102+
'column_type' => 'timestamp',
103+
'column_default' => 'current_timestamp()',
104+
'is_nullable' => 'NO',
105+
'character_set_name' => null,
106+
'collation_name' => null],
107+
['column_name' => 'audit_statement',
108+
'column_type' => "enum('INSERT','DELETE','UPDATE')",
109+
'column_default' => 'NULL',
110+
'is_nullable' => 'NO',
111+
'character_set_name' => 'ascii',
112+
'collation_name' => 'ascii_general_ci'],
113+
['column_name' => 'audit_type',
114+
'column_type' => "enum('OLD','NEW')",
115+
'column_default' => 'NULL',
116+
'is_nullable' => 'NO',
117+
'character_set_name' => 'ascii',
118+
'collation_name' => 'ascii_general_ci'],
119+
['column_name' => 'c1',
120+
'column_type' => 'tinyint(4)',
121+
'column_default' => 'NULL',
122+
'is_nullable' => 'YES',
123+
'character_set_name' => null,
124+
'collation_name' => null],
125+
['column_name' => 'c2',
126+
'column_type' => 'smallint(6)',
127+
'column_default' => 'NULL',
128+
'is_nullable' => 'YES',
129+
'character_set_name' => null,
130+
'collation_name' => null],
131+
['column_name' => 'c3',
132+
'column_type' => 'timestamp',
133+
'column_default' => 'NULL',
134+
'is_nullable' => 'YES',
135+
'character_set_name' => null,
136+
'collation_name' => null],
137+
['column_name' => 'c4',
138+
'column_type' => 'timestamp',
139+
'column_default' => 'NULL',
140+
'is_nullable' => 'YES',
141+
'character_set_name' => null,
142+
'collation_name' => null],
143+
['column_name' => 'c5',
144+
'column_type' => 'int(11)',
145+
'column_default' => 'NULL',
146+
'is_nullable' => 'YES',
147+
'character_set_name' => null,
148+
'collation_name' => null]];
149+
150+
self::assertSame($expected, $actual);
151+
152+
// Test triggers.
153+
AuditDataLayer::$dl->executeNone('insert into `TABLE1`(c1, c2, c4, c5) values(1, 2, \'2000-01-01\', 5)');
154+
AuditDataLayer::$dl->executeNone('update `TABLE1` set c1=10, c2=20, c4=\'2020-01-01\', c5=50');
155+
156+
$rows = AuditDataLayer::$dl->executeRows(sprintf('select * from `%s`.`TABLE1`',
157+
self::$dataSchema));
158+
AuditDataLayer::$dl->executeNone('delete from `TABLE1`');
159+
160+
$rows = AuditDataLayer::$dl->executeRows(sprintf('select * from `%s`.`TABLE1` where c5 is not null',
161+
self::$auditSchema));
162+
self::assertSame(4, count($rows), 'row_count');
163+
164+
$rows = AuditDataLayer::$dl->executeRows(sprintf('select * from `%s`.`TABLE1` where c3 is null',
165+
self::$auditSchema));
166+
self::assertSame(0, count($rows), 'row_count');
167+
}
168+
169+
//--------------------------------------------------------------------------------------------------------------------
170+
}
171+
172+
//----------------------------------------------------------------------------------------------------------------------
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"database": {
3+
"credentials": "credentials.ini"
4+
},
5+
"audit_columns": [
6+
{
7+
"column_name": "audit_timestamp",
8+
"column_type": "timestamp not null default now()",
9+
"expression": "now()"
10+
},
11+
{
12+
"column_name": "audit_statement",
13+
"column_type": "enum('INSERT','DELETE','UPDATE') character set ascii collate ascii_general_ci not null",
14+
"value_type": "ACTION"
15+
},
16+
{
17+
"column_name": "audit_type",
18+
"column_type": "enum('OLD','NEW') character set ascii collate ascii_general_ci not null",
19+
"value_type": "STATE"
20+
}
21+
],
22+
"tables": {
23+
"TABLE1": {
24+
"audit": true,
25+
"skip": null,
26+
"alias": "t1"
27+
}
28+
}
29+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
alter table `TABLE1` add column `c3` timestamp default CURRENT_TIMESTAMP after `c2`;
2+
alter table `TABLE1` add column `c4` timestamp null default null after `c3`;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[database]
2+
host = localhost
3+
user = test
4+
password = test
5+
data_schema = test_data
6+
audit_schema = test_audit
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
create table `TABLE1` (
2+
c1 tinyint,
3+
c2 smallint,
4+
c5 int
5+
);
6+

0 commit comments

Comments
 (0)