Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix "Big query PREG_JIT_STACKLIMIT_ERROR" #433

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions src/DebugBar/DataCollector/PDO/TracedStatement.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,18 +125,19 @@ public function getSqlWithParams(string $quotationChar = '<>') : string
}

$matchRule = "/({$marker}(?!\w))(?=(?:[^$quotationChar]|[$quotationChar][^$quotationChar]*[$quotationChar])*$)/";
$count = mb_substr_count($sql, $k);
if ($count < 1) {
$count = mb_substr_count($sql, $matchRule);
}
for ($i = 0; $i <= $count; $i++) {
$sql = preg_replace($matchRule, $v, $sql, 1);
$sqlSplit = explode(PHP_EOL, $sql);
$sql = null;
foreach ($sqlSplit as $pieces) {
for ($i = 0; $i <= mb_substr_count($pieces, $k); $i++) {
$pieces = preg_replace($matchRule, $v, $pieces, 1);
}
$sql .= $pieces . PHP_EOL;
}
}

$sql = strtr($sql, array_flip($cleanBackRefCharMap));

return $sql;
return trim($sql);
}

/**
Expand Down
244 changes: 244 additions & 0 deletions tests/DebugBar/Tests/TracedStatementTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,250 @@ public function testRepeadParamsQuery()
$this->assertEquals($expected, $result);
}

/**
* Big query generate regex error
*/
public function testBigQuery()
{
$params = [
':id_segmento' => 1,
':id_part' => 1,
':inativo' => 1,
':ativo' => 1
];
$query = 'select sum(qtd) as total from (
select count(*) as qtd from (
select distinct vw.id_modulo, vw.id_envio, vw.id_form,
vw.versao, vw.id_sistema, vw.id_grupo
from vw_forms_disponiveis vw
where vw.id_part = :id_part
and vw.id_servico = :id_segmento
and vw.concluido = :inativo
) as forms

union
select distinct count(pesq.*) as qtd from
pesquisa.avaliacao_modulo_disponivel pesq
join envio e
on e.id_envio = pesq.id_envio
and e.id_servico = pesq.id_servico
join rodada r
on e.id_envio = r.id_envio
join part_form pf
on r.ano = pf.ano
and r.id_rodada = pf.id_rodada
and pf.id_modulo = r.id_modulo
where pf.id_part = :id_part
and (
r.data_fim > date(now())
or pf.data_excecao_fim > date(now())
)
and (
r.data_ini <= date(now())
or pf.data_excecao_ini <= date(now())
)
and e.id_servico = :id_segmento
and pesq.id_modulo = :inativo

union
select distinct count(p.id_pesquisa) as qtd
from pesquisas.pesquisa p
join pesquisas.publicacao as pub
on pub.id_pesquisa = p.id_pesquisa
left join pesquisas.resposta r
on r.id_pesquisa = p.id_pesquisa
and r.id_publicacao = pub.id_publicacao
and r.id_part = :id_part
where pub.id_servico = :id_segmento
and pub.excluido = :inativo
and p.excluido = :inativo
and r.id_resposta is null
and pub.data_ini <= date(now())
and pub.data_fim >= date (now())
and (
p.resp_primeira_publicacao = :inativo
or (
pub.id_publicacao in (
select r2.id_publicacao
from pesquisas.resposta r2
where r2.id_part = :id_part
and r2.id_pesquisa = p.id_pesquisa
)
)
or (
not exists (
select r2.id_pesquisa
from pesquisas.resposta r2
where r2.id_part = :id_part
and r2.id_pesquisa = p.id_pesquisa
)
)
)
and (
pub.todos_parts = :ativo
or :id_part in (
select id_part
from pesquisas.publicacao_part pp
where pp.id_pesquisa = pub.id_pesquisa
and pp.id_publicacao = pub.id_publicacao
and pp.id_part = :id_part
)
)

union
select count(es.*) as qtd from especial.solicitacao es
join especial.dados_solicitacao d
on es.id_servico = d.id_servico
and es.ano = d.ano
join especial.liberacao el
on el.ano = d.ano
and el.id_servico = d.id_servico
and el.id_part = es.id_part
left join especial.prorrogados p
on p.ano = el.ano
and p.id_servico = el.id_servico
and p.id_part = el.id_part
where es.id_usu is null -- possui resp
and el.id_servico = :id_segmento
and el.id_part = :id_part
and (
el.id_part in (8005, 8012)
or
d.liberada = :ativo
)
and ((d.data_ini <= date(now()) and d.data_fim >= date(now()))
or (
d.data_ini_excecao <= date(now())
and d.data_fim_excecao >= date(now())
and p.id_part not in (
select s.id_part from especial.solicitacao s
where s.data < d.data_ini_excecao
and s.id_part = el.id_part and s.ano = d.ano
and s.id_servico = d.id_servico
)
)
or (p.data_fim >= date(now()))
)
) as resultados_em_aberto';
$expected = 'select sum(qtd) as total from (
select count(*) as qtd from (
select distinct vw.id_modulo, vw.id_envio, vw.id_form,
vw.versao, vw.id_sistema, vw.id_grupo
from vw_forms_disponiveis vw
where vw.id_part = <1>
and vw.id_servico = <1>
and vw.concluido = <1>
) as forms

