Get h2 compatibility mode of current connection - h2

In H2 I can set the compatibility mode for a connection:
SET MODE DB2;
Is there a way to query the mode like:
GET MODE;
For the current schema I can do select schema() but select mode() will not work. Any suggestions?

With H2 1.*.* use
SELECT `VALUE` FROM INFORMATION_SCHEMA.SETTINGS WHERE NAME = 'MODE';
With H2 2.*.* use
SELECT SETTING_VALUE FROM INFORMATION_SCHEMA.SETTINGS WHERE SETTING_NAME = 'MODE';
Use upper-case names of tables and columns in these queries for more safety, H2 has really weird settings for case conversion and sensitivity and some applications may enable them.
If old information schema was enabled in H2 2.*.* with a special setting or because old driver was used for remote connection to a new server, use variant for H2 1.*.*.

Related

How can I find which compatibility mode an H2 database is in?

I know I can set a compatibility mode via SQL in H2, eg.
SET MODE ORACLE
Is there corresponding SQL to query which mode the database is currently in?
You can do:
SELECT VALUE FROM INFORMATION_SCHEMA.SETTINGS WHERE NAME = 'MODE';
Then make a case insensitive comparison to the different modes.

rawToHex(sys_guid()) usage in h2 in memory with oracle mode

I'm trying to write some tests for my java application and my entity persistence uses oracle's sys_guid() for primary key.
Everything works fine when connected to oracle, but when I use H2 in memory for my testing, the following statement used to generate the primary guid value as a char(32) returns a much bigger string (144).
select rawtohex(sys_guid()) from dual
Is there an extra configuration to correctly setup oracle mode or is this somehow a bug
I'm using springboot with spring-data and hibernate to handle database comunication, here is a sample method that generates the guid.
#Repository
public interface TokenRecuperacaoSenhaRepository extends ExtendedSpringRepo<TokenRecuperacaoSenha, String>
{
#Query(value = "select rawtohex(sys_guid()) from dual", nativeQuery = true)
public String genereateToken();
}
When connected to Oracle, returns "8E0FFC48082AB39FE0539BD3E10AC537"
While with H2, returns "00660032003300620037003000360065002d0031006400630066002d0034003700620030002d0039003400360066002d006100620065003400320034006400360030006300360038"
I'm guessing there is some conversion issue with the functions used.
Both SYS_GUID() and RAWTOHEX() functions are non-standard and aren't fully compatible between Oracle and H2.
This incompatibility was fixed in Oracle compatibility mode of H2, so if you can build H2 from its current sources you will be able to use these functions in this compatibility mode.
You can get the sources from the GitHub:
https://github.com/h2database/h2database
Building instructions are here:
https://h2database.com/html/build.html#building
You need the jar target.
Don't forget to set the compatibility mode by appending ;MODE=Oracle to your connection URL or by using SET MODE Oracle; command.
If you cannot use an own build of H2 you need an alternative method for H2 that will use something like SELECT CAST(CAST(UUID() AS BINARY) AS VARCHAR)

set locale on Oracle connection

In my company's product, we retrieve results a page at a time from the database. Because of this all filtering and sorting must be done on the database. One of the problems is coded values. For filtering and sorting to work properly, the code values need to be translated to locale specific labels in the query.
My plan is to use a table similar to the following:
t_code_to_label (
type varchar2(10),
locale varchar2(10),
code varchar2(10),
label varchar2(50)
)
The first three columns are the primary (unique) key.
When using this table, you would see something like this
select ent.name, ent.ent_type, entlabel.label as ent_type_label
from t_entitlements ent
join t_code_to_label entlabel on entlabel.type='entlabel' and entlabel.locale=currentLocale() and entlabel.code=ent.ent_type
The problem is that currentLocale() is something that I made up. How can I on the Java side of a JDBC connection do something to set the locale for the Connection object that I have that I can read on the Oracle side in a simple function. Ideally this is true locale support by Oracle but I can't find such a thing.
I am using Oracle 10g and 11g.
Are you talking about the NLS_LANGUAGE setting of the Oracle database? Would you (from the client side) like to dictate the usage of a particular NLS_LANGUAGE by Oracle database?
Then maybe this would work: Set Oracle NLS_LANGUAGE from java in a webapp
If you want an "all american" session you could do you could do something like:
ALTER SESSION SET NLS_LANGUAGE= 'AMERICAN' NLS_TERRITORY= 'AMERICA'
NLS_CURRENCY= '$' NLS_ISO_CURRENCY= 'AMERICA'
NLS_NUMERIC_CHARACTERS= '.,' NLS_CALENDAR= 'GREGORIAN'
NLS_DATE_FORMAT= 'DD-MON-RR' NLS_DATE_LANGUAGE= 'AMERICAN'
NLS_SORT= 'BINARY'

