How to prepare a C++ string for sql query - c++

I have to prepare strings to be suitable for queries because these strings will be used in the queries as field values. if they contain a ' etc the sql query fails to execute.
I therefore want to replace ' with '' I have seen the code to find and replace a substring with a substring. but I guess the problem is a little tricky because replacing string also contains two single quotes '' replacing one quote ' so when I have to find the next occurance it would encounter a ' which was intentionally replaced.
I am using Sql lite C api and the example query might look like this
select * from persons where name = 'John' D'oe'
Since John Doe contain a ' the query will fail , so I want all occurances of ' in the name to replaced with ''
Any ideas how you guys prepares your field values in query to be used in sql ??? may be it's a basic thing but I am not too smart in C/C++.
your help would be very helpful

Use queries with arguments instead of replacing stuff, which could lead to several problems (like SQL injection vulnerabilities).
MySQL example:
sql::Connection *con = ...;
string query = "SELECT * FROM TABLE WHERE ID = ?";
sql::PreparedStatement *prep_stmt = con->prepareStatement(query);
prep_stmt->setInt(1, 1); // Replace first argument with 1
prep_stmt->execute();
This will execute SELECT * FROM TABLE WHERE ID = 1.
EDIT: more info for SQLite prepared statements here and here.

It depends on the SQL Library you are using. Some of them will have the concept of a PreparedStatement, which you will use question marks in place of the variables, then when you set those variables on the statement, it will internally ensure that you cannot inject sql commands.

Related

RegEx to find unique occurences of a match

I have found a couple of related threads:
Regular expression - match all words but match unique words only once and
get unique regex matcher results (without using maps or lists)
there are a few others but I just could not get their solutions to solve my issues.
I've been reading on looharounds and backreferences but I'm still missing something.
I need to search through several large code-bases, and find all unique occurrences of data source names or variables for them.
I tried the following regular expressions:
(datasource=\"(.*?)\")(?!.+\1)
(datasource=\"(.*?)\")(?!.*\1)
(datasource=\"(.*?)\")(?!.+\2)
(datasource=\"(.*?)\")(?!.*\2)
(datasource=\"(.*?)(?!.+\1)\")
(datasource=\"(.*?)(?!.*\1)\")
(datasource=\"(.*?)(?!.+\2)\")
(datasource=\"(.*?)(?!.*\2)\")
datasource="someDSN"
datasource="anotherDNS"
datasource = "anotherDNS"
datasource="someDSN"
The code can be complex, but basically it looks something like this:\
<cfquery name="qry_getEvent" datasource="#APPLICATION.firstDSN#">
SELECT *
FROM events
WHERE id = 1
</cfquery>
<cfquery name="qry_getPlayers" datasource="#APPLICATION.firstDSN#">
SELECT *
FROM players
WHERE event_id = 1
</cfquery>
<cfquery name="qry_getLocation" datasource="secondDSN">
SELECT *
FROM locations
WHERE event_id = 1
</cfquery>
The result should look something like:
#APPLICATION.firstDSN#
secondDSN
The only semi-solution I've discovered is to run the (datasource=\"([^"]*)\") multiple times, but after every time, prefix it with a known value to exclude it for example:
(?!datasource="dsnname1"|datasource="dsnname2")(datasource=\"([^"]*)\")
This helped me narrow down all the DSN names in a few minutes, but would have been so much easier if I could just get all the distinct results automatically. Maybe this need a little Node.js work added to it to streamline the process

Matching number sequences in SQLite with random character separators

I have an sqlite database which has number sequences with random separators. For example
_id data
0 123-45/678>90
1 11*11-22-333
2 4-4-5-67891
I want to be able to query the database "intelligently" with and without the separators. For example, both these queries returning _id=0
SELECT _id FROM myTable WHERE data LIKE '%123-45%'
SELECT _id FROM myTable WHERE data LIKE '%12345%'
The 1st query works as is, but the 2nd query is the problem. Because the separators appear randomly in the database there are too many combinations to loop through in the search term.
I could create two columns, one with separators and one without, running each query against each column, but the database is huge so I want to avoid this if possible.
Is there some way to structure the 2nd query to achieve this as is ? Something like a regex on each row during the query ? Pseudo code
SELECT _id
FROM myTable
WHERE REPLACEALL(data,'(?<=\\d)[-/>*](?=\\d)','') LIKE '%12345%'
Ok this is far from being nice, but you could straightforwardly nest the REPLACE function. Example:
SELECT _id FROM myTable
WHERE REPLACE(..... REPLACE(REPLACE(data,'-',''),'_',''), .... '<all other separators>','') = '12345'
When using this in practice (--not that I would recommend it, but at least its simple), you surely might wrap it inside a function.
EDIT: for a small doc on the REPLACE function, see here, for example.
If I get it right, is this what you want?
SELECT _id
FROM myTable
WHERE Replace(Replace(Replace(data, '?', ''), '/', ''), '-', '') LIKE '%12345%'

How to tweak LISTAGG to support more than 4000 character in select query?

Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production.
I have a table in the below format.
Name Department
Johny Dep1
Jacky Dep2
Ramu Dep1
I need an output in the below format.
Dep1 - Johny,Ramu
Dep2 - Jacky
I have tried the 'LISTAGG' function, but there is a hard limit of 4000 characters. Since my db table is huge, this cannot be used in the app. The other option is to use the
SELECT CAST(COLLECT(Name)
But my framework allows me to execute only select queries and no PL/SQL scripts.Hence i dont find any way to create a type using "CREATE TYPE" command which is required for the COLLECT command.
Is there any alternate way to achieve the above result using select query ?
You should add GetClobVal and also need to rtrim as it will return delimiter in the end of the results.
SELECT RTRIM(XMLAGG(XMLELEMENT(E,colname,',').EXTRACT('//text()')
ORDER BY colname).GetClobVal(),',') from tablename;
if you cant create types (you can't just use sql*plus to create on as a one off?), but you're OK with COLLECT, then use a built-in array. There's several knocking around in the RDBMS. run this query:
select owner, type_name, coll_type, elem_type_name, upper_bound, length
from all_coll_types
where elem_type_name = 'VARCHAR2';
e.g. on my db, I can use sys.DBMSOUTPUT_LINESARRAY which is a varray of considerable size.
select department,
cast(collect(name) as sys.DBMSOUTPUT_LINESARRAY)
from emp
group by department;
A derivative of #anuu_online but handle unescaping the XML in the result.
dbms_xmlgen.convert(xmlagg(xmlelement(E, name||',')).extract('//text()').getclobval(),1)
For IBM DB2, Casting the result to a varchar(10000) will give more than 4000.
select column1, listagg(CAST(column2 AS VARCHAR(10000)), x'0A') AS "Concat column"...
I end up in another approach using the XMLAGG function which doesn't have the hard limit of 4000.
select department,
XMLAGG(XMLELEMENT(E,name||',')).EXTRACT('//text()')
from emp
group by department;
You can use:
SELECT department
, REGEXP_REPLACE(XMLCAST(XMLAGG(XMLELEMENT(x, name, ',')) AS CLOB), ',$')
FROM emp
GROUP BY department
it will return CLOB that has no size limit, handles correctly XML entity escapes and separators.
Instead of REGEXP_REPLACE(..., ',$')) you can use RTRIM(..., ','), which should be faster, but will remove all separators from the end of the result (including those that can appear in name at the end, or previous ones if last names are empty).

Empty blob insert query in ODBC c ++ (oracle)

I need to insert a blob in o oracle database. I am using c++ and ODBC library.
I am stucked at the insert query and update query .It is abstract for me how to make an blob insert query.
I know how to make an query for a non blob column.
My table structure is :
REATE TABLE t_testblob (
filename VARCHAR2(30) DEFAULT NULL NULL,
apkdata BLOB NULL
)
I found an exemple on insert and update :
INSERT INTO table_name VALUES (memberlist,?,memberlist)
UPDATE table_name SET ImageFieldName = ? WHERE ID=yourId
But these structure of querys or abstract to me . What should memberlist be ? why is there "?" where are the values to be inserted ?
Those question marks means that it is PreparedStatement. Such statements are good for both server and client. Server has less work because it is easier to parse such statement, and client do not need to worry about SQLInjection. Client prepares such query, builds buffer for input values and calls it.
Also such statement is executed very quick compared to "normal" queries, especially in loops, importing data from csv file etc.
I don't know what ODBC C++ library you use while ODBC is strictly C library. Other languages like Java or Python can use it too. I think the easiest is example in Python:
cursor = connection.cursor()
for txt in ('a', 'b', 'c'):
cursor.execute('SELECT * FROM test WHERE txt=?', (txt,))
Of course such PreparedStatement can be used in INSERT or UPDATE statements too, and for your example it can look like:
cursor.execute("INSERT INTO t_testblob (filename, apkdata) VALUE (?, ?)", filename, my_binary_data)

How to find all stored procedures that delete rows from a particular table

If there's a way of doing this without regular expressions, that's great. If there isn't, here's what I've got so far:
I've written a simple CLR user-defined function (which as you can see I've called CLR_RegExMatch) that performs regex matches on a supplied string. I use it to search for patterns inside stored procedures, triggers, functions etc.
Here's an example of its use - searching for inserts into a table called ExampleTable:
SELECT O.name, O.type_desc
FROM
SYS.OBJECTS O
INNER JOIN SYS.SQL_MODULES M ON
M.object_id = O.object_id
AND dbo.CLR_RegExMatch('INSERT\s+(INTO\s+)?ExampleTable\b', M.definition) = 1
The issue I've got is that I can't come up with a regex pattern to find all routines that delete rows from a given table. Obviously I could substitute the following for the last line in the previous example:
AND dbo.CLR_RegExMatch('DELETE\s+(FROM\s+)?ExampleTable\b', M.definition) = 1
and that gets me part of the way there. However it wouldn't pick up the following:
DELETE T1
FROM
ExampleTable T1
INNER JOIN AnotherTable T2 ON T2.ParentId = T1.Id
So what I'm looking for is either a regex pattern that will match deletes as above, or alternatively a different way of going about this.
N.B. The reason that I'm querying the definition column of SYS.SQL_MODULES instead of the ROUTINE_DEFINITION column of INFORMATION_SCHEMA.ROUTINES is that the latter only contains the first 4000 characters a routine definition, whereas the former contains the full text.
Have a look at the FREE Red-Gate tool called SQL Search which does this - it searches your entire database for any kind of string(s).
It's a great must-have tool for any DBA or database developer - did I already mention it's absolutely FREE to use for any kind of use??
It will not tell you which procedures actually delete something from a table - but it will very easily and nicely find all procedures which reference that table in any way. Look at those and find those you need!
If can help, i use this stored procedure that can find a string in all modules in the database/s
usage:
exec find_text 'text to search', 'db_name'
-- if no db_name specified search in all DB
Code below:
CREATE PROCEDURE [dbo].[find_text]
#text varchar(250),
#dbname varchar(64) = null
AS BEGIN
SET NOCOUNT ON;
if #dbname is null
begin
-- enumerate all databases.
DECLARE #db CURSOR FOR Select Name from master..sysdatabases
declare #c_dbname varchar(64)
OPEN #db FETCH #db INTO #c_dbname
while ##FETCH_STATUS <> -1
begin
execute find_text #text, #c_dbname
FETCH #db INTO #c_dbname
end
CLOSE #db DEALLOCATE #db
end
else
begin
declare #sql varchar(250)
--create the find like command
select #sql = 'select ''' + #dbname + ''' as db, o.name,m.definition '
select #sql = #sql + ' from '+#dbname+'.sys.sql_modules m '
select #sql = #sql + ' inner join '+#dbname+'..sysobjects o on m.object_id=o.id'
select #sql = #sql + ' where [definition] like ''%'+#text+'%'''
select #sql = #sql + ' order by o.name'
execute (#sql)
end
END