using Qt Stored procedure in Firebird - plsql

Good Afternoon,
I'm starting in the world of Qt and a Firebird database.And finish the driver installation process and perform operations onthe database insert, update and consultation.
When I started to make stored procedures and run them from Qt did not work. Does not fail and always us that everything was made ​​perfect, but the database does not run.
I am programming in Linux using Qt 2.0.1 and Firebird 2.1
I create a simple stored procedure test which makes it an insert into a table. It works by running the console but when trying to run fromQt does not work and gives me no errors.The SQL code is:
SET TERM ^ ;CREATE PROCEDURE AGREEGAR_UNO AS BEGIN insert into JUEGO(CODIGO,ESCRUTINIO,ESTADO,FECHA,HORAINICIO) values (next value for GNECODIGOJUEGO,'111,123,154,169,178','Hi', current_date, current_time);END^SET TERM ; ^
GRANT EXECUTE ON PROCEDURE AGREEGAR_UNO TO SYSDBA;
The following code will use to connect to firebird from Qt
bool VentanaPrueba::conectar()
{
this->db= QSqlDatabase::addDatabase("QIBASE","Data");
this->db.setDatabaseName("./BD/Data.fdb");
this->db.setPassword("password");
this->db.setUserName("SYSDBA");
if(!db.open())
{
return false;
}
else
return true;
}
And this is the code that is responsible for calling the procedure
void VentanaPrueba::procedimiento()
{
if (!this->db.isOpen()) this->conectar();
if(this->db.isOpen())
{ QSqlQuery procedimiento = QSqlQuery::QSqlQuery(this->db);
bool bandera = procedimiento.prepare("EXECUTE PROCEDURE AGREEGAR_UNO");
QString err = procedimiento.lastError().text();
bool respuesta= procedimiento.exec();
//this->db.commit();
if(!respuesta)
{
this->db.close();
}else
{
procedimiento.finish();
this->db.commit();
this->db.close();
}
}else{
//error
}
}
Thank you very much for your help.

IBPP or InterBase Plus Plus is a client interface project which connects for Qt with Interbase database system like firebird. Using it you can easily use your firebird database. Download its source code package from http://sourceforge.net/projects/ibpp/files/ or ibpp official site, and unpack. Copy the core folder into your project folder. And add these files in your Qt project.
Read complete guide at
https://rongsheng007.wordpress.com/2010/08/23/make-qt-applications-work-with-firebird-database/

I can't tell if this works for firebird, but you could try the following:
procedimiento.prepare("BEGIN EXECUTE PROCEDURE AGREEGAR_UNO; END;");
This is similar to the PL/SQL passage
BEGIN
EXECUTE PROCEDURE AGREEGAR_UNO;
END;
I am accessing Oracle databases with Qt and had to include the "BEGIN" and "END;" commands there. You don't have the "EXECUTE PROCEDURE" in oracle, but it might be required for Firebird.
Also, I am using Qt 4 so there might be a difference as well.

There is a simpler way, even though little bit weird.
Create a stored procedure in firebird with some output variable to suspend, and a VARCHAR(1024) input variable to pass the procedure call.
And call it in Qt with procedure call as a string parameter.
SET TERM ^ ;
create PROCEDURE SP_EXECUTE (STMNT varchar(1024) )
RETURNS (
INRETURN integer )
AS
BEGIN
execute statement stmnt;
inReturn=1;
suspend;
END^
SET TERM ; ^
}
Then in Qt,
procedimiento.prepare("SELECT INRETURN FROM SP_EXECUTE('EXECUTE PROCEDURE AGREEGAR_UNO')");

Related

Error during compiling: `identifier not found` (code C3861)

