BlackTDN :: 🚨 **CUIDADO COM REGEX NO PROTHEUS (TL++) – ISSO PODE DERRUBAR SEU SERVIDOR!** 🚨

_Créditos da imagem: ChatGPT

🚨 **CUIDADO COM REGEX NO PROTHEUS (TL++) – ISSO PODE DERRUBAR SEU SERVIDOR!** 🚨

Recentemente enfrentei um problema sério usando Regex no TL++ (linguagem do ERP TOTVS Protheus).

Estava desenvolvendo uma função para parsear URLs, servidores e paths. Usei Regex, afinal a linguagem oferece:

🔹 `Regex:Match()`
🔹 `Regex:Split()`
🔹 `Regex:Tokenizer()`

**Resultado?** 💥 **Desastre total.**

Bastou executar esta expressão:

```
"(?:(.*)://)?([^?/]*)(/[^?]*)?\??(.*)"
```

E…

🔥 CPU foi a 100%
🧠 Memória disparou
🐌 Threads ficaram presas
💣 Sem retorno, sem erro, apenas travamento

Testei também estas:

```
"(?:([^:@]*):?([^@:]*)@|)([^:]+):?(.*)"
"^((?:/.*/)|/)*(.*)$"
```

**Todas com o mesmo efeito: servidor colapsando.**

---

⚠️ **Por quê isso acontece?**

A engine de Regex do TL++ tem limitações severas:

❌ Não lida bem com backtracking
❌ Quantificadores `*`, `+`, `?` dentro de grupos destroem o desempenho
❌ Grupos opcionais e aninhados causam travamentos

O clássico problema de **Catastrophic Backtracking**, que leva ao consumo descontrolado de CPU e memória.

---

✅ **Solução prática:**

**Abandone regex no TL++ para esse tipo de processamento.**

Use parsing manual com:

🛠️ `At()`
🛠️ `SubStr()`
🛠️ `Left()`
🛠️ `Right()`
🛠️ `StrTokArr()`

---

🚀 **Exemplo real – Parseando uma URL sem Regex:**

```xBase
static function ParseURL(cUrl as character) as array

    local cProtocolo:="" as character
    local cHostPorta:="" as character
    local cCaminho:="" as character
    local cQuery:="" as character

    local nPosPath as numeric
    local nPosQuery as numeric
    local nPosProto as numeric

    // Protocolo
    nPosProto:=AT("://",cUrl)
    if (nPosProto>0)
        cProtocolo:=Left(cUrl,nPosProto-1)
        cUrl:=SubStr(cUrl,nPosProto+3)
    endif

    // HostPorta
    nPosPath:=AT("/",cUrl)
    nPosQuery:=AT("?",cUrl)

    if (nPosPath>0)
        cHostPorta:=Left(cUrl,nPosPath-1)
        cUrl:=SubStr(cUrl,nPosPath)
    elseif (nPosQuery>0)
        cHostPorta:=Left(cUrl,nPosQuery-1)
        cUrl:=SubStr(cUrl,nPosQuery)
    else
        cHostPorta:=cUrl
        cUrl:=""
    endif

    // Caminho
    if (Left(cUrl,1)=="/")
        nPosQuery:=AT("?",cUrl)
        if (nPosQuery>0)
            cCaminho:=Left(cUrl,nPosQuery-1)
            cUrl:=SubStr(cUrl,nPosQuery)
        else
            cCaminho:=cUrl
            cUrl:=""
        endif
    endif

    // Query
    if (Left(cUrl,1)=="?")
        cQuery:=SubStr(cUrl,2)
    endif

return({cProtocolo,cHostPorta,cCaminho,cQuery})
```

💡 Simples, rápido, eficiente e seguro.

---

## ✅ Solução viável no SQL Server (ou qualquer banco relacional que suporte expressões regulares ou funções string):

### ✔️ SQL Server não tem suporte nativo a regex, mas você consegue obter os dados da URL de forma eficiente usando `STRING_SPLIT`, `CHARINDEX`, `SUBSTRING` e `PARSE` combinados.

### 🎯 Exemplo prático para a URL:

