Completed
Pull Request — master (#31)
by
unknown
02:42
created

DataLayer::showColumns()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 6
rs 9.4285
cc 1
eloc 3
nc 1
nop 2
1
<?php
2
//----------------------------------------------------------------------------------------------------------------------
3
namespace SetBased\Audit\MySql;
4
5
use SetBased\Audit\MySql\Helper\CompoundSyntaxStore;
6
use SetBased\Audit\MySql\Sql\AlterAuditTableAddColumns;
7
use SetBased\Audit\MySql\Sql\CreateAuditTable;
8
use SetBased\Audit\MySql\Sql\CreateAuditTrigger;
9
use SetBased\Audit\MySql\Table\Columns;
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 DataLayer
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 \SetBased\Audit\MySql\Table\Columns $columns         The metadata of the new columns.
41
   */
42
  public static function addNewColumns($auditSchemaName, $tableName, $columns)
43
  {
44
    $helper = new AlterAuditTableAddColumns($auditSchemaName, $tableName, $columns);
45
    $sql    = $helper->buildStatement();
46
47
    self::executeNone($sql);
48
  }
49
50
  //--------------------------------------------------------------------------------------------------------------------
51
  /**
52
   * Connects to a MySQL instance.
53
   *
54
   * Wrapper around [mysqli::__construct](http://php.net/manual/mysqli.construct.php), however on failure an exception
55
   * is thrown.
56
   *
57
   * @param string $host     The hostname.
58
   * @param string $user     The MySQL user name.
59
   * @param string $passWord The password.
60
   * @param string $database The default database.
61
   * @param int    $port     The port number.
62
   */
63
  public static function connect($host, $user, $passWord, $database, $port = 3306)
64
  {
65
    self::$dl = new StaticDataLayer();
66
67
    self::$dl->connect($host, $user, $passWord, $database, $port);
68
  }
69
70
  //--------------------------------------------------------------------------------------------------------------------
71
  /**
72
   * Creates an audit table.
73
   *
74
   * @param string  $dataSchemaName  The name of the data schema.
75
   * @param string  $auditSchemaName The name of the audit schema.
76
   * @param string  $tableName       The name of the table.
77
   * @param Columns $columns         The metadata of the columns of the audit table (i.e. the audit columns and columns
78
   *                                 of the data table).
79
   */
80
  public static function createAuditTable($dataSchemaName, $auditSchemaName, $tableName, $columns)
81
  {
82
    $helper = new CreateAuditTable($dataSchemaName, $auditSchemaName, $tableName, $columns);
83
    $sql    = $helper->buildStatement();
84
85
    self::executeNone($sql);
86
  }
87
88
  //--------------------------------------------------------------------------------------------------------------------
89
  /**
90
   * Creates a trigger on a table.
91
   *
92
   * @param string                              $dataSchemaName  The name of the data schema.
93
   * @param string                              $auditSchemaName The name of the audit schema.
94
   * @param string                              $tableName       The name of the table.
95
   * @param string                              $triggerAction   The trigger action (i.e. INSERT, UPDATE, or DELETE).
96
   * @param string                              $triggerName     The name of the trigger.
97
   * @param \SetBased\Audit\MySql\Table\Columns $tableColumns    The data table columns.
98
   * @param \SetBased\Audit\MySql\Table\Columns $auditColumns    The audit table columns.
99
   * @param string                              $skipVariable    The skip variable.
100
   * @param string[]                            $additionSql     Additional SQL statements.
101
   */
102
  public static function createAuditTrigger($dataSchemaName,
103
                                            $auditSchemaName,
104
                                            $tableName,
105
                                            $triggerAction,
106
                                            $triggerName,
107
                                            $tableColumns,
108
                                            $auditColumns,
109
                                            $skipVariable,
110
                                            $additionSql)
111
  {
112
    $helper = new CreateAuditTrigger($dataSchemaName,
113
                                     $auditSchemaName,
114
                                     $tableName,
115
                                     $triggerAction,
116
                                     $triggerName,
117
                                     $tableColumns,
118
                                     $auditColumns,
119
                                     $skipVariable,
120
                                     $additionSql);
121
    $sql    = $helper->buildStatement();
122
123
    self::executeNone($sql);
124
  }
125
126
  //--------------------------------------------------------------------------------------------------------------------
127
  /**
128
   * Closes the connection to the MySQL instance, if connected.
129
   */
130
  public static function disconnect()
131
  {
132
    if (self::$dl!==null)
133
    {
134
      self::$dl->disconnect();
135
      self::$dl = null;
136
    }
137
  }
138
139
  //--------------------------------------------------------------------------------------------------------------------
140
  /**
141
   * Drops a trigger.
142
   *
143
   * @param string $triggerSchema The name of the trigger schema.
144
   * @param string $triggerName   The mame of trigger.
145
   */
146
  public static function dropTrigger($triggerSchema, $triggerName)
147
  {
148
    $sql = sprintf('drop trigger `%s`.`%s`', $triggerSchema, $triggerName);
149
150
    self::executeNone($sql);
151
  }
152
153
  //--------------------------------------------------------------------------------------------------------------------
154
  /**
155
   * @param string $query The SQL statement.
156
   *
157
   * @return int The number of affected rows (if any).
158
   */
159
  public static function executeNone($query)
160
  {
161
    self::logQuery($query);
162
163
    return self::$dl->executeNone($query);
164
  }
165
166
  //--------------------------------------------------------------------------------------------------------------------
167
  /**
168
   * Executes a query that returns 0 or 1 row.
169
   * Throws an exception if the query selects 2 or more rows.
170
   *
171
   * @param string $query The SQL statement.
172
   *
173
   * @return array|null The selected row.
174
   */
175
  public static function executeRow0($query)
176
  {
177
    self::logQuery($query);
178
179
    return self::$dl->executeRow0($query);
180
  }
181
182
  //--------------------------------------------------------------------------------------------------------------------
183
  /**
184
   * Executes a query that returns 1 and only 1 row.
185
   * Throws an exception if the query selects none, 2 or more rows.
186
   *
187
   * @param string $query The SQL statement.
188
   *
189
   * @return array The selected row.
190
   */
191
  public static function executeRow1($query)
192
  {
193
    self::logQuery($query);
194
195
    return self::$dl->executeRow1($query);
196
  }
197
198
  //--------------------------------------------------------------------------------------------------------------------
199
  /**
200
   * Executes a query that returns 0 or more rows.
201
   *
202
   * @param string $query The SQL statement.
203
   *
204
   * @return \array[]
205
   */
206
  public static function executeRows($query)
207
  {
208
    self::logQuery($query);
209
210
    return self::$dl->executeRows($query);
211
  }
212
213
  //--------------------------------------------------------------------------------------------------------------------
214
  /**
215
   * Executes a query that returns 0 or 1 row.
216
   * Throws an exception if the query selects 2 or more rows.
217
   *
218
   * @param string $query The SQL statement.
219
   *
220
   * @return int|string|null The selected row.
221
   */
222
  public static function executeSingleton0($query)
223
  {
224
    self::logQuery($query);
225
226
    return self::$dl->executeSingleton0($query);
227
  }
228
229
  //--------------------------------------------------------------------------------------------------------------------
230
  /**
231
   * Executes a query that returns 1 and only 1 row with 1 column.
232
   * Throws an exception if the query selects none, 2 or more rows.
233
   *
234
   * @param string $query The SQL statement.
235
   *
236
   * @return int|string The selected row.
237
   */
238
  public static function executeSingleton1($query)
239
  {
240
    self::logQuery($query);
241
242
    return self::$dl->executeSingleton1($query);
243
  }
244
245
  //--------------------------------------------------------------------------------------------------------------------
246
  /**
247
   * Selects metadata of all columns of table.
248
   *
249
   * @param string $schemaName The name of the table schema.
250
   * @param string $tableName  The name of the table.
251
   *
252
   * @return \array[]
253
   */
254 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...
255
  {
256
    $sql = sprintf('
257
select COLUMN_NAME        as column_name
258
,      COLUMN_TYPE        as column_type
259
,      IS_NULLABLE        as is_nullable
260
,      CHARACTER_SET_NAME as character_set_name
261
,      COLLATION_NAME     as collation_name
262
from   information_schema.COLUMNS
263
where  TABLE_SCHEMA = %s
264
and    TABLE_NAME   = %s
265
order by ORDINAL_POSITION',
266
                   self::$dl->quoteString($schemaName),
267
                   self::$dl->quoteString($tableName));
268
269
    return self::$dl->executeRows($sql);
270
  }
271
272
  //--------------------------------------------------------------------------------------------------------------------
273
  /**
274
   * Selects table engine, character_set_name and table_collation.
275
   *
276
   * @param string $schemaName The name of the table schema.
277
   * @param string $tableName  The name of the table.
278
   *
279
   * @return array
280
   */
281 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...
282
  {
283
    $sql = sprintf('
284
SELECT t1.TABLE_COLLATION    as table_collation
285
,      t1.ENGINE             as engine
286
,      t2.CHARACTER_SET_NAME as character_set_name
287
FROM       information_schema.TABLES                                t1
288
inner join information_schema.COLLATION_CHARACTER_SET_APPLICABILITY t2  on  t2.COLLATION_NAME = t1.TABLE_COLLATION
289
WHERE t1.TABLE_SCHEMA = %s
290
AND   t1.TABLE_NAME   = %s',
291
                   self::$dl->quoteString($schemaName),
292
                   self::$dl->quoteString($tableName));
293
294
    return self::$dl->executeRow1($sql);
295
  }
296
297
  //--------------------------------------------------------------------------------------------------------------------
298
  /**
299
   * Create temp table for getting column type information for audit columns.
300
   *
301
   * @param string  $schemaName   The name of the table schema.
302
   * @param string  $tableName    The table name.
303
   * @param array[] $auditColumns Audit columns from config file.
304
   */
305
  public static function createTemporaryTable($schemaName, $tableName, $auditColumns)
306
  {
307
    $sql = new CompoundSyntaxStore();
308
    $sql->append(sprintf('create temporary table `%s`.`%s` (', $schemaName, $tableName));
309
    foreach ($auditColumns as $column)
310
    {
311
      $sql->append(sprintf('%s %s', $column['column_name'], $column['column_type']));
312
      if (end($auditColumns)!==$column)
313
      {
314
        $sql->appendToLastLine(',');
315
      }
316
    }
317
    $sql->append(')');
318
319
    self::$dl->executeNone($sql->getCode());
320
  }
321
322
  //--------------------------------------------------------------------------------------------------------------------
323
  /**
324
   * Drop table.
325
   *
326
   * @param string $schemaName The name of the table schema.
327
   * @param string $tableName  The name of the table.
328
   *
329
   * @return \array[]
330
   */
331
  public static function showColumns($schemaName, $tableName)
332
  {
333
    $sql = sprintf('SHOW COLUMNS FROM `%s`.`%s`', $schemaName, $tableName);
334
335
    return self::$dl->executeRows($sql);
336
  }
337
338
  //--------------------------------------------------------------------------------------------------------------------
339
  /**
340
   * Drop table.
341
   *
342
   * @param string $schemaName The name of the table schema.
343
   * @param string $tableName  The name of the table.
344
   */
345
  public static function dropTemporaryTable($schemaName, $tableName)
346
  {
347
    $sql = sprintf('drop temporary table `%s`.`%s`', $schemaName, $tableName);
348
349
    self::$dl->executeNone($sql);
350
  }
351
352
  //--------------------------------------------------------------------------------------------------------------------
353
  /**
354
   * Selects all triggers on a table.
355
   *
356
   * @param string $schemaName The name of the table schema.
357
   * @param string $tableName  The name of the table.
358
   *
359
   * @return \array[]
360
   */
361 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...
362
  {
363
    $sql = sprintf('
364
select Trigger_Name as trigger_name
365
from   information_schema.TRIGGERS
366
where  TRIGGER_SCHEMA     = %s
367
and    EVENT_OBJECT_TABLE = %s
368
order by Trigger_Name',
369
                   self::$dl->quoteString($schemaName),
370
                   self::$dl->quoteString($tableName));
371
372
    return self::$dl->executeRows($sql);
373
  }
374
375
  //--------------------------------------------------------------------------------------------------------------------
376
  /**
377
   * Selects all table names in a schema.
378
   *
379
   * @param string $schemaName The name of the schema.
380
   *
381
   * @return \array[]
382
   */
383
  public static function getTablesNames($schemaName)
384
  {
385
    $sql = sprintf("
386
select TABLE_NAME as table_name
387
from   information_schema.TABLES
388
where  TABLE_SCHEMA = %s
389
and    TABLE_TYPE   = 'BASE TABLE'
390
order by TABLE_NAME", self::$dl->quoteString($schemaName));
391
392
    return self::$dl->executeRows($sql);
393
  }
394
395
  //--------------------------------------------------------------------------------------------------------------------
396
  /**
397
   * Acquires a write lock on a table.
398
   *
399
   * @param string $tableName The table name.
400
   */
401
  public static function lockTable($tableName)
402
  {
403
    $sql = sprintf('lock tables `%s` write', $tableName);
404
405
    self::$dl->executeNone($sql);
406
  }
407
408
  //--------------------------------------------------------------------------------------------------------------------
409
  /**
410
   * Sets the Output decorator.
411
   *
412
   * @param StratumStyle $io The Output decorator.
413
   */
414
  public static function setIo($io)
415
  {
416
    self::$io = $io;
417
  }
418
419
  //--------------------------------------------------------------------------------------------------------------------
420
  /**
421
   * Releases all table locks.
422
   */
423
  public static function unlockTables()
424
  {
425
    $sql = 'unlock tables';
426
427
    self::$dl->executeNone($sql);
428
  }
429
430
  //--------------------------------------------------------------------------------------------------------------------
431
  /**
432
   * Logs the query on the console.
433
   *
434
   * @param string $query The query.
435
   */
436
  private static function logQuery($query)
437
  {
438
    $query = trim($query);
439
440
    if (strpos($query, "\n")!==false)
441
    {
442
      // Query is a multi line query.
443
      self::$io->logVeryVerbose('Executing query:');
444
      self::$io->logVeryVerbose('<sql>%s</sql>', $query);
445
    }
446
    else
447
    {
448
      // Query is a single line query.
449
      self::$io->logVeryVerbose('Executing query: <sql>%s</sql>', $query);
450
    }
451
  }
452
453
  //--------------------------------------------------------------------------------------------------------------------
454
}
455
456
//----------------------------------------------------------------------------------------------------------------------
457