Nelze provádět manipulaci s Oracle databází

Akroman
Člen | 3
+
0
-

Zdravím,
potřeboval bych poradit, co dělám špatně při vkládání dat do Oracle databáze.

Zde je můj presenter s formulářem a vložením dat do databáze:

<?php

namespace App\Presenters;

use Nette\Application\UI\Presenter;
use Nette\Database\Connection;
use Nette\Application\UI\Form;
use Nette;

final class RegisterPresenter extends BasePresenter
{
    public function __construct(Connection $database)
    {
        parent::__construct($database);
    }

    private $rasy = [
        'Nautolan' => 'Nautolan',
        'Clovek' => 'Člověk',
        'Cerean' => 'Cerean',
        'Kel dor' => 'Kel dor',
        'Togruta' => 'Togruta',
        'Mirialan' => 'Mirialan'
    ];

    protected function createComponentRegisterForm()
    {
        $form = new Form;

        $flotily = $this->database->fetchPairs('SELECT flotila_id FROM Flotila');
        $planety = $this->database->fetchPairs('SELECT planeta_id, nazev FROM Planeta');

        $form->addText('jedi_id', 'ID Jedi:')
             ->setRequired('Prosím zadejte ID Jedi');

        $form->addText('jmeno', 'Jméno:')
             ->setRequired('Prosím zadejte jméno Jedi');

        $form->addText('prijmeni', 'Příjmení:')
             ->setRequired('Prosím zadejte příjmení Jedi');

        $form->addSelect('planeta_id', 'Planeta původu:', $planety)
             ->setRequired('Prosím zadejte planetu původu');

        $form->addSelect('flotila_id', 'ID flotily', $flotily);


        $form->addSelect('rasa', 'Rasa:', $this->rasy);

        $form->addText('midichlorian', 'Množství midichlorianů');

        $form->addText('barva_mece', 'Barva meče:');

        $form->addText('narozeni', 'Datum narození:');

        $form->addSelect('padawan', 'Jedi je padawanem', [0 => 'Ne', 1 => 'Ano']);

        $form->addText('username', 'Uživatelské jméno')
             ->setRequired('Prosím vyplňte uživatelské jméno');

        $form->addText('pass', 'Heslo:')
             ->setRequired('Prosím vyberte si heslo');

        $form->addSubmit('submit', 'Zaregistrovat');

        $form->onSuccess[] = [$this, 'registerFormSucceeded'];

        return $form;
    }

    public function registerFormSucceeded($form, $values)
    {
        $values = $form->getValues();
        $request = $this->database->query('INSERT INTO Jedi ?', [
            'jedi_id' => intval($values->jedi_id),
            'planeta_id' => $values->planeta_id,
            'flotila_id' => $values->flotila_id,
            'jmeno' => $values->jmeno,
            'prijmeni' => $values->prijmeni,
            'rasa' => $values->rasa,
            'mnozstvi_chlorianu' => intval($values->midichlorian),
            'barva_mece' => $values->barva_mece,
            'dat_narozeni' => $values->narozeni,
            'je_padawan' => $values->padawan,
            'username' => $values->username,
            'heslo' => $values->pass
        ]);
        $this->flashMessage('Jedi byl úspěšně přídán do systému', 'success');
        $this->redirect('Homepage:');
    }
}

Při INSERT požadavku dostanu následující error:

SQLSTATE[HY000]: General error: 904 OCIStmtExecute: ORA-00904: „heslo“: invalid identifier
(ext\pdo_oci\oci_statement.c:157)

Děje se to pouze při provádění dotazů, kde vkládám nebo vybírám proměnné (při statických dotazech, jako je třeba SELECT pro výběr ID a názvu planety ve formuláři je všechno v pohodě). Vyzkoušel jsem už všechno, co jsem na netu našel a nic mi nepomohlo.

Takhle vypadá tabulka

CREATE TABLE Jedi(
jedi_id NUMBER,
planeta_id NUMBER NOT NULL,
flotila_id NUMBER,
jmeno VARCHAR2(50 CHAR) NOT NULL,
prijmeni VARCHAR2(50 CHAR) NOT NULL UNIQUE,
rasa VARCHAR2(50 CHAR),
mnozstvi_chlorianu NUMBER,
barva_mece VARCHAR2(50 CHAR),
dat_narozeni DATE,
je_padawan NUMBER(1) DEFAULT 0 NOT NULL,
username VARCHAR2(200 CHAR) UNIQUE,
pass VARCHAR2(200 CHAR),
CONSTRAINT jedi_pk PRIMARY KEY(jedi_id),
CONSTRAINT jedi_planeta_puvodu FOREIGN KEY (planeta_id) REFERENCES Planeta (planeta_id),
CONSTRAINT jedi_flotila_fk FOREIGN KEY (flotila_id) REFERENCES Flotila (flotila_id)
);

