Delphi Interbase Sql Conversion to Sql Server and Oracle - sql

i have a delphi application which uses database
interbase / firebird. To consult and write data I use the
InterBase components palette (IBTable, IBQuery, IBDataset). I'm
performing the conversion of my system to sqlserver / Oracle but i have
thousands of queries that are assembled at runtime with SQL Instructions
Specific of database InterBase/Firebird. Anyone know
any component or tool that makes Parse commands Interbase -> SQL Server or Interbase-> Oracle ?
what i need its something like:
Var
Parser: TParser;
OutputSql: String;
Begin
Parser := TParser.Create();
Parser.Text := 'SELECT FIRST 10 CITYNAME FROM TBCITY';
if Firebird then
OutPutSql := Parser.ParseTo('SQLSERVER');
if Oracle then
OutPutSql := Parser.ParseTo('ORACLE');
ComponentAccess.Sql.Text := OutPutSql;
...
The Result Of:
Parser.ParseTo('SQLSERVER');
Will Be
'SELECT TOP 10 CITYNAME FROM TBCITY'
And
Parser.ParseTo('ORACLE');
Will Be
'SELECT CITYNAME FROM TBCITY WHERE ROWNUM <= 10'

1) AFAIK, libraries like AnyDAC, have SQL abstraction syntax. May be you can use this feature in your SQL command text.
2) If you are assembling your SQL at runtime, then why not just code like that:
if Firebird then
SQL.Add(...)
else if Oracle then
SQL.Add(...)
...

We have implemented that in AnyDAC. You may use LIMIT escape function:
ADQuery1.Sql.Text := 'SELECT {LIMIT(10)} CITYNAME FROM TBCITY';
AnyDAC will automatically translate that into target DBMS syntax.

I have used kbmMW from Components4Developers and it has an abstracted set of queries that provide macros and the like to enable /easier/ cross database work but it's mainly for client/server use. Devart also do a good set of cross database components - we use their SQL Server set. However, each project I've done I've ended up writing a specific set of SQL scripts for each database. Obviously there is a fair bit of common ground for simple select stuff but the feature sets of the different databases are often too different to make it easily workable.
I end up with something similar to #oodesigner's response except that we use $ifdef and define my SQL strings in a separate const unit.
{$ifdef USE_MSSQL}
QUERY_ONE = 'select blah blah blah...';
{$else}
QUERY_ONE = 'select nah nah nah...';
{$endif}
Then in the main unit a simple assignment
SQL.Text := QUERY_ONE;
or
SQL.Text := Format(QUERY_TWO, [some_very_carefully_quoted_stuff_or_use_params]);
Don't know of anything that would automate or parse it. And the problem with that is that you still have to go through and check every single query because it's too easy to get things wrong when converting.

Related

Will it avoid SQL Injections by not allowing sql keywords in params?

I know that sanitizing parameters (removing quotes for example) is not a perfect solution against SQL injection when you can't use setParameters().
But is it safe to sanitize parameters by checking if they (parameters) don't contain strings with an empty space after it as you see below???
'DELETE ', 'ALTER ', 'DROP ', 'SELECT ', 'TABLE '
For example, email parameter was passed to server but it contains DROP keyword:
String param = "john#mail'DROP myTable"
SELECT * from Users where email = 'john#mail'DROP mytable'
So, my table is dropped;
Notice the space I left after each keyword. This way if a data in db contain the listed keywords but without space, then it will be allowed to use, otherwise it should be a hacker trying to harm my data (ALTER TABLE mydb).
Please feel free to add as example any SQL engine: SQL, Oracle, HANA, MySQL
Thanks
No this is not sufficient.
Please follow the industry standards for preventing SQL Injection that are laid out by OWASP.
One obvious example of SQL injection for the query you posted would be if someone provided the following input for user:
john#mail' OR '1' = '1
Which would produce the query:
SELECT * from Users where email = 'john#mail' OR '1' = '1'
They could also inject a UNION to start selecting data from other tables. There are probably even more devastating examples.
The bottom line is never try to "roll your own" SQL Injection protection. Much smarter people than you and I have tried to solve this problem and the currently accepted standard of using parameterized queries is simply the best solution we currently have available.

Can I prepare a statement in plain Oracle SQL?

