Autor Téma: SQLite BUG ?: SELECT Alias FROM ( Select Field1 Alias::<T> FROM Table)  (Přečteno 687 krát)

Offline Miroslav Baláž

  • Plnoletý
  • ***
  • Příspěvků: 119
  • Karma: 4
    • Verze Delphi: D1,2,3,4,7,2005,2009, XE8,S,B,T10.2.2 Pro
Toto funguje (vráti pole x) :
Kód: MySQL [Vybrat]
  1. SELECT * FROM ( select datum AS [x::DATE] from demo )
Príkaz v zmysle predošlého, s istotou obsahuje pole x, takže by nemal byť problém, ale skončí s chybou:
[FireDAC].[Phys].[SQLite] ERROR: no such column: x
Kód: MySQL [Vybrat]
  1. SELECT x FROM ( select datum AS [x::DATE] from demo )
Test projekt je priložený

Offline Delfin

  • Guru
  • *****
  • Příspěvků: 545
  • Karma: 25
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
Pouzij uvozovky, jde o alias:

Kód: MySQL [Vybrat]
  1. SELECT "x" FROM ( select datum AS [x::DATE] from demo )
Kód: MySQL [Vybrat]
  1. SELECT "uvozovky jsou treba, protoze pro alias lze napsat i kratkou pohadku" FROM ( select datum AS [uvozovky jsou treba, protoze pro alias lze napsat i kratkou pohadku::DATE] from demo )
« Poslední změna: 26-11-2017, 22:21:08 od Delfin »
Shiny disco balls! I don't like :)

Offline Miroslav Baláž

  • Plnoletý
  • ***
  • Příspěvků: 119
  • Karma: 4
    • Verze Delphi: D1,2,3,4,7,2005,2009, XE8,S,B,T10.2.2 Pro
Tak som to skusil cez Create View
A veru nejde ani to.
Ospravedlnujem sa, ze je tam kdesi vidiet kod mysql. To je len formatovaci oznam.
Pracujem v SQLite
Kód: MySQL [Vybrat]
  1. CREATE TABLE if not exists [demo] ( id Integer, name TEXT( 20 ), Datum DateTime );
  2. INSERT INTO [demo] ( id, name, Datum ) VALUES ( 1, ''Skúška'', GETDATE() );
  3. CREATE VIEW if not exists AliasT AS select id, datum AS [x::DATE] from demo;

ale ani takto to nefunguje:
Kód: MySQL [Vybrat]
  1. SELECT x FROM AliasT
ani takto to nefunguje (A to by snad uz malo fungovat. Alebo ?):
Kód: MySQL [Vybrat]
  1. SELECT [x] FROM AliasT
toto tusim vypisuje iba string x :
Kód: MySQL [Vybrat]
  1. SELECT "x" FROM AliasT

Pritom toto ide a pole x tam je..
Kód: MySQL [Vybrat]
  1. SELECT * FROM AliasT
Mam to overene aj cez
Kód: Delphi [Vybrat]
  1. FDQuery1.Fields[ 1 ].FieldName

Delfin sorry, ale Tvoj navrh mi vypise iba "x", miesto datumu.
Mam skusenost so zapisom:
Kód: MySQL [Vybrat]
Ale aj v tomto pripade hlasi chybu.
Horsi je ten SELECT VIEW, co je hore. Ten by teda veru ist mal..
Pouzij uvozovky, jde o alias:

Kód: MySQL [Vybrat]
  1. SELECT "x" FROM ( select datum AS [x::DATE] from demo )
Kód: MySQL [Vybrat]
  1. SELECT "uvozovky jsou treba, protoze pro alias lze napsat i kratkou pohadku" FROM ( select datum AS [uvozovky jsou treba, protoze pro alias lze napsat i kratkou pohadku::DATE] from demo )

Offline Delfin

  • Guru
  • *****
  • Příspěvků: 545
  • Karma: 25
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
Pravda; mel bych si napred zkusit nez odpovim ::) Ano, hodnoty uvnitr uvozovek jsou brany za konstantni. Omlouvam se!

Ohledne view; ten hint pro alias ::<T> je interni vec FireDAC pouzita pri sestavovani datasetu prikazu ktery nejaky vraci.

Nema tedy zadny vyznam pro CREATE VIEW. Sloupec tak ve skutecnosti dostane pro view z pohledu SQLite alias [x::DATE]. No a kdyz pak na nem spoustis dotaz na sloupec s nazvem x, koncis na chybe protoze o x SQLite nema tuseni. Pokud vsak spustis SELECT * FROM AliasT, SQLite vrati sloupce vsechny vcetne toho s aliasem [x::DATE], ktery pak shodou okolnosti FireDAC rozparsuje na nazev a hint datoveho typu pri sestavovani datasetu.