```sql
DECLARE @URL VARCHAR(500) = 'https://localhost:1234/webapp/?DEBUG=853000&E=Environment&P=U_410FSQL&M=1';

-- Quebrando a URL
WITH Parsed AS (
    SELECT 
        -- Protocolo
        CASE 
            WHEN CHARINDEX('://', @URL) > 0 
            THEN LEFT(@URL, CHARINDEX('://', @URL) - 1)
            ELSE NULL
        END AS Protocolo,

        -- Host + Porta
        CASE 
            WHEN CHARINDEX('://', @URL) > 0 
            THEN 
                SUBSTRING(
                    @URL,
                    CHARINDEX('://', @URL) + 3,
                    CHARINDEX('/', @URL + '/', CHARINDEX('://', @URL) + 3) - (CHARINDEX('://', @URL) + 3)
                )
            ELSE 
                LEFT(@URL, CHARINDEX('/', @URL + '/') - 1)
        END AS HostPorta,

        -- Caminho (Path)
        CASE 
            WHEN CHARINDEX('/', @URL + '/', CHARINDEX('://', @URL) + 3) > 0 
            THEN 
                SUBSTRING(
                    @URL,
                    CHARINDEX('/', @URL + '/', CHARINDEX('://', @URL) + 3),
                    CHARINDEX('?', @URL + '?') - CHARINDEX('/', @URL + '/', CHARINDEX('://', @URL) + 3)
                )
            ELSE NULL
        END AS Caminho,

        -- QueryString
        CASE 
            WHEN CHARINDEX('?', @URL) > 0 
            THEN RIGHT(@URL, LEN(@URL) - CHARINDEX('?', @URL))
            ELSE NULL
        END AS QueryString
)
SELECT * FROM Parsed;
```

### 🔥 Saída:

| Protocolo | HostPorta      | Caminho  | QueryString                                    |
| --------- | -------------- | -------- | ---------------------------------------------- |
| https     | localhost:1234 | /webapp/ | DEBUG=853000\&E=Environment\&P=U\_410FSQL\&M=1 |

---

## ✔️ Se quiser quebrar os parâmetros da QueryString em linhas no SQL:

```sql
DECLARE @QueryString VARCHAR(MAX) = 'DEBUG=853000&E=Environment&P=U_410FSQL&M=1';

SELECT 
    LTRIM(RTRIM(value)) AS ParametroValor
FROM STRING_SPLIT(@QueryString, '&');
```

### 🔸 Resultado:

| ParametroValor |
| -------------- |
| DEBUG=853000   |
| E=Environment  |
| P=U\_410FSQL   |
| M=1            |

Se quiser ainda quebrar chave e valor:

```sql
SELECT 
    LEFT(ParametroValor, CHARINDEX('=', ParametroValor) - 1) AS Parametro,
    RIGHT(ParametroValor, LEN(ParametroValor) - CHARINDEX('=', ParametroValor)) AS Valor
FROM (
    SELECT LTRIM(RTRIM(value)) AS ParametroValor
    FROM STRING_SPLIT(@QueryString, '&')
) AS T
WHERE CHARINDEX('=', ParametroValor) > 0;
```

| Parametro | Valor       |
| --------- | ----------- |
| DEBUG     | 853000      |
| E         | Environment |
| P         | U\_410FSQL  |
| M         | 1           |

---

🧠 **Aprendizado:**

> Nem sempre a solução mais “bonita” (Regex) é a melhor.
> Conhecer as limitações da plataforma é papel de qualquer desenvolvedor profissional.

## 🚩 Conclusão

Sim, você consegue extrair os mesmos dados que a expressão regex tentava obter diretamente em AdvPL/TLPP ou no SQL, de forma bem mais performática e estável, **sem o risco de travar servidor Protheus ou aumentar uso de memória**.

---

👉 E você? Já passou por algo parecido no Protheus ou em outro sistema? Me conta aqui nos comentários. 👇

---

\#totvs #protheus #tlpp #regex #erp #desenvolvimento #devprotheus #programacao #desenvolvedores #tech #erpdevelopment #parsing #performancesoftware

---

Comentários

Postagens mais visitadas