PLSQL works not correct in ajax callback - plsql

I have following oracle apex ajax callback process:
DECLARE
inspection_id number;
inner_id number;
BEGIN
inspection_id := apex_application.g_x01;
inner_id := apex_application.g_x02;
apex_debug.info('=====================================');
apex_debug.info('DELETE ENTRY WITH INSPECTION_ID: '||inspection_id||' AND INNER_ID: '||inner_id);
DELETE FROM CHLI_IMAGES WHERE (INSPECTION_ID = inspection_id AND INNER_ID = inner_id);
apex_debug.info('ROWS DELETED '|| SQL%ROWCOUNT);
apex_json.open_object;
apex_json.write('success', true);
apex_json.write('message', sqlerrm);
apex_json.write('INSPECTION_ID', inspection_id);
apex_json.write('INNER_ID', inner_id);
apex_json.write('result', true);
apex_json.close_object;
EXCEPTION
WHEN OTHERS THEN
apex_json.open_object;
apex_json.write('success', false);
apex_json.write('message', sqlerrm);
apex_json.close_object;
END;
And it is called by the js here:
apex.server.process("DeleteFromDB", {
x01: 0, //inspection_id
x02: 2, //inner_id
}, {
success: function (pData) {
console.log(pData);
if (pData.success === true) {
resolve(true);
}
},
error: function (request, status, error) {
console.log(request);
resolve(false);
}
});
The really weired things is that it does not work as expected. This code deletes not only rows with inespection = 0 & inner_id = 2. It also deletes every other row in table. The two ids comming correctly to the process I cheked it within debugging. The JS snippet is in a async loop, but I also checked within debugging that it runs only once.
The weired thing is that it only works with this static line:
DELETE FROM CHLI_IMAGES WHERE (INSPECTION_ID = 0 AND INNER_ID = 2);
Does oracle apex has a bug or do I overlook something always and always again.
Thanks in advance,
Filip.

The problem is here:
DELETE FROM CHLI_IMAGES WHERE (INSPECTION_ID = inspection_id AND INNER_ID = inner_id);
As the language is case-insensitive, that just means inspection_id and inner_id are equal to themselves, i.e. not null. Give the variables different names, for example:
declare
l_inspection_id number;
l_inner_id number;
begin
l_inspection_id := apex_application.g_x01;
l_inner_id := apex_application.g_x02;
apex_debug.info('=====================================');
apex_debug.info('DELETE ENTRY WITH INSPECTION_ID: '|| l_inspection_id ||' AND INNER_ID: '||l_inner_id);
delete chli_images i where i.inspection_id = l_inspection_id and i.inner_id = l_inner_id;
...

Related

Delphi: Delete files in a directory older than X days and/or having a special file mask (*.xxx)

Language: Delphi 10.1 Berlin
Problem:
There is a directory with measurement files (*.csv) and other files.
Every few hours a new measurement file will be created.
I need a possibility to delete all .csv files in that folder that are older than a specific number of days. All other file types should not be touched.
Question:
Is there any built-in function in Delphi to do that job? If not, what is an efficient way to solve this problem?
I didn't find a Delphi built-in function for that specific problem.
This function worked for me:
function TUtilities.DeleteFilesOlderThanXDays(
Path: string;
DaysOld: integer = 0; // 0 => Delete every file, ignoring the file age
FileMask: string = '*.*'): integer;
var
iFindResult : integer;
SearchRecord : tSearchRec;
iFilesDeleted: integer;
begin
iFilesDeleted := 0;
iFindResult := FindFirst(TPath.Combine(Path, FileMask), faAnyFile, SearchRecord);
if iFindResult = 0 then begin
while iFindResult = 0 do begin
if ((SearchRecord.Attr and faDirectory) = 0) then begin
if (FileDateToDateTime(SearchRecord.Time) < Now - DaysOld) or (DaysOld = 0) then begin
DeleteFile(TPath.Combine(Path, SearchRecord.Name));
iFilesDeleted := iFilesDeleted + 1;
end;
end;
iFindResult := FindNext(SearchRecord);
end;
FindClose(SearchRecord);
end;
Result := iFilesDeleted;
end;
procedure DeleteFilesOlderThan(
const Days: Integer;
const Path: string;
const SearchPattern: string = '*.*');
var
FileName: string;
OlderThan: TDateTime;
begin
Assert(Days >= 0);
OlderThan := Now() - Days;
for FileName in TDirectory.GetFiles(Path, SearchPattern) do
if TFile.GetCreationTime(FileName) < OlderThan then
TFile.Delete(FileName);
end;

