Completed
Push — master ( 8e94f8...744b49 )
by P.R.
04:26
created

AuditDataLayer::getTableColumns()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 17
Code Lines 5

Duplication

Lines 17
Ratio 100 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 17
loc 17
ccs 6
cts 6
cp 1
rs 9.4285
cc 1
eloc 5
nc 1
nop 2
crap 1
1
<?php
2
//----------------------------------------------------------------------------------------------------------------------
3
namespace SetBased\Audit\MySql;
4
5
use SetBased\Audit\MySql\Metadata\TableColumnsMetadata;
6
use SetBased\Audit\MySql\Sql\AlterAuditTableAddColumns;
7
use SetBased\Audit\MySql\Sql\CreateAuditTable;
8
use SetBased\Audit\MySql\Sql\CreateAuditTrigger;
9
use SetBased\Helper\CodeStore\MySqlCompoundSyntaxCodeStore;
10
use SetBased\Stratum\MySql\StaticDataLayer;
11
use SetBased\Stratum\Style\StratumStyle;
12
13
//----------------------------------------------------------------------------------------------------------------------
14
/**
15
 * Class for executing SQL statements and retrieving metadata from MySQL.
16
 */
17
class AuditDataLayer
18
{
19
  //--------------------------------------------------------------------------------------------------------------------
20
  /**
21
   * The connection to the MySQL instance.
22
   *
23
   * @var StaticDataLayer
24
   */
25
  private static $dl;
26
27
  /**
28
   * The Output decorator.
29
   *
30
   * @var StratumStyle
31
   */
32
  private static $io;
33
34
  //--------------------------------------------------------------------------------------------------------------------
35
  /**
36
   * Adds new columns to an audit table.
37
   *
38
   * @param string               $auditSchemaName The name of audit schema.
39
   * @param string               $tableName       The name of the table.
40
   * @param TableColumnsMetadata $columns         The metadata of the new columns.
41
   */
42 8
  public static function addNewColumns($auditSchemaName, $tableName, $columns)
43
  {
44
    // Return immediately if there are no columns to add. 
45 8
    if ($columns->getNumberOfColumns()==0) return;
46
47
    $helper = new AlterAuditTableAddColumns($auditSchemaName, $tableName, $columns);
48
    $sql    = $helper->buildStatement();
49
50
    self::executeNone($sql);
51
  }
52
53
  //--------------------------------------------------------------------------------------------------------------------
54
  /**
55
   * Connects to a MySQL instance.
56
   *
57
   * Wrapper around [mysqli::__construct](http://php.net/manual/mysqli.construct.php), however on failure an exception
58
   * is thrown.
59
   *
60
   * @param string $host     The hostname.
61
   * @param string $user     The MySQL user name.
62
   * @param string $passWord The password.
63
   * @param string $database The default database.
64
   * @param int    $port     The port number.
65
   */
66 9
  public static function connect($host, $user, $passWord, $database, $port = 3306)
67
  {
68 9
    self::$dl = new StaticDataLayer();
69
70 9
    self::$dl->connect($host, $user, $passWord, $database, $port);
71 9
  }
72
73
  //--------------------------------------------------------------------------------------------------------------------
74
  /**
75
   * Creates an audit table.
76
   *
77
   * @param string               $dataSchemaName  The name of the data schema.
78
   * @param string               $auditSchemaName The name of the audit schema.
79
   * @param string               $tableName       The name of the table.
80
   * @param TableColumnsMetadata $columns         The metadata of the columns of the audit table (i.e. the audit
81
   *                                              columns and columns of the data table).
82
   */
83 5
  public static function createAuditTable($dataSchemaName, $auditSchemaName, $tableName, $columns)
84
  {
85 5
    $helper = new CreateAuditTable($dataSchemaName, $auditSchemaName, $tableName, $columns);
86 5
    $sql    = $helper->buildStatement();
87
88 5
    self::executeNone($sql);
89 5
  }
90
91
  //--------------------------------------------------------------------------------------------------------------------
92
  /**
93
   * Creates a trigger on a table.
94
   *
95
   * @param string               $dataSchemaName  The name of the data schema.
96
   * @param string               $auditSchemaName The name of the audit schema.
97
   * @param string               $tableName       The name of the table.
98
   * @param string               $triggerAction   The trigger action (i.e. INSERT, UPDATE, or DELETE).
99
   * @param string               $triggerName     The name of the trigger.
100
   * @param TableColumnsMetadata $auditColumns    The audit table columns.
101
   * @param TableColumnsMetadata $tableColumns    The data table columns.
102
   * @param string               $skipVariable    The skip variable.
103
   * @param string[]             $additionSql     Additional SQL statements.
104
   */
105 8
  public static function createAuditTrigger($dataSchemaName,
106
                                            $auditSchemaName,
107
                                            $tableName,
108
                                            $triggerAction,
109
                                            $triggerName,
110
                                            $auditColumns,
111
                                            $tableColumns,
112
                                            $skipVariable,
113
                                            $additionSql)
114
  {
115 8
    $helper = new CreateAuditTrigger($dataSchemaName,
116 8
                                     $auditSchemaName,
117 8
                                     $tableName,
118 8
                                     $triggerAction,
119 8
                                     $triggerName,
120 8
                                     $auditColumns,
121 8
                                     $tableColumns,
122 8
                                     $skipVariable,
123 8
                                     $additionSql);
124 8
    $sql    = $helper->buildStatement();
125
126 8
    self::executeNone($sql);
127 8
  }
128
129
  //--------------------------------------------------------------------------------------------------------------------
130
  /**
131
   * Create temp table for getting column type information for audit columns.
132
   *
133
   * @param string  $schemaName   The name of the table schema.
134
   * @param string  $tableName    The table name.
135
   * @param array[] $auditColumns Audit columns from config file.
136
   */
137 8
  public static function createTemporaryTable($schemaName, $tableName, $auditColumns)
138
  {
139 8
    $sql = new MySqlCompoundSyntaxCodeStore();
140 8
    $sql->append(sprintf('create table `%s`.`%s` (', $schemaName, $tableName));
141 8
    foreach ($auditColumns as $column)
142
    {
143 8
      $sql->append(sprintf('%s %s', $column['column_name'], $column['column_type']));
144 8
      if (end($auditColumns)!==$column)
145 8
      {
146 8
        $sql->appendToLastLine(',');
147 8
      }
148 8
    }
149 8
    $sql->append(')');
150
151 8
    self::executeNone($sql->getCode());
152 8
  }
153
154
  //--------------------------------------------------------------------------------------------------------------------
155
  /**
156
   * Closes the connection to the MySQL instance, if connected.
157
   */
158 9
  public static function disconnect()
159
  {
160 9
    if (self::$dl!==null)
161 9
    {
162 9
      self::$dl->disconnect();
163 9
      self::$dl = null;
164 9
    }
165 9
  }
166
167
  //--------------------------------------------------------------------------------------------------------------------
168
  /**
169
   * Drop table.
170
   *
171
   * @param string $schemaName The name of the table schema.
172
   * @param string $tableName  The name of the table.
173
   */
174 8
  public static function dropTemporaryTable($schemaName, $tableName)
175
  {
176 8
    $sql = sprintf('drop table `%s`.`%s`', $schemaName, $tableName);
177
178 8
    self::executeNone($sql);
179 8
  }
180
181
  //--------------------------------------------------------------------------------------------------------------------
182
  /**
183
   * Drops a trigger.
184
   *
185
   * @param string $triggerSchema The name of the trigger schema.
186
   * @param string $triggerName   The mame of trigger.
187
   */
188 3
  public static function dropTrigger($triggerSchema, $triggerName)
189
  {
190 3
    $sql = sprintf('drop trigger `%s`.`%s`', $triggerSchema, $triggerName);
191
192 3
    self::executeNone($sql);
193 3
  }
194
195
  //--------------------------------------------------------------------------------------------------------------------
196
  /**
197
   * @param string $query The SQL statement.
198
   *
199
   * @return int The number of affected rows (if any).
200
   */
201 8
  public static function executeNone($query)
202
  {
203 8
    self::logQuery($query);
204
205 8
    return self::$dl->executeNone($query);
206
  }
207
208
  //--------------------------------------------------------------------------------------------------------------------
209
  /**
210
   * Executes a query that returns 0 or 1 row.
211
   * Throws an exception if the query selects 2 or more rows.
212
   *
213
   * @param string $query The SQL statement.
214
   *
215
   * @return array|null The selected row.
216
   */
217
  public static function executeRow0($query)
218
  {
219
    self::logQuery($query);
220
221
    return self::$dl->executeRow0($query);
222
  }
223
224
  //--------------------------------------------------------------------------------------------------------------------
225
  /**
226
   * Executes a query that returns 1 and only 1 row.
227
   * Throws an exception if the query selects none, 2 or more rows.
228
   *
229
   * @param string $query The SQL statement.
230
   *
231
   * @return array The selected row.
232
   */
233 5
  public static function executeRow1($query)
234
  {
235 5
    self::logQuery($query);
236
237 5
    return self::$dl->executeRow1($query);
238
  }
239
240
  //--------------------------------------------------------------------------------------------------------------------
241
  /**
242
   * Executes a query that returns 0 or more rows.
243
   *
244
   * @param string $query The SQL statement.
245
   *
246
   * @return \array[]
247
   */
248 9
  public static function executeRows($query)
249
  {
250 9
    self::logQuery($query);
251
252 9
    return self::$dl->executeRows($query);
253
  }
254
255
  //--------------------------------------------------------------------------------------------------------------------
256
  /**
257
   * Executes a query that returns 0 or 1 row.
258
   * Throws an exception if the query selects 2 or more rows.
259
   *
260
   * @param string $query The SQL statement.
261
   *
262
   * @return int|string|null The selected row.
263
   */
264
  public static function executeSingleton0($query)
265
  {
266
    self::logQuery($query);
267
268
    return self::$dl->executeSingleton0($query);
269
  }
270
271
  //--------------------------------------------------------------------------------------------------------------------
272
  /**
273
   * Executes a query that returns 1 and only 1 row with 1 column.
274
   * Throws an exception if the query selects none, 2 or more rows.
275
   *
276
   * @param string $query The SQL statement.
277
   *
278
   * @return int|string The selected row.
279
   */
280
  public static function executeSingleton1($query)
281
  {
282
    self::logQuery($query);
283
284
    return self::$dl->executeSingleton1($query);
285
  }
286
287
  //--------------------------------------------------------------------------------------------------------------------
288
  /**
289
   * Selects metadata of all columns of table.
290
   *
291
   * @param string $schemaName The name of the table schema.
292
   * @param string $tableName  The name of the table.
293
   *
294
   * @return \array[]
295
   */
296 8 View Code Duplication
  public static function getTableColumns($schemaName, $tableName)
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
297
  {
298 8
    $sql = sprintf('
299
select COLUMN_NAME        as column_name
300
,      COLUMN_TYPE        as column_type
301
,      IS_NULLABLE        as is_nullable
302
,      CHARACTER_SET_NAME as character_set_name
303
,      COLLATION_NAME     as collation_name
304
from   information_schema.COLUMNS
305
where  TABLE_SCHEMA = %s
306
and    TABLE_NAME   = %s
307 8
order by ORDINAL_POSITION',
308 8
                   self::$dl->quoteString($schemaName),
309 8
                   self::$dl->quoteString($tableName));
310
311 8
    return self::executeRows($sql);
312
  }
313
314
  //--------------------------------------------------------------------------------------------------------------------
315
  /**
316
   * Selects table engine, character_set_name and table_collation.
317
   *
318
   * @param string $schemaName The name of the table schema.
319
   * @param string $tableName  The name of the table.
320
   *
321
   * @return array
322
   */
323 5 View Code Duplication
  public static function getTableOptions($schemaName, $tableName)
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
324
  {
325 5
    $sql = sprintf('
326
SELECT t1.TABLE_COLLATION    as table_collation
327
,      t1.ENGINE             as engine
328
,      t2.CHARACTER_SET_NAME as character_set_name
329
FROM       information_schema.TABLES                                t1
330
inner join information_schema.COLLATION_CHARACTER_SET_APPLICABILITY t2  on  t2.COLLATION_NAME = t1.TABLE_COLLATION
331
WHERE t1.TABLE_SCHEMA = %s
332 5
AND   t1.TABLE_NAME   = %s',
333 5
                   self::$dl->quoteString($schemaName),
334 5
                   self::$dl->quoteString($tableName));
335
336 5
    return self::executeRow1($sql);
337
  }
338
339
  //--------------------------------------------------------------------------------------------------------------------
340
  /**
341
   * Selects all triggers on a table.
342
   *
343
   * @param string $schemaName The name of the table schema.
344
   * @param string $tableName  The name of the table.
345
   *
346
   * @return \array[]
347
   */
348 8 View Code Duplication
  public static function getTableTriggers($schemaName, $tableName)
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
349
  {
350 8
    $sql = sprintf('
351
select Trigger_Name as trigger_name
352
from   information_schema.TRIGGERS
353
where  TRIGGER_SCHEMA     = %s
354
and    EVENT_OBJECT_TABLE = %s
355 8
order by Trigger_Name',
356 8
                   self::$dl->quoteString($schemaName),
357 8
                   self::$dl->quoteString($tableName));
358
359 8
    return self::executeRows($sql);
360
  }
361
362
  //--------------------------------------------------------------------------------------------------------------------
363
  /**
364
   * Selects all table names in a schema.
365
   *
366
   * @param string $schemaName The name of the schema.
367
   *
368
   * @return \array[]
369
   */
370 9
  public static function getTablesNames($schemaName)
371
  {
372 9
    $sql = sprintf("
373
select TABLE_NAME as table_name
374
from   information_schema.TABLES
375
where  TABLE_SCHEMA = %s
376
and    TABLE_TYPE   = 'BASE TABLE'
377 9
order by TABLE_NAME", self::$dl->quoteString($schemaName));
378
379 9
    return self::executeRows($sql);
380
  }
381
382
  //--------------------------------------------------------------------------------------------------------------------
383
  /**
384
   * Acquires a write lock on a table.
385
   *
386
   * @param string $tableName The table name.
387
   */
388 8
  public static function lockTable($tableName)
389
  {
390 8
    $sql = sprintf('lock tables `%s` write', $tableName);
391
392 8
    self::executeNone($sql);
393 8
  }
394
395
  //--------------------------------------------------------------------------------------------------------------------
396
  /**
397
   * Sets the Output decorator.
398
   *
399
   * @param StratumStyle $io The Output decorator.
400
   */
401 9
  public static function setIo($io)
402
  {
403 9
    self::$io = $io;
404 9
  }
405
406
  //--------------------------------------------------------------------------------------------------------------------
407
  /**
408
   * Drop table.
409
   *
410
   * @param string $schemaName The name of the table schema.
411
   * @param string $tableName  The name of the table.
412
   *
413
   * @return \array[]
414
   */
415
  public static function showColumns($schemaName, $tableName)
416
  {
417
    $sql = sprintf('SHOW COLUMNS FROM `%s`.`%s`', $schemaName, $tableName);
418
419
    return self::executeRows($sql);
420
  }
421
422
  //--------------------------------------------------------------------------------------------------------------------
423
  /**
424
   * Releases all table locks.
425
   */
426 8
  public static function unlockTables()
427
  {
428 8
    $sql = 'unlock tables';
429
430 8
    self::executeNone($sql);
431 8
  }
432
433
  //--------------------------------------------------------------------------------------------------------------------
434
  /**
435
   * Logs the query on the console.
436
   *
437
   * @param string $query The query.
438
   */
439 9
  private static function logQuery($query)
440
  {
441 9
    $query = trim($query);
442
443 9
    if (strpos($query, "\n")!==false)
444 9
    {
445
      // Query is a multi line query.
446 9
      self::$io->logVeryVerbose('Executing query:');
447 9
      self::$io->logVeryVerbose('<sql>%s</sql>', $query);
448 9
    }
449
    else
450
    {
451
      // Query is a single line query.
452 8
      self::$io->logVeryVerbose('Executing query: <sql>%s</sql>', $query);
453
    }
454 9
  }
455
456
  //--------------------------------------------------------------------------------------------------------------------
457
}
458
459
//----------------------------------------------------------------------------------------------------------------------
460