3GLs provide mechanisms to prepare statements before executing them. E.g.
SELECT name
FROM people
WHERE age=:AGE
The same query can then be executed for different ages. But can such a statement also be prepared in a "plain" Oracle SQL client? Can the same be done in e.g. SQL Plus or dbForge Studio for Oracle as in Java or C# or any other programming language that supports prepared statements?
In dbForge Studio for Oracle, named parameters can be used, preceded by a colon :
SELECT *
FROM people
WHERE name=:name
The parameters can then be filled in with the "Edit parameters dialog box", available from the SQL toolbar.
I know you didn't ask about PostgreSQL but about Oracle. However, of note, PostgreSQL has this feature right in its SQL language.
The SQL standard includes a PREPARE statement, but it is only for use in embedded SQL. The PostgreSQL version of the PREPARE statement works like this:
PREPARE nameByAge(number) AS
SELECT name
FROM People
WHERE age=$1;
and you use it like this:
EXECUTE nameByAge(18);
EXECUTE nameByAge(50);
So unfortunately for Oracle SQLPlus the answer seems to be no, not bind variables. But SQLPlus has substitution variables, similar to shell scripts. You use them as &1, &2, &3, ... and they get their parameters from the way you call the SQLPlus script.
sqlplus user/password #script.sql 18
sqlplus user/password #script.sql 50
with the script.sql being
SELECT name
FROM People
WHERE age=&1;
this would work, even though it is not bind. But then, do you really care about the slight savings in repeat parse time? In fact Oracle hashes SQL statements and already replaces constants with bind variables to be able to better reuse query plans. So the savings you would get with PREPARE and BIND are really minuscule.

How do I SQL inject a Java Statement that uses JDBC?

The following lines of code appear in my Java program:
stmt.executeQuery("SELECT * FROM metropolises WHERE metropolis =\"" + metropolis + "\" AND continent=\"" + continent + "\" AND population>" + population);
I can put anything in for metropolis, continent, and population via a GUI, but I can't seem to get it to work if I put metropolis = a, continent = b, and population is 2; DROP TABLE tablename;
Any suggestions? I'm trying to DROP a table named metropolises so I can better understand SQL injection.
Some database libraries don't allow to execute multiple queries per call (PHP's mysql binder for example). In those, this kind of injection is not possible. Unfortunately, I don't know whether this is true for JDBC, but it might be the reason.
You don't specify what brand of database you're using (unless the "sql" tag implies Microsoft SQL Server). So here's my experience w.r.t. MySQL:
By default, the MySQL JDBC driver will execute only a single SQL statement per call. This is a good idea for defending against some types of SQL injection.
The JDBC driver has an optional connection property allowMultiQueries that you must set to allow semicolon-separated statements. See http://dev.mysql.com/doc/refman/5.5/en/connector-j-reference-configuration-properties.html

whats the syntax for params in a DB2 query

in MS-SQL I can do something like this
#myVar AS int;
#myVar = 12;
SELECT * FROM table WHERE field = #myVar;
this totally bombs out in DB2 - and I'm not sure if it's RDBMS specific or if it's because I've FUBAR'd the syntax...
Any help is appreciated
there are a limited number of things you can do dynamically in db2 sql compared to ms-sql. most of the syntax for what you appear to be attempting is reserved for use only in a procedure in db2. see the documentation here http://publib.boulder.ibm.com/infocenter/db2luw/v9r5/topic/com.ibm.db2.luw.sql.ref.doc/doc/r0004240.html for what you can do dynamically in db2.
if you are ok supplying parameter value on the fly just use
select * from table where field = ?; when you run it, it will ask you to supply a value for the parm.
If you are using ADO.NET Data Provider to connect to the DB2 Express-C, you can prefix bound SQL parameters with #.
I'm not sure about other DB2 environments, but common symbols used in other databases are: : and ?, so it might be worth trying one of those.

What is embedded SQL?

for example, Delphi has components TADOQuery, TADOStoredProcedure, TADOtable.
Do they represent Embedded SQL??
What is the difference between Embedded SQL and just using SQL in programming languages??
No, TADO* aren't embedded SQL.
Embedded SQL is a (mostly archaic) technique where you write specially delimited SQL in your code and use a pre-processing application to convert that to direct DB API calls.
You can read about it in Chapter 14 of the InterBase Embedded SQL guide [PDF], if you care to.
No those Delphi components are not embedded SQL. In embedded SQL the SQL statements are intermixed with regular code, the most common form I know of is ESQL/C. It should be considered deprecated.
The way it works is a preprocessor that translates all the SQL related stuff to the host language, and that pretranslated code is fed through the host language compiler.
A short fragment based on PostgreSQL's ESQL/C implementation:
void showesql() {
EXEC SQL BEGIN DECLARE SECTION;
int FooBar;
VARCHAR DooDad;
EXEC SQL END DECLARE SECTION;
EXEC SQL DECLARE foo_bar CURSOR FOR
SELECT number, ascii FROM foo
ORDER BY ascii;
EXEC SQL OPEN foo_bar;
EXEC SQL FETCH foo_bar INTO :FooBar, DooDad;
printf ("number is %d and ascii was %s\n",FooBar, DooDad);
EXEC SQL CLOSE foo_bar;
EXEC SQL COMMIT;
}
In my experience working in such code is quite hard, and that's why this once pretty common technique has been abandoned.
Embedded SQL is using SQL statements within your program code
http://en.wikipedia.org/wiki/Embedded_SQL