Dotaz jako je tento by Te k tomu sloupci dostal (a i tady by doslo k parsovani nazvu sloupce a pouziti datoveho hintu):

Kód: MySQL [Vybrat]
  1. SELECT [x::DATE] FROM AliasT

To same plati i pro uvodni dotaz; k parsovani nazvu sloupce dojde az na strane klienta pri sestavovani datasetu. SQLite povazuje i tam pri spousteni dotazu alias za celek, tj. [x::DATE]. Slo by leda:

Kód: MySQL [Vybrat]
  1. SELECT [x::DATE] FROM ( select datum AS [x::DATE] from demo )
« Poslední změna: 26-11-2017, 23:23:52 od Delfin »
Shiny disco balls! I don't like :)

Offline Miroslav Baláž

  • Plnoletý
  • ***
  • Příspěvků: 119
  • Karma: 4
    • Verze Delphi: D1,2,3,4,7,2005,2009, XE8,S,B,T10.2.2 Pro
Aha, tomu rozumiem, co pises.
Ale v zasade myslim, ze ide o chybu.
Vid aj
CREATE VIEW v predoslom prispevku a
CREATE TEMPORARY TABLE v tomto prispevku nizsie.
Pretoze, ako uzivatel, chcem aby veci fungovali ocakavane.
Ked autori ponuknu riesenie, nemaju skoncit v polovici (myslim autorov FireDAC)
Bohuzial vsetky veci okolo funkcii, ktore nevracaju typ, ale tvaria sa, ze by to malo nejako ist, je dost komplikovane. Dnes som to hodne studoval, robil testy, ved asi vies. Nemam teraz este kompletne informacie. Pokracujem v testoch. Vratim sa k tomu, az budem mat jasnejsie.
Inak aspon cez to create view, by clovek cakal, ze s typmi nejako lepsie vysporiadaju.
CREATE VIEW vrati spravny typ, ale nevie v SQL menom zavolat to predmetne alias::<T> pole.
Da sa otvorit len pomocou *    (v zmysle vsetky polia)
Vid moj predosly prispevok

Inak test CREATE TEMPORARY TABLE dopadol  presne s rovnako nepriaznivym vysledkom, ako CREATE VIEW.
Pole vytvorene metodou alias::<T> nie je mozne nasledne v selecte zavolat.
Znovu len ako
SELECT * FROM myTempTable

Offline Miroslav Baláž

  • Plnoletý
  • ***
  • Příspěvků: 119
  • Karma: 4
    • Verze Delphi: D1,2,3,4,7,2005,2009, XE8,S,B,T10.2.2 Pro
