How to get Oracle next sequence value in liqiibase 1.9.5 for insert - oracle

How to get Oracle next sequence value in liqiibase 1.9.5 for insert
<changeSet author="MIGRATE" id="070214010049877">
<insert tableName="MYTABLE">
<column name="ID" valueNumeric=" nextval( 'MYTABLE_SEQ' ) "/>
<column name="NUMBER" value="5"/>
</insert>
</changeSet>
it is trying to put the value of ID " nextval( 'MYTABLE_SEQ' )" in table so it gives error

With Liquibase 1.9.5, there is no support for finding the next sequence value with the <insert> tag. You will have to either drop back to using <sql> or use <modifySql> assuming that existed in 1.9.5.

Related

Liquibase with column type numeric(x, y) is creating postgreSQL table with column type number

I have a spring application connected to a postgreSQL DB. My issue is that this bit of script:
<column name="utmx" type="numeric(20, 5)">
<constraints nullable="true"/>
</column>
<column name="utmy" type="numeric(20, 5)">
<constraints nullable="true"/>
</column>
Is being executed like this:
CREATE TABLE PUBLIC.table (... utmx NUMBER(20, 5), utmy NUMBER(20, 5)...
As you can see, the column type NUMERIC is being changed to NUMBER on table creation.
Why is that? How can I solve it?
Thanks in advance

Liquibase ignores autoIncrement="true" for Oracle DB

I generated a schema/tables via the DDL that Hibernate generated which was correct:
create table cat_component.organisation (
id number(19,0) generated as identity,
archived number(1,0),
is_in_avaloq_group number(1,0) not null,
mdm_uuid varchar2(255 char),
name varchar2(255 char),
primary key (id)
)
After that, I tried to generate Liquibase changelog which looks like this:
<changeSet author="blabla (generated)" id="1582733383680-5">
<createTable tableName="organisation">
<column autoIncrement="true" name="id" type="NUMBER(19, 0)">
<constraints primaryKey="true" primaryKeyName="organisationPK"/>
</column>
<column name="archived" type="NUMBER(1, 0)"/>
<column name="is_in_avaloq_group" type="NUMBER(1, 0)">
<constraints nullable="false"/>
</column>
<column name="mdm_uuid" type="VARCHAR2(255 CHAR)"/>
<column name="name" type="VARCHAR2(255 CHAR)"/>
</createTable>
</changeSet>
The problem is that if I try to run the liquibase changelog, it translates the XML definition into this:
2020-02-26 16:15:10.779 INFO 8064 --- [main] liquibase.executor.jvm.JdbcExecutor : CREATE TABLE CAT_COMPONENT.organisation (id NUMBER(19, 0) NOT NULL, archived NUMBER(1, 0), is_in_avaloq_group NUMBER(1, 0) NOT NULL, mdm_uuid VARCHAR2(255 CHAR), name VARCHAR2(255 CHAR), CONSTRAINT organisationPK PRIMARY KEY (id))
2020-02-26 16:15:10.787 INFO 8064 --- [main] liquibase.changelog.ChangeSet : Table organisation created
2020-02-26 16:15:10.787 INFO 8064 --- [main] liquibase.changelog.ChangeSet : ChangeSet classpath:/db/changelog/db.changelog-master.xml::1582733383680-5::blabla (generated) ran successfully in 9ms
As you may have noticed, "generated as identity" is missing, which
makes me believe that for whatever reason, the autoIncrement="true"
is ignored.
I use Oracle 12.1.0.2 and org.liquibase:liquibase-core 3.8.2.
The OJDBC driver is version 19.3.0.0.
The gradle properties are:
spring.datasource.url=jdbc:oracle:thin:#//host:1522/SID
spring.datasource.driverClassName=oracle.jdbc.OracleDriver
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.datasource.username=user
spring.datasource.password=pass
spring.jpa.database-platform=org.hibernate.dialect.Oracle12cDialect
spring.jpa.show-sql=true
logging.level.org.hibernate.SQL=debug
logging.level.org.hibernate.type=trace
spring.datasource.continue-on-error=true
spring.datasource.platform=oracle
spring.liquibase.url=${spring.datasource.url}
spring.liquibase.user=${spring.datasource.username}
spring.liquibase.password=${spring.datasource.password}
spring.liquibase.url=${spring.datasource.url}
spring.liquibase.user=${spring.datasource.username}
spring.liquibase.password=${spring.datasource.password}
spring.liquibase.change-log=classpath:/db/changelog/db.changelog-master.xml
spring.liquibase.default-schema=${spring.jpa.properties.hibernate.default_schema}
spring.liquibase.liquibase-schema=${spring.jpa.properties.hibernate.default_schema}
I've read the Internet, and I know that my Oracle version is compatible with this column type and I don't need to create extra oracle Sequences.
Any clue what could be the problem?
It seems to be a bug in Liquibase. I just found it here https://liquibase.jira.com/projects/CORE/issues/CORE-3524?filter=allissues&orderby=updated%20DESC&keyword=Oracle
As it states, there is a work-around to add the
generationType="BY DEFAULT"
at each column definition, where autoIncrement="true" has been used.
Correct the autoIncrement="true" is ignored due to the missing support on Oracle side for auto incremented columns as seen in the docs from liquienter link description here:
Is column an auto-increment column. Ignored on databases that do not
support autoincrement/identity functionality.
You will need to create a sequence for generating the IDs and providing the sequence to the id column when inserting the data i.e. with hibernate:
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "XXX_ID_GEN")
#SequenceGenerator(name = "XXX_ID_GEN", sequenceName = "SEQ_XXX")
long id;

Parsing multiple columns from XMLTYPE

