FireDAC TFDTable CreateTable - c++builder

I am trying to use the CreateTable() method of FireDAC's TFDTable class to create a table on my MySQL Server.
void __fastcall TFormMain::ButtonCreateTableClick(TObject *Sender)
{
TFDTable *Table = new TFDTable(this);
try
{
Table->Connection = FDConnection;
Table->TableName = "Setting";
Table->Exclusive = true;
//Table->FieldDefs->Add( "SettingCode", ftString, 99 );
//Table->FieldDefs->Add( "SettingValue", ftString, 255 );
TField *Field;
Field = new TStringField( this );
Field->Name = "FieldSettingCode";
Field->FieldName = "SettingCode";
Field->Size = 100;
Field->DataSet = Table;
Field = new TStringField( this );
Field->Name = "FieldSettingValue";
Field->FieldName = "SettingValue";
Field->Size = 255;
Field->DataSet = Table;
// Fires "Table 'Setting' doesn't exist" error
Table->CreateTable( false, TFDPhysCreateTableParts() << tpTable << tpPrimaryKey << tpIndexes );
Table->Open();
Table->Insert();
Table->FieldByName("SettingCode")->Value = "test2";
Table->FieldByName("SettingValue")->Value = "testValue2";
Table->Post();
// Table->CreateDataSet();
}
__finally
{
Table->Free();
}
}
As soon as I call the CreateTable method it throws an error that the table xxxx.Setting does not exist:
Im Projekt DBCreator.exe ist eine Exception der Klasse EMySQLNativeException mit der Meldung '[FireDAC][Phys][MySQL] Table 'setting' already exists' aufgetreten.
So far so good: This error message is correct - but the real fun fact is, that the table has been successfully created and the code has been inserted.
This also happens using SQLite instead of MySQL.
I am using Embarcadero C++ Builder XE10 Seattle.
How should I handle this correctly?
Is there a way to supress this pretty useless error message?
Edit:
It turned out that EMySQLNativeException is only thrown when the debugger is running. So I just clicked the checkbox to ignore these exceptions and everything is good.
Creating databases with TFDTable and CreateTable() works like charm. Unfortunately it is just undocumented at all (like almost everything #Borland/CodeGear/Embarcadero)...

That exception is thrown by the FireDAC engine and is caused by an attempt to create table without checking if already exists. It is internally handled and the engine acts properly, so what you see is a debugger exception message. If you called the CreateTable method with the recreation parameter enabled:
Table->CreateTable( True, TFDPhysCreateTableParts() << tpTable << tpPrimaryKey << tpIndexes );
the table would be first deleted and you would not get the mentioned exception for this reason.

Related

How to make the task fail when the calling stored procedure throws an error

I had a stored procedure to insert the data from a stage which is called by task. if the load fails(due to on_error= skip_file option) it throws an error which is handled. but the status of the task shows as success. what to do to make the task fail when there is error in stored procedure.
here is the sample code
create or replace procedure sample_procedure()
returns varchar not null
language javascript
execute as caller
as
$$
try
{
try
{
var ct_table_cmd = `create or replace table sample_table_temp like sample_table`;
var ct_table_stmt = snowflake.createStatement({sqlText: ct_table_cmd});
var result_set= ct_table_stmt.execute();
result_set.next();
}
catch(err)
{
var queryId = ct_table_stmt.getQueryId();
var queryText = ct_table_stmt.getSqlText();
var log_insert_into=snowflake.createStatement({sqlText:`insert into error_table
(code, message, queryid, querytext) VALUES (?,?,?,?);`
,binds : [err.code, err.message,queryId,queryText]
});
log_insert_into.execute();
var ct_task_ret_value = snowflake.createStatement({sqlText: `call system$set_return_value('{err.message'});`}).execute();
return err.message;
}
var copy_cmd = `copy into smaple_table_temp from #mystage
file_format=(format_name= 'sample_csv_format')
files=('/file_name')
on_error=skip_file;`;
var copy_cmd_stmt = snowflake.createStatement({sqlText:copy_cmd});
var result_set =copy_cmd_stmt.execute();
result_set.next();
if(result_set.getColumnValue(2)=='LOADED')
{
var swap_cmd = `alter table sample_table_temp swap with sample_table;`;
var swap_stmt = snowflake.createStatement({sqlText: swap_cmd});
swap_stmt.execute();
}
else if (result_set.getColumnValue(2)== 'LOAD_FAILED')
{
var err_message= result_set.getColumnValue(7);
var queryId = copy_cmd_stmt.getQueryId();
var queryText = copy_cmd_stmt.getSqlText();
var log_insert_into=snowflake.createStatement({sqlText:`insert into error_table
(code, message, queryid, querytext) VALUES (?,?,?,?);`
,binds : [err.code, err.message,queryId,queryText]
});
var task_ret_value = snowflake.createStatement({sqlText: `call system$set_return_value('{err_message'});`}).execute();
log_insert_into.execute();
return err_message
}
}
$$
;
The error log table and task to call the procedure is :
create or replace table error_table (ts timestamp_ntz, src varchar(50),code varhcar(100) ,
message varchar, queryid varchar, querytext varhcar);
create or replace task sample task
warehouse = 'my_warehouse'
schedule= '10 minute'
as
call sample_procedure();
when the task call the procedure with no data in the location it throws an error in the task history as "execution error in stored procedure sample procedure:
SQL compilation error:
Syntax error line at position 47 unexpected 'remote'. at statement.execute, line 172 position 111". but the actual error is "remote file is not existed at. there are several potential causes. The file might not exist. The required credentials may be missing or invalid."
and when the table is not existed, the error shown is different in task_history of information schema. It is not showing the error which is shown when the procedure is called independently (i.e call sample_procdure()).
Any suggestions are helpful.
You're setting the return value for the task here:
var ct_task_ret_value = snowflake.createStatement({sqlText: `call system$set_return_value('{err.message'});`}).execute();
You're setting the return for the stored procedure here:
return err.message;
The problem is err.message is a string containing the text of an error message, which is not an error indication. You've caught the error, so as far as Snowflake's concerned it's been handled.
To indicate an error on SP execution, you can either 1) not catch the error or 2) catch the error, handle it, and throw an error.
Option 2 seems to be what you're looking to do. Catch the error as you're already doing, but instead of returning err.message, do this:
//return err.message;
throw err.message;
Snowflake will wrap the error message with its own error text. There is currently no way to avoid that, so you may want to do something in the text to call out attention to your error text like *wrapping in stars* or something like that. Snowflake Stored Procedure Exception & Failure