Budu vděčný za jakoukoliv radu.

EncryptSL
Člen | 11
+
0
-

Ahoj nevím jestli si na to přišel, ale uvádíš že máš v příkazu pro vytvoření tabulky máš pass ale v kódu to vkládáš do pole se jménem heslo.

Ta chyba to sama o sobě říká „heslo“: invalid identifier.

Zkus si to zaměnit za pass v tom kódu :).
Dej vědět jestli jsem se trefil správně.

Akroman
Člen | 3
+
0
-

Pardon, dal jsem sem starší verzi SQL skriptu, přejmenoval jsem to na heslo, jelikož jsem chtěl zkusit, jestli náhodou pass není rezervované slovo.

Každopádně jsem přišel na to, že když třeba výše uvedený SELECT

$flotily = $this->database->fetchPairs('SELECT flotila_id FROM Flotila');

Nahradím za

$id = 'flotila_id';
$flotily = $this->database->fetchPairs('SELECT ? FROM Flotila', $id);

Provede se následující query:
SELECT ‚flotila_id‘
FROM Flotila

A ta nefunguje. Když ale napíšu

$id = 'flotila_id';
$flotily = $this->database->fetchPairs('SELECT ' . $id . ' FROM Flotila');

Provede se query:
SELECT flotila_id
FROM Flotila

A všechno funguje v pohodě. Myslím si, že to je tím, že tam PHP vkládá ty uvozovky, nevím ale jak to zrušit a tu variantu s konkatenací stringů bych raději nepoužíval, i když je aplikace jen jako školní projekt a nikde se využívat nebude, tak bych se rád vyhnul nebezpečí SQL injection.

David Matějka
Moderator | 6445
+
0
-

opravdu potrebujes skladat sql dotazy? ten otaznik ? se pouziva pro vkladani parametru, nikolik pro vkladani identifikatoru, tedy napriklad kdyz chces dosadit ID z url

->query('select * from foo where id = ?', $id)

pokud bys chtel skladat sql dotazy, tak stejne neni dobry napad brat treba ten nazev sloupecku (flotila_id) primo z nejakeho uzivatelskeho vstupu. mel bys tam mit v kodu definovanou nejakou mnozinu povolenych hodnot

Akroman
Člen | 3
+
0
-

Uvedl jsem ten příklad trochu nešikovně. O co mi šlo je, že při tom INSERT to dělá to samé, čili výsledný požadavek vypadá například následovně:

INSERT INTO Jedi („jedi_id“, „planeta_id“, „flotila_id“, „jmeno“, „prijmeni“, „rasa“,
„mnozstvi_chlorianu“, „barva_mece“, „dat_narozeni“, „je_padawan“, „username“, „heslo“)
VALUES (12, 6, 1, ‚Qui-Gon‘, ‚Jinn‘, ‚Clovek‘, 12000, ‚Zelena‘, ‚19.3.1975‘, 0, ‚qui-gon‘, ‚neco‘)

Zkoušel jsem takto INSERT přímo v Oracle SQL Developer a vypíše to ten samý error, pokud odstraním uvozovky z názvů sloupců, tak INSERT proběhne v pořádku. Takže mi jde o to, jak odstranit uvozovky z názvů těch sloupců, aniž bych musel vypisovat celý zdlouhavý INSERT ručně a mohl tam ty hodnoty předat jako asociativní pole.

Kaczmi
Člen | 8
+
0
-

Ahoj,
nevím, jestli jsi už problém vyřešil, ale pokud by někdo další se s tímto setkal, tak v dotazu lze použít placeholder ?name

Je to uvedené i v dokumentaci: https://doc.nette.org/…atabase/core#…

vladoha
Člen | 3
+
0
-

Ahoj, oracle pouziva pre nazvy objektov, stlpcov velke pismena. Ak su nazy stlpcov v uvodzovkach pouzije sa camelcasesensitive porovnavanie. Skus zapisat nazvy stlpcov, tabuli velkym pismom.