Uma consulta com parâmetros
Tradução automática
Esta página foi traduzida automaticamente do inglês e ainda não foi revisada por um falante nativo; correções são bem-vindas no GitHub. Se algo não bater, vale o original em inglês. O código e os resultados são os mesmos do original, importados dos arquivos testados.
Tarefa: listar os produtos cujo nome contém o que a URL pede (/?name=mouse), com segurança.
yaml
# Recipe: a query that takes a value from the URL, bound as a parameter.
paths:
components: ./components
migrations: ./migrations
datasources:
db:
driver: sqlite
database: ./data/shop.dbsql
CREATE TABLE products (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
price REAL NOT NULL
);
INSERT INTO products (name, price) VALUES
('Notebook', 3500.0), ('Mouse', 80.0), ('Monitor', 1200.0), ('Mousepad', 25.0);Cada :name no SQL é ligado ao q:param de mesmo nome: o valor vai para o banco separado do texto do SQL, convertido antes pelo seu type. Um :name sem q:param não passa pelo parser, então não há como colar um valor no SQL sem querer.
xml
<q:component name="Products">
<!-- ?name=mouse from the URL; empty when it is not there. -->
<q:set name="term" value="{query.name}" default="" />
<!-- :pattern is bound to the q:param: the value is sent to the database
apart from the SQL, so it can never change what the SQL does. -->
<q:query name="products" datasource="db">
SELECT name, price FROM products WHERE name LIKE :pattern ORDER BY price
<q:param name="pattern" value="%{term}%" type="string" />
</q:query>
<ui:window title="Products">
<ui:text>{products_result.recordCount} products</ui:text>
<ui:table source="{products}">
<ui:column key="name" label="Name" />
<ui:column key="price" label="Price" />
</ui:table>
</ui:window>
</q:component>O último teste manda SQL na URL. É só um texto a procurar: nenhum produto o tem no nome, e a tabela fica intacta.
xml
<q:test name="without a filter, every product" page="/">
<test:visit />
<test:expect text="4 products" />
<test:expect text="Notebook" />
</q:test>
<q:test name="the value from the URL filters" page="/">
<test:visit name="mouse" />
<test:expect text="2 products" />
<test:expect text="Mousepad" />
<test:expect no-text="Monitor" />
</q:test>
<q:test name="SQL in the URL is only text to search for" page="/">
<test:visit name="' OR '1'='1" />
<test:expect text="0 products" />
<test:expect table="products" count="4" />
</q:test>text
tests/products.test.q
PASS without a filter, every product
PASS the value from the URL filters
PASS SQL in the URL is only text to search for
3 passed, 0 failedVeja DB-1.