I am using Oracle Express Edition to work with a project. I have the following code to connect to my database:
public static void main(String[] args) {
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection con = DriverManager.getConnection("jdbc:oracle:driver_type:[username/password]#//host_name:port_number:SID");
Statement st = con.createStatement();
ResultSet rs = st.executeQuery("Select * from [Sheet1$]");
ResultSetMetaData rsmd = rs.getMetaData();
int numberOfColumns = rsmd.getColumnCount();
while (rs.next()) {
for (int i = 1; i <= numberOfColumns; i++) {
if (i > 1)
System.out.print(", ");
String columnValue = rs.getString(i);
System.out.print(columnValue);
}
System.out.println("");
}
st.close();
con.close();
} catch (Exception ex) {
System.err.print("Exception: ");
System.err.println(ex.getMessage());
}
}
When I try to run it, I get a failed to call database error, Missing in or out parameter at index 1. What is wrong with my code? Any help would be appreciated.
Related
This is my first app on Android with Java and SQLite.
ISSUE:
I have a local SQLIte db on my app. I was very surprised to see how easy it is to get access to the db once you have installed the app (no need to be a programmer nor a hacker).
I tried adding SQLCipher to my app but it only worked for newer Android versions 11 & 12 and didn't work for Android 9 for example and it did make my app's size much bigger.
After researching more I found a better solution for my case which doesn"t involve crypting the db with SQLCipher but rather it consists of corrupting the first bytes of the db file then after each launch of the app the code will decorrupt the file and use the fixed file instead. This insures that anyone who decompiles the apk will only get access to a corrupt db file and will have to put more effort to fix it which is my goal.
I came across this solution in a reply [here][1] but I don't know how to implement it as I am new to Android and SQLite programming. Any help is much appreciated on how to actually do it.
These are the steps as mentioned by the user: farhad.kargaran which need more explanation as I don't get how to do it:
1- corrupt the db file (convert it to byte array and change some values)
2- copy it in asset folder
3- in first run fix corrupted file from asset and copy it in database
folder.
Change first 200 byte values like this:
int index = 0;
for(int i=0;i<100;i++)
{
byte tmp = b[index];
b[index] = b[index + 1];
b[index + 1] = tmp;
index += 2;
}
As only the first 200 bytes were replaced, the same code is used for fixing first 200 byte values.
Here is my code for the SQLiteOpenHelper if needed:
public class DatabaseHelper extends SQLiteOpenHelper {
private static final String TAG = DatabaseHelper.class.getSimpleName();
public static String DB_PATH;
public static String DB_NAME;
public SQLiteDatabase database;
public final Context context;
public SQLiteDatabase getDb() {
return database;
}
public DatabaseHelper(Context context, String databaseName, int db_version) {
super(context, databaseName, null, db_version);
this.context = context;
DB_PATH = getReadableDatabase().getPath();
DB_NAME = databaseName;
openDataBase();
// prepare if need to upgrade
int cur_version = database.getVersion();
if (cur_version == 0) database.setVersion(1);
Log.d(TAG, "DB version : " + db_version);
if (cur_version < db_version) {
try {
copyDataBase();
Log.d(TAG, "Upgrade DB from v." + cur_version + " to v." + db_version);
database.setVersion(db_version);
} catch (IOException e) {
Log.d(TAG, "Upgrade error");
throw new Error("Error upgrade database!");
}
}
}
public void createDataBase() {
boolean dbExist = checkDataBase();
if (!dbExist) {
this.getReadableDatabase();
this.close();
try {
copyDataBase();
} catch (IOException e) {
Log.e(TAG, "Copying error");
throw new Error("Error copying database!");
}
} else {
Log.i(this.getClass().toString(), "Database already exists");
}
}
private boolean checkDataBase() {
SQLiteDatabase checkDb = null;
try {
String path = DB_PATH + DB_NAME;
checkDb = SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READONLY);
} catch (SQLException e) {
Log.e(TAG, "Error while checking db");
}
if (checkDb != null) {
checkDb.close();
}
return checkDb != null;
}
private void copyDataBase() throws IOException {
InputStream externalDbStream = context.getAssets().open(DB_NAME);
String outFileName = DB_PATH + DB_NAME;
OutputStream localDbStream = new FileOutputStream(outFileName);
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = externalDbStream.read(buffer)) > 0) {
localDbStream.write(buffer, 0, bytesRead);
}
localDbStream.close();
externalDbStream.close();
}
public SQLiteDatabase openDataBase() throws SQLException {
String path = DB_PATH + DB_NAME;
if (database == null) {
createDataBase();
database = SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READWRITE);
}
return database;
}
#Override
public synchronized void close() {
if (database != null) {
database.close();
}
super.close();
}
Much appreciated.
[1]: https://stackoverflow.com/a/63637685/18684673
As part of the copyDatabase, correct and then write the corrupted data, then copy the rest.
Could be done various ways
e.g.
long buffersRead = 0; //<<<<< ADDED for detecting first buffer
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = externalDbStream.read(buffer)) > 0) {
if (bufferesRead++ < 1) {
//correct the first 200 bytes here before writing ....
}
localDbStream.write(buffer, 0, bytesRead);
}
What is the proper syntax to call the procedure ? It works if I remove the 2nd out parameter and used returning
to return the result, but I have use case where there will be more than 1 different results
to be returned by the procedure. I can't figure out other way to return different result
from a single procedure call. Any help are deeply appreciated.
Tools
IBM Informix Dynamic Server Version 12.10.FC13, 14.10.FC4W1DE
JDBC 4.10.14, 4.50.7
Java version "1.7.0_60"
Stored procedure
create procedure sp_demo_set_arg5(
arg1 set(integer not null),
out arg2 integer
)
returning integer as retval;
define p_arg1 integer;
define p_arg2 integer;
define p_retval integer;
begin
let p_arg2 = 0;
let p_retval = 0;
foreach
select *
into p_arg1
from table(arg1)
let p_arg2 = p_arg2 + p_arg1;
let p_retval = 1;
end foreach ;
return p_retval;
end
end procedure;
Java code
String dbUrl = "jdbc:informix-sqli://someserver:28090/demodb:INFORMIXSERVER=ol_informix1410";
String user = "someuser";
String password = "somepass";
String sql = "{ ? = call sp_demo_set_arg5(?::SET(integer not null), ?) }";
HashSet<Integer> arg1 = new HashSet<>();
Integer intObject;
int i;
for (i=1; i <= 1; i++)
{
intObject = new Integer(i);
arg1.add(intObject);
arg1.add(i);
}
Connection conn = null;
try {
conn = Database.getConnection(dbUrl, user, password);
CallableStatement stmt = conn.prepareCall(sql);
int arg2 = 0;
stmt.setObject(1, arg1);
stmt.registerOutParameter(2, Types.INTEGER );
ResultSet rs = stmt.executeQuery();
arg2 = stmt.getInt(2);
while (rs.next()) {
System.out.println("retval = " + rs.getInt(1) + " , arg2 = " + arg2);
}
return;
} catch (SQLException e) {
e.printStackTrace();
}
Stacktrace
java.sql.SQLException: Illegal attempt to convert a collection type into another type.
at com.informix.util.IfxErrMsg.buildExceptionWithMessage(IfxErrMsg.java:422)
at com.informix.util.IfxErrMsg.buildIsamException(IfxErrMsg.java:401)
at com.informix.jdbc.IfxSqli.addException(IfxSqli.java:3022)
at com.informix.jdbc.IfxSqli.receiveError(IfxSqli.java:3273)
at com.informix.jdbc.IfxSqli.dispatchMsg(IfxSqli.java:2269)
at com.informix.jdbc.IfxSqli.receiveMessage(IfxSqli.java:2194)
at com.informix.jdbc.IfxSqli.executeFastPath(IfxSqli.java:4862)
at com.informix.jdbc.IfxResultSet.executeFastPath(IfxResultSet.java:251)
at com.informix.jdbc.IfxCallableStatement.executeFastPath(IfxCallableStatement.java:1470)
at com.informix.jdbc.IfxCallableStatement.executeQuery(IfxCallableStatement.java:233)
Have you tried using the driver's PreparedStatement (IfmxPreparedStatement)?
The classes:
com.informix.lang.IfxToJavaType,
com.informix.lang.JavaToIfxType
com.informix.lang.IfxTypes
are very helpful.
And these ones:
com.informix.jdbc.IfxComplexInput
com.informix.jdbc.IfxComplexOutput
make calls to IfxTypes' method:
public static boolean isCollection(int ifxType) {
ifxType &= 0xFF;
if (ifxType == 21 || ifxType == 19 || ifxType == 20)
return true;
return false;
}
(The IfxType for SET is 19)
What is the recommended way to reset a C3P0 managed connection to its initial state?
I am using the Microsoft JDBC driver and setting a SET ROWCOUNT 1 on one connection. This results in all queries executed by that connection to return only one row even after the connection has been returned to the pool and later fetched again. Should I be resetting the values explicitly onCheckin or onCheckout?
Main class
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.beans.PropertyVetoException;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Connection;
import java.sql.ResultSet;
public class Main {
final ComboPooledDataSource cpds;
Main() throws PropertyVetoException {
cpds = new ComboPooledDataSource();
cpds.setDriverClass("com.microsoft.sqlserver.jdbc.SQLServerDriver");
cpds.setJdbcUrl("jdbc:sqlserver://10.42.62.41:1433;databaseName=mach;integratedSecurity=false;SendStringParametersAsUnicode=true;applicationName=panda;");
cpds.setUser("testuser");
cpds.setPassword("welcome123");
cpds.setInitialPoolSize(0);
cpds.setMinPoolSize(1);
cpds.setMaxPoolSize(1);
cpds.setConnectionCustomizerClassName("C3p0ConnectionCustomizer");
cpds.setDescription("Netbeans test project");
}
Connection getConnection() throws SQLException{
return cpds.getConnection();
}
public static void main(String[] args) throws PropertyVetoException, SQLException {
Main m = new Main();
try(Connection connection = m.getConnection()){
Statement stmt = connection.createStatement();
stmt.execute("SET ROWCOUNT 1");
}
try(Connection connection = m.getConnection()){
try(Statement stmt = connection.createStatement()) {
int cnt = 0, rsCnt = 0;
boolean results = stmt.execute("select * from Foo; select * from Bar");
if(results) {
do {
rsCnt++;
ResultSet rs = stmt.getResultSet();
while(rs.next()) {
cnt++;
}
System.out.println(rsCnt + " -> " + cnt);
rs.close();
results = stmt.getMoreResults();
cnt = 0;
} while (results);
}
}
}
}
}
Customizer - Mainly to see the connection being used.
import com.mchange.v2.c3p0.AbstractConnectionCustomizer;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
public class C3p0ConnectionCustomizer extends AbstractConnectionCustomizer {
#Override
public void onAcquire(Connection c, String pdsIdt) {
try (Statement stmt = c.createStatement()) {
stmt.execute("SET ROWCOUNT 0");
} catch(SQLException sqle) {
sqle.printStackTrace();
}
}
#Override
public void onCheckOut(Connection c, String pdsIdt) {
System.out.println("Checked out " + c + " [" + pdsIdt + "]");
}
#Override
public void onCheckIn(Connection c, String pdsIdt) throws SQLException {
System.out.println("Checking in " + c + " [" + pdsIdt + "]");
}
}
Without the SET ROWCOUNT 1 line, more rows are returned by the above queries. The customizer logging shows that the same connection is being used.
One could argue that, ideally, code that calls SET ROWCOUNT 1 really should "clean up after itself" by making sure that it calls SET ROWCOUNT 0 before releasing the connection back to the pool.
However, if we cannot absolutely guarantee such behaviour then it seems quite reasonable to simply move your SET ROWCOUNT 0 call from the onAcquire method to the onCheckIn method. It would result in an extra round-trip for each check-in, even if resetting ROWCOUNT was not really necessary, but a SET ROWCOUNT 0 would be a relatively inexpensive operation.
(I just tried it with c3p0-0.9.5.2 and mssql-jdbc, and moving SET ROWCOUNT 0 to the onCheckIn method had the desired effect.)
Im trying to invoke a java program through C using JNI. The Java program is basically a JDBC connection to Hive.
Here is my code snippet
Java program
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.DriverManager;
public class HiveJdbcClient {
private static String driverName = "org.apache.hive.jdbc.HiveDriver";
/**
* #param args
* #throws SQLException
*/
public static void main(String[] args) throws SQLException {
try {
Class.forName(driverName);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.exit(1);
}
//replace "hive" here with the name of the user the queries should run as
Connection con = DriverManager.getConnection("jdbc:hive2://localhost:10000/default", "cloudera", "cloudera");
//Connection con = DriverManager.getConnection("jdbc:hive2://");
Statement stmt = con.createStatement();
String tableName = "testHiveDriverTable";
stmt.execute("drop table if exists " + tableName);
stmt.execute("create table " + tableName + " (key int, value string)");
String sql = "show tables '" + tableName + "'";
System.out.println("Running: " + sql);
ResultSet res = stmt.executeQuery(sql);
if (res.next()) {
System.out.println(res.getString(1));
}
}
}
and my C program looks like this
#include<stdio.h>
#include "jni.h"
int main ( void )
{
char cpath;
JNIEnv *env;
JavaVM *jvm;
int res;
jclass cls;
jmethodID mid = NULL;
//JavaVMOption options;
JavaVMOption options [3];
options[0].optionString="-Djava.class.path=desired-classpath";
options[1].optionString = "-verbose:class";
options[2].optionString = "-Xdebug";
JavaVMInitArgs vm_args;
vm_args.version = JNI_VERSION_1_6;
vm_args.options = options;
vm_args.nOptions = 3;
res = JNI_CreateJavaVM (&jvm, (void **)&env, &vm_args);
if(res < 0 || !env)
printf("\nUnable to Launch JVM\n");
else
printf("**JVM launched successfully**\n");
cls = ( * env) -> FindClass(env, "HiveJdbcClient2");
printf("**cls**:\n",cls);
if (cls!=NULL)
printf("**HiveJdbcClient2 find success**\n");
else
printf("**Something happend with FindClass\n");
mid = (* env) -> GetStaticMethodID (env,cls, "main", "([Ljava/lang/String;)V");
if (mid!=0)
{
printf("**GetStaticMethodID success -test worked**\n");
(* env) -> CallStaticVoidMethod (env, cls, mid, NULL);
}
(* jvm) -> DestroyJavaVM (jvm);
return 0;
}
When I run just the java program, then the jdbc connection seems to to work. However, when invoked through the C program, the execution stops at DriverManager.getConnection() without any error messages or warning. I've checked that the hiverserver2 is running. Are there any additional configurations that need to be done like in hive-site.xml? I'm using cloudera CDH virtualbox so have not performed any additional configurations. I've seen a couple of similar queries and resolutions on this site but nothing has worked for me....
I resolved the issue by catching exceptions in the JNI calls. By way, the issue was missing classes which I corrected in -D.Java.path.
I am using a Postgresql database in my rails application.
To store large file or data in database I have used blob data type in MySql.
For Postgres which data type I have to use instead of blob in MySql?
use bytea (or Large Objects if you absolutely have to)
I think this is the most comprehensive answer on the PostgreSQL wiki itself: https://wiki.postgresql.org/wiki/BinaryFilesInDB
Read the part with the title 'What is the best way to store the files in the Database?'
Storing files in your database will lead to a huge database size. You may not like that, for development, testing, backups, etc.
Instead, you'd use FileStream (SQL-Server) or BFILE (Oracle).
There is no default-implementation of BFILE/FileStream in Postgres, but you can add it:
https://github.com/darold/external_file
And further information (in french) can be obtained here:
http://blog.dalibo.com/2015/01/26/Extension_BFILE_pour_PostgreSQL.html
To answer the acual question:
Apart from bytea, for really large files, you can use LOBS:
// http://stackoverflow.com/questions/14509747/inserting-large-object-into-postgresql-returns-53200-out-of-memory-error
// https://github.com/npgsql/Npgsql/wiki/User-Manual
public int InsertLargeObject()
{
int noid;
byte[] BinaryData = new byte[123];
// Npgsql.NpgsqlCommand cmd ;
// long lng = cmd.LastInsertedOID;
using (Npgsql.NpgsqlConnection connection = new Npgsql.NpgsqlConnection(GetConnectionString()))
{
using (Npgsql.NpgsqlTransaction transaction = connection.BeginTransaction())
{
try
{
NpgsqlTypes.LargeObjectManager manager = new NpgsqlTypes.LargeObjectManager(connection);
noid = manager.Create(NpgsqlTypes.LargeObjectManager.READWRITE);
NpgsqlTypes.LargeObject lo = manager.Open(noid, NpgsqlTypes.LargeObjectManager.READWRITE);
// lo.Write(BinaryData);
int i = 0;
do
{
int length = 1000;
if (i + length > BinaryData.Length)
length = BinaryData.Length - i;
byte[] chunk = new byte[length];
System.Array.Copy(BinaryData, i, chunk, 0, length);
lo.Write(chunk, 0, length);
i += length;
} while (i < BinaryData.Length);
lo.Close();
transaction.Commit();
} // End Try
catch
{
transaction.Rollback();
throw;
} // End Catch
return noid;
} // End Using transaction
} // End using connection
} // End Function InsertLargeObject
public System.Drawing.Image GetLargeDrawing(int idOfOID)
{
System.Drawing.Image img;
using (Npgsql.NpgsqlConnection connection = new Npgsql.NpgsqlConnection(GetConnectionString()))
{
lock (connection)
{
if (connection.State != System.Data.ConnectionState.Open)
connection.Open();
using (Npgsql.NpgsqlTransaction trans = connection.BeginTransaction())
{
NpgsqlTypes.LargeObjectManager lbm = new NpgsqlTypes.LargeObjectManager(connection);
NpgsqlTypes.LargeObject lo = lbm.Open(takeOID(idOfOID), NpgsqlTypes.LargeObjectManager.READWRITE); //take picture oid from metod takeOID
byte[] buffer = new byte[32768];
using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
{
int read;
while ((read = lo.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
} // Whend
img = System.Drawing.Image.FromStream(ms);
} // End Using ms
lo.Close();
trans.Commit();
if (connection.State != System.Data.ConnectionState.Closed)
connection.Close();
} // End Using trans
} // End lock connection
} // End Using connection
return img;
} // End Function GetLargeDrawing
public void DeleteLargeObject(int noid)
{
using (Npgsql.NpgsqlConnection connection = new Npgsql.NpgsqlConnection(GetConnectionString()))
{
if (connection.State != System.Data.ConnectionState.Open)
connection.Open();
using (Npgsql.NpgsqlTransaction trans = connection.BeginTransaction())
{
NpgsqlTypes.LargeObjectManager lbm = new NpgsqlTypes.LargeObjectManager(connection);
lbm.Delete(noid);
trans.Commit();
if (connection.State != System.Data.ConnectionState.Closed)
connection.Close();
} // End Using trans
} // End Using connection
} // End Sub DeleteLargeObject