I have a field in my acore_characters table named 'rank' with a tinyint which ranges from 0 to 3 inclusive, based on player's progression. I need to read that value at both login and at certain specific circumstances.
I wrote the following PreparedStatement: "SELECT rank FROM acore_characters WHERE guid = ?" and then the code which is supposed to read that value:
uint16 GetCharactersRank(uint64 guid) {
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(mystatement);
stmt->setUInt32(0, GetGUID());
PreparedQueryResult result = CharacterDatabase.Query(stmt);
if (result) {
[...truncated]
and then fetching the result and so on, but then I get a code C8361 when compiling because 'GetGUID':identifier not found in Player.cpp file...what goes wrong? The other GetGUID calls throughout the file dont give this result. I'm not very fond of c++, any help is very appreciated.
It's not recommended to directly patch the core to add customisations to it. Instead, use modules.
An example can be found here: Is it possible to turn a core patch into a module for AzerothCore?
You can have a look and copy the skeleton-module and start modifying it to create your own.
In your case, you probably want to use the OnLogin player hook.

How to get Delphi to access an SQLite database in the directory of the executable? [duplicate]

This question already has answers here:
Delphi Get file location
(2 answers)
Closed 6 years ago.
I am using SQLite, rather than MySQL, because it is simpler and requires no extra running software, just my executable.
For simplicity's sake I would prefer to have the database file in the same directory as my executable, and to be able to copy or move that folder elsewhere and still have the program work. Meaning that it can find the SQLite database file, which was copied along with it, in its new location.
However, it looks like I have to specify an absolute path to the database file.
Is there any way to change this at run time?
For those who don't quite follow that, I will try to explain:
let us say that my app's .exe is in C:\A\A.exe
so, I want to put the database file in the same directory. Lets call it C:\A\A.db
Delphi seems to require an absolute path. I.e, C:A\A.db and not .\A.db
I want to be able to copy both the .exe and its database to C:\B and still have the .exe be able to find its database file, which is now in C:\B\A.db
How can I do that programmatically, at run-time?
Answer
The path to the database is stored in the database connection component, so something like myConnection.parameters.database := 'C:\my_database.db;
Just compute the SQlite3 database file name on the fly, using:
myDbFileName := ExtractFilePath(paramstr(0)) + 'mysqlite3file.db3';
This will point e.g. to c:\my\app\folder\mysqlite3file.db3 file, when you run c:\my\app\folder\myprogam.exe.
First you want to copy the db to the EXE folder :
if FileExists(FDConnection1.Params.Database) then
CopyFile(Pchar(FDConnection1.Params.Database),Pchar('EXE Folder\A.db'),True);
then you can change the connection to the new db (copy) :
if FileExists('EXE Folder\A.db') then
begin
FDConnection1.Params.Database := 'EXE Folder\A.db';
FDConnection1.Connected := True;
end;
You always have to specify absolute path to the database file. Alternative would be preforming a full search for the database file which is stupid.
Here is a little piece of code I use to create backup of the database so you get the idea:
procedure TForm1.dxBarButton1Click(Sender: TObject);
var fileSource, fileDest,dirName: string;
begin
dirname := ExtractFilePath(Application.ExeName)+'\backup database' ;
if not directoryexists(dirName) then
CreateDir(dirName);
if MessageDlg('Create database copy ?'+ #13#10 +'Attention,new copy will overwrite existing one',
mtConfirmation, [mbYes, mbNo], 0, mbYes) = mrNo then
exit
else
try
dataModule2.ACRDatabase1.Close;
fileSource := ExtractFilePath(Application.ExeName)+'sgit.adb';
fileDest := ExtractFilePath(Application.ExeName)+'\backup database\sgit.adb';
If CopyFile(PChar(fileSource), PChar(fileDest), False) then begin
dataModule2.ACRDatabase1.Open;
dataModule2.FIRME.Open;
ShowMessage('Copy was made !');
end else
RaiseLastOSError;
except on E: Exception do
showMessage(Format('Error during copying : %s',[E.Message]));
end;
end;
So in your case you can write to an *.ini file where the database was copied to and then load the information during startup of your application. So basically you must always supply the database path (fileSource). How you do it is up to you. Just an idea ...

File Exists and Exception Handling in U-Sql

Two questions
How to check file exists or not before EXTRACT?
we have scenario where new inputs file is generated every day for catalog data. we need to merge new input with d-1 file. before merge we what to make sure that new input file exists at source location
does u-sql supports try...catch block?
Regarding checking if a file exists. We recently released a compile-time IF statement that indeed can check for partition existence (and other objects such as files and tables are on the roadmap).
Once that feature is released (still one or two refreshs out at the time of this answer) it may look something like (syntax subject to change):
IF FILE.EXISTS("/mydir/myfile.csv") THEN
#data = EXTRACT ... FROM "/mydir/myfile.csv" USING ...;
...
#jobstate = SELECT * FROM (VALUES("job completed")) AS T(status);
ELSE
#jobstate = SELECT * FROM (VALUES("file not ready. Job not executed.")) AS T(status);
END;
OUTPUT #jobstate TO "/jobs/myjobstate.csv" USING Outputters.Csv();
You will be able to provide the name as a parameter as well. Please let me know if that will work for your scenario.
An other alternative is to use the file set syntax, especially if you want to use a dynamic value to determine the process. That would simply create an empty rowset:
#data = EXTRACT ..., date DateTime
FROM "/mydir/{date:yyyy}/{date:MM}/{date:dd}/data.csv"
USING ...;
#data = SELECT * FROM #data WHERE date == DateTime.Now.AddDays(-1);
... // continue processing #data that is empty if yesterday's file is not yet there
Having said that, you may want to check of your job orchestration framework (such as ADF) may be a better place to check for existence before submitting the job in the first place.
As to the try catch block: U-SQL itself is a script-level optimizable, declarative language where the plan gets generated and optimized at runtime over the whole script. Thus providing a dynamic TRY-CATCH is currently not available, since it would severely impact the ability to optimize the script (e.g., you cannot move predicates or column pruning outside of a try-catch block). Also TRY/CATCH can lead to some very hard to understand and debug code, especially if it is used to mimic procedural workflows in an otherwise declarative environment.
However, you can use try/catch inside your C# functions without problems if you need to catch C# runtime errors.
FILE.EXISTS() always returns True when executed locally. However, it works when executing against Azure Data Lake.
Tried MSDN example and the following returns True, True
DECLARE #filepath_good = "/Samples/Data/SearchLog.tsv";
DECLARE #filepath_bad = "/Samples/Data/zzz.tsv";
#result =
SELECT FILE.EXISTS(#filepath_good) AS exists_good,
FILE.EXISTS(#filepath_bad) AS exists_bad
FROM (VALUES (1)) AS T(dummy);
OUTPUT #result
TO "/Output/FileExists.txt"
USING Outputters.Csv();
I have Microsoft Azure Data Lake Tools for Visual Studio version 2.2.5000.0

SQL Server Deploy Script

I use sql server 2005 for an asp.net project. I want to run a SQL file that contains all DB changes from the last release to easily bring a DB up to the latest version.
I basically just have a bunch of alter table, create table, create index, alter view, call stored proc, etc statements. But I would like to wrap it in a transaction so if any part of it fails, none of the changes will go through. Otherwise it could make for some really messy debugging where it finished.
Also, if you know of a better way to manage DB deployment let me know!
I do something similar with a Powershell script using SMO.
Pseudocode would be:
$SDB = SourceDBObject
$TDB = TargetDBObject
ForEach $table in $SDB.Tables
{
Add an entry to a hash table with the name
and some attributes (rowcount, columns, datasize)
}
# Same thing for $TDB
# Compare the two arrays, and make a list of all the ones that exist in the source but not in the target, or that are different
# Same thing for Procs and Views
# Pass this list to a SMO.Scripter as an UrnCollection object, and it will script them out in dependency order (it's an option), with drops
# Wrap the script in a transaction and execute it on target server
# Use SQLBulkCopy class to transfer data server-to-server
What version of Visual Studio do you use? In Visual Studio 2010 and from what I can remember Visual Studio 2008 - in the menu under "Data" there are two options - "Schema Compare" and "Data Compare". That should move you in the right direction.
BEGIN TRANSACTION #TranName;
USE AdventureWorks2008R2;
DELETE FROM AdventureWorks2008R2.HumanResources.JobCandidate
WHERE JobCandidateID = 13;
COMMIT TRANSACTION #TranName;
You should execute everything within a transaction
Note that some DDL statements have to be the first statement in a batch (batches are separate from transactions). (GO is the default batch separator in SSMS and SQLCMD).

How to encrypt a string using InstallScript

I'm building an installer using InstallScript MSI project. During installation I save some information to a local file. This file is created based on the user's preferences and it may contain sensitive information.
I would like to encrypt this information but couldn't find any InstallScript function to handle this. I know I can have feature files encrypted, but this file is create during installation and is not a part of a specific feature.
Does anyone know of a way to encrypt strings using InstallScript?
Thanks!
Like KMoraz wrote - I don't know of a builtin function for this.
For what it's worth - the way I do it is by using an external COM DLL to do the encryption/decryption for me.
You will of course need to obtain/create such a DLL to use and deploy it with the installation.
(I use pure installscript installation - not MSI)
function STRING Encryption(bEncrypt,sInput)
STRING sEncryptionKey, sResult;
OBJECT oEncryption;
begin
try
// create encryption key
sEncryptionKey = "key";
// create COM object
set oEncryption = CoCreateObject("Encryption");
if (IsObject(oEncryption)) then
// set encryption key
oEncryption.Initialize(sEncryptionKey);
if (bEncrypt = TRUE) then
sResult = oEncryption.Encode(sInput);
else
sResult = oEncryption.Decode(sInput);
endif;
endif;
// free object
set oEncryption = NOTHING;
catch
sResult = "";
endcatch;
return sResult;
end;
Hope this helps in any way.

Resources