I'm working on a spring boot application where we are using liquibase to keep up to date the DB.
We have a scenario when we import some JSON data, which is kept as varchar into a table on SQL Server. This JSON contains UI configurations and sometimes the developers forget to check if the JSON is valid before importing the data, resulting on errors in UI because of invalid JSON.
In order to prevent this kind of errors we added a constraint on DB level to make sure the data contains only valid JSON, but when we run the application,
using an invalid JSON, there is no crash or errors logged - SQL error is silently ignored.
My liquibase changeset:
<changeSet author="my.name" id="02_my_script" runOnChange="true" failOnError="true" >
<sqlFile dbms="h2, oracle, mssql" encoding="utf8"
endDelimiter="\nGO"
path="classpath:sql/02_my_script.sql"
relativeToChangelogFile="false" splitStatements="true" stripComments="true"/>
02_my_script.sql - contains a sql script which contains a JSON, something like this (I cannot use the real json):
DELETE FROM My_Table WHERE ID = 1;
INSERT INTO My_Table (Json)
VALUES ('{
"name" : "Test"
"firstName" : "ABC"
}');
The constraint on My_Table:
ALTER TABLE My_Table ADD CONSTRAINT Chk_JSON_is_json CHECK (ISJSON(Json) > 0)
If I try to run the script directly on the DB then I get an error as expected.
Is there a setting we can use in order to make liquibase show an error when there is a constraint violation ? Or maybe a configuration just to log the error in a log file?
Liquibase version I use is 3.5.3
There is a bug reported in Liquibase Jira related to this behavior.
I did a little bit of debug in Liquibase source code and I found in JdbcExecutor.ExecuteStatementCallback#doInStatement method a call
stmt.execute(statement); and according to the java doc
Executes the given SQL statement, which may return multiple results.
In some (uncommon) situations, a single SQL statement may return
multiple result sets and/or update counts. Normally you can ignore
this unless you are (1) executing a stored procedure that you know may
return multiple results or (2) you are dynamically executing an
unknown SQL string. The execute method executes an SQL statement and
indicates the form of the first result. You must then use the methods
getResultSet or getUpdateCount to retrieve the result, and
getMoreResults to move to any subsequent result(s).
I think I was in the second case ("executing an unknown SQL string"), and the the exception was not thrown. When I called getMoreResults method from the debugger the exception was thrown.
I was able to workaround the problem by creating a custom liquibase extension where I validated the json using jackson library.
Related
I am using Liquibase v3.9 with PostgreSQL v11 for the first time.
When testing out my changelog for the very first time I run updateSQL to see the output of the SQL that will be run against the database. I get this error:
Unexpected error running Liquibase: liquibase.exception.DatabaseException: org.postgresql.util.PSQLException: The database returned ROLLBACK, so the transaction cannot be committed. Transaction failure cause is <<ERROR: relation "public.databasechangeloglock" does not exist
Position: 22>>
For more information, please use the --logLevel flag
This happens because updateSQL is expecting databasechangelog table to exist, and if this is the first time you are running Liquibase against the database then those tables won't exist yet (they get created the first time you run liquibase update).
I do think this is a valid use case for running updateSQL, you can request this feature here:
https://github.com/liquibase/liquibase/issues
relation "public.databasechangeloglock" does not exist
I was with this issue using PostgreSQL in a container.
Then I realized the memory limit given to PostgreSQL was insufficient.
After Increasing PostgreSQL limit memory to 512MiB the problem was solved.
Running following statement in DB2 CLP (Command Window)
db2 "truncate table MYSCHEMA.TABLEA immediate"
DB21034E The command was processed as an SQL statement because it was not a
valid Command Line Processor command. During SQL processing it returned:
SQL0969N There is no message text corresponding to SQL error "-20356" in the
message file on this workstation. The error was returned from module
"SQLNQBE2" with original tokens "MYSCHEMA.TABLEA".
Can some please tell me what I'm doing wrong or what I'm missing? I'm trying to simply truncate from a single table and I'm getting the following error message. Not sure what I'm doing wrong. I've tried it with/without quotes, with/without schema, with/without immediate. I've also tried in Command Editor (remove db2 and quotes) and still not working. I'm using:
DB2/AIX64 9.7.9
Also, I have delete privilege as I am able to delete records but I want to truncate.
Thanks in advance!
The version of the DB2 client you're using doesn't seem to match that of the server, this is why you cannot see the actual error message for SQLCODE -20356. If you could, you'd see this:
The table MYSCHEMA.TABLEA cannot be truncated because DELETE triggers
exist for the table, or the table is the parent in a referential
constraint.
Further explanation and suggested actions can be found, as usual, in the fine manual.
ALTER TABLE MYSCHEMA.TABLEA ACTIVATE NOT LOGGED INITIALLY WITH EMPTY TABLE
or
import from /dev/null of del replace into MYSCHEMA.TABLEA
I had this problem recently too. In my case I had to do a COMMIT WORK right before TRUNCATE. This solved my problem. Please try and tell us if this helped.
I tried to update the field "contract_id" in the table "contract_scan_image".
However, the update was failed and an error "746: Field contract_id and type of contract_scan_image cannot be updated!" was shown.
My SQL command is:
update contract_scan_image
set contract_id = '14864730'
where contract_id = '1486473'
and type = 'RM'
and account = '00193400944'
Does anyone know what happened and how to fix it?
Error message -746 is for user-defined errors. It typically is used in stored procedures in a RAISE EXCEPTION statement:
RAISE EXCEPTION -746, 0, "Field contract_id and type of contract_scan_image cannot be updated!"
The actual message text for error -746 in the message files is:
%s
That is, it prints the string it is given as a string.
So, you are going to need to track down the triggers and stored procedures invoked by those triggers on the contract_scan_image table, and deduce from where the error is generated what you are doing wrong. Superficially, though, it appears that you are not allowed to alter the contract ID, yet that is what you are trying to do.
First things first, I would take a look at a list of Reserved words in SQL - https://drupal.org/node/141051
I would get in the habit of surrounding fields with `` See below:
update contract_scan_image
set `contract_id` = '14864730'
where `contract_id` = '1486473'
and `type` = 'RM'
and `account` = '00193400944'
** Note - type is a reserved word
The error is caused by something being triggered. Then no table can be modified by UPDATE command.
Finally I deleted the record I want to update. Then added back the modified record.
I copy the error description here from the net for reference.
BTW, I asked my supervisor and he said he did trigger something to cause this. (He didn't tell me how to un-trigger it...)
-746
THE SQL STATEMENT IN FUNCTION, TRIGGER, OR IN STORED PROCEDURE name VIOLATES THE NESTING SQL RESTRICTION
Explanation
If a table is being modified (by INSERT, DELETE, UPDATE, or MERGE), the table can not be accessed by the lower level nesting SQL statement.
If any table is being accessed by a SELECT statement, no table can be modified (by INSERT, DELETE, UPDATE, or MERGE) in any lower level nesting SQL statement.
System action
The SELECT, INSERT, DELETE, UPDATE or MERGE SQL statement failed.
Programmer response
Remove the failing statement from the named function, trigger or the stored procedure.
SQLSTATE
57053
I would like the following SQL query to be executed in a migration file after adding a column (updating the new field with existing column value from the same row)
UPDATE users SET last_login=updated_at;
The SQL statements work properly when executed on the database, but in rails I tried multiple syntax using the ActiveRecord update_all method but without success
User.update_all("last_login=updated_at")
I get the following error
ActiveRecord::StatementInvalid: PGError: ERROR: current transaction is aborted, commands ignored until end of transaction block
: UPDATE "users" SET last_login=updated_at
Obviously something is missing in my syntax, but can't figure out what.
Can anyone point me to the right syntax?
Regards/J.
Syntax is indeed correct, the issue was relying in the fact that I had to rollback the previous transaction.
User.update_all("last_login=updated_at")
This statement works properly.
Can the dbms_errlog function be used for SELECT queries?
I earlier encountered an error where Oracle is throwing an ORA-0722, i was trying to identify which column and possibly, row of a PL/SQL statement that was throwing that error. However i found out that dbms_errlog is native to only Oracle 10g and above.
In the case also, what alternatives do i have if i am using Oracle 9i?
DBMS_ERRLOG ist not a function, it is a PL/SQL package. It contains one procedure that creates an error table. To log errors to this error, you need to specify the "log errors" clause to your DML statements. From this description it should be obvious that this is tightly integrated with the transaction layer.
One way to reproduce similar behavior in earlier releases is to
Create your own error table
Create a PL/SQL procedure that inserts into that error table. To
make sure that the log is written in case of errors this procedure has to use
autonomous transactions.
The calls to log errors have to be explicitly added to the
corresponding exception handlers.