SQLite3 Consulta armazenando erro de sintaxe de endereço IP

0

Estou tentando executar uma consulta sqlite3 em um banco de dados pequeno para atualizar uma tabela. Enquanto o script é mais complicado, para testar, eu defino as seguintes variáveis:

DN=123
UP=123
downlocalip=10.1.2.3
downremoteip=123
uplocalip=123
upremoteip=123

Eu então executo o seguinte comando para atualizar a tabela.

sqlite3 /var/www/server/newserverstats.db "UPDATE stats SET downspeed='''$DN''', upspeed='''$UP''', downlocalip='''$downlocalip''', downremoteip='''$downremoteip''', uplocalip='''$uplocalip''', upremoteip='''$upremoteip''' WHERE primkey=1"

Isso gera um erro de sintaxe:

Error: near ".2": syntax error

Se eu definir o downlocalip como 10.1 somente, ele funcionará bem, por isso não está gostando dos decimais adicionais.

Na tabela em si eu tenho o tipo definido como texto, então eu não acho que isso importaria?

Saída de tabela do Pragma:

0|primkey|integer|0||1
1|downspeed|integer|1||0
2|upspeed|integer|1||0
3|downlocalip|text|1||0
4|downremoteip|text|1||0
5|uplocalip|text|1||0
6|upremoteip|text|1||0

Eu tentei todos os tipos de configurações de aspas, mas não consigo ver o que estou fazendo de errado.

Alguma idéia?

EDITAR:

Os comandos completos que tentei, conforme comentários abaixo, são:

/usr/bin/ssh [email protected] 'sqlite3 /var/www/server/newserverstats.db "UPDATE stats SET downspeed=$DN, upspeed=$UP, downlocalip="$downlocalip", downremoteip="$downremoteip", uplocalip="$uplocalip", upremoteip="$upremoteip" WHERE primkey=1"'

ou

/usr/bin/ssh [email protected] 'sqlite3 /var/www/server/newserverstats.db "UPDATE stats SET downspeed=$DN, upspeed=$UP, downlocalip='$downlocalip', downremoteip='$downremoteip', uplocalip='$uplocalip', upremoteip='$upremoteip' WHERE primkey=1;"'

ambos me deram o seguinte erro:

Error: near ",": syntax error

Novo comando, mais próximo:

ssh [email protected] sqlite3 /var/www/server/newserverstats.db <<END_SQL
    UPDATE stats
    SET downspeed=$DN,
        upspeed=$UP,
        downlocalip="$downlocalip",
        downremoteip="$downremoteip",
        uplocalip="$uplocalip",
        upremoteip="$upremoteip"
    WHERE primkey=1
END_SQL

Recolhendo de volta para uma única linha em um script de teste:

#!/bin/bash -x
DN=123
UP=123
downlocalip=10.1.2.3
downremoteip=123
uplocalip=123
upremoteip=123
sql="UPDATE stats SET downspeed=$DN, upspeed=$UP, downlocalip="$downlocalip", downremoteip="$downremoteip", uplocalip="$uplocalip", upremoteip="$upremoteip" WHERE primkey=1"
echo $sql
ssh [email protected] sqlite3 /var/www/server/newserverstats.db "$sql"

Isso me dá a resposta de:

UPDATE stats SET downspeed=123, upspeed=123, downlocalip=10.1.2.3, downremoteip=123, uplocalip=123, upremoteip=123 WHERE primkey=1
sqlite3: Error: too many options: "stats"
Use -help for a list of options.
    
por Matthew Hodder 07.03.2018 / 11:26

2 respostas

1

O problema é a citação das strings nos campos de texto.

Use um documento aqui (que permite escrever uma declaração mais atraente):

sqlite3 database <<END_SQL
    UPDATE stats
    SET downspeed=$DN,
        upspeed=$UP,
        downlocalip="$downlocalip",
        downremoteip="$downremoteip",
        uplocalip="$uplocalip",
        upremoteip="$upremoteip"
    WHERE primkey=1
END_SQL

Isso pressupõe que você tenha controle total sobre os valores nas variáveis, para que você saiba que eles estão adequadamente higienizados e não apresentarão nenhuma vulnerabilidade de injeção de SQL.

Dos comentários:

Fazendo isso por SSH:

ssh user@server sqlite3 database <<END_SQL
    UPDATE stats
    SET downspeed=$DN,
        upspeed=$UP,
        downlocalip="$downlocalip",
        downremoteip="$downremoteip",
        uplocalip="$uplocalip",
        upremoteip="$upremoteip"
    WHERE primkey=1
END_SQL
    
por 07.03.2018 / 11:36
0

O principal problema é que você está usando três aspas simples antes e depois de cada variável, em vez de apenas uma. Isso não é necessário - na verdade, não funcionará.

Você está recebendo o erro no endereço IP $downlocalip porque está efetivamente sem aspas, então sqlite3 está tentando interpretá-lo como um número de ponto flutuante ao invés de uma string de texto ... e números de ponto flutuante não têm duas casas decimais aponta neles.

Outro problema menor é que você está colocando aspas simples em torno dos valores dos campos inteiros ( downspeed e upspeed ).

Tente isso:

sqlite3 /var/www/server/newserverstats.db "UPDATE stats SET downspeed=$DN,
   upspeed=$UP, downlocalip='$downlocalip', downremoteip='$downremoteip',
   uplocalip='$uplocalip', upremoteip='$upremoteip' WHERE primkey=1;"

As aspas simples nessa string estão dentro das aspas duplas, portanto, não impeça que as variáveis sejam expandidas pelo shell. Eles não têm nenhum significado especial entre aspas duplas, são apenas parte do texto. As variáveis têm um significado especial dentro de aspas duplas, portanto, seja expandido como esperado.

Ou use um heredoc como na resposta de Kusalananda - é mais legível.

BTW, se você está fazendo um monte de operações sqlite, seria muito melhor escrever seu script em uma linguagem que tenha um módulo de biblioteca sqlite que suporte valores de espaço reservado. por exemplo. ambos perl e python possuem bibliotecas excelentes para trabalhar com sqlite3 e outros bancos de dados SQL. Geralmente, é possível escrever código usando essas bibliotecas para que elas requeiram poucas alterações, se houver, para trabalhar com outros bancos de dados, como postgresql ou mysql.

    
por 07.03.2018 / 11:40