Capture Success Message in Snowflake Stored Procedure

I have several Snowflake Stored Procedures and when they are successful, it has the custom message that I created displayed, I would rather be displaying the same message that Snowflake shows in the Query Results window.
For Example, I execute a Stored Proc with the COPY TO statements. I would like the Successful execution of this Stored Proc to show the number of Rows successfully Exported. Can they success information be captured and displayed as easily as the Error messages are?
Yes, you can do this using JavaScript stored procedures. When Snowflake runs a query that returns only a status message, it returns it as a table with a single column "status" and a single row with the status. You can return that value. You may want to consider what happens if there's a SQL error: handle it locally in the SP or throw the error so the calling session knows there was an error. Either way the status return will show an error message if there is one.
Here's a sample using JavaScript SP. It also has some helper functions that I use routinely to execute single value queries and non-query statements just looking for a return value:
create or replace procedure SampleSP()
returns string
language javascript
as
$$
try{
return ExecuteNonQuery("create table MY_NATION_TABLE as select * from SNOWFLAKE_SAMPLE_DATA.TPCH_SF1.NATION;");
}
catch(err){
return err;
}
// ----------------------------------------------------------------------------------
// Main function above; helper functions below
function ExecuteNonQuery(queryString) {
return ExecuteSingleValueQuery("status", queryString)
}
function ExecuteSingleValueQuery(columnName, queryString) {
var out;
cmd1 = {sqlText: queryString};
stmt = snowflake.createStatement(cmd1);
var rs;
try{
rs = stmt.execute();
rs.next();
return rs.getColumnValue(columnName);
}
catch(err) {
if (err.message.substring(0, 18) == "ResultSet is empty"){
throw "ERROR: No rows returned in query.";
} else {
throw "ERROR: " + err.message.replace(/\n/g, " ");
}
}
return out;
}
$$;
-- Run this twice to see the effect of an error. You can remove the try block
-- in the main function of the SP to generate a SQL error instead of just
-- returning a string with the error text
call SampleSP();

