I am trying to learn Apache Calcite by following the RelBuilderExample with the storage layer being HSQLDB.
Unfortunately, I keep getting "Table Not Found exception" when i call builder.scan(tableName) API of Apache Calcite. When I query the data in HSQL directly using ResultSet rs = statement.executeQuery("SELECT * from file"); then i am able to retrieve the data. Here is the relevant code:
//I create an instance of RelBuilder using the Config defined below
RelBuilder builder = RelBuilder.create(config().build());
//This line throws me exception: org.apache.calcite.runtime.CalciteException: Table 'file' not found
builder = builder.scan("file");
/**
Building the configuration backed by HSQLDB
*/
public static Frameworks.ConfigBuilder config() throws Exception{
//Getting the ConnectionSpec for the in memory HSQLDB
//FileHSQLDB.URI = "jdbc:hsqldb:mem:intel"
//FileHSQLDB.USER = "user"
//FileHSQLDB.PASSWORD = "password"
final ConnectionSpec cs = new ConnectionSpec(FileHSQLDB.URI, FileHSQLDB.USER, FileHSQLDB.PASSWORD, "org.hsqldb.jdbcDriver", "intel");
//cs.url = "jdbc:hsqldb:mem:intel"
//cs.driver = "org.hsqldb.jdbcDriver"
//cs.username = "user"
//cs.password = "password"
DataSource dataSource = JdbcSchema.dataSource(cs.url, cs.driver, cs.username, cs.password);
Connection connection = dataSource.getConnection();
Statement statement = connection.createStatement();
//This returns me 3 results
ResultSet rs = statement.executeQuery("SELECT * from file");
while(rs.next()) {
String id = rs.getString("file_id");
System.out.println(id);
}
// Next I create the rootSchema
SchemaPlus rootSchema = Frameworks.createRootSchema(true);
//I suspect that there is some issue in the below line. I think I
//am not using Apache Calcite APIs properly, but not sure what I
//am doing wrong.
rootSchema.add("intel", JdbcSchema.create(rootSchema, "intel", dataSource, cs.catalog, cs.schema));
return Frameworks.newConfigBuilder().defaultSchema(rootSchema);
Can someone please help me what I may be doing wrong.
If your table is file (lowercase) then make sure you quote the table name in the query, i.e. "SELECT * from \"file\"".
Related
This problem is frustrating me so much, that I've finally created a Stackoverflow Account - this is my first question here, go easy on me.
I've got an SQL Script like this:
select * from d_table
where id = :line;
I'd like to execute that query from a groovy script. So far I've written this:
static void main(String[] args) {
String dbURL = 'some.db:Port:serviceName'
String dbUser = 'dbUser'
String dbPw = 'aReallyStrongPassword'
// connect to SQL Instance and DB
def sql = Sql.newInstance(dbURL, dbUser, dbPw, 'oracle.jdbc.OracleDriver')
// read Inputfile from local dir
new File("inputfile.csv").eachLine { inputLine ->
// loop over Inputfile
try {
// read SQL Script from local dir
String sqlString = new File("script.sql").getText("UTF-8")
// execute SQL Script, replace :line with input-ID
resp = sql.execute sqlString, line: inputLine
} catch(Exception e) {
println(e)
}
}
// close SQL Session
sql.close()
}
But I'll always get an error like this:
WARNING: Failed to execute: select * from d_table
where id = :line; because: ORA-00933: SQL command not properly ended
I've got the feeling the query is not built properly, but I don't know whats the problem?
Using groovy 3.0.4.
We recently moved our data to a new server - however the new one is using MariaDB.
We do a lot of queries and calculations in Google Apps Script for spreadsheet. Since the server switch our scripts return the following error:
Unknown system variable 'OPTION' (line 21, file "")
Line 21 refers to the query inside the following script:
function mysql_invoice() {
// Replace the variables in this block with real values.
var address = 'xxx';
var user = 'xxx';
var userPwd = 'xxx';
var db = 'xxx';
var dbUrl = 'jdbc:mysql://' + address + '/' + db;
// Read up to 100000 rows of data from the table and log them.
var conn = Jdbc.getConnection(dbUrl, user, userPwd);
var stmt = conn.createStatement();
// Call SO DATA
stmt.setMaxRows(10000);
var start = new Date();
var rs = stmt.executeQuery("select * from sales_flat_invoice");
Any ideas?
I believe the way you used setMaxRows is the problem.
If you change the way you set the limit it will work.
// Call SO DATA
// stmt.setMaxRows(10000);
var start = new Date();
var rs = stmt.executeQuery("select * from sales_flat_invoice limit 10000");
This should fix your problem. This definetly comes from the missmatch of version of your MariaDB and the version of jdbc connector.
Cheers
I have a very strange error with dapper:
there is already an open DataReader associated with this Command
which must be closed first
But I don't use DataReader! I just call select query on my server application and take first result:
//How I run query:
public static T SelectVersion(IDbTransaction transaction = null)
{
return DbHelper.DataBase.Connection.Query<T>("SELECT * FROM [VersionLog] WHERE [Version] = (SELECT MAX([Version]) FROM [VersionLog])", null, transaction, commandTimeout: DbHelper.CommandTimeout).FirstOrDefault();
}
//And how I call this method:
public Response Upload(CommitRequest message) //It is calling on server from client
{
//Prepearing data from CommitRequest
using (var tr = DbHelper.DataBase.Connection.BeginTransaction(IsolationLevel.Serializable))
{
int v = SelectQueries<VersionLog>.SelectVersion(tr) != null ? SelectQueries<VersionLog>.SelectVersion(tr).Version : 0; //Call my query here
int newVersion = v + 1; //update version
//Saving changes from CommitRequest to db
//Updated version saving to base too, maybe it is problem?
return new Response
{
Message = String.Empty,
ServerBaseVersion = versionLog.Version,
};
}
}
}
And most sadly that this exception appearing in random time, I think what problem in concurrent access to server from two clients.
Please help.
This some times happens if the model and database schema are not matching and an exception is being raised inside Dapper.
If you really want to get into this, best way is to include dapper source in your project and debug.
I have a query
SELECT instance_guid FROM service_instances WHERE service_template_guid='E578F99360A86E4EE043C28DE50A1D84' AND service_family_name='TEST'
Directly executing this returns me
4FEFDE7671A760A8DC8FC63CFBFC8316
F2F9DF641D8E2CACC03175A7A628D51D
Now I am trying same code from JDBC.
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = executionContext.getConnection();
if (conn != null) {
ps = (PreparedStatement)conn.prepareStatement(query);
if (params == null) params = new Object[0];
for (int i=0;i<params.length;i++) {
if (params[i] instanceof Integer) {
ps.setInt(i+1, ((Integer)params[i]).intValue());
} else if (params[i] instanceof java.util.Date) {
((PreparedStatement)ps).setDATE(i+1, new oracle.sql.DATE((new java.sql.Timestamp(((Date)params[i]).getTime()))));
//ps.setObject(i+1, new oracle.sql.DATE(new Time(((Date)params[i]).getTime())));
} else {
if (params[i] == null) params[i] = "";
ps.setString(i+1, params[i].toString());
}
}
rs = ps.executeQuery();
I see params[0] =E578F99360A86E4EE043C28DE50A1D84 and params[1]=TEST
But the resultSet is empty and not getting the result.I debugged but not much help?
Can you please let me know Am i trying right?
In java its defined as below
final static private String INSTANCE_GUID_BY_TEMPLATE_GUID =
"SELECT instance_guid FROM service_instances WHERE service_template_guid=? AND service_family_name=? "
SERVICE_FAMILY_NAME NOT NULL VARCHAR2(256)
SERVICE_TEMPLATE_GUID NOT NULL RAW(16 BYTE)
First and foremost this breaks every sql mapping pattern I have ever seen.
String sql = "SELECT instance_guid FROM service_instances WHERE service_template_guid=? AND service_family_name=?";
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = executionContext.getConnection();
ps = conn.prepareStatement(sql);
ps.setString(1,guid);
ps.setString(2,family);
rs = ps.executeQuery();
while(rs.next(){...}
...
}
You should not be dynamically figuring out the data types as they come in, unless you are trying to write some code to port from database X to database Y.
UPDATE
I see you are using RAW as a datatype, from this post:
As described in the Oracle JDBC Developer's guide and reference 11g,
when using a RAW column, you can treat it as a BINARY or VARBINARY
JDBC type, which means you can use the JDBC standard methods
getBytes() and setBytes() which returns or accepts a byte[]. The other
options is to use the Oracle driver specific extensions getRAW() and
setRAW() which return or accept a oracle.sql.RAW. Using these two will
require you to unwrap and/or cast to the specific Oracle
implementation class.
Further from a code readability standpoint, your solution makes it painful for a new developer to take over. Far too often I see people making sql be "dynamic" when in reality 99% of the time you don't need this level of dynamic query building. It sounds good in most people's heads but it just causes pain and suffering in the SDLC.
Sorry for my English first of all. I have a problem and need help.
I have a simple tool made by myself on c#. This tool makes connect to local or remote firebird server (v.2.5). And my tool can create specified .fdb file (database) somewhere on the server.
Also I have a file with SQL statements (create table, triggers and so on). I want to execute this file after database was created. Executing this file will fill structure of user database - not data, only structure.
But then I try to execute my SQL script - firebird server returns a
SQL error code = -104 Token unknown line xxx column xxx.
That's the line on this CREATE TABLE SQL statement, for example:
CREATE TABLE tb1
(
col1 INTEGER NOT NULL,
col2 VARCHAR(36)
);
/* This next create statement causes an error */
CREATE TABLE tb2
(
col1 INTEGER NOT NULL,
col2 VARCHAR(36)
);
If I will leave only one create statement in my file - all will be good... I don't know how I explained (it's clear or not)) - another words - why can't I execute full query with many create statements in one transaction? There is my main method which executes query:
public static string Do(string conString, string query)
{
using (FbConnection conn = new FbConnection())
{
try
{
conn.ConnectionString = conString;
conn.Open();
FbTransaction trans = conn.BeginTransaction();
FbCommand cmd = new FbCommand(query, conn, trans);
cmd.ExecuteNonQuery();
trans.Commit();
}
catch (Exception ex)
{
System.Windows.MessageBox.Show(ex.ToString());
return "Transaction Fail";
}
}
return "Transaction Commited";
}
There is a query is my SQL file.
As Victor already stated in his final comment, you can use the FBScript class for batch execution.
I was just confronted with the same task. This question pointed me in the right direction but i had to do some further digging.
I this example, the source of the statements is a external script file:
private void ExecuteScript(FbConnection myConnection, string scriptPath) {
if (!File.Exists(scriptPath))
throw new FileNotFoundException("Script not found", scriptPath);
FileInfo file = new FileInfo(scriptPath);
string script = file.OpenText().ReadToEnd();
// use FbScript to parse all statements
FbScript fbs = new FbScript(script);
fbs.Parse();
// execute all statements
FbBatchExecution fbe = new FbBatchExecution(myConnection, fbs);
fbe.Execute(true);
}
This will work fine, but you may wonder why this whole thing isn't surrounded by a transaction. Actually there is no support to "bind" FbBatchExecution to a transaction directly.
The first thing i tried was this (will not work)
private void ExecuteScript(FbConnection myConnection, string scriptPath) {
using (FbTransaction myTransaction = myConnection.BeginTransaction()) {
if (!File.Exists(scriptPath))
throw new FileNotFoundException("Script not found", scriptPath);
FileInfo file = new FileInfo(scriptPath);
string script = file.OpenText().ReadToEnd();
// use FbScript to parse all statements
FbScript fbs = new FbScript(script);
fbs.Parse();
// execute all statements
FbBatchExecution fbe = new FbBatchExecution(myConnection, fbs);
fbe.Execute(true);
myTransaction.Commit();
}
}
This will result in an exception stating: "Execute requires the Command object to have a Transaction object when the Connection object assigned to the command is in a pending local transaction. The Transaction property of the Command has not been initialized."
This means nothing more than that the commands that are executed by FbBatchExecution are not assigned to our local transaction that is surrounding the code block. What helps here is that that FbBatchExecution provides
the event CommandExecuting where we can intercept every command and assign our local transaction like this:
private void ExecuteScript(FbConnection myConnection, string scriptPath) {
using (FbTransaction myTransaction = myConnection.BeginTransaction()) {
if (!File.Exists(scriptPath))
throw new FileNotFoundException("Script not found", scriptPath);
FileInfo file = new FileInfo(scriptPath);
string script = file.OpenText().ReadToEnd();
// use FbScript to parse all statements
FbScript fbs = new FbScript(script);
fbs.Parse();
// execute all statements
FbBatchExecution fbe = new FbBatchExecution(myConnection, fbs);
fbe.CommandExecuting += delegate(object sender, CommandExecutingEventArgs args) {
args.SqlCommand.Transaction = myTransaction;
};
fbe.Execute(true);
// myTransaction.Commit();
}
}
Note that i have uncommented the myTransaction.Commit() line. I was a little bit surprised by this behavior, but if you keep that line the transaction will throw an exception stating that it has already been committed. The bool parameter fbe.Execute(true) is named "autoCommit", but changing this to false seems to have no effect.
I would like some feedback if you see any potential issues with assigning the local transaction this way, or if it has any benefits at all or could as well be omitted.
Probably error in launching two create statements in one batch. Would it work if you break it to separate queries? Does it work in your SQL tool?