Italian community of Lazarus and Free Pascal

Programmazione => Databases => Topic aperto da: Mimmo - Settembre 08, 2023, 04:51:09 pm

Titolo: SqlDb: TSQLConnection.ConnOptions in sola lettura
Inserito da: Mimmo - Settembre 08, 2023, 04:51:09 pm
Carissimi,
sono un paio di giorni che sbatto la testa contro il muro per risolvere alcuni perversi problemi di escape dei caratteri nelle query sql verso un db postgres.
I problemi li ho aggirati ed ho trovato il modo di far funzionare le cose ma mi chiedevo se qualcuno si fosse mai trovato nella necessità di cambiare la proprietà ConnOptions della classe TSQLConnection.
Nello specifico mi avrebbe fatto comodo poter eliminare il parametro sqEscapeSlash perchè secondo me c'è qualche baco logico in sqldb..
So che posso creare una classe derivata e cracckare il valore che è protected ma mi piacerebbe trovare una soluzione pulita oppure capire se son io che non capisco...
Grazie a chiunque per l'aiuto!

Titolo: Re:SqlDb: TSQLConnection.ConnOptions in sola lettura
Inserito da: nomorelogic - Settembre 09, 2023, 01:57:49 pm
Ciao
Puoi farci un esempio pratico del problema che incontri?
Titolo: Re:SqlDb: TSQLConnection.ConnOptions in sola lettura
Inserito da: Mimmo - Settembre 11, 2023, 09:25:42 am
Si, certamente. In effetti così non si capisce.. è una roba un po' perversina che avviene solo con specifiche query sql e infatti m'è uscita fuori dopo anni di funzionamento senza traumi di un demone che cataloga messaggi mail.
Cerco di raccontarla con un esempio, è un po' un rimpallo di chiamate però.
Allora... immaginiamo di avere un'applicazione che si connette ad un db postgres tramite sqldb e che debba eseguire un comando sql un po' strano simile a questo:
Codice: [Seleziona]
INSERT INTO test(testo, dataora, dataora2) values (''DUMMY\'',(timestamp ''2023-09-08 11:14:16''),(timestamp ''2023-09-08 11:14:16''))
(ovviamente c'è una tabella test con un campo varchar-qualcosa e 2 campi timestamp without timezone).
Quando viene fatta la prepare della query, sqldb esegue questo codice:
Codice: [Seleziona]
procedure TCustomSQLStatement.DoPrepare; 
[...]
Database.PrepareStatement(FCursor,Transaction,FServerSQL,FParams);
[...]
che esegue la procedura
Codice: [Seleziona]
procedure TPQConnection.PrepareStatement
[...]
AParams.ParseSQL(buf,false,sqEscapeSlash in ConnOptions, sqEscapeRepeat in ConnOptions,psPostgreSQL)
[...]
che a sua volta richiama nella unit DB questo codice:
Codice: [Seleziona]
function TParams.DoParseSQL(SQL: String; Options : TSQLParseOptions; ParameterStyle: TParamStyle; out
  ParamBinding: TParambinding; MacroChar : Char; out ReplaceString: string): String;
[...]
while SkipComments(p,spoEscapeSlash in Options ,spoEscapeRepeat in options) do ;
[...]
quest'ultima viene quindi invocata con il parametro dell'escape slash a true perchè travasato dalle ConnOptions della connessione:
Codice: [Seleziona]
function SkipComments(var p: PChar; EscapeSlash, EscapeRepeat : Boolean) : Boolean; 
[...]
SkipQuotesString(p, p^, EscapeSlash, EscapeRepeat); 
[...]
che richiama:

Codice: [Seleziona]
procedure SkipQuotesString(var p : pchar; QuoteChar : char; EscapeSlash, EscapeRepeat : Boolean);    
[...]
if EscapeSlash and (p^='\') and (p[1] <> #0) then Inc(p,2) // make sure we handle \' and \\ correct   
[...]
che interpreta malamente la stringa SQL e fa fallire la prepare.

Gli viene passata una stringa sql un po' stramba che non andrebbe analizzata ma come faccio ad evitare che bypassi la ricerca dei parametri senza escape degli slash? Dovrei levare sqEscapeSlash dalla ConnOptions della connessione al db ma mi pare non si possa. Sto perdendo di vista la luna concentrato sul dito?

Per tamponare 2 workaround possono essere o quello di derivare una classe da TPQConnection per poi andare a eliminare il parametro da FConnOptions che è protected oppure quello di sterilizzare lo slash della query con
Codice: [Seleziona]
|| U&''\005C'' ||
ma mi chiedevo se stavo perdendo di vista una via più semplice e pulita.

Grazie!!
Titolo: Re:SqlDb: TSQLConnection.ConnOptions in sola lettura
Inserito da: Mimmo - Settembre 11, 2023, 09:48:17 am
Forse mi rispondo da solo: tenendo
Codice: [Seleziona]
ParamCheck
del TSQLStatement a false si svicola dal problema.
Titolo: Re:SqlDb: TSQLConnection.ConnOptions in sola lettura
Inserito da: nomorelogic - Settembre 11, 2023, 10:13:54 am
quindi così hai risolto?
Titolo: Re:SqlDb: TSQLConnection.ConnOptions in sola lettura
Inserito da: Mimmo - Settembre 11, 2023, 10:55:05 am
quindi così hai risolto?

Si si, mettendo ParamCheck a false il problema non si presenta perchè non fa l'analisi della stringa SQL. In effetti sbagliavo io a non farlo vista la presenza dei : nel testo della query.

A naso direi che qualche problema comunque ci sia anche nella libreria sqldb perchè non mi quadra tanto la cosa dell'escaping del simbolo /, intendo il fatto di non poterlo disabilitare.
Titolo: Re:SqlDb: TSQLConnection.ConnOptions in sola lettura
Inserito da: DragoRosso - Settembre 11, 2023, 02:55:32 pm
In realtà, ".connoptions" è una proprietà che descrive appunto le alcune caratteristiche del connettore usato. E' read only appunto perchè tali caratteristiche vengono rilevate dal driver del DB.

Teoricamente però con l'altra proprietà "param" dovresti poter settare tutte le proprietà della connessione a tuo piacere.