1C-Bitrix
25.700.0
Загрузка...
Поиск...
Не найдено
sql_format.php
См. документацию.
1
<?php
2
if
(!defined(
'T_KEYWORD'
))
3
{
4
define(
'T_KEYWORD'
, 400);
5
}
6
if
(!defined(
'T_BAD_CHARACTER'
))
7
{
8
define(
'T_BAD_CHARACTER'
, 401);
9
}
10
if
(!defined(
'T_CHARACTER'
))
11
{
12
define(
'T_CHARACTER'
, 402);
13
}
14
15
class
CSqlFormatFormatter
16
{
17
public
function
format
($tokens)
18
{
19
$result
=
''
;
20
$skipWS =
false
;
21
foreach
($tokens as
$i
=> $token)
22
{
23
if
($token[1] ===
','
)
24
{
25
$this->
removeTrailingSpaces
(
$result
);
26
$result
.=
",\x3"
. str_repeat(
"\x2"
, $token[2]);
27
$skipWS =
true
;
28
}
29
elseif
(
30
$token[1] ===
'='
31
|| $token[1] ===
'-'
32
|| $token[1] ===
'+'
33
|| $token[1] ===
'*'
34
|| $token[1] ===
'/'
35
|| $token[1] ===
'<='
36
|| $token[1] ===
'>='
37
)
38
{
39
$this->
removeTrailingSpaces
(
$result
);
40
$result
.=
"\x1"
. $token[1] .
"\x1"
;
41
$skipWS =
true
;
42
}
43
elseif
(
44
$token[1] ===
'INNER'
45
|| $token[1] ===
'LEFT'
46
|| $token[1] ===
'SET'
47
|| $token[1] ===
'AND'
48
|| $token[1] ===
'OR'
49
)
50
{
51
$result
.=
"\x3"
. str_repeat(
"\x2"
, $token[2]) . $token[1];
52
}
53
else
54
{
55
if
($skipWS)
56
{
57
$skipWS =
false
;
58
if
($token[0] === T_WHITESPACE)
59
{
60
continue
;
61
}
62
}
63
elseif
(
$i
> 0 && ($tokens[
$i
- 1][2] <> $token[2]))
64
{
65
$result
.=
"\x3"
. str_repeat(
"\x2"
, $token[2]);
66
if
($token[0] === T_WHITESPACE)
67
{
68
continue
;
69
}
70
}
71
72
if
($token[0] === T_WHITESPACE)
73
{
74
$result
.=
"\x1"
;
75
}
76
else
77
{
78
$result
.= $token[1];
79
}
80
}
81
}
82
83
$result
= preg_replace_callback(
"/(
84
\\([\\x1\\x2\\x3_0-9A-Za-z.0-9_,]+\\)
85
|\\([\\x1\\x2\\x3'x%0-9,]+\\)
86
|\\([\\x1\\x2\\x3]*[a-zA-Z0-9_.]+[\\x1\\x2\\x3]*=[\\x1\\x2\\x3]*[a-zA-Z0-9_.']+[\\x1\\x2\\x3]*\\)
87
)/x"
, [$this,
'removeSpaces'
],
$result
);
88
89
$result
= str_replace([
90
"\x1"
,
91
"\x2"
,
92
"\x3"
,
93
], [
94
$this->
getSpace
(),
95
$this->
getTab
(),
96
$this->
getEol
(),
97
],
$result
);
98
99
return
$result
;
100
}
101
102
public
function
removeSpaces
($match)
103
{
104
$result
= preg_replace(
"/^\\([\\x1\\x2\\x3]+/"
,
'('
, $match[0]);
105
$result
= preg_replace(
"/[\\x1\\x2\\x3]+\\)\$/"
,
')'
,
$result
);
106
$result
= preg_replace(
"/,[\\x1\\x2\\x3]+/"
,
', '
,
$result
);
107
return
$result
;
108
}
109
110
public
function
removeTrailingSpaces
(&
$str
)
111
{
112
$str
= rtrim(
$str
,
"\x1\x2\x3"
);
113
}
114
115
public
function
getEol
()
116
{
117
return
' '
;
118
}
119
120
public
function
getSpace
()
121
{
122
return
' '
;
123
}
124
125
public
function
getTab
()
126
{
127
return
' '
;
128
}
129
}
130
131
class
CSqlFormatText
extends
CSqlFormatFormatter
132
{
133
public
function
getEol
()
134
{
135
return
"\n"
;
136
}
137
138
public
function
getSpace
()
139
{
140
return
' '
;
141
}
142
143
public
function
getTab
()
144
{
145
return
"\t"
;
146
}
147
}
148
149
class
CSqlTokenizer
150
{
151
private
$tokens =
null
;
152
private
$current = 0;
153
154
public
function
parse
($sql)
155
{
156
$this->tokens = token_get_all(
'<?'
. $sql);
157
array_shift($this->tokens);
158
$this->current = 0;
159
160
while
(isset($this->tokens[$this->current]))
161
{
162
//Remove excessive brackets
163
if
(
164
$this->tokens[$this->current] ===
'('
165
&& $this->
lookForwardFor
(
'('
)
166
)
167
{
168
if
($this->
removeBalancedBrackets
())
169
{
170
continue
;
171
}
172
}
173
174
//Remove following spaces
175
if
($this->tokens[$this->current][0] === T_WHITESPACE && $this->tokens[$this->current - 1][0] === T_WHITESPACE)
176
{
177
array_splice($this->tokens, $this->current, 1);
178
continue
;
179
}
180
181
$this->tokens[$this->current] = $this->
transform
($this->tokens[$this->current]);
182
$this->current++;
183
}
184
185
//Remove leading spaces
186
while
(
187
isset($this->tokens[0])
188
&& $this->tokens[0][0] === T_WHITESPACE
189
)
190
{
191
array_splice($this->tokens, 0, 1);
192
}
193
194
//Remove trailing spaces
195
while
(
196
!empty($this->tokens)
197
&& $this->tokens[
count
($this->tokens) - 1][0] === T_WHITESPACE
198
)
199
{
200
array_splice($this->tokens, -1, 1);
201
}
202
203
return
$this->tokens;
204
}
205
206
protected
function
transform
($token)
207
{
208
static
$keywords =
'UPDATE|SET|DELETE|SELECT|DISTINCT|INNER|LEFT|OUTER|JOIN|ON|FROM|WHERE|GROUP|BY|IN|EXISTS|HAVING|ORDER|ASC|DESC|LIMIT|AND|OR'
;
209
static
$functions =
'DATE_FORMAT|UNIX_TIMESTAMP|CONCAT|DATE_ADD|UPPER|LENGTH|IFNULL'
;
210
211
if
(isset($token[1]))
212
{
213
$token = [$token[0], $token[1]];
214
}
215
else
216
{
217
$token = [T_CHARACTER, $token[0]];
218
}
219
220
switch
($token[0])
221
{
222
case
T_STRING:
223
if
(preg_match(
'/^('
. $keywords .
')$/i'
, $token[1]))
224
{
225
$token = [T_KEYWORD, mb_strtoupper($token[1])];
226
}
227
elseif
(preg_match(
'/^('
. $functions .
')$/i'
, $token[1]))
228
{
229
$token = [T_FUNCTION, $token[1]];
230
}
231
break
;
232
case
T_LOGICAL_AND:
233
case
T_LOGICAL_OR:
234
$token = [T_KEYWORD, mb_strtoupper($token[1])];
235
break
;
236
case
T_AS:
237
$token = [T_KEYWORD, $token[1]];
238
break
;
239
case
T_COMMENT:
240
case
T_BAD_CHARACTER:
241
$token = [T_WHITESPACE,
' '
];
242
break
;
243
}
244
245
return
$token;
246
}
247
248
protected
function
removeBalancedBrackets
()
249
{
250
$pos = $this->current;
251
$balance = 0;
252
$hasOp = [
false
];
253
while
(isset($this->tokens[$pos]))
254
{
255
if
($this->tokens[$pos][0] ===
'('
)
256
{
257
$balance++;
258
$hasOp[$balance] =
false
;
259
}
260
elseif
($this->tokens[$pos][0] ===
')'
)
261
{
262
$balance--;
263
}
264
elseif
(
265
$this->tokens[$pos][0] === T_LOGICAL_AND
266
|| $this->tokens[$pos][0] === T_LOGICAL_OR
267
|| $this->tokens[$pos][0] ===
','
268
)
269
{
270
$hasOp[$balance] =
true
;
271
}
272
273
if
($balance === 0)
274
{
275
if
(!$hasOp[$balance + 1])
276
{
277
array_splice($this->tokens, $pos, 1);
278
array_splice($this->tokens, $this->current, 1);
279
return
true
;
280
}
281
else
282
{
283
return
false
;
284
}
285
}
286
$pos++;
287
}
288
return
false
;
289
}
290
291
protected
function
lookForwardFor
($token)
292
{
293
$pos = $this->current + 1;
294
while
(isset($this->tokens[$pos]))
295
{
296
if
($this->tokens[$pos] == $token)
297
{
298
return
true
;
299
}
300
elseif
($this->tokens[$pos][0] !== T_WHITESPACE)
301
{
302
return
false
;
303
}
304
$pos++;
305
}
306
return
false
;
307
}
308
}
309
310
class
CSqlLevel
311
{
312
private
$tokens = [];
313
private
$balance = 0;
314
private
$level = 0;
315
private
$current = 0;
316
317
public
function
addLevel
(
array
$tokens)
318
{
319
$this->level = [];
320
$this->balance = 0;
321
$this->tokens = $tokens;
322
$this->current = 0;
323
while
(isset($this->tokens[$this->current]))
324
{
325
if
($this->tokens[$this->current][1] ===
'('
)
326
{
327
$this->balance++;
328
}
329
elseif
($this->tokens[$this->current][1] ===
')'
)
330
{
331
$this->balance--;
332
}
333
334
if
($this->tokens[$this->current][0] !== T_WHITESPACE)
335
{
336
$this->
changeLevelBefore
();
337
}
338
339
$this->tokens[$this->current][] = array_sum($this->level);
340
341
if
($this->tokens[$this->current][0] !== T_WHITESPACE)
342
{
343
$this->
changeLevelAfter
();
344
}
345
346
$this->current++;
347
}
348
349
return
$this->tokens;
350
}
351
352
public
function
changeLevelBefore
()
353
{
354
if
($this->tokens[$this->current][1] ===
')'
)
355
{
356
$this->level[
'('
]--;
357
$this->level[
'SELECT_'
. ($this->balance + 1)] = 0;
358
$this->level[
'JOIN_'
. ($this->balance + 1)] = 0;
359
}
360
elseif
(
361
$this->tokens[$this->current][1] ===
'FROM'
362
|| $this->tokens[$this->current][1] ===
'LIMIT'
363
)
364
{
365
$this->level[
'SELECT_'
. $this->balance]--;
366
}
367
elseif
(
368
$this->tokens[$this->current][1] ===
'WHERE'
369
|| $this->tokens[$this->current][1] ===
'GROUP'
370
|| $this->tokens[$this->current][1] ===
'HAVING'
371
|| $this->tokens[$this->current][1] ===
'ORDER'
372
)
373
{
374
$this->level[
'SELECT_'
. $this->balance]--;
375
if
($this->level[
'JOIN_'
. $this->balance] ?? 0)
376
{
377
$this->level[
'JOIN_'
. $this->balance]--;
378
}
379
}
380
elseif
(
381
$this->tokens[$this->current][1] ===
'INNER'
382
|| $this->tokens[$this->current][1] ===
'LEFT'
383
)
384
{
385
if
($this->level[
'JOIN_'
. $this->balance] > 0)
386
{
387
$this->level[
'JOIN_'
. $this->balance]--;
388
}
389
}
390
}
391
392
public
function
changeLevelAfter
()
393
{
394
if
($this->tokens[$this->current][1] ===
'('
)
395
{
396
if
(isset($this->level[
'('
]))
397
{
398
$this->level[
'('
]++;
399
}
400
else
401
{
402
$this->level[
'('
] = 1;
403
}
404
}
405
elseif
(
406
(
407
$this->tokens[$this->current][1] ===
'SELECT'
408
&& !$this->
lookForwardFor
(
'DISTINCT'
)
409
) || (
410
$this->tokens[$this->current][1] ===
'DISTINCT'
411
)
412
)
413
{
414
if
(isset($this->level[
'SELECT_'
. $this->balance]))
415
{
416
$this->level[
'SELECT_'
. $this->balance]++;
417
}
418
else
419
{
420
$this->level[
'SELECT_'
. $this->balance] = 1;
421
}
422
}
423
elseif
(
424
$this->tokens[$this->current][1] ===
'FROM'
425
|| $this->tokens[$this->current][1] ===
'WHERE'
426
|| $this->tokens[$this->current][1] ===
'BY'
427
|| $this->tokens[$this->current][1] ===
'HAVING'
428
|| $this->tokens[$this->current][1] ===
'SET'
429
)
430
{
431
if
(isset($this->level[
'SELECT_'
. $this->balance]))
432
{
433
$this->level[
'SELECT_'
. $this->balance]++;
434
}
435
else
436
{
437
$this->level[
'SELECT_'
. $this->balance] = 1;
438
}
439
}
440
elseif
($this->tokens[$this->current][1] ===
'ON'
)
441
{
442
if
(isset($this->level[
'JOIN_'
. $this->balance]))
443
{
444
$this->level[
'JOIN_'
. $this->balance]++;
445
}
446
else
447
{
448
$this->level[
'JOIN_'
. $this->balance] = 1;
449
}
450
}
451
}
452
453
protected
function
lookForwardFor
($token)
454
{
455
$pos = $this->current + 1;
456
while
(isset($this->tokens[$pos]))
457
{
458
if
($this->tokens[$pos][1] == $token)
459
{
460
return
true
;
461
}
462
elseif
($this->tokens[$pos][0] !== T_WHITESPACE)
463
{
464
return
false
;
465
}
466
$pos++;
467
}
468
return
false
;
469
}
470
471
protected
function
lookBackwardFor
($token)
472
{
473
$pos = $this->current - 1;
474
while
(isset($this->tokens[$pos]))
475
{
476
if
($this->tokens[$pos][1] == $token)
477
{
478
return
true
;
479
}
480
elseif
($this->tokens[$pos][0] !== T_WHITESPACE)
481
{
482
return
false
;
483
}
484
$pos--;
485
}
486
return
false
;
487
}
488
}
489
490
class
CSqlFormat
491
{
493
private
$tokenizer =
null
;
495
private
$levelizer =
null
;
496
497
private
$current =
null
;
498
private
$level = 0;
499
private
$add = 0;
500
private
$result =
''
;
502
private
$formatter =
null
;
503
504
public
function
__construct
()
505
{
506
$this->tokenizer =
new
CSqlTokenizer
;
507
$this->levelizer =
new
CSqlLevel
;
508
509
$this->level = 0;
510
$this->add = 0;
511
$this->current = 0;
512
$this->result =
''
;
513
}
514
515
public
static
function
reformatSql
($sql,
CSqlFormatFormatter
$formatter =
null
)
516
{
517
if
(function_exists(
'token_get_all'
))
518
{
519
$format =
new
CSqlFormat
;
520
$format->
setFormatter
($formatter ??
new
CSqlFormatText
);
521
return
$format->format($sql);
522
}
523
else
524
{
525
return
$sql;
526
}
527
}
528
529
public
function
setFormatter
(
CSqlFormatFormatter
$formatter)
530
{
531
$this->formatter = $formatter;
532
}
533
534
public
function
format
($sql)
535
{
536
$tokens = $this->tokenizer->parse($sql);
537
$tokens = $this->levelizer->addLevel($tokens);
538
return
$this->formatter->format($tokens);
539
}
540
}
CSqlFormatFormatter
Определения
sql_format.php:16
CSqlFormatFormatter\format
format($tokens)
Определения
sql_format.php:17
CSqlFormatFormatter\removeTrailingSpaces
removeTrailingSpaces(&$str)
Определения
sql_format.php:110
CSqlFormatFormatter\getSpace
getSpace()
Определения
sql_format.php:120
CSqlFormatFormatter\getTab
getTab()
Определения
sql_format.php:125
CSqlFormatFormatter\removeSpaces
removeSpaces($match)
Определения
sql_format.php:102
CSqlFormatFormatter\getEol
getEol()
Определения
sql_format.php:115
CSqlFormat
Определения
sql_format.php:491
CSqlFormat\__construct
__construct()
Определения
sql_format.php:504
CSqlFormat\format
format($sql)
Определения
sql_format.php:534
CSqlFormat\setFormatter
setFormatter(CSqlFormatFormatter $formatter)
Определения
sql_format.php:529
CSqlFormat\reformatSql
static reformatSql($sql, CSqlFormatFormatter $formatter=null)
Определения
sql_format.php:515
CSqlFormatText
Определения
sql_format.php:132
CSqlFormatText\getSpace
getSpace()
Определения
sql_format.php:138
CSqlFormatText\getTab
getTab()
Определения
sql_format.php:143
CSqlFormatText\getEol
getEol()
Определения
sql_format.php:133
CSqlLevel
Определения
sql_format.php:311
CSqlLevel\addLevel
addLevel(array $tokens)
Определения
sql_format.php:317
CSqlLevel\changeLevelAfter
changeLevelAfter()
Определения
sql_format.php:392
CSqlLevel\lookForwardFor
lookForwardFor($token)
Определения
sql_format.php:453
CSqlLevel\changeLevelBefore
changeLevelBefore()
Определения
sql_format.php:352
CSqlLevel\lookBackwardFor
lookBackwardFor($token)
Определения
sql_format.php:471
CSqlTokenizer
Определения
sql_format.php:150
CSqlTokenizer\lookForwardFor
lookForwardFor($token)
Определения
sql_format.php:291
CSqlTokenizer\removeBalancedBrackets
removeBalancedBrackets()
Определения
sql_format.php:248
CSqlTokenizer\transform
transform($token)
Определения
sql_format.php:206
CSqlTokenizer\parse
parse($sql)
Определения
sql_format.php:154
$str
$str
Определения
commerceml2.php:63
array
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения
file_new.php:804
$result
$result
Определения
get_property_values.php:14
elseif
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения
prolog_main_admin.php:393
$i
$i
Определения
factura.php:643
count
</p ></td >< td valign=top style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 2.0pt 0cm 2.0pt;height:9.0pt'>< p class=Normal align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center;line-height:normal'>< a name=ТекстовоеПоле54 ></a ><?=($taxRate > count( $arTaxList) > 0) ? $taxRate."%"
Определения
waybill.php:936
bitrix
modules
perfmon
classes
general
sql_format.php
Создано системой
1.14.0