How to display progress of the TFDScript execution using TProgressBar?

I have some script in some file "MyScript.sql"
On the form I have my TProgressBar.
I want to read script with TFDScript and move progressbar according to the script.
My code is
Var
Lista: TStringList; // SQL DDL list for creating table and populate table
I: Integer;
Begin
With FDConn Do //FDConn is my FaireDac connection
Begin
LoginPrompt := False;
With Params Do
Begin
Clear;
DriverID := 'SQLite';
Database := 'MyDatabase.sdb';
LoginPrompt := False;
End;
Lista := TStringList.Create;
Lista.Clear;
Try
FDScript.ValidateAll; //FDScript is TFDScript and prgBar is TProgressBar
prgBar.Max := FDScript.TotalJobSize - 1;
prgBar.Update;
Lista.Clear;
Lista.LoadFromFile('MyScript.sql');
// Now how I can read script 1 line by 1 line and move progress bar with
prgBar.StepIt;
prgBar.Update;`
You can handle the OnProgress event and read there e.g. TotalJobSize property to determine the number of bytes to proceed and TotalJobDone to get number of bytes processed. For example:
procedure TForm1.FDScript1Progress(Sender: TObject);
begin
ProgressBar1.Max := TFDScript(Sender).TotalJobSize;
ProgressBar1.Position := TFDScript(Sender).TotalJobDone;
end;
If you were having progress bar control with progress value setup by percentage, you'd better read the TotalPct10Done property.

How to pass out additional values with table in ref_cursor

I want to output an additional variable that's not in my table, can someone explain how to do this, or why it's not possible?
ie -
OPEN V_CURSOR FOR SELECT ee.EmployeeID, v_overtime_worked FROM EMPLOYEE_RECORDS ee;
So basically you want to store in that cursor, data from the table, and another variable v_overtime_worked, that has nothing to do with the table?
What error are you receiving?
What I know for sure is that this is working...so basically you can put another variable in the cursor:
declare
c_Curs SYS_REFCURSOR;
v_overtime_worked VARCHAR2(120) := '1000';
v_book_title VARCHAR2(255) := '';
v_xxx VARCHAR2(120);
BEGIN
OPEN c_Curs FOR SELECT book_title, v_overtime_worked FROM books;
LOOP
FETCH c_Curs INTO v_book_title, v_xxx;
EXIT WHEN c_Curs%NOTFOUND OR c_Curs IS NULL;
DBMS_OUTPUT.PUT_LINE(v_book_title || v_xxx);
end loop;
close c_Curs;
END;
As for your Java problem I'm afraid I don't know the answer..and i would need to do research :)
Maybe you need something like this :
#Override
public void execute(Connection con) throws SQLException {
CallableStatement call = con.prepareCall(ProcedureCalls.GET_ALL_BOOKS);
call.registerOutParameter(1, OracleTypes.CURSOR);
call.execute();
ResultSet rs = (ResultSet) call.getObject(1);
if(rs!=null){
while (rs.next ()) {
Book b = new Book();
b.setBookId(rs.getLong("book_id"));
b.setBookTitle(rs.getString("title"));
b.setBookYear(rs.getInt("book_year"));
b.setBookAuthor(rs.getString("author"));
book_list.add(b);
}
if(rs!=null) rs.close();
if(call!= null) call.close();
}
}

Can any one tell what's going wrong with my Routine

My requirement is if the user click on update data with out changing any field on the form i would like to show as No changes made and if any changes i would like to update the data
I have written a Routine for updating data as follows
CREATE DEFINER=`root`#`%` PROCEDURE `uspEmployeeFaxDetailsUpdate`(_EmpID int(11),
_FaxNumberTypeID varchar(45),
_FaxNumber decimal(10,0),
_EndDate datetime)
BEGIN
declare p_ecount int;
set p_ecount= (select count(1) from tblemployeefaxdetails where
FaxNumberTypeID=_FaxNumberTypeID and
FaxNumber=_FaxNumber and
EndDate='9999-12-31');
if p_ecount=0 then
begin
update tblemployeefaxdetails
set
EndDate=_EndDate WHERE EmpID=_EmpID and EndDate="9999-12-31";
insert into tblemployeefaxdetails(EmpID,FaxNumberTypeID,FaxNumber,StartDate,EndDate) values
(_EmpID,_FaxNumberTypeID,_FaxNumber,curdate(),'9999-12-31');
end;
end if;
END
I am getting some time my required message but some time it is showing the update message
This is my code on update
oEmployeePersonalData.EmpID = EmpID;
oEmployeePersonalData.FaxNumberTypeID = ddlFaxTypeID.SelectedItem.Text;
oEmployeePersonalData.FaxNumber = Convert.ToInt64(txtFaxNumber.Text);
oEmployeePersonalData.EndDate = DateTime.Today.AddDays(-1);
if (oEmployeePersonalData.FaxDetailUpdate())
{
oMsg.Message = "Updated Sucessfully";
Label m_locallblMessage;
oMsg.AlertMessageBox(out m_locallblMessage);
Page.Controls.Add(m_locallblMessage);
}
else
{
oMsg.Message = "Not Sucessfully";
Label m_locallblMessage;
oMsg.AlertMessageBox(out m_locallblMessage);
Page.Controls.Add(m_locallblMessage);
}
Updated code
public bool FaxDetailUpdate()
{
m_bFlag = false;
try
{
m_oCmd = new MySqlCommand(StoredProcNames.tblEmployeeFaxdetails_uspEmployeeFaxdetailsUpdate, m_oConn);
m_oCmd.CommandType = CommandType.StoredProcedure;
m_oCmd.Parameters.AddWithValue("_EmpID", EmpID);
m_oCmd.Parameters.AddWithValue("_FaxNumberTypeID", FaxNumberTypeID);
m_oCmd.Parameters.AddWithValue("_FaxNumber", FaxNumber);
m_oCmd.Parameters.AddWithValue("_EndDate", EndDate);
if (m_oConn.State == ConnectionState.Closed)
{
m_oConn.Open();
}
if ((m_oCmd.ExecuteNonQuery()) > 0)
{
this.m_bFlag = true;
}
}
catch (MySqlException oSqlEx)
{
m_sbErrMsg.Length = 0;
m_sbErrMsg = Utilities.SqlErrorMessage(oSqlEx);
//DB write the Error Log
m_oErrlog.Add(m_sbErrMsg.ToString(), DateTime.Now);
}
catch (Exception oEx)
{
m_sbErrMsg = Utilities.ErrorMessage(oEx);
//DB write the Error Log
m_oErrlog.Add(m_sbErrMsg.ToString(), DateTime.Now);
}
finally
{
m_oConn.Close();
}
return this.m_bFlag;
}
I am not getting any error but i would like to be done as per i said
Can any one tell what changes i have to made in this
I do not really understand the routine, what the magic date 9999-12-31 represents, and why a new record is inserted every time, instead of updating the old one.
What you can do, is have the routine return a indicator if the row was changed or not, returning the value of p_ecount through a OUT parameter.
For more information on how to use OUT parameters using the .net MySql client see http://dev.mysql.com/doc/refman/5.0/en/connector-net-programming-stored.html

NS_ERROR_FILE_IS_LOCKED when several requests using SQLite on Mozilla plateform

I'm trying to use Storage mechanism in Mozilla platform (in thundebird 3.0).
The following code is used after each test to erase the table present in the database:
function tearDown()
{
let database = new Database();
let req1 = "SELECT name FROM sqlite_master WHERE type='table'";
let statement = database.connection.createStatement(req1);
let tables = [];
while(statement.executeStep()) {
tables.push(statement.row.name);
}
statement.reset();
for(table in tables) {
let req2 = "DROP TABLE " + tables[table];
database.connection.executeSimpleSQL(req2);
}
}
But I've an error during executeSimpleSQL of req2 (NS_ERROR_FILE_IS_LOCKED), It seems that SQLite doesn't release the lock from the first statement. I've tried reset(), finalize(), but nothing works. How can I properly release the lock of the first statement?
Answering myself: I forgot to release a previous statement in previous code of my application.
Final story: when you use
statement.executeStep()
Check:
be sure that the last call of this statement return false
or never forgot to release it:
statement.reset();
var statement = dbConn.createStatement("SELECT COUNT(name) AS nameOcurrences FROM Table1 WHERE name = '" + aName + "';");
var occurrences;
while(statement.executeStep()) {
occurrences = statement.row.nameOcurrences;
}

Resources