Default Schema in Oracle Connection URL

I'd like to set default database schema in Oracle Connection URL
jdbc:oracle:thin:#<server>:<port1521>:<sid>
My sample SQL statement:
select monkey_name from animals.monkey
I need to query database without schema prefix animals. i.e. when I run this statement
select monkey_name from monkey
it will use animals schema by default.
What do I need to specify in connection URL above get such effect?
Thanks.
You can't put anything in the connection URL.
In Oracle each user has their own schema (even if doesn't contain any objects) and that is their default schema. Once logged in/connected, they can change their default schema with an
ALTER SESSION SET CURRENT_SCHEMA=animals
So you'd need to do the extra statement after connecting.
It is possible to have a logon trigger on the user and/or database that will run this when they log in. I'd personally prefer an explicit statement when an application connects.
If you use C3PO you can make it do it when it checks the connection out.
As properties:
c3p0.preferredTestQuery=alter session set current_schema=animals
c3p0.testConnectionOnCheckout=true
As Java code:
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setPreferredTestQuery("alter session set current_schema=animals");
dataSource.setTestConnectionOnCheckout(true);
Downside is this will happen every time the connection is taken out of the pool.
If you are using a JDBC connection yourself you could just do:
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection connection = getConnection("jdbc:oracle:thin:#//server:1521/instance", "username", "password");
connection.createStatement().execute("alter session set current_schema=animals"));
What about the use of synonyms?
create synonym monkey for animals.monkey;
select monkey_name from monkey
You can create a trigger using connection DB user to change the current schema.
create or replace trigger SET_SCHEMA_AFTER_LOGON
after logon on database
begin
execute immediate 'alter session set CURRENT_SCHEMA=animals';
end SET_SCHEMA_AFTER_LOGON;
Since Java 1.7 there is a setSchema method on java.sql.Connection.
In the Oracle's oracle.jdbc.driver.PhysicalConnection implementation this method execute the alter session set current_schema = ? statement.

Change Oracle JDBC Thin Client Identifier

When connecting to Oracle the JDBC driver identifies itself as "JDBC Thin Client" to Oracle (in v$session as the 'program'). There is also a 'ClientInfo' column in v$session that might be used for this, but it's always empty.
We have a need to identify different applications connecting to Oracle (which are running on the same host, so the 'machine' column in v$session is all the same), so is it possible to change how the Oracle JDBC Thin Client driver identifies itself (so we could put the application name in, for example)?
Or is there a recommended way to do this? One restriction is that we're doing this within Struts for some of the applications, which is handling the connection setup internally.
[Identical to this answer]
java.util.Properties props = new java.util.Properties();
props.setProperty("password","mypassword");
props.setProperty("user","myusername");
props.put("v$session.osuser", System.getProperty("user.name").toString());
props.put("v$session.machine", InetAddress.getLocalHost().getCanonicalHostName());
props.put("v$session.program", "My Program Name");
DriverManager.registerDriver (new oracle.jdbc.OracleDriver());
Connection conn=
DriverManager.getConnection("jdbc:oracle:thin:#myhostname:1521:mysid", props);
SQL>select username,osuser,program,machine
from v$session
where username = 'ROB';
USERNAME OSUSER PROGRAM MACHINE
--------- ----------- ------------------ -----------
ROB rmerkw My Program Name machine
At application level you can use the following methods to set client_info, module and action in v$session:
dbms_application_info.set_client_info
dbms_application_info.set_module
dbms_application_info.set_action
There is also an Oracle function:
dbms_application_info.set_client_info('Client Info');
which sets the ClientInfo column in v$session.

Resources