Página 1 de 1

Consultas o busquedas TDataSet

Publicado: Sab Abr 21, 2018 4:16 pm
por XeviCOMAS
Me encuentro con un problemón al buscar o filtar en DataSets MariaDB.

dado un TEdit... ::oEdit1:cText

Carta de Oro

y al realizar la búsqueda aproximada...
::oDSTable:Locate( "DESCRIPCIO >= '" + " '" +::oEdit1:cText+ "'",, .F. )
localiza el primer registro que empieza por el texto solicitado correctamente...

O un filtro...
::oDSTable:Filter( "DESCRIPCIO LIKE '%" + Upper(::oEdit1:cText) + "%'",, .F. )

***********
PERO...
si el contenido del ::oEdit1:cText

Carte D'Or

lanzo el mismo Locate y no funciona, se queja y me lanza error.
Es por la comilla simple que hay en cText del oEdit1.

Puedo "saltar" este inconveniente cambiando las comillas simples por dobles i las dobles por simples...
::oDSTable:Locate( 'DESCRIPCIO >= "' + ' "' +::oEdit1:cText+ '"',, .F. )
O un filtro...
::oDSTable:Filter( 'DESCRIPCIO LIKE "%' + Upper(::oEdit1:cText) + '%"',, .F. )

***********
PERO el tema se complica si el texto del oEdit1 contiene comillas simples y dobles conjuntamente.

Carte d'Or serie "XL"

Dado ese posible caso... como lo hago???
Como lo haceis???
Como aplicar correctamente el Locate o Filter en un DataSet MariaDB???


Gracias.

Re: Consultas o busquedas TDataSet

Publicado: Dom Abr 22, 2018 12:31 pm
por Jose Lopez
Xevi,
Has probado esto: cCadenaBuscar := [Carte d'Or serie "XL"]
Saludos.
Pepe.

Re: Consultas o busquedas TDataSet

Publicado: Dom Abr 22, 2018 4:07 pm
por jfgimenez
Xevi,

debes utilizar el método :StrSql() del datasource. Ese método te devuelve la cadena "escapada" para usarla sin problemas en las sentencias. Échale un vistazo también al método :BuildSqlSt().

Por otro lado, NUNCA, NUNCA, NUNCA, se deben usar cadenas que teclee el usuario directamente en una sentencia SQL. P.ej., imagina una simple e inocente sentencia que obtiene el código de cliente buscandolo por su nombre:

Código: Seleccionar todo

cCodigo := oDB:QueryValue( "SELECT Codigo FROM Clientes WHERE Nombre='" + ::oEdit1:Value + "'" )
Sí, ya sé que debería haber usado el operador LIKE en vez de el igual, pero es sólo un ejemplo de lo que viene ahora.
Bien, hasta aquí todo normal, ¿no? Si un usuario escribe "JOSE" en el edit, la sentencia que se va a ejecutar sobre la base de datos es:

Código: Seleccionar todo

SELECT Codigo FROM Clientes WHERE Nombre='JOSE'
y devolverá el valor del campo Codigo si encuentra ese cliente, y si no, devolverá NULL (o Nil ya en PRG).

Pero ahora imagina que el usuario escribe " '; DROP TABLE Clientes; #". Pues ahora, lo que se estaría ejecutando es

Código: Seleccionar todo

SELECT Codigo FROM Clientes WHERE Nombre=''; DROP TABLE Clientes; #'
Resultado: se carga la tabla Clientes. Eso es lo que se llama "SQL injection" o "inyección de código SQL". Si utilizas :StrSql() o :BuildSqlSt() no tendrás ese problema.

Este ya es un clásico, pero para los que no lo hayan visto antes: http://xkcd.com/327

Re: Consultas o busquedas TDataSet

Publicado: Dom Abr 22, 2018 8:35 pm
por XeviCOMAS
Jose,

GRACIAS!!!


Jod*rrrr!!!
Con la de vueltas que he lidiado con este temilla!!!
Un par de noches sin descansar, dandole vueltas, unas funcioncillas mias tirando de UniToU8()...

Function xDateSQL( c )
IF( ValType(c) = "D", c := DToC(c), )
RETURN Right(c,4) +"/"+ SubStr(c,4,2) +"/"+ Left(c,2)
***
Function xStrSQL( c )
c := StrTran( c, "²", "d" ) //No vol aquest caracter
c := UniToU8(c)
c := StrTran( c, "\", "\\" )
c := StrTran( c, "'", "\'" ) // Substitueixo el signe ' per \' ja que MariaDB l'utilitza de delimitador de camps
RETURN c
Function xStr2SQL( c )
c := StrTran( c, "\", "\\" )
c := StrTran( c, "'", "\'" ) // Substitueixo el signe ' per \' ja que MariaDB l'utilitza de delimitador de camps
RETURN c

y NO SE ME OCURRIÓ PROBAR CON LA FUNCION StrSQL() !!!

Muchas gracias por tus respuestas, siempre concisas y efectivas.

Re: Consultas o busquedas TDataSet

Publicado: Dom Abr 22, 2018 8:45 pm
por XeviCOMAS
Jose, el método :StrSql() en el datasource, no existe o no lo encuentro...

Lo estoy probando como función y parece funcionar bien...

::oDSTable:Locate( "DESCRIPCIO >= '" +StrSQL(::oEditRecerca:cText)+ "'",, .F. )
O
::oDSTable:Filter( "LOCATE ('"+ StrSQL(Upper(::oEditRecerca:cText)) +"', `DESCRIPCIO`)",, .F. )


Gracias.