Does MySQL's JDBC driver have a facility for parsing SQL? - mysql

I'm writing a Java tool to validate SQL statements. For SELECT queries, I can do it with Connection.prepareStatement and PreparedStatemet.getMetaData. No exceptions == good query. Unfourtunately it doesn't work with eg. INSERT statements -- errors in query create exception only at executing the statement.
Is there a way to parse SQL via JDBC without executing the statement? An internal method maybe?
Unfourtunately I was also unable to find source code for Connector/J -- I'd be grateful for links to it.

OK, found an answer myself, need to call a protected method:com.mysql.jdbc.ServerPreparedStatement.getInstance(MySQLConnection conn, String sql, String catalog, int, int)

Related

can we handle exception in snowflake "sql" udf

I'm migrating javascript udf to sql udf in snowflake. In javascript udf there is try catch block to handle exception. How can I implement the same in SQL udf.
Snowflake SQL user defined functions can’t include execution handling. The function definition needs to be a SQL expression, not a Snowflake Scripting block.
The function definition can be a SQL expression that returns either a scalar (i.e. single) value or, if defined as a table function, a set of rows.
Your choices are to code the UDF to avoid triggering any error condition that you wanted to trap (e.g. with a CASE to avoid all “troublesome” input values) or use a JavaScript UDF for any place where exception handling can’t be avoided.
P.S. post a new question with your actual code if you want help on if your use case can be implemented in a SQL UDF

Invalid descriptor index on LAST_INSERT_ID after insert

Strange situation with my ODBC code ( called from a C library ). Basically, I have the following sequence of events:
Create insert statement ( just a string )
Call SQLPrepare with that insert statement string
Bind the various parameters ( column values ), using
SQLBindParameter
Call SQLExecute to insert the row ( this works, by the way, as I can
see the row in the MySQL DB )
Create "select last_insert_id()" statement string
NOTE: if in SQL Server mode, we would create a "select ##identity"
statement
Bind column using SQLBindCol - this is where I get the "Invalid
descriptor index" error
NOTE: if in SQL Server mode, this works fine, with no error
Call SQLExecDirect to get the last insert id - this never happens
because of SQLBindCol error
Does the standard MySQL ODBC connector require something special in this situation? Does anyone have an ODBC example of this type of "insert" then "get last insert id" behavior? Maybe I need to call "SQLPrepare" before step 6 ( where I bind the column )? Another way to ask this: Should there be an SQLPrepare call for each SQLExecute or SQLExecDirect call?
I know it works directly in SQL, so the problem is my C ODBC code.
Thanks.
For those who are interested, I ended up changing the above steps by adding an SQLPrepare call between creating the "select last_insert_id()" ( step 5 ) and calling SQLBindCol ( step 6 ). Not sure if that would work for others, but it seems to be working rather well for me.
As for research, I looked all over the place online and never found a really good or clear answer. Most comments were about the SQL involved, not ODBC. And the references to ODBC were vague and did not seem to apply to my situation, from what I could see.
My assumption is that the SqlServer ODBC driver I am using handles the missing prepare statement differently ( maybe even better, but that is debatable ) than my MySql ODBC driver.
SQL Server ODBC driver was the one provided by Easysoft
MySql ODBC driver was the one provided with the standard CentOS install of MySql
Hopefully this will help people. Obviously, if people have a better idea, please tell us.

How do I write an SQL query that fails?

I need this query for testing exception handling, so I would prefer that the query is not schema dependent. I am looking for something like SELECT 1; but of course that doesn't fail.
I am using Java and MySQL but I hope to find answers that doesn't depend on programming languages and/or RDBMSs.
What about "SELECT 1/0" for starters?
You could put an invalid token into the query
select doesnotexist.* from something_else
Or of course, what you should do is mock out the method and have it throw the exception during your test.
there are tons of ways to make a query fail, like mispelling a field, or selecting from non existing tables. for example:
SELECT some_fake_field FROM table_that_doesnt_exists
One way to trigger a failure is to call a stored procedure with the wrong number of parameters. Another similar idea is to write an update/insert statement with the wrong number of arguments...
More ideas here:
How to raise an error within a MySQL function
Any old syntax error will do... like an unterminated string
select 'bob
To get 1/0 to raise an error in MySQL, you need to set sql_mode to ERROR_FOR_DIVISION_BY_ZERO.
Try this:
SET sql_mode = 'ERROR_FOR_DIVISION_BY_ZERO';
SELECT 1/0;
If this sql_mode isn't set, MySQL will return a NULL instead of an error.
You can check what your current settings are with the following:
SELECT ##GLOBAL.sql_mode;
SELECT ##SESSION.sql_mode;

