Fitnesse and dbFit: how to escape colons in SQL queries - testing

I've a problem with escaping colons and dashes in SQL queries when I use dbFit with Fitnesse.
Such statement doesn't work:
!|Query|select to_char(my_birthday,'YYYY-MM-DD HH24:MI:SI') from family|
I need to replace colons and dashes with some other acceptable characters, ex.
!|Query|select to_char(my_birthday,'YYYY_MM_DD HH24_MI_SI') from family|
Do you know how to solve it properly without using the 2nd approach ?
Cheers,
foxrafi

I think this is what you need. From http://dbfit.github.io/dbfit/docs/reference.html
Avoiding parameter mapping
If you want to prevent DbFit from mapping parameters to bind variables
(eg to execute a stored procedure definition that contains the #
symbol in Sql Server), disable bind symbols option before running the
query.
|set option|bind symbols|false|
|execute| insert into users (name, username) values ('#hey','uuu')|
|query|select * from users| |name|username| |#hey|uuu|
Remember to re-enable the option after the query is executed. You can
use the same trick with the Execute command.

In addition to Mike's answer, you can also solve this by using bind parameters. This is useful if you have to use bind parameters at other places in the same query.
!|DatabaseEnvironment|ORACLE|
|Connect|${HOSTNAME}|${USERNAME}|${PASSWORD}|
!|Query|!-select current_timestamp ts from dual-!|
|ts?|
|>>my_birthday_ts|
|set parameter|my_birthday_ts| <<my_birthday_ts|
#Set bind parameter :MI to string ':MI'
|set parameter|MI|:MI|
# and do it in the same way with :SS.
|set parameter|SS|:SS|
!|Query|!-select to_char(:my_birthday_ts, 'YYYY-MM-DD HH24'|| :MI || :SS) bds from dual-!|
|bds?|
|>>birthday_string|
Note that you have to use !- -! around your query, otherwise FitNesse will expand the concatenation operator to table cells. The main drawback of this manner is that you cannot use ordinary FitNesse variables (${varname}) in the query.