Kód: MySQL [Vybrat]
  1. CREATE TABLE if not exists [demo] ( id Integer, txtTest TEXT( 20 ), Datum DateTime;
  2. INSERT INTO [demo] ( id, txtTest, Datum ) VALUES ( 1, ''Skúška'', GETDATE() )
  3. CREATE TEMPORARY TABLE tempTbl AS select id, txtTest AS [myText::Text(20)], datum AS [myDateTime::DATE] from demo
Veru Delfin mas pravdu, ide to zavolat len takto:
Kód: Delphi [Vybrat]
  1. SELECT id, [myText::Text(20)], [myDateTime::DATE] FROM tempTbl
Cakal by som ze nazvy stlpcov v tomto pripade skratia o to "::<T>"
Moc by to pomohlo.
Snad si to spravim sam.
Ale potom aku mam istotu, ze tam niekde dalej, nie je milion inych chytakov?

Davam este na povsimnutie tento zadrhel:
Ako vidiet tabulka obsahuje aj pole typu text :  txtTest Text(20)
Po ulozeni do Temporary table sa vsak pole zmeni na Text(32000), nejak tak, plus minus.
Takze aj tam, kde nie je pole vypocitane, ale dalo by sa prevziat z povodnej struktury tabulky sa stane text neznamej dlzky. A neda sa zobrazit  v gride. No viem da sa to naprogramovat. Ale na toto veru nie som z Access enginy celkom zvyknuty. Tam to je dost hladsie..
Takze aj s textom nastavaju presne tie neiste hratky, ako je to u datumov.. Grrr..

Offline Delfin

  • Guru
  • *****
  • Příspěvků: 545
  • Karma: 25
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
Inak test CREATE TEMPORARY TABLE dopadol  presne s rovnako nepriaznivym vysledkom, ako CREATE VIEW.
Pole vytvorene metodou alias::<T> nie je mozne nasledne v selecte zavolat.
Znovu len ako
SELECT * FROM myTempTable

Jiste ze nejde. Asi jsem se vsak spatne vyjadril. Staci si v hlave oddelit prikazy spoustene na SQLite engine od deskriptoru sloupcu datasetu ktery FireDAC dostane jako popis vysledku spusteneho prikazu (a podle kterych pak sestavuje kolekci poli). Tedy prikaz jako napr. tento:

Kód: MySQL [Vybrat]
  1. SELECT x FROM (SELECT MyColumn AS [x::DATE] FROM MyTable)

se spusti na SQLite tak jak je; a SQLite cte prikaz jako "vyber hodnoty sloupce MyColumn vsech zaznamu tabulky MyTable a pro dataset je pojmenuj aliasem [x::DATE]; z tohoto datasetu pak vyber hodnoty sloupce x vsech zaznamu". A protoze zadne x v tom vnitrnim datasetu neni (je tam [x::DATE]), prikaz skonci chybou.

Ten ::<T> hint aliasu se zpracovava az s deskriptorem datasetu, prikaz se tedy na SQLite spousti vcetne datovych hintu.

A jestli je to chyba, hm, tezko posoudit... Ty datove hinty mely byt jen pro vyrazy v SELECT listu - ze je tim myslen vnejsi uz v popisu neni. Muselo by se navic sahat pred spustenim do prikazu a hinty z nej vyparsovat. Jeden by si pak mohl chybne vylozit pouziti tech hintu s funkci jako napr. CONVERT a mohl by pak ocekavat v komplexnich prikazech striktni datove typy za pomoci prave tech hintu.
« Poslední změna: 27-11-2017, 00:32:07 od Delfin »
Shiny disco balls! I don't like :)

Offline Delfin

  • Guru
  • *****
  • Příspěvků: 545
  • Karma: 25
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
Davam este na povsimnutie tento zadrhel:
Ako vidiet tabulka obsahuje aj pole typu text :  txtTest Text(20)
Po ulozeni do Temporary table sa vsak pole zmeni na Text(32000), nejak tak, plus minus.
Takze aj tam, kde nie je pole vypocitane, ale dalo by sa prevziat z povodnej struktury tabulky sa stane text neznamej dlzky. A neda sa zobrazit  v gride. No viem da sa to naprogramovat. Ale na toto veru nie som z Access enginy celkom zvyknuty. Tam to je dost hladsie..
Takze aj s textom nastavaju presne tie neiste hratky, ako je to u datumov.. Grrr..

Pro textove retezce ma SQLite datovy typ TEXT. Vse ostatni je bonus FireDACu. Zase, zkus se podivat jestli jsi toho nenechal moc v rezii SQLite.
Shiny disco balls! I don't like :)

Offline Miroslav Baláž

  • Plnoletý
  • ***
  • Příspěvků: 119
  • Karma: 4
    • Verze Delphi: D1,2,3,4,7,2005,2009, XE8,S,B,T10.2.2 Pro
No a uplne vtipne je toto zistenie:
SELECT z CREATE VIEW, presnejsie tento:
Kód: MySQL [Vybrat]
  1. SELECT * FROM AliasT
v tomto prikaz v Delphi kode:
Kód: Delphi [Vybrat]
  1. s := FDQuery1.Fields[ 1 ].FieldName
naplni do premennej s, hodnotu x
Ale SELECT tam tu hodnotu nevidi!
Ten vidi skutocny, dlhy nazov pola v tabulke:
[x::DATE]
Tak to povazujem za ozaj dost zlomyselne od autorov.

Chapem, ako je to technicky. Ozaj tak, ako pise Delfin, ale nechapem, ako moze programator (autori FireDAC) ponukat taketo riesenie.
Z pohladu na jednu a tu istu vec, by som mal ako z SQL, tak na druhej strane z pohladu v Delphi
Kód: Delphi [Vybrat]
  1. FDQuery1.Fields[ 1 ]
ziskat tem isty vysledok.
Ale nie: raz je to
[x::DATE]
a druhy raz iba
x

Uff mozno to je technicko-abstraktne-logicky v poriadku, lenze sme skor ludia nez stroje.
Potom jasne, ze IT oddelenie sa len tazko moze dohodnut s marketingom.
Ked jedni ziju v praktickom a druhi v abstraktnom svete.
Ti jedni maju realne peniaze a ti druhi skor abstrakne:)

