Passed
Push — master ( f71b04...7dcb0c )
by P.R.
12:30
created

MysqlWrapper::generateMethodBodyWithLob()   B

Complexity

Conditions 7
Paths 24

Size

Total Lines 90
Code Lines 69

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 69
nc 24
nop 1
dl 0
loc 90
rs 7.743
c 1
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
declare(strict_types=1);
3
4
namespace SetBased\Stratum\MySql\Wrapper;
5
6
use SetBased\Exception\FallenException;
7
use SetBased\Stratum\Common\Wrapper\CommonWrapper;
8
use SetBased\Stratum\Common\Wrapper\Helper\WrapperContext;
9
use SetBased\Stratum\Middle\Exception\ResultException;
10
use SetBased\Stratum\MySql\Exception\MySqlDataLayerException;
11
use SetBased\Stratum\MySql\Exception\MySqlQueryErrorException;
12
use SetBased\Stratum\MySql\Loader\Helper\MySqlDataTypeHelper;
13
14
/**
15
 * Abstract parent class for all wrapper generators.
16
 */
17
abstract class MysqlWrapper extends CommonWrapper
18
{
19
  //--------------------------------------------------------------------------------------------------------------------
20
  /**
21
   * A factory for creating the appropriate object for generating a wrapper method for a stored routine.
22
   *
23
   * @param WrapperContext $context The wrapper context.
24
   */
25
  public static function createRoutineWrapper(WrapperContext $context): MysqlWrapper
26
  {
27
    $type = $context->phpStratumMetadata['designation']['type'];
28
    switch ($type)
29
    {
30
      case 'bulk':
31
        $wrapper = new BulkWrapper();
32
        break;
33
34
      case 'insert_multiple':
35
        $wrapper = new InsertMultipleWrapper();
36
        break;
37
38
      case 'log':
39
        $wrapper = new LogWrapper();
40
        break;
41
42
      case 'map':
43
        $wrapper = new MapWrapper();
44
        break;
45
46
      case 'none':
47
        $wrapper = new NoneWrapper();
48
        break;
49
50
      case 'row0':
51
        $wrapper = new Row0Wrapper();
52
        break;
53
54
      case 'row1':
55
        $wrapper = new Row1Wrapper();
56
        break;
57
58
      case 'rows':
59
        $wrapper = new RowsWrapper();
60
        break;
61
62
      case 'rows_with_key':
63
        $wrapper = new RowsWithKeyWrapper();
64
        break;
65
66
      case 'rows_with_index':
67
        $wrapper = new RowsWithIndexWrapper();
68
        break;
69
70
      case 'singleton0':
71
        $wrapper = new Singleton0Wrapper();
72
        break;
73
74
      case 'singleton1':
75
        $wrapper = new Singleton1Wrapper();
76
        break;
77
78
      case 'function':
79
        $wrapper = new FunctionWrapper();
80
        break;
81
82
      case 'table':
83
        $wrapper = new TableWrapper();
84
        break;
85
86
      default:
87
        throw new FallenException('routine type', $type);
88
    }
89
90
    return $wrapper;
91
  }
92
93
  //--------------------------------------------------------------------------------------------------------------------
94
  /**
95
   * Returns true if one of the parameters is a BLOB or CLOB.
96
   *
97
   * @param WrapperContext $context The wrapper context.
98
   */
99
  public function hasBlobParameter(WrapperContext $context): bool
100
  {
101
    foreach ($context->phpStratumMetadata['parameters'] as $parameter)
102
    {
103
      if (MySqlDataTypeHelper::isBlobParameter($parameter['data_type']))
104
      {
105
        return true;
106
      }
107
    }
108
109
    return false;
110
  }
111
112
  //--------------------------------------------------------------------------------------------------------------------
113
  /**
114
   * Generates a complete wrapper method.
115
   *
116
   * @param WrapperContext $context The wrapper context.
117
   */
118
  protected function generateMethodBody(WrapperContext $context): void
119
  {
120
    if ($this->hasBlobParameter($context))
121
    {
122
      $this->generateMethodBodyWithLob($context);
123
    }
124
    else
125
    {
126
      $this->generateMethodBodyWithoutLob($context);
127
    }
128
  }
129
130
  //--------------------------------------------------------------------------------------------------------------------
131
  /**
132
   * Generates a complete wrapper method.
133
   *
134
   * @param WrapperContext $context The wrapper context.
135
   */
136
  abstract protected function generateMethodBodyWithLobFetchData(WrapperContext $context): void;
137
138
  //--------------------------------------------------------------------------------------------------------------------
139
  /**
140
   * Generates a complete wrapper method.
141
   *
142
   * @param WrapperContext $context The wrapper context.
143
   */
144
  abstract protected function generateMethodBodyWithLobReturnData(WrapperContext $context): void;
145
146
  //--------------------------------------------------------------------------------------------------------------------
147
  /**
148
   * Returns a wrapper method for a stored routine without LOB parameters.
149
   *
150
   * @param WrapperContext $context The wrapper context.
151
   */
152
  abstract protected function generateMethodBodyWithoutLob(WrapperContext $context): void;
153
154
  //--------------------------------------------------------------------------------------------------------------------
155
  /**
156
   * Returns code for the arguments for calling the stored routine in a wrapper method.
157
   *
158
   * @param WrapperContext $context The wrapper context.
159
   */
160
  protected function getRoutineArgs(WrapperContext $context): string
161
  {
162
    $ret = '';
163
164
    foreach ($context->phpStratumMetadata['parameters'] as $parameter)
165
    {
166
      $mangledName = $context->mangler::getParameterName($parameter['parameter_name']);
167
168
      if ($ret)
169
      {
170
        $ret .= ',';
171
      }
172
      $ret .= $context->dataType->escapePhpExpression($parameter, '$'.$mangledName);
173
    }
174
175
    return $ret;
176
  }
177
178
  //--------------------------------------------------------------------------------------------------------------------
179
  /**
180
   * Generates a complete wrapper method for a stored routine with a LOB parameter.
181
   *
182
   * @param WrapperContext $context The wrapper context.
183
   */
184
  private function generateMethodBodyWithLob(WrapperContext $context): void
185
  {
186
    $this->throws(MySqlDataLayerException::class);
187
    $this->throws(MysqlQueryErrorException::class);
188
    $this->throws(ResultException::class);
189
190
    $routineArgs = $this->getRoutineArgs($context);
191
192
    $bindings = '';
193
    $nulls    = '';
194
    foreach ($context->phpStratumMetadata['parameters'] as $parameter)
195
    {
196
      $binding = MySqlDataTypeHelper::getBindVariableType($parameter);
197
      if ($binding=='b')
198
      {
199
        $bindings .= 'b';
200
        if ($nulls!=='')
201
        {
202
          $nulls .= ', ';
203
        }
204
        $nulls .= '$null';
205
      }
206
    }
207
    $context->codeStore->append('$query = \'call '.$context->phpStratumMetadata['routine_name'].'('.$routineArgs.')\';');
208
    $context->codeStore->append('$stmt  = @$this->mysqli->prepare($query);');
209
    $context->codeStore->append('if (!$stmt)');
210
    $context->codeStore->append('{');
211
    $context->codeStore->append("throw \$this->dataLayerError('mysqli::prepare');");
212
    $context->codeStore->append('}');
213
    $context->codeStore->append('');
214
    $context->codeStore->append('$null = null;');
215
    $context->codeStore->append('$success = @$stmt->bind_param(\''.$bindings.'\', '.$nulls.');');
216
    $context->codeStore->append('if (!$success)');
217
    $context->codeStore->append('{');
218
    $context->codeStore->append("throw \$this->dataLayerError('mysqli_stmt::bind_param');");
219
    $context->codeStore->append('}');
220
    $context->codeStore->append('');
221
    $context->codeStore->append('$this->getMaxAllowedPacket();');
222
    $context->codeStore->append('');
223
224
    $blobArgumentIndex = 0;
225
    foreach ($context->phpStratumMetadata['parameters'] as $parameter)
226
    {
227
      if (MySqlDataTypeHelper::getBindVariableType($parameter)=='b')
228
      {
229
        $mangledName = $context->mangler::getParameterName($parameter['parameter_name']);
230
231
        $context->codeStore->append('$this->sendLongData($stmt, '.$blobArgumentIndex.', $'.$mangledName.');');
232
233
        $blobArgumentIndex++;
234
      }
235
    }
236
237
    if ($blobArgumentIndex>0)
238
    {
239
      $context->codeStore->append('');
240
    }
241
242
    $context->codeStore->append('if ($this->logQueries)');
243
    $context->codeStore->append('{');
244
    $context->codeStore->append('$time0 = microtime(true);');
245
    $context->codeStore->append('}');
246
    $context->codeStore->append('');
247
    $context->codeStore->append('try');
248
    $context->codeStore->append('{');
249
    $context->codeStore->append('$success = @$stmt->execute();');
250
    $context->codeStore->append('}');
251
    $context->codeStore->append('catch (\mysqli_sql_exception)');
252
    $context->codeStore->append('{');
253
    $context->codeStore->append('$success = false;');
254
    $context->codeStore->append('}');
255
    $context->codeStore->append('if (!$success)');
256
    $context->codeStore->append('{');
257
    $context->codeStore->append("throw \$this->queryError('mysqli_stmt::execute', \$query);");
258
    $context->codeStore->append('}');
259
    $context->codeStore->append('');
260
    $context->codeStore->append('if ($this->logQueries)');
261
    $context->codeStore->append('{');
262
    $context->codeStore->append("\$this->queryLog[] = ['query' => \$query,");
263
    $context->codeStore->append("                     'time'  => microtime(true) - \$time0];", false);
264
    $context->codeStore->append('}');
265
    $context->codeStore->append('');
266
    $this->generateMethodBodyWithLobFetchData($context);
267
    $context->codeStore->append('$stmt->close();');
268
    $context->codeStore->append('if ($this->mysqli->more_results())');
269
    $context->codeStore->append('{');
270
    $context->codeStore->append('$this->mysqli->next_result();');
271
    $context->codeStore->append('}');
272
    $context->codeStore->append('');
273
    $this->generateMethodBodyWithLobReturnData($context);
274
  }
275
276
  //--------------------------------------------------------------------------------------------------------------------
277
}
278
279
//----------------------------------------------------------------------------------------------------------------------
280