Return message in Jira out of Java (is only visible after page refresh...)

I have problems with returning a message in Jira out of Java.
I made a plugin, overwriting the CreateWorklog class (the doExecute() method) when creating an issue.
After my functionalities the method ends with those lines:
[...]
if (NONE.equals(superResult))
{
return returnMsgToUser(getReturnUrl(), messageToUser, MessageType.SUCCESS, true, null);
}
return superResult;
And before that, there are some options to return before creating the issue, those look like this for example:
[...]
if (httpPostReq.getResponseCode() != 201)
{
System.out.println("ERROR: Webservice-Aufruf fehlgeschlagen! Response-Code: " + httpPostReq.getResponseCode());
return returnMsgToUser(getReturnUrl(), "ERROR: Webservice call failed! Response-Code: " + httpPostReq.getResponseCode(), MessageType.ERROR, true, null);
}
[...]
The return argument makes the method cancels the issue-creation, but the return message is not as wanted.
First, the normal return message of the unchanged function appears, but after reloading the website, my own message appears.
Why it's only visible after refreshing the Jira website? How could I change that behavior?
And another question:
What exactly is the String target (last constructor parameter) doing in returnMsgToUser? The only information I could find, is that if you put in null, it's placed in a global spot. And what else could you put in there? I have no ideas...

How to print GeckoWebBrowser to default printer?

