Finding the try for an except or finally - ide

I'm dealing with some code that has fantastically long methods (10k lines!) and some odd use of try-finally and try-except blocks. Some of the latter are long by themselves, and don't always have the try at the start of the method.
Obviously I'm trying to refactor the code, but in the meantime just being able to fix a couple of common pathologies would be much easier if I could jump to the start of a block and see what is happening there. When it's 20+ pages away finding it even with the CNPack rainbows ("code structure highlight") is just tedious.
I'm using D2010 and have GExperts (with DelForExp), CNPack and DDevExtensions installed, but I can't find anything that lets me jump from the try to the finally or back. Am I missing something? Is there another add-in that I can use that will get me this?

GExperts have it in Editor Experts: "Move to Matching Delimiter", with the keyboard shortcut Ctrl+Alt+Right by default. If you invoke it repeatedly it cycles from try to the matching finally or except, to end, then back to try, and so on.

If you are going to refactor the code, I'd advice you to name each Try Except/finally End code block and move it into a separate function/procedure within the main method.
Second advice, start with the inner most try except/finally end code block.
procedure class1.method1 ;
var
anyVariables : ... ;
begin
....
try
....
finally
...
end ;
....
end ;
.
procedure class1.method1 ;
var
anyVariables : ... ;
procedure first_try_finally_block ;
begin
try
....
finally
...
end ;
end ;
begin
....
first_try_finally_block
....
end ;
I hope that this will help you to solve your problem.

Related

How to prevent SQL Injection in PL/SQL

We have some few packages where we need to resolve some SQL Injection issues. I need some help to rewrite sql statement or sanitize the inputs. Below is the line number where veracode throw the error.
open c_ccl (p_part_nr,p_ctry_cd);
// Source code
CREATE OR REPLACE EDITIONABLE PACKAGE BODY "schema"."Test_PKG" AS
v_data t_cla_class_data;
FUNCTION nat_eccn_cd( p_part_nr IN t_part_nr, p_ctry_cd IN t_ctry_cd )
RETURN t_us_eccn_cd IS
CURSOR c_ccl(p_part_nr CHAR, p_ctry_cd CHAR) IS
SELECT NAT_CCL_CD FROM CLSDBA.CLA_EXP_PART_CTRY e
WHERE e.PART_NR = p_part_nr AND e.CTRY_CD = p_ctry_cd
ORDER BY e.VAL_FROM_DT DESC;
v_ctry_cd char(4) := p_ctry_cd;
v_trf_cd char(4);
BEGIN
v_data.nat_eccn_cd := NULL;
open c_ccl (p_part_nr,p_ctry_cd);
fetch c_ccl INTO v_data.nat_eccn_cd;
close c_ccl;
return (trim(v_data.nat_eccn_cd));
exception when others then return NULL;
end;
I don't see any SQL injection issues with your code - there is no dynamic code where the user inputs could be evaluated and escape out of the expected code flow. Unless your code snippet is generated somewhere else, or one of the column names is really a function that calls dynamic SQL, your code looks safe.
You used the phrase "sanitize the inputs", which is terrible advice for database programming. As much as I love the comic strip XKCD, Randall got this one wrong.
Bind variables are the best solution to avoiding SQL injection. I'll take this opportunity to (poorly) change his comic:

DB2 PL/SQL structure, begin atomic including with query

I'm trying to use db2 pl/sql script giving a template code.
--#set delimiter !
begin atomic
for S as
<query statement that finds quests, "swaps", with a donor/donation & recipient pair>
do
<update statement that fixes Loot with the swap 'S'>;
end for;
-- handle each swap
end!
-- we're done once through
in my query statement i used something like this:
with
t1 (args) as (
...
)
...
select ...
where ... ;
in the update statement
update Loot set ... where ...
but the problem is, when i try to run the full sql code script on the database, I keep getting the message :
"An unexpected token "begin" was found following "<identifier>".
Expected tokens may include: "USER". SQLSTATE=42601 DB21007E End of file
reached while reading the command.
I want to know, how to use the proper syntax or format to include the "with queries" and also update statement to stop giving me the error. I have the "with query" working in a separate file, but when i combine both statements into the template, it would give me this error. Also as well, if I were to include triggers, which part of the code should i put it in. Thank you.
Here is an example that might help.
CREATE TABLE EG(I INT, J INT)!
INSERT INTO EG VALUES (1,1),(2,3)!
begin
for c as with w(i,u) as(values (2,5)) select i,u from w
do
update eg set j = j + c.u where i = c.i;
end for;
end
!
If this does not help your problem, please post a version of your code that we can run and which returns the error message that you are struggling with.

Delphi Parameterised Query won't work