Offline Miroslav Baláž

  • Plnoletý
  • ***
  • Příspěvků: 119
  • Karma: 4
    • Verze Delphi: D1,2,3,4,7,2005,2009, XE8,S,B,T10.2.2 Pro
Ano bonus FireDAC to je.
Lenze a la Microsoft (Gates), nie a la Apple (Jobs)  :)

Offline Delfin

  • Guru
  • *****
  • Příspěvků: 545
  • Karma: 25
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
No a uplne vtipne je toto zistenie:
SELECT z CREATE VIEW, presnejsie tento:
Kód: MySQL [Vybrat]
  1. SELECT * FROM AliasT
v tomto prikaz v Delphi kode:
Kód: Delphi [Vybrat]
  1. s := FDQuery1.Fields[ 1 ].FieldName
naplni do premennej s, hodnotu x
Ale SELECT tam tu hodnotu nevidi!
Ten vidi skutocny, dlhy nazov pola v tabulke:
[x::DATE]
Tak to povazujem za ozaj dost zlomyselne od autorov.

Proc zlomyslne? Hinty pouzivej ve vnejsim SELECT listu prikazu ktere vraceji dataset; nikde jinde! Co se deje je to, ze do SQLite ulozis definici view kde je psano:

Kód: MySQL [Vybrat]
  1. CREATE VIEW if not exists AliasT AS select id, datum AS [x::DATE] from demo;

SQLite cte, "pokud neexistuje, vyrob pohled AliasT na tabulku demo ze sloupcu id a datum, kde datum bude mit alias [x::DATE] (ne x, protoze FireDAC prikaz neupravuje!)". Ty pak spoustis:

Kód: MySQL [Vybrat]
  1. SELECT x FROM AliasT

SQLite cte, "prines mi vsechny zaznamy pro sloupec x pohledu AliasT". Zadny takovy sloupec vsak SQLite nezna. V definici ma [x::DATE]. Pak zkusis:

Kód: MySQL [Vybrat]
  1. SELECT * FROM AliasT

SQLite cte, "prines mi vsechny zaznamy vsech sloupcu (na nazvech mi nezalezi)". Prikaz se spustit podari a FireDAC si od SQLite vyzada popis datasetu. Najde v nem nazev sloupce [x::DATE], ten si rozparsuje a sloupec nazve jako x s datovym typem ftDate. Zadna veda ;D

A konecne, viz. reference:

Citace
For an expression in a SELECT list, SQLite avoids type name information. When the result set is not empty, FireDAC uses the value data types from the first record. When empty, FireDAC describes those columns as dtWideString. To explicitly specify the column data type, append ::<type name> to the column alias:

Kód: MySQL [Vybrat]
  1. SELECT count(*) as "cnt::INT" FROM mytab

Kde SELECT list je definovan jako sloupce resultsetu prikazu SELECT.
« Poslední změna: 27-11-2017, 00:49:29 od Delfin »
Shiny disco balls! I don't like :)

Offline Miroslav Baláž

  • Plnoletý
  • ***
  • Příspěvků: 119
  • Karma: 4
    • Verze Delphi: D1,2,3,4,7,2005,2009, XE8,S,B,T10.2.2 Pro
No, ak by sme sa pozreli hlbsie na FireDAC a jeho parsovanie SQL, tak by sme tam nasli take veci, ze hlada zatvorku v obecnom poli "vyraz AS xy::Date", kde vyraz moze byt hocico napriklad toto:
Kód: MySQL [Vybrat]
  1. "ja som text so zatvorkou (, prave bola, ukoncenie)" || GetDATE() || " a este ( dalsie ) zatvorky tu mozu byt" AS mojText::Text(32)
No a ktoru zatvorku asi najde prvu?
Je tam jesne pouzite
Kód: Delphi [Vybrat]
  1. ..Pos( '(', text ) ..

To mi pripada hodne dobrodruzne parsovanie. To riesenie, co ponukaju je z mojho pohladu dost alibisticke.
Potrebujem SQL realne vyuzit. Pomerne v obecnej rovine. A tam veru narazam na necakane mantinely u toho FireDAC riesenia.
Ano v teoretickej rovine je vsetko ako vravis. Lenze rad by som ziskal vysledky. A zacinam narazat na znacne prakticke problemy, kde moznosti FireDAC v tomto pripade nevedu k rieseniu.
Mam rozpracovany Tvoj i svoj navrh riesenia prenosu informacie zo vzorca do vysledku, ale zatial som nedosiahol ziadne uspokojive a jasne vysledky.
Nieze by to neslo. Ono to ide podla planu, ale ani to nestaci pre dokoncenie praktickej myslienky. Zatial.. Budem sa snazit dalej..

