ODBC-JDBC Bridge Windows-1251 (Cyrillic) character encoding - jdbc

I've got a dbase file with window 1251 encoding. I've made an ODBC datasource for this file and I would like to access it with JDBC-ODBC bridge from java with the following code:
PrintStream ps = new PrintStream(System.out, true, "UTF-8");
System.out.println("TEST: Русский язык");
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Properties properties = new Properties();
properties.put("charSet", "windows-1251");
Connection conn = DriverManager.getConnection( "jdbc:odbc:test_ds",properties);
Statement statement = conn.createStatement();
String sql = "SELECT * FROM table";
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()) {
System.out.println(resultSet.getString("DESC"));
}
Character encoding is OK for test println (2nd line), but encoding for data from dbase is incorrect.
I'm able to open dbf file with LibreOffice with the same encoding where everything is correct.
Is there any chance to set encoding correctly?
Is it possible to set connection encoding in the connection string?
EDIT: After further investigation, I think the problem is ODBC related. I tried to open the defined datasource with Excel and the encoding was wrong. (I had no chance to set encoding either for odbc connection, neither for Excel connection)

This works for me on cyrillic characters:
properties.put("charSet", "Cp1251");

Related

H2 show value of DB_CLOSE DELAY (set by SET DB_CLOSE_DELAY)

The H2 Database has a list of commands starting with SET, in particular SET DB_CLOSE_DELAY. I would like to find out what the value of DB_CLOSE_DELAY is. I am using JDBC. Setting is easy
cx.createStatement.execute("SET DB_CLOSE_DELAY 0")
but none of the following returns the actual value of DB_CLOSE_DELAY:
cx.createStatement.executeQuery("DB_CLOSE_DELAY")
cx.createStatement.executeQuery("VALUES(#DB_CLOSE_DELAY)")
cx.createStatement.executeQuery("GET DB_CLOSE_DELAY")
cx.createStatement.executeQuery("SHOW DB_CLOSE_DELAY")
Help would be greatly appreciated.
You can access this and other settings in the INFORMATION_SCHEMA.SETTINGS table - for example:
String url = "jdbc:h2:mem:;DB_CLOSE_DELAY=3";
Connection conn = DriverManager.getConnection(url, "sa", "the password goes here");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM INFORMATION_SCHEMA.SETTINGS where name = 'DB_CLOSE_DELAY'");
while (rs.next()) {
System.out.println(rs.getString("name"));
System.out.println(rs.getString("value"));
}
In this test, I use an unnamed in-memory database, and I explicitly set the delay to 3 seconds when I create the DB.
The output from the print statements is:
DB_CLOSE_DELAY
3

How to read a COMPRESS()-ed H2 blob column via JDBC?

I have a file-based H2 database (engine version 1.4.196) with a mediumblob column containing data returned by the COMPRESS() function:
create table foo (compressed_data mediumblob);
...
insert into foo (compressed_data) values (COMPRESS(STRINGTOUTF8('Test'), 'DEFLATE'));
(The table is created and filled by flyway.)
I'd like to read this data in a JDBC client without calling DECOMPRESS() first. (I want to do the decompression client-side for compatibility with another system). I've tried to read the data via an InflaterInputStream, which can uncompress DEFLATE data:
try (InputStream dbStream = rs.getBinaryStream("compressed_data");
InflaterInputStream inflaterStream = new InflaterInputStream(dbStream);
) {
inflaterStream.read();
...
But this causes an error:
java.util.zip.ZipException: incorrect header check
at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:164)
...
Is there any way I can get InflaterInputStream-compatible compressed data from a column in H2?
Since you are already using H2 JDBC to access the database you can simply retrieve the compressed data with getBytes and use the expand method of org.h2.tools.CompressTool to uncompress it:
// .java source file is Cp1252 encoded
String sql = "SELECT COMPRESS(STRINGTOUTF8('fermé'), 'DEFLATE') AS foo";
ResultSet rs = st.executeQuery(sql);
rs.next();
byte[] bytesOut = rs.getBytes(1);
byte[] expanded = org.h2.tools.CompressTool.getInstance().expand(bytesOut);
String strOut = new String(expanded, "UTF-8");