I'm only a beginner in learning to use Parameterised Queries as I used to do a lot of concatentating before. I've been trying to get this query below to work. It is a simple 'Book' table, with a field called 'BookTitle'. I have a simple textbox where I invite the user to enter any title...and it should run the query below to find if that book exists. Below is my code that, when run, manages to compile. However, when an entry into the textbox is added and the button to run the query is pressed, a Debugger Exception Notification appears with the following statement.
Debugger Exception Notification: Project Project1.exe raised exception class EOleException with message 'Arguments are of the wrong type, are out of acceptable range, or are in conflict with one another'.
I then have the option to press 'Break' or 'Continue'. If I press 'Break', the line:
qbook.Parameters.ParamByName('BookTitle').DataType := ftString;
is filled with a purple/red colour (not sure what this means?).
That said, if I press 'Continue', the program will work as expected, and will continue to do so. Here is the code i've been testing.
procedure TForm4.btnRunQueryClick(Sender: TObject);
var BookEntry:string;
begin
BookEntry:=edtBookTitle.Text;
qbook.SQL.Text:='SELECT BookTitle FROM Book WHERE BookTitle = :BookTitle';
qbook.Parameters.ParamByName('BookTitle').DataType := ftString;
qbook.Parameters.ParamByName('BookTitle').Value := BookEntry;
qbook.Open;
end;
Further points to note: The components in my Delphi form are as follows
a TADOQuery named 'qbook',
a TDataSource,
a TDBGrid,
aTEdit into which the user enters their desired search criteria and
a TButton that once pressed, initiates the query.
With regards to the database, it is:
a MySQL database (Community Edition)
a table named 'Book', where BookID is the PK and is of INT data type.
a field entitled 'BookTitle' which i've set as VARCHAR(35). It is not part of the key. However, it is in the BookTitle field, that i want to apply my query.
NOTE: This answer was posted based on the original code in the question, which has been edited to match what is in my answer. See the question's revision history for the first version of the question on which my answer was based.
The solution you saw in the other post was correct; it was just for a standard TQuery and not TADOQuery. TADOQuery requires a couple of minor syntax changes:
Use Parameters.ParamByName() instead of Parameters
Set a DataType for each parameter before using it
Use .Value instead of .AsString
Here's a corrected version of your code (which also includes setting a value for BookTitle before using it.
procedure TForm4.btnRunQueryClick(Sender: TObject);
var
BookEntry:string;
begin
BookEntry := 'Some book title'; // or QueryEdit.Text or whatever
qbook.SQL.Text:='SELECT BookTitle FROM Book WHERE BookTitle = :BookTitle';
qbook.Parameters.ParamByName('BookTitle').DataType := ftString;
qbook.Parameters.ParamByName('BookTitle').Value := BookEntry;
qbook.Open;
end;
I have never known a string type query parameter need the datatype or whatever set, I would simply remove any reference to the datatype.
After all, if it hurts when you bang your head on a wall, just stop banging it.

Problem with Thinking Sphinx and Functional Tests

this is my test (with shoulda helpers):
context "searching from header" do
setup do
Factory(:city, :name => 'Testing It')
ThinkingSphinx::Test.index 'city_core', 'city_delta'
ThinkingSphinx::Test.start
get :index,
:query => 'Testing It'
end
should respond_with(:success)
should assign_to(:results)
should "have one city on the result" do
assert_equal( assigns(:results).count, 1 )
assert_kind_of( assigns(:results).first, City )
end
ThinkingSphinx::Test.stop
end
Everything works fine except the test always say the count of the results is 0, not 1.
I have debugged this code and when the request reaches the controller, the Sphinx indexes are completely empty, even with the explicit call of index for it.
Am I doing something wrong here?
Any help appreciated.
I found out the problem... even tho the insertion in the database is right before the ThinkingSphinx.index, with transactional fixtures, after the setup block the records get deleted.
The solution was adding to the test the following line:
self.use_transactional_fixtures = false
Hope this helps anyone with the same problem.

CodeIgniter - continue on SQL error?

Basically I have a table with a couple of columns marked Unique. I have a script that dumps a bunch of values into the table with a command like this:
$this->db->query("INSERT INTO `table` (`col1`, `col2`, `col3`) VALUES (`val1`, `val2`, `val3`)");
Every so often my script will try to insert a row which would violate the uniqueness of one of the columns. However, instead of causing the script to abort with a database error, I'd like it to continue, possible outputting a little message. Basically I'm looking for the codeigniter equivalent of
mysql_query("INSERT blah blah blah") or print("fail");
Thanks!
Mala
Yeah, took me a while too and annoyed the hell out of me:
$db['default']['db_debug'] = FALSE;
... in config/database.php - disables the error page.
After a query ran, use this to check for an error:
if (!empty($this->db->_error_message())) {
echo "FAIL";
}
I know you already have a solution, but thought this might be useful for others viewing this question as well.
Let the database do the work for you:
$this->db->query("INSERT IGNORE INTO `table` (`col1`, `col2`, `col3`) VALUES (`val1`, `val2`, `val3`)");
When you use INSERT IGNORE, things like duplicate key errors become warnings instead of errors, which let your queries run without interrupting the flow of your script.
You could then do a
SHOW WARNINGS;
after all the queries have run to see what warnings occurred.
http://dev.mysql.com/doc/refman/5.1/en/insert.html