Offline Delfin

  • Guru
  • *****
  • Příspěvků: 545
  • Karma: 25
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
Mam rozpracovany Tvoj i svoj navrh riesenia prenosu informacie zo vzorca do vysledku, ale zatial som nedosiahol ziadne uspokojive a jasne vysledky.
Nieze by to neslo. Ono to ide podla planu, ale ani to nestaci pre dokoncenie praktickej myslienky. Zatial.. Budem sa snazit dalej..

Porad si muzes parsovat prikazy sam. A pro resultset si pred otevrenim sestavit kolekci perzistentnich poli. A ty datove hinty, pokud bys je potreboval pouzit z prikazu odstranovat. Verim ze lexeru pro SQLite budou mraky (mozna i pro Delphi) ;)
Shiny disco balls! I don't like :)

Offline Miroslav Baláž

  • Plnoletý
  • ***
  • Příspěvků: 119
  • Karma: 4
    • Verze Delphi: D1,2,3,4,7,2005,2009, XE8,S,B,T10.2.2 Pro
Porad si muzes parsovat prikazy sam. A pro resultset si pred otevrenim sestavit kolekci perzistentnich poli. A ty datove hinty, pokud bys je potreboval pouzit z prikazu odstranovat. Verim ze lexeru pro SQLite budou mraky (mozna i pro Delphi) ;)
Dobre, ak by som išiel touto cestou. Teda nejaký low-level API. Myslím toto:
http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Using_SQLite_with_FireDAC#Using_SQLite_low-level_API
tak ako budem prezentovať dáta? Napríklad do dbGrid.
Môžeš mi naznačiť ako ďalej pokračovať, keď by som to riešil napr. takto:
(vybraté z uvedeného dokazu)
Kód: Delphi [Vybrat]
  1.     oStmt := TSQLiteStatement.Create(oDB);
  2.     try     // prepare statement
  3.       oStmt.Prepare('select * from "Orders" where OrderID > :ID1 and OrderID < :ID2');
  4.              // add bind variables (parameters)
  5.       for i := 1 to oStmt.ParamDefsCount do
  6.         TSQLiteBind.Create(oStmt.Params);
  7.              // add column variables (fields)
  8.       for i := 1 to oStmt.ColumnDefsCount do
  9.         TSQLiteColumn.Create(oStmt.Columns).Index := i - 1;
  10.              // set parameter values and execute
  11.       oStmt.Params[0].AsInteger := 11000;
  12.       oStmt.Params[1].AsInteger := 12000;
  13.       oStmt.Execute;
  14.              // fetch records and read columns
  15.       while oStmt.Fetch do
  16.         Memo1.Lines.Add(Format('OrderID: %d, CustomerID: %s',
  17.           [oStmt.Columns[0].AsInteger, oStmt.Columns[1].AsString]));
  18.     finally
  19.       oStmt.Free;
  20.     end;
ako nasypem údaje do nejakého dataSetu namiesto toho Memo1, čo je použité vyššie?
Ak sa tu niekto podelí so skúsenosťami s uvedenej oblasti, bol by som veľmi vďačný.
Poznatky, upozornenia, zdroje, vzory kódov, výstrahy, čokoľvek.
Pre získanie predstavy, či by bola schodná táto cesta.
Takže vopred ďakujem:)

Offline Miroslav Baláž

  • Plnoletý
  • ***
  • Příspěvků: 119
  • Karma: 4
    • Verze Delphi: D1,2,3,4,7,2005,2009, XE8,S,B,T10.2.2 Pro
Hura, jeden existujuci priklad vyuzitia TSQLiteStatement, som nasiel na disku:)
FireDAC.Phys.SQLiteIniFile.pas v ceste:
Kód: Delphi [Vybrat]
  1. Database\FireDAC\Samples\AddOn\SQLiteIniFile\
Je tam funkcne demo.
Ale inak bieda, ziadna dalsia slusna dokumentacia, ci priklady. Ani googlenie nepomohlo.

 

S rychlou odpovědí můžete používat BB kódy a emotikony jako v běžném okně pro odpověď, ale daleko rychleji.

Jméno: E-mail:
Ověření:
Kolik je šest plus čtyři (slovem):