.NET Core 2 + System.Data.OracleClient. Chinese characters doesn't work

I'm using .NET Core 2 with the System.Data.OracleClient package published some weeks ago here: https://www.nuget.org/packages/System.Data.OracleClient/
I can read numbers, dates and normal English characters. But not Chinese. Probably a lot of other non-western characters.
Here's a sample program to illustrate the error:
using System;
using System.Text;
using System.Diagnostics;
using System.IO;
using System.Data.OracleClient;
namespace OracleConnector
{
class Program
{
static void Main()
{
TestString();
return;
}
private static void TestString()
{
string connStr = "Data Source = XE; User ID = testuser; Password = secret";
using (OracleConnection conn = new OracleConnection(connStr))
{
conn.Open();
var cmd = conn.CreateCommand();
cmd.CommandText = "select 'some text in English language' as a, '储物组合带门/抽屉, 白色 卡维肯, 因维肯 白蜡木贴面' as b from dual";
var reader = cmd.ExecuteReader();
reader.Read();
string sEnglish = reader.GetString(0);
string sChinese = reader.GetString(1);
Trace.WriteLine("English from db: " + sEnglish);
Trace.WriteLine("Chinese from db: " + sChinese);
Trace.WriteLine("Chinese from the code: 储物组合带门 / 抽屉, 白色 卡维肯, 因维肯 白蜡木贴面");
}
}
}
}
It outputs this:
English from db: some text in English languageဂ
Chinese from db: ¿¿¿¿¿¿/¿¿, ¿¿ ¿¿¿, ¿¿¿ ¿¿¿¿¿e
Chinese from the code: 储物组合带门 / 抽屉, 白色 卡维肯, 因维肯 白蜡木贴面
As you can see, Chinese characters from normal code works. But not when it comes from the database. Also, the last character in the English text is some messed up thing. I've also tried the corresponding Mono nuget package with the same result.
Anyone have any clue how to fix this?
Edit: Tried adding Unicode=True to the connection string but Chinese characters still doesn't work.
This is a problem with the System.Data.OracleClient DLL. I am having the same problem where 2, 3, or even 4-byte Unicode characters are getting tacked to the end of my strings.
Switching to Mono.Data.OracleClientCore helped slightly, but I still got some odd characters at the end of some strings (Unicode backspace and backslash).
I just tried the following library, and it seems to work for my needs (so far):
https://github.com/ericmend/oracleClientCore-2.0
You will need to re-compile for Windows (change to #define OCI_WINDOWS in OciCalls.cs). Will update this answer if I find that it doesn't continue to work.
Still, I think that we'll have to wait for Oracle to release their .NET Core supported solution for any sort of production ready library.
Please try
Environment.SetEnvironmentVariable ("NLS_LANG",".UTF8");
before creation of the connection-Object.
The System.Data.OracleClient-Implementations uses external Oracle libraries, which assumes (at least on Windows) the ANSI-Charset.
Setting the NLS_LANG-Environmentvariable informs the Oracle-Libs that you want the UTF8-Encoding.
(much) more Details on the NLS_LANG-FAQ-Page:
http://www.oracle.com/technetwork/database/database-technologies/globalization/nls-lang-099431.html
Append ";Unicode=True" to connectionstring and add Environment.SetEnvironmentVariable ("NLS_LANG",".UTF8"); before create connection
string conn = "DATA SOURCE=hostname.company.org:1521/servicename.company.org;PASSWORD=XYZ;USER ID=ABC;Unicode=True"
Environment.SetEnvironmentVariable("NLS_LANG", ".UTF8");
using (DbConnection conn = create_connection(app_conn))
{
//...
}

db2 Invalid parameter: Unknown column name SERVER_POOL_NAME . ERRORCODE=-4460, SQLSTATE=null

I am using SQL 'select' to access a db2 table with schemaname.tablename as follows:
select 'colname' from schemaname.tablename
The tablename has 'colname' = SERVER_POOL_NAME for sure . yet I get the following error :
"Invalid parameter: Unknown column name SERVER_POOL_NAME . ERRORCODE=-4460, SQLSTATE=null"
I am using db2 v10.1 FP0 jdbc driver version 3.63.123. JDBC 3.0 spec
The application is run as db2 administrator and also Windows 2008 admin
I saw a discussion about this issue at : db2jcc4.jar Invalid parameter: Unknown column name
But i do not know where the connection parameter 'useJDBC4ColumnNameAndLabelSemantics should be set ( to value =2)
I saw the parameter should appear in com.ibm.db2.jcc.DB2BaseDataSource ( see: http://publib.boulder.ibm.com/infocenter/db2luw/v9r5/index.jsp?topic=%2Fcom.ibm.db2.luw.apdv.java.doc%2Fsrc%2Ftpc%2Fimjcc_r0052607.html)
But i do not find this file on my DB2 installation . maybe it is packed in a .jar file
Any advice ?
There is a link on the page you're referring to, showing you the ways to set properties. Specifically, you can populate a Properties object with desired values and supply it to the getConnection() call:
String url = "jdbc:db2://host:50000/yourdb";
Properties props = new Properties();
props.setProperty("useJDBC4ColumnNameAndLabelSemantics", "2");
// set other required properties
Connection c = DriverManager.getConnection(url, props);
Alternatively, you can embed property name/value pairs in the JDBC URL itself:
String url = "jdbc:db2://host:50000/yourdb:useJDBC4ColumnNameAndLabelSemantics=2;";
// set other required properties
Connection c = DriverManager.getConnection(url);
Note that each name/value pair must be terminated by a semicolon, even the last one.

Firebird connection to remote server using FbConnectionStringBuilder

We're having trouble connecting to a remote Firebird server using the .NET provider FbConnectionStringBuilder class. We can connect to a local database file in either embedded or server mode however when it comes to establishing a connection to a remote server we can't establish the connection.
We assign properties of the FbConnectionStringBuilder class with the following code (server mode). I have omitted the code which assigns properties for embedded mode.
var cs = new FbConnectionStringBuilder
{
Database = databaseSessionInfo.PathAbsoluteToDatabase,
Charset = "UTF8",
Dialect = 3,
};
cs.DataSource = databaseSessionInfo.Hostname;
cs.Port = databaseSessionInfo.Port;
cs.ServerType = (FbServerType)databaseSessionInfo.Mode;
cs.Pooling = true;
cs.ConnectionLifeTime = 30;
if (databaseSessionInfo.UseCustomUserAccount)
{
cs.UserID = databaseSessionInfo.Username;
cs.Password = databaseSessionInfo.Password;
}
else
{
cs.UserID = Constants.DB_DefaultUsername;
cs.Password = Constants.DB_DefaultPassword;
}
Pretty straightforward. Our software contains a connection configuration screen whereby a user can supply different connection properties. These properties get assigned to the FbConnectionStringBuilder class using the code above.
The connection builder class outputs a connection string in the following format:
initial catalog="P:\Source\database.fdb";character set=UTF8;dialect=3;data source=localhost;port number=3050;server type=Default;pooling=True;connection lifetime=30;user id=USER;password=example
However literature on Firebird connection strings as indicated on this page (Firebird Connection Strings) talk of a different structure. I can only assume the FbConnectionStringBuilder class builds a Firebird connection string satisfying the requirements of Firebird.
Does the FbConnectionStringBuilder class append the hostname to the connection string correctly?
The Firebird server is running on the server. I assume there is no need to install it on the client?
What libraries need to be installed with the client to support a remote server connection?
Are we doing this right?
Any advice is appreciated.
Answering your questions:
1) Yes it will.
2) Correct, the client library will connect over the network.
3) If you use the ADO library, just FirebirdSql.Data.FirebirdClient.dll
4) Maybe, I dont know if this will help but this is how I connect.
FbConnectionStringBuilder ret = new FbConnectionStringBuilder();
ret.DataSource = Host;
ret.Port = Port;
ret.Database = Database;
ret.UserID = User;
ret.Password = Password;
ret.Charset = CharacterSet;
FbConnection ret = new FbConnection(connectionString);
Interestingly, what is the absolute path you are providing to the StringBuilder ? Is it the server absolute path, or some kind of network mapped drive?
Also, I assume you've reviewed firewall settings and allowing port 3050 inbound.

Resources