Function definition not properly passed to MySQL database using MySQL Workbench

I'm using MySQL 5.5 (x64) and MySQL Workbench 5.2 deployed locally on a Windows 7 workstation for development purposes. I used MySQL Workbench to build a schema with the following function definition:
CREATE FUNCTION `db`.`get_public_name` (GPN_entID INT) RETURNS VARCHAR(64)
DETERMINISTIC
BEGIN
DECLARE GPN_pubName VARCHAR(64);
SELECT public_name INTO GPN_pubName
FROM entity WHERE id_entity=GPN_entID LIMIT 1;
RETURN GPN_pubName;
END
I then attempt to "Forward Engineer" the schema to the database with the following options specified:
DROP Objects Before Each Create Object
Generate DROP SCHEMA
Add SHOW WARNINGS After Every DDL Statement
GENERATE INSERT Statements for Tables
After this, MySQL Workbench attempts to publish to the server:
CREATE FUNCTION `db`.`get_public_name` (GPN_entID INT) RETURNS VARCHAR(64)
DETERMINISTIC
BEGIN
DECLARE GPN_pubName VARCHAR(64);
SELECT public_name FROM entity WHERE id_entity = GPN_entID;
RETURN GPN_pubName;
END
This results in the following error:
Executing SQL script in server
ERROR: Error 1415: Not allowed to return a result set from a function
Upon closer examination, I noticed the "INTO" and "LIMIT" clauses of the SELECT statement have been removed from the original function definition. This looks like it might be a cached version of the function, but I have tried everything I can think of (short of uninstalling and reinstalling MySQL Workbench) to flush any such cache to reload the correct version, but to no avail.
So, why is this change happening and how do I prevent it from happening?
Try changing to this:
SELECT public_name FROM entity WHERE id_entity = GPN_entID LIMIT 1 INTO GPN_pubName;
I'm embarrassed; if it wasn't for the fact this may be useful to others, I'd just go ahead and delete this question to hide my shame.
It turns out I created two functions with the same name and MySQL Workbench happily let me do so. I didn't notice that was the case until I started going through the stored routines with a more careful eye. I was editing one, but the other one (which had the error) was never changed. Since publishing each function involved dropping any earlier version from the database, I probably wouldn't have noticed this until things weren't working properly.

Problems calling MySQL stored procedures from C API

I have a problem calling a stored procedure on my MySQL server using the C API.
I use mysql_query(&handle,"CALL myprocedure") but the function fails (returns 1) and error lookup gives
the following message "Procedure myprocedure can't return a result set in the given context."
I even tried to use mysql_real_query insted, but no better.
I've seen a few topics about this bug, but only PHP related. So there seems to be the same problem for C programs too.
The weird thing is that my stored procedure is not even supposed to return any result set. It just works with data in tables, doesn't really return anything.
Thanks for any advices.
Refer to functions:
mysql_set_server_option() &
mysql_real_connect()
here.
Multiple statements are only enabled(temporarily) using the MYSQL_OPTION_MULTI_STATEMENTS_ON and _OFF arguments
to mysql_set_server_option().
The problem here is that CLIENT_MULTI_STATEMENTS in
mysql_real_connects()
implicitly enables CLIENT_MULTI_RESULTS, too, but
MYSQL_OPTION_MULTI_STATEMENTS_ON only enables multiple statements,
not multiple results.
So add CLIENT_MULTI_STATEMENTS on connect and try again.
Did you try to call this procedure from 'mysql' command line client?
Are you able to call (another) empty procedure to test if problem is related to the procedure?