SQLite Data Studio: rutine
Nazaj: SQLite Data Studio
Rutina je poimenovana delovna enota SQL: manifest s parametri in obliko rezultata, poleg tega pa poizvedba sama ali klic izvorne procedure.
[Live]
Pojmi
| Pojem | Pomen |
|---|---|
| Rutina | Poimenovana delovna enota SQL: manifest (.json) in ena ali več datotek SQL (.sql) ali klic izvorne procedure. |
| Nabor rutin | Mapa z rutinami; te so glede na vrsto v podmapah Functions/ in Procedures/. Nabor default je mapa sql/ paketa; paketi, ki rutine uporabljajo, prijavijo svoje nabore (glejte referenco API). Naslavljanje: ime (privzeti nabor) ali nabor:ime. |
| Manifest | JSON s parameters, returns in eno ali več implementations za posamezna zaledja. |
| Zaledje | Vedenje, značilno za pogon (navajanje identifikatorjev, točke shranjevanja, lastInsertId, narečje izvornega klica), izbrano po gonilniku PDO povezave. |
Hitri začetek
$routines = plugin_load('helper', 'wksqliteds'); // nad obstoječim PDO: $affected = $routines->execute($pdo, 'close_inspection', ['id' => 123, 'user' => 'wolfgang']); // nad poimenovano povezavo: $rows = $routines->execute('reporting', 'reports:monthly', ['month' => '2026-07']); // prek storitve wkcore: $svc = ServiceHub::fromDokuWiki()->service('sql.routines'); $svc?->execute($pdo, 'close_inspection', ['id' => 123, 'user' => 'wolfgang']);
execute($connection, $routine, $params):
- $connection:
\PDO, objekt z metodogetPdo(), ime povezave alinull(uporabi se možnostdefault_connection). - $routine:
„ime“(privzeti nabor) ali„nabor:ime“; pripeta končnica.jsonse dopušča. - $params:
['ime' => vrednost, ...]. - Rezultat po polju
returnsv manifestu, sicer se vržeRoutineException.
Manifest
Manifest je datoteka <ime>.json v podmapi svoje vrste, npr. sql/Functions/close_inspection.json. Datoteka SQL, ki jo navaja, je v isti podmapi.
Ploščati (ena izvedba – prvotna specifikacija, še vedno podprta):
{ "name": "close_inspection", "type": "nonquery", "file": "close_inspection.sql", "transaction": true, "parameters": { "id": "integer", "user": "string" }, "returns": "rows_affected" }
Za več zaledij (izvedbe za posamezne gonilnike):
{ "name": "close_inspection", "parameters": { "id": "integer", "user": "string" }, "returns": "rows_affected", "implementations": { "default": { "type": "sql", "file": "close_inspection.sql", "transaction": true }, "mysql": { "type": "procedure", "call": "close_inspection", "transaction": true }, "pgsql": { "type": "sql", "file": "close_inspection.pgsql.sql", "transaction": true } } }
| Polje | Vrednosti |
|---|---|
name | [A-Za-z0-9_-]+; se mora ujemati z imenom datoteke. |
parameters | preslikava ime → vrsta: integer, string, boolean, float. Pripona [] = seznam IN (polje → (?, ?, …)); pripona ? = dovoljen NULL. |
returns | rows_affected | insert_id | rows | row | scalar | none. |
type | sql (stavki iz datoteke) ali procedure (izvorni klic). Stare besede nonquery/query → sql; proc/call/function → procedure. Obliko rezultata določa returns, ne type. |
file | (sql) pot glede na podmapo vrste (Functions/ oz. Procedures/), končnica .sql, brez ..; datoteka mora biti v tej podmapi. |
call | (procedure) [A-Za-z_][A-Za-z0-9_.]*. |
transaction | bool (privzeto true). |
Razreševanje: ključ za konkreten gonilnik ima prednost, sicer velja default.
Datoteke SQL
Datoteka type:sql sme vsebovati več stavkov; wksqliteds jih loči sam (pravila spodaj).
Vsaka nadomestna oznaka :ime se prepiše v
pozicijski ? in se veže (nikoli stakne) – enako za vsa zaledja, vključno z ODBC/Access.
Stavek veže samo oznake, ki se v njem dejansko pojavijo (brez napake PDO HY093).
Pravila ločevanja: stavki se ločijo pri ; – vendar ne znotraj nizov ('…' z
ubežnim zapisom ''), komentarjev (-- tudi za kodo v isti vrstici, /* … */)
in identifikatorjev v narekovajih ("…", krativci, […]). Tudi ; znotraj bloka
BEGIN … END ali CASE … END stavka ne loči: telo prožilca ali procedure ostane en stavek.
Nezaključen blokovni komentar izvajanje prekine z RoutineException, namesto da bi pogoltnil
preostanek datoteke.
Dinamični SQL
- Seznami IN: parameter deklarirajte kot
integer[]/string[]in podajte polje →(?, ?, …). Prazno polje →(NULL). V besedilu SQL stoji oznaka brez lastnih oklepajev (WHERE id IN :ids, neIN (:ids)– sicer po razširitvi seznama nastane neveljavniIN ((?, ?))). - Dinamični identifikatorji / vdelani PHP: datoteka rutine sme vsebovati PHP; v obsegu sta
$paramsin$ctx.$ctx->ident('stolpec')vrne preverjen identifikator v narekovajih, kot jih zahteva pogon (edina varna pot za dinamična imena tabel in stolpcev). Vrednosti vedno ostanejo oznake:ime.
Model groženj za vdelani PHP
Vdelani PHP teče s polnimi pravicami aplikacije (eval, kot pri wksnippet). Zato je
zavarovan večkrat:
- Potrebuje tako možnost paketa
allowPhpkot globalno možnost$conf['phpok'](dvojna vrata). Privzeto: izklopljeno. Če datoteka vsebuje PHP, vrata pa so zaprta, izvedba varno odpove (RoutineException). - Od 2. stopnje modela pravic (podrobnosti): tudi ko so odprta obe vrata v nastavitvah, sme datoteko SQL rutine s PHP shraniti (sama zmožnost
designne zadošča) ali jo interaktivno sprožiti v studiu (sama zmožnostusene zadošča) samo pravi superuporabnik – ne glede na to, kaj sicer dovoljuje matrika zmožnosti. Razlog: brez te dodatne vezave bi uporabnik, ki ni superuporabnik, z dovoljenjemdesignlahko shranil kodo PHP, ki bi pozneje tekla s polnimi pravicami aplikacije (ko bi jo sprožil sam, superuporabnik ali storitevsql.routines). Pot prek storitvesql.routines(programski klicatelji, kot jewkblog) te dodatne vezave nima – zaupa že shranjeni datoteki rutine, natanko kot pred 2. stopnjo.
Prijava naborov rutin iz drugega paketa
// (a) z dogodkom $controller->register_hook('WKSQLITEDS_REGISTER_ROUTINE_SETS', 'BEFORE', $this, 'sets'); public function sets(\dokuwiki\Extension\Event $event) { $event->data->register('reports', __DIR__ . '/sql'); } // (b) programsko plugin_load('helper', 'wksqliteds')->registerSet('reports', __DIR__ . '/sql');
Naslavljanje je nato reports:monthly. Celotna pogodba metod: referenca API.
Dogodek iz časa pred preimenovanjem (WVDSDWMSQLITE_REGISTER_ROUTINE_SETS) se ne sproži več;
prehodni most je bil odstranjen, ko so vsi znani paketi prešli na novo ime.
Nastavitve
| Možnost | Privzeto | Pomen |
|---|---|---|
allowPhp | 0 | dovoli vdelani PHP v rutinah (potreben je še globalni phpok; od 2. stopnje poleg tega strukturno vezan na superuporabnike). |
default_connection | '''' | povezava, kadar execute() ne dobi nobene. |
slow_ms | 200 | zabeleži rutine, ki trajajo dlje (ms); 0 = izklopljeno. |
Varnost
- CSRF: vsak zapis v skrbniškem delu prek
checkSecurityToken(). - Avtorizacija: izvedba prek spleta (vmesnik studia) sledi matriki zmožnosti; nobena spletna končna točka ne izvede rutine samo na podlagi vnosov iz zahteve brez preverjanja.
- Prehod poti (CWE-22): imena so omejena na dovoljen nabor znakov;
fileje prekrealpathzaprt v mapo nabora, končnica.sql. - Vrivanje SQL (CWE-89): vrednosti so vedno vezane; identifikatorji samo prek
$ctx→ident(); SQL se nikoli ne sestavlja iz vrednosti. - Dostopni podatki: nikoli kot čisto besedilo v JSON in nikoli v sporočilih o napakah – podrobnosti: Povezave.
- XSS (CWE-79): vsi izpisi v skrbniškem delu gredo skozi
hsc(). - Transakcije:
transaction:trueje atomaren (begin/commit oziromaSAVEPOINTpri gnezdenju), ob napaki povrnitev.
Opombe o zaledjih
| Zaledje | Gonilnik | Identifikator | Točke shranjevanja | Klic procedure | insert_id |
|---|---|---|---|---|---|
| SQLite | sqlite | „x“ | da | – (samo SQL) | lastInsertId() |
| MySQL/MariaDB | mysql | `x` | da | CALL p(…) | LAST_INSERT_ID() |
| PostgreSQL | pgsql | „x“ | da | SELECT * FROM p(…) | lastval() – bolje RETURNING in returns:scalar |
| SQL Server | sqlsrv | [x] | SAVE TRANSACTION | EXEC p … | SCOPE_IDENTITY() |
| MS Access | odbc | [x] | jih ni (pridruži se zunanji transakciji, zabeleženo) | {CALL p(…)} | SELECT @@IDENTITY |
MS Access potrebuje gonilnik ODBC ACE/Jet »Microsoft Access Driver (*.mdb, *.accdb)« in
pdo_odbc (Windows).
Pogoste napake
Simptom: PDOException »HY093« pri manifestu z več stavki.
Vzrok: stavek veže oznako, ki je deklarirana v drugem stavku datoteke, v tem stavku pa se ne uporablja.
Rešitev: v praksi odpade – izvajalec v vsakem stavku veže samo oznake, ki se v njem dejansko pojavijo. Če se napaka vseeno pojavi, je navadno v imenu oznake tipkarska napaka (velike in male črke se morajo ujemati).
Simptom: filter IN s parametrom seznama vrne skladenjsko napako SQL.
Vzrok: oznaka ima v besedilu SQL lastne oklepaje (IN (:ids)); po samodejni razširitvi
seznama nastane neveljavni IN ((?, ?)).
Rešitev: oklepaje v besedilu SQL izpustite – IN :ids (glejte razdelek »Dinamični SQL«).
Sorodne teme
- Povezave – na katero povezavo se obrne
execute() - Pravice – preverjanje zmožnosti pri izvedbi iz studia
- Referenca API – celotna pogodba metod pomočnika
- Recepti – recept »Ustvarjanje rutine«