I'm trying to print the document in a GeckoWebBrowser, but documentation is limited and to me, it's not at all clear.
I found some code on the internet that at least communicates with the printer (it starts beeping) but I think the printer is asking for a Letter size paper, but it requires the settings to be from print.GetGlobalPrintSettingsAttribute(), if I try my own settings, it gives me a NotImplementedException.
I suspect this is exception is raised on my Gecko.PrinterSettings, because when I swap ps in the print.Print(ps, null);
with the global settings, this exception isn't raised.
The code below:
var domWindow = browser.Window.DomWindow;
var print = Gecko.Xpcom.QueryInterface<Gecko.nsIWebBrowserPrint>(domWindow);
Gecko.PrintSettings ps = new Gecko.PrintSettings();
ps.SetPrintSilentAttribute(false);
ps.SetPrintToFileAttribute(false);
ps.SetShowPrintProgressAttribute(false);
ps.SetOutputFormatAttribute(1); //2 == PDF, so I assume 1 is actual printer
ps.SetPrintBGImagesAttribute(true);
ps.SetStartPageRangeAttribute(1);
ps.SetEndPageRangeAttribute(100);
ps.SetPrintOptions(2, true); // evenPages
ps.SetPrintOptions(1, true); // oddpages
ps.SetEffectivePageSize(768 * 20f, 1024 * 20f);
ps.SetShrinkToFitAttribute(true);
ps.SetScalingAttribute(1.0);
ps.SetPrintBGImagesAttribute(true);
print.Print(ps, null);
Managed to come up with a solution.
What was throwing an exception was
public void SetPersistMarginBoxSettingsAttribute(bool aPersistMarginBoxSettings)
{
throw new NotImplementedException();
}
The above is in PrinterSettings.cs, so it is hard-coded coded to throw a NotImplementedException on a number off attributes (the attribute above isn't the only one hard-coded to throw the exception) as it is not finished(?), so I cannot use it.
However, I can use the GetGlobalSettingsAttribute() as it uses the same interface as PrinterSettings (nsiPrintSettings), so therefore it will have the same attributes all populated for me.
So what can I do is:
I simply copy the GetGlobalPrintSettingsAttribute() into my own printer settings, and adjust them as necessary.
var mySettings = print.GetGlobalPrintSettingsAttribute();
mySettings.SetPrintSilentAttribute(true);
mySettings.SetPrintToFileAttribute(true);
mySettings.SetShowPrintProgressAttribute(false);
mySettings.SetOutputFormatAttribute(2); //2 == PDF
mySettings.SetToFileNameAttribute(#"c:\temp\temp.pdf");
mySettings.SetPrintBGImagesAttribute(true);
mySettings.SetStartPageRangeAttribute(1);
mySettings.SetEndPageRangeAttribute(100);
mySettings.SetPrintOptions(2, true); // evenPages
mySettings.SetPrintOptions(1, true); // oddpages
mySettings.SetShrinkToFitAttribute(true);
mySettings.SetScalingAttribute(1.0);
mySettings.SetPrintBGImagesAttribute(true);
print.Print(mySettings, new Gecko.WebProgressListener());
Please notice I reverted back to PDF for now, in the SetOutputFormatAttribute(2); //2 == PDF
Also changed the print.Print(ps, null); to print.Print(mySettings, new Gecko.WebProgressListener()); but I think having null or Gecko.WebProgressListener() won't make a difference.
Et voilĂ ! - Now, onto the next step, which is to print to a printer, and not as a PDF file.

error while using groovy.sql Out parameter

I am trying to execute some stored procedures in groovy way. I am able to do it quite easily by using straight JDBC but this does not seem in the spirit of Grails.
I am trying to call the stored procedure as:
sql.query( "{call web_GetCityStateByZip(?,?,?,?,?)}",[params.postalcode,
sql.out(java.sql.Types.VARCHAR), sql.out(java.sql.Types.VARCHAR),
sql.out(java.sql.Types.INTEGER), sql.out(java.sql.Types.VARCHAR)]) { rs ->
params.city = rs.getString(2)
params.state = rs.getString(3)
}
I tried various ways like sql.call. I was trying to get output variable value after this.
Everytime error:
Message: Cannot register out parameter.
Caused by: java.sql.SQLException: Cannot register out parameter.
Class: SessionExpirationFilter
but this does not seem to work.
Can anyone point me in the right direction?
This is still unanswered, so I did a bit of digging although I don't fully understand the problem. The following turned up from the Groovy source, perhaps it's of some help:
This line seems to be the origin of the exception:
http://groovy.codehaus.org/xref/groovy/sql/Sql.html#1173
This would seem to indicate that you have a Statement object implementing PreparedStatement, when you need the subinterface CallableStatement, which has the registerOutParameter() method which should be ultimately invoked.
Thanks Internet Friend,
If i write code like-
Sql sql = new Sql(dataSource)
Connection conn
ResultSet rs
try {
conn = sql.createConnection()
CallableStatement callable = conn.prepareCall(
"{call web_GetCityStateByZip(?,?,?,?,?)}")
callable.setString("#p_Zip",params.postalcode)
callable.registerOutParameter("#p_City",java.sql.Types.VARCHAR)
callable.registerOutParameter("#p_State",java.sql.Types.VARCHAR)
callable.registerOutParameter("#p_RetCode",java.sql.Types.INTEGER)
callable.registerOutParameter("#p_Msg",java.sql.Types.VARCHAR)
callable.execute()
params.city = callable.getString(2)
params.state = callable.getString(3)
}
It working well in JDBC way. But i wanted to try it like the previous code using sql.query/sql.call.
Any comments??
Thanks
Sadhna
groovy way could be this code:
def getHours(java.sql.Date date, User user) throws CallProceduresServiceException {
log.info "Calling stored procedure for getting hours statistics."
def procedure
def hour
try {
def sql = Sql.newInstance(dataSource.url, user.username, user.password, dataSource.driverClassName)
log.debug "Date(first param): '${date}'"
procedure = "call ${dbPrefixName}.GK_WD_GET_SCHEDULED_TIME_SUM(?, ?, ?, ?)"
log.debug "procedure: ${procedure}"
sql.call("{${procedure}}", [date, Sql.out(Sql.VARCHAR.getType()), Sql.out(Sql.VARCHAR.getType()), Sql.out(Sql.VARCHAR.getType())]) {
hourInDay, hourInWeek, hourInMonth ->
log.debug "Hours in day: '${hourInDay}'"
log.debug "Hours in week: '${hourInWeek}'"
log.debug "Hours in month: '${hourInMonth}'"
hour = new Hour(hourInDay, hourInWeek, hourInMonth)
}
log.info "Procedure was executed."
}
catch (SQLException e) {
throw new CallProceduresServiceException("Executing sql procedure failed!"
+ "\nProcedure: ${procedure}", e)
}
return hour
}
In my app it works great.
Tomas Peterka

Resources