I want to select data from a XML file using Oracle SQL.
Here is my XML file:
<worksheet>
<sheetData>
<row>
<column>
<value>0</value>
</column>
<column>
<value>1</value>
</column>
<column>
<value>2</value>
</column>
</row>
<row>
<column>
<value>3</value>
</column>
<column>
<value>4</value>
</column>
<column>
<value>5</value>
</column>
</row>
<row>
<column>
<value>6</value>
</column>
<column>
<value>7</value>
</column>
<column>
<value>8</value>
</column>
</row>
</sheetData>
</worksheet>
The following code is the SQL I'm using to extract the XML (minified in SQL query):
SELECT
*
FROM
XMLTABLE(
'for $i in worksheet/sheetData/row return $i'
PASSING XMLTYPE('<worksheet><sheetData><row><column><value>0</value></column><column><value>1</value></column><column><value>2</value></column></row><row><column><value>3</value></column><column><value>4</value></column><column><value>5</value></column></row><row><column><value>6</value></column><column><value>7</value></column><column><value>8</value></column></row></sheetData></worksheet>')
COLUMNS
column1 CLOB PATH 'column[1]/value',
column2 CLOB PATH 'column[2]/value'
) xml;
And this is the output:
---------------------
| COLUMN1 | COLUMN2 |
|---------|---------|
| 0 | 1 |
| 3 | 4 |
| 6 | 7 |
---------------------
You can see that the third <column> child of <row> is missing from the output but if I add column3 CLOB PATH 'column[3]/value' to the COLUMNS property, it will appear.
My problem is that the XML can have any number of <column> tags and since I don't know the count from the beginning, I can't define a fixed solution.
Can you help to tell me which modification should make my query to work for multiple <column> tags? Or which query should output a dynamic number of <column>?
Easy ways
Predefined redundant amount of columns.
SELECT
*
FROM
XMLTABLE(
'/worksheet/sheetData/row'
PASSING XMLTYPE('<worksheet><sheetData><row><column><value>0</value></column><column><value>1</value></column><column><value>2</value></column></row><row><column><value>3</value></column><column><value>4</value></column><column><value>5</value></column></row><row><column><value>6</value></column><column><value>7</value></column><column><value>8</value></column></row></sheetData></worksheet>')
COLUMNS
column_cnt number path 'count(column)',
column1 varchar2(4000) PATH 'column[1]/value',
column2 varchar2(4000) PATH 'column[2]/value',
--etc. ...
column10 varchar2(4000) path 'column[10]/value'
) xml;
Pivot the result
SELECT
row_nr,
col_nr,
col_value
FROM
XMLTABLE(
'/worksheet/sheetData/row'
PASSING XMLTYPE('<worksheet><sheetData><row><column><value>0</value></column><column><value>1</value></column><column><value>2</value></column></row><row><column><value>3</value></column><column><value>4</value></column><column><value>5</value></column></row><row><column><value>6</value></column><column><value>7</value></column><column><value>8</value></column></row></sheetData></worksheet>')
COLUMNS
columns_xml xmltype path '.',
row_nr FOR ORDINALITY
) xml
,xmltable('row/column' passing columns_xml
columns
col_nr for ordinality,
col_value varchar2(10) path './value/text()')
Hardcore approach.
Alway you can use pipelined table function.
1) Find max count of columns
2) Generate dynamic type
3) Populate dynamic type
4) Two days later enjoy the most sophisticated code written in pl sql :)
Good example of pipelline function below. This is not exactly what you need but you can build on it
Return dynamic result set from sys_refcursor

Preconditions column exists

Using liquibase 3.4.1 I want to rename my columns in Oracle to uppercase if they exist.
I always get the following error no matter what I do:
Unexpected error running Liquibase: ORA-00957: duplicate column name
[Failed SQL: ALTER TABLE "SYSTEM"."MYTABLE" RENAME COLUMN "id" TO "ID"]
My precondition looks like this:
<changeSet author="sake" id="gfdgfd" dbms="oracle" objectQuotingStrategy="QUOTE_ALL_OBJECTS">
<preConditions onFail="MARK_RAN" >
<columnExists tableName="MYTABLE" columnName="id" />
</preConditions>
<renameColumn tableName="MYTABLE" oldColumnName="id" newColumnName="ID"/>
</changeSet>
I tried following:
- removing objectQuotingStrategy
- adding SQL check:
<sqlCheck expectedResult="1">
SELECT COUNT(*) FROM USER_TAB_COLUMNS
WHERE TABLE_NAME='MYTABLE'
AND COLUMN_NAME='id'
</sqlCheck>
Any idea why this happens? :/

How can I generate response after insert query in wso2dss?

I am using wso2dss.
I just insert one row.
Table has only one field and it is not the unique and it is not a key.
I can't use the "GenerateKeys" option.
However, I need to generate response after insert query is success in the wso2dss.
I created table as below.
create table SAMPLETABLE (My_VALUE VARCHAR (100));
<data name="MyTESTSERVICE">
<config id="testconfig">
<property name="username">sa</property>
<property name="password">sa</property>
<property name="url">jdbc:h2:tcp://localhost/~/test;MODE=Oracle</property>
<property name="driverClassName">org.h2.Driver</property>
</config>
<query id="insertMyValue" useConfig="testconfig">
<sql>INSERT INTO SAMPLETABLE (My_VALUE) VALUES (:MyValue)</sql>
<param name="MyValue" sqlType="STRING"/>
</query>
<operation name="insertOP">
<call-query href="insertMyValue">
<with-param name="MyValue" query-param="MyValue"/>
</call-query>
</operation>
</data>
It was working without any response.
But I need customized response after inserting is successful. How can I do?
You can try stored procedures that return value. ie you can write sp which is insert values in database and returns the status of transaction, in dss it returns that whether your query ran on DB or not.

Resources