union
select distinct count(pesq.*) as qtd from
pesquisa.avaliacao_modulo_disponivel pesq
join envio e
on e.id_envio = pesq.id_envio
and e.id_servico = pesq.id_servico
join rodada r
on e.id_envio = r.id_envio
join part_form pf
on r.ano = pf.ano
and r.id_rodada = pf.id_rodada
and pf.id_modulo = r.id_modulo
where pf.id_part = <1>
and (
r.data_fim > date(now())
or pf.data_excecao_fim > date(now())
)
and (
r.data_ini <= date(now())
or pf.data_excecao_ini <= date(now())
)
and e.id_servico = <1>
and pesq.id_modulo = <1>

union
select distinct count(p.id_pesquisa) as qtd
from pesquisas.pesquisa p
join pesquisas.publicacao as pub
on pub.id_pesquisa = p.id_pesquisa
left join pesquisas.resposta r
on r.id_pesquisa = p.id_pesquisa
and r.id_publicacao = pub.id_publicacao
and r.id_part = <1>
where pub.id_servico = <1>
and pub.excluido = <1>
and p.excluido = <1>
and r.id_resposta is null
and pub.data_ini <= date(now())
and pub.data_fim >= date (now())
and (
p.resp_primeira_publicacao = <1>
or (
pub.id_publicacao in (
select r2.id_publicacao
from pesquisas.resposta r2
where r2.id_part = <1>
and r2.id_pesquisa = p.id_pesquisa
)
)
or (
not exists (
select r2.id_pesquisa
from pesquisas.resposta r2
where r2.id_part = <1>
and r2.id_pesquisa = p.id_pesquisa
)
)
)
and (
pub.todos_parts = <1>
or <1> in (
select id_part
from pesquisas.publicacao_part pp
where pp.id_pesquisa = pub.id_pesquisa
and pp.id_publicacao = pub.id_publicacao
and pp.id_part = <1>
)
)

union
select count(es.*) as qtd from especial.solicitacao es
join especial.dados_solicitacao d
on es.id_servico = d.id_servico
and es.ano = d.ano
join especial.liberacao el
on el.ano = d.ano
and el.id_servico = d.id_servico
and el.id_part = es.id_part
left join especial.prorrogados p
on p.ano = el.ano
and p.id_servico = el.id_servico
and p.id_part = el.id_part
where es.id_usu is null -- possui resp
and el.id_servico = <1>
and el.id_part = <1>
and (
el.id_part in (8005, 8012)
or
d.liberada = <1>
)
and ((d.data_ini <= date(now()) and d.data_fim >= date(now()))
or (
d.data_ini_excecao <= date(now())
and d.data_fim_excecao >= date(now())
and p.id_part not in (
select s.id_part from especial.solicitacao s
where s.data < d.data_ini_excecao
and s.id_part = el.id_part and s.ano = d.ano
and s.id_servico = d.id_servico
)
)
or (p.data_fim >= date(now()))
)
) as resultados_em_aberto';
$traced = new TracedStatement($query, $params);
$result = $traced->getSqlWithParams();
$this->assertEquals($expected, $result);
}

/**
* Check that query parameters are being replaced only once
* @bugFix Before fix it: select * from
Expand Down
Loading