!|DatabaseEnvironment|ORACLE|
|Connect|${HOSTNAME}|${USERNAME}|${PASSWORD}|
!|Query|!-select current_timestamp ts from dual-!|
|ts?|
|>>my_birthday_ts|
!|Query|!-select to_char(:my_birthday_ts, 'YYYY-MM-DD HH24:'||'MI:'||'SS) bds from dual-!|
|bds?|
|>>birthday_string|

Related

SQL - ignore where clause if null / no input

I'm building a SSRS report and would like one of my parameters to be optional where data is entered or not.
Here is an example query for a better understanding:
SELECT
C1
,C2
,C3
FROM
db_Database..tb_Table
WHERE
tb_Table_DateTime between [THEN] and [NOW]
AND
tb_Table_Integer IN (#Integer)
I'm trying to work out if, in my query, I can ignore the whole:
AND tb_Table_Integer IN (#Integer)
line if user chooses not to input any number.
Bascially, I want all data returned unless specified otherwise via #integer.
If not possible in the query, can this be achieved in the Visual Studio?
Cheers.
This is typically handled by doing:
WHERE . . . AND
(#Integer IS NULL OR tb_Table_Integer = #Integer)
Do not use IN (#Integer). It sort of implies that you think that #Integer could be a list. That is not possible.
The most common way to do this is with coalesce or nullif. Like this:
WHERE coalesce(#integer,tb_Table_Integer) = tb_Table_Integer

Yii Join Table Command

I'm currently working on Yii SQL Injection. I have the following command sql command to run:
SELECT p.email, p.email_secret, p.verificationcode, r.name
FROM personal p
JOIN profile r
ON p.email='example#example.com'
I have written the following code with yii:
$connection=Yii::app()->db;
$command=$connection->createCommand();
$command->select('p.email, p.email_secret, p.verificationcode, r.name');
$command->from('personal p');
$command->join('profile r', 'p.email = r.email');
$command->where('p.email=:email', array(':email'=>'yeoh.chan1#gmail.com'));
$rows=$command->queryAll();
I would like to know where this would be vulnerable SQL Injection and if so, what would be a better approach to deal with table joinings.
Since this has no variables in it, there is no possibility for SQL injection. However, I am guessing that you are planning to pass the email address in as a parameter, and since you have the :email parameter marker you are safe.
Just a tidbit here, you don't have to repeat $command-> on every line. You can write it like this:
$connection=Yii::app()->db;
$command=$connection->createCommand();
$command->select('p.email, p.email_secret, p.verificationcode, r.name')
->from('personal p')
->join('profile r', 'p.email = r.email')
->where('p.email=:email', array(':email'=>'yeoh.chan1#gmail.com'));
$rows=$command->queryAll();
This works because all the statement clauses (except distinct) return the command object, and can be strung together. If you need distinct, you can make ->setDistinct() the last item in the chain.

web.py db.insert() doesn't work

I use db.insert() to insert data to database, the code is something like this,
db.insert('categories', name=cate_name, description=desc, _test=True)
but it doesn't work, the data can't not be found in table 'categories' after the code is execute, and no exceptions by the way.
Anybody know why this happened?
_Test variable stands for debug purposes.
It lets you get SQL statement instead of executing one.
It means that your command
result = db.insert('categories', name=cate_name, description=desc, _test=True)
will not execute anything on your DB. It will only return a string:
"INSERT INTO categories (name, description) VALUES ('cate_name value', 'desc value')"
If you want to make a real query, you need to remove it:
db.insert('categories', name=cate_name, description=desc)
It should work.
remove _test=True or set _test=False

How use the insert query using parameters?

When i try with this query i get an error says that Perameter email doesn't exist, i am sure that the variables : email, login_pass, payment_method,operateur are valid and exists.
SQLQuery2.sql.Text := 'INSERT INTO registered (email,login_pass,payment_method,operateur) VALUES (":email",":login_pass",":payment_method",":avecpuce")';
SQLQuery2.ParamByName('email').AsString := email;
SQLQuery2.ParamByName('login_pass').AsString := login_pass;
SQLQuery2.ParamByName('payment_method').AsString := payment_method;
SQLQuery2.ParamByName('avecpuce').AsString := avecpuce;
SQLQuery2.ExecSQL(true);
I tried removing the quotation, but i get
You have an error in your Sql syntax, check the manual that corresponds to your SQL server for the right syntax to use near
':email,:login_pass,:payment_method,:avecpuce)' at line 1
How to use the insert query above using parameters?
From the TSQLQuery.ExecSQL documentation:
ExecDirect indicates that the query does not need to be prepared
before it is executed. This parameter can be set to true if the query
does not include any parameters.
So if the code uses
SQLQuery2.ExecSQL(true);
this means that there will be no support for parameters.
But because you use parameters, just use
SQLQuery2.ExecSQL;
and also remove the quotes around parameters.
Remove quotation marks:
SQLQuery2.sql.Text := 'INSERT INTO registered (email,login_pass,payment_method,operateur)
VALUES (:email, :login_pass, :payment_method, :avecpuce)';
Found the answer !
MySQLQuery2.SQL.Clear;
MySQLQuery2.SQL.Add('INSERT INTO COUNTRY (NAME, CAPITAL, POPULATION)');
MySQLQuery2.SQL.Add('VALUES (:Name, :Capital, :Population)');
MySQLQuery2.Params[0].AsString := 'Lichtenstein';
MySQLQuery2.Params[1].AsString := 'Vaduz';
MySQLQuery2.Params[2].AsInteger := 420000;
MySQLQuery2.ExecSQL;
Thankyou All !!
You don't usually quote parameters, only literals. So instead of:
VALUES (":email",":login_pass",":payment_method",":avecpuce")
Try:
VALUES (:email,:login_pass,:payment_method,:avecpuce)
You should not use quotes around the parameter name.
Parameters are automatically generated for you if your TSQLQuery has a connection assigned and ParamCheck is true and you assign TSQLQuery.CommandText.
It will not generate the parameters when you assign the query to TSQLQuery.SQL.Text.
You can have the parameters generated for you by calling TSQLQuery.Params.ParseSQL:
SQLQuery2.Params.ParseSQL(SQLQuery2.SQL.Text, True);
Or you can add them yourself by calling TSQLQuery.Params.AddParameter.

Using normal SQL with Active Records in Code Igniter

I have a single normal SQL statement in the middle of my Active Records query. Is there any way I can 'add' this query to the AR one without having two independent queries? The SQL is as follows if someone would help me 'convert' it into Active Records-style in case it doesn't work.
SELECT birthday
FROM usertable
WHERE STR_TO_DATE(birthday, '%d.%m.%Y')
BETWEEN $minimumDate AND $maximumDate
You can simply do this:
$this->db
->select('birthday')
->where("STR_TO_DATE(birthday, '%d.%m.%Y') BETWEEN $minimumDate AND $maximumDate")
->get('usertable');
But you will have to escape the variables yourself in this case.
You could also do this:
$this->db
->select('birthday')
->where("STR_TO_DATE(birthday, '%d.%m.%Y') >", $minimumDate)
->where("STR_TO_DATE(birthday, '%d.%m.%Y') <", $maximumDate)
->get('usertable');
This will automatically escape the second parameter of where(), but now we're running STR_TO_DATE() twice and have a slightly less elegant query (not using BETWEEN).
Active Record can be difficult to use MySQL functions with. Sometimes it's best to just do the query manually if you are not building it dynamically. CI offers some methods of doing this easily while escaping your input properly for you.
See the section in the user guide about Query Bindings:
$sql = "SELECT birthday
FROM usertable
WHERE STR_TO_DATE(birthday, '%d.%m.%Y')
BETWEEN ? AND ?";
$this->db->query($sql, array($minimumDate, $maximumDate));
You can do this -
SELECT birthday
FROM usertable
WHERE STR_TO_DATE(birthday, '%d.%m.%Y')
BETWEEN $minimumDate AND $maximumDate
by chaining like this -
$this->db->select('birthday')->from('usertable')->where('STR_TO_DATE', '%d.%m.%Y')->limit($minimumDate, $maximumDate);