how to insert html tag inside sql in Liquibase migration? - database

I need to update my data that have html tag inside so wrote this on liquibase
<sql> update table_something set table_content = " something <br/> in the next line " </sql>
it apparently doesn't work on liquibase ( i got loooong errors .. and meaningless). I tried to remove <br/> and it works.
my question is, is it possible to insert / update something that contains xml tag in Liquibase ?
I am using liquibase 1.9.3 with Grails 1.1.1
edited: forgot to set code sample tag in my examples.

As the liquibase author mentions here you'll need to add CDATA section inside <sql>.
In your particular example that would become:
<sql><![CDATA[ update table_something set table_content = " something <br/> in the next line " ]]></sql>

Even better not to use a <sql> tag at all (I added the where clause ...):
<changeSet author="author" id="table_something_1">
<update tableName="table_something">
<column name="table_content"><![CDATA[ something <br/> in the next line ]]></column>
<where>id=1</where>
</update>
<rollback />
</changeSet>

Related

Mule 4 dynamic queries in the Database Connector

In my flow in Mule 4 I am trying to query a database for specific data.
For example I want to run a query like this:
SELECT * FROM mulesoft WHERE plant = CCCNNB;
The thing is both plant and CCNNB need to be dynamic. They will come through an API request. I can handle the value to be dynamic, but I get empty results whenever I try to make the field dynamic.
I first create a variable which stores the json from the request:
set-variable value="#[payload]" doc:name="Set Variable" doc:id="8ed26865-d722-4fdb-9407-1f629b45d318" variableName="SORT_KEY"/>
Request looks like this:
{
"FILTER_KEY": "plant",
"FILTER_VALS": "CCNNB"
}
Afterwards in the db connector I configure the following:
<db:select doc:name="Select" doc:id="13a66f51-2a4e-4949-b383-86c43056f7a3" config-ref="Database_Config">
<db:sql><![CDATA[SELECT * FROM mulesoft WHERE :filter_key = :filter_val;]]></db:sql>
<db:input-parameters ><![CDATA[#[{
"filter_val": vars.SORT_KEY.FILTER_VALS,
"filter_key": vars.SORT_KEY.FILTER_KEY
}]]]></db:input-parameters>
Replacing :filter_key with plant works but as soon as I try to make it dynamic I get nothing in the response. It does not fail though, response code is 200 but I get nothing inside it.
How can I make this work?
You can directly use the stored variables in the query itself.
Query Should be an expression in DataWeave.
#["SELECT * FROM $(vars.table) WHERE $(vars.SORT_KEY.FILTER_KEY) = :filter_val"]
<db:select config-ref="Database_Config">
<db:sql><![CDATA[#["SELECT * FROM $(vars.table) WHERE $(vars.SORT_KEY.FILTER_KEY) = :filter_val"]]]></db:sql>
<db:input-parameters ><![CDATA[#[{
"filter_val": vars.SORT_KEY.FILTER_VALS
}]]]>
</db:input-parameters>
</db:select>
There is another way also to read values from payload to build a dynamic query as below
#["SELECT * FROM mulesoft
WHERE " ++ vars.SORT_KEY.FILTER_KEY ++ " = '" ++ vars.SORT_KEY.FILTER_VALS ++ "'"]
Below is the XML that is created for this, as a POC
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:os="http://www.mulesoft.org/schema/mule/os"
xmlns:salesforce="http://www.mulesoft.org/schema/mule/salesforce"
xmlns:db="http://www.mulesoft.org/schema/mule/db"
xmlns:xml-module="http://www.mulesoft.org/schema/mule/xml-module"
xmlns:http="http://www.mulesoft.org/schema/mule/http"
xmlns:ee="http://www.mulesoft.org/schema/mule/ee/core"
xmlns="http://www.mulesoft.org/schema/mule/core"
xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/ee/core http://www.mulesoft.org/schema/mule/ee/core/current/mule-ee.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/db http://www.mulesoft.org/schema/mule/db/current/mule-db.xsd
http://www.mulesoft.org/schema/mule/os http://www.mulesoft.org/schema/mule/os/current/mule-os.xsd">
<http:listener-config name="HTTP_Listener_config1"
doc:name="HTTP Listener config"
doc:id="6d5de64b-1355-4967-9352-4b324f02c7ad">
<http:listener-connection host="0.0.0.0"
port="8081" />
</http:listener-config>
<db:config name="Database_Config" doc:name="Database Config"
doc:id="d5c4d49c-aef3-4d4a-a7b5-470da3354127">
<db:my-sql-connection host="localhost"
port="3306" user="root" password="admin123" database="Mysql" />
</db:config>
<flow name="testFlow"
doc:id="8cfea1b0-d244-40d9-989c-e136af0d9f80" initialState="started">
<http:listener doc:name="Listener"
doc:id="265e671b-7d2f-4f3a-908c-8065a5f36a07"
config-ref="HTTP_Listener_config1" path="test" />
<set-variable value="#[payload]" doc:name="Set Variable"
doc:id="265a16c5-68d4-4217-8626-c4ab0a3e38e5" variableName="SORT_KEY" />
<db:select doc:name="Select"
doc:id="bdf4a59c-0bcc-46ac-8258-f1f1762c4e7f"
config-ref="Database_Config">
<db:sql><![CDATA[#["SELECT * FROM mulesoft.mulesoft WHERE " ++ vars.SORT_KEY.FILTER_KEY ++ " = '" ++ vars.SORT_KEY.FILTER_VALS ++ "'"]]]></db:sql>
</db:select>
<ee:transform doc:name="Transform Message"
doc:id="72cbe69f-c52e-4df9-ba5b-dd751990bc08">
<ee:message>
<ee:set-payload><![CDATA[%dw 2.0
output application/json
---
payload]]></ee:set-payload>
</ee:message>
</ee:transform>
</flow>
</mule>
Explanation of the Flow
I am using the payload that is in Question
Seting a variable name "SORT_KEY", value of this varibale is complete payload that we receive.
then creating a dynamic query inside the Db connector
using transform message sending the data as response, that we received from DataBase
So, there are several issues here. One, the creation of the sql statement.
You can do DW inside the DB:SELECT component if you want, as shown by previous answers. Either the
#["SELECT * FROM myTable" ++ vars.myWhere]
OR
#["SELECT * FROM myTable $(vars.myWhere)"]
work.
The problem you will run into is that DataSense doesn't like this. Without the literal text for the column names, DataSense can't figure out what columns to retrieve so it raises an error "Unable to resolve value for the prameter: sql". This leaves an error in your code, which always gives me angst. I wish Mulesoft would resolve this problem.
BTW, if you do dynamic SQL, you should STILL use input parameters for each value to avoid SQL injections.
I have an "Idea" posted here to fix the bogus error: https://help.mulesoft.com/s/ideas#0872T000000XbjkQAC

Magento 2 InstallSchema method not executed

On my own Magento 2 custom module, I want to install a custom database table. This is the InstallSchema class code:
<?php
namespace MyVendor\MyModule\Setup;
use Magento\Framework\Setup\InstallSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
class InstallSchema implements InstallSchemaInterface
{
/**
* #inheritdoc
*/
public function install(SchemaSetupInterface $setup, ModuleContextInterface $context)
{
$setup->startSetup();
$table = $setup->getConnection()
->newTable($setup->getTable('my_table'))
->addColumn(
'greeting_id',
\Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
null,
['identity' => true, 'unsigned' => true, 'nullable' => false, 'primary' => true],
'Greeting ID'
)
->addColumn(
'message',
\Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
255,
['nullable' => false, 'default' => ''],
'Message'
)->setComment("Greeting Message table");
$setup->getConnection()->createTable($table);
$setup->endSetup();
}
}
But the install method is not being executed.
Attached an xdebug session with breakpoints inside the function, never called.
Removed the module line in setup_module database table and re-run bin/magento setup:upgrade
Set the developer mode, disable cache, run a setup:di:compile, still fails.
Any ideas?
I've also tried to use UpdateSchema changing the module version, no luck.
I'm running Magento 2 on a Ubuntu Server virtual box. Permissions on folders are set correctly.
#wildchild great to get it working with another solution. In your question, you did not mention if you are using 2.2.* or 2.3.*, you just stated Magento 2.
I had the same issue after moved from one server to another and upgrading from 2.2 to 2.3 my custom module stop working, the PHP script not creating the table in the database.
I later found out that Magento has changed the music now you have to use declarative schema structure
The Module_Vendor/Module_Name/etc/db_schema.xml file declares a module’s database structure.
See the sample below and you should read more here
Create a table
The following example creates the declarative_table table with four columns. The id_column column is the primary key.
<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
<table name="declarative_table">
<column xsi:type="int" name="id_column" padding="10" unsigned="true" nullable="false" comment="Entity Id"/>
<column xsi:type="int" name="severity" padding="10" unsigned="true" nullable="false" comment="Severity code"/>
<column xsi:type="varchar" name="title" nullable="false" length="255" comment="Title"/>
<column xsi:type="timestamp" name="time_occurred" padding="10" comment="Time of event"/>
<constraint xsi:type="primary" referenceId="PRIMARY">
<column name="id_column"/>
</constraint>
</table>
</schema>
Then run these command // ubuntu
php bin/magento setup:upgrade && php bin/magento cache:flush && php bin/magento cache:clean
In my case the package name was wrong. After replacing by right package name issue is fixed.
namespace Package_Name\Module_Name\Setup;
Please declare and add dependencies in InstallSchema file as given below:-
namespace <Your_Package>\<Your_Module>\Setup;
use Magento\Framework\Setup\InstallSchemaInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
use Magento\Framework\Setup\ModuleContextInterface;
Then clear the cache and remove data from generated folder and remove module entry from setup_module.
Make sure that you have defined correct setup version in your module.xml file
Found the solution. It was the module name in the module.xml file. The setup:upgrade installer search for the InstallSchema in a case-sensitive folder path, so if you declare the module as
my_module
it will search on MyVendor/my/module/Setup folder.
I resolve it by replacing the name with:
MyModule
So the installer will search correctly on MyVendor/MyModule/Setup folder.
I found the problem with the "old-way", by placing log messages on the Install.php file on the Magento setup folder.

Hibernate sql exception when table empty

The following code causes an exception when the Job table has no rows.
public List<Job> getAll(int currentPage, int pageSize) {
return this.sessionFactory.getCurrentSession()
.createCriteria(Job.class).addOrder(Order.asc("id"))
.setFirstResult(currentPage * pageSize).setMaxResults(pageSize)
.setFetchSize(pageSize).list();
}
I am using SQL Server and the JTDS driver.
The error i get is
java.sql.SQLException: ResultSet may only be accessed in a forward direction.
net.sourceforge.jtds.jdbc.JtdsResultSet.checkScrollable(JtdsResultSet.java:319)
net.sourceforge.jtds.jdbc.JtdsResultSet.absolute(JtdsResultSet.java:716)
org.apache.commons.dbcp.DelegatingResultSet.absolute(DelegatingResultSet.java:335)
org.hibernate.loader.Loader.advance(Loader.java:1469)
org.hibernate.loader.Loader.getResultSet(Loader.java:1783)
org.hibernate.loader.Loader.doQuery(Loader.java:662)
org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:224)
org.hibernate.loader.Loader.doList(Loader.java:2211)
org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2095)
org.hibernate.loader.Loader.list(Loader.java:2090)
org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:95)
org.hibernate.impl.SessionImpl.list(SessionImpl.java:1569)
org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:283)
The issue is associated with trying to page an empty table.
drop these:
.setFirstResult(currentPage * pageSize).setMaxResults(pageSize)
.setFetchSize(pageSize)
and you should be able to query the empty table without issue.
If you want to page the data, run a regular query first, then page the data with your query after you know you have data to page.
Adding following property to persistence.xml solves this issue for me (jboss7, hibernate4)
<property name="hibernate.jdbc.use_scrollable_resultset" value="false" />
Alternative solution with changed dialect (not checked by me) - https://forum.hibernate.org/viewtopic.php?p=2452163
I was having this same problem, and after looking around for a while I was adviced by a coworker to change the hibernate dialect from this:
org.hibernate.dialect.SQLServerDialect
to this
org.hibernate.dialect.SQLServer2005Dialect
and it solved my problem.
Posting just as a note for people to check their dialect.

ibatis - where to place the <cacheModel> tag?

I have the map config file like this
<sqlMap ..............>
<alias>
<typeAlias ......../>
</alias>
<statements>
....
<sql>....</sql>
<select cacheModel="cache-select-all">....</select>
<update>...</update>
<procedure>...</procedure>
.....
</statements>
<parameterMaps>
<parameterMap>....</parameterMap>
</parameterMaps>
<cacheModel id="cache-select-all" type="LRU" readOnly="true" serialize="false">
<flushInterval hours="24"/>
<flushOnExecute statement="InsertIOs"/>
<!--<property name="CacheSize" value="1000"/>-->
</cacheModel>
</sqlMap>
I am using ibatis (.net, if that matters) and i have one question: where to place the tags? is There a or because placing it like i did, in the statements seems not to work. What am i doing wrong?
You must reference the cacheModel you defined inside a statement tag as shown in the following link:
http://ibatis.apache.org/docs/dotnet/datamapper/ch03s08.html
Before you use it in the select statement. Order does matter here. Otherwise sql map parser wouldn't be able to validate your sql map.

alternative to ancestor-or-self ( or select all nodes in the tree with a specific child node)

I am trying to identify all the nodes in a tree that lead to a specific node.
I am trying to accomplish this through either MSSQL XML (2005) or by the Microsoft.XMLDOM in ASP classic.
I know the logic with XPATH but SQL Server does not support the ancestor-or-self axis and XMLDOM seems to choke on the :: notation..
The xpath that works when i test it in XPATH testers is
//static[#id=6]/ancestor-or-self::static
my XML (generated recursively in sql server) looks like
<root>
<static id="1" title="some title 1" />
<static id="2" title="some title 2">
<children>
<static id="3" title="some title 3" />
<static id="4" title="some title 4">
<children>
<static id="5" title="some title 5" />
<static id="6" title="some title 6" />
</children>
</static>
</children>
</static>
<static id="7" title="some title 7" />
</root>
the XPATH should select nodes with id (2,4,6) in any order, so i can add an attribute to all of them ..
This is for a menu system, where i only know the selected leaf, and need to mark as hilited all the nodes leading to it..
I would appreciate any assistance in either overcoming the XMLDOM choking
(running xml.documentElement.selectNodes("//static[#id=6]/ancestor-or-self::static") produces the following error: Expected token 'eof' found ':'. //static[#id=6]/ancestor-or-self-->:<--:static)
or with finding an alternative solution. Maybe finding all nodes that contain the specific node (with id = 6 ) at any depth..
This a "tidy up the loose ends" sort of answers.
First your primary problem would be that "Microsoft.XMLDOM" would normally load version 3.0 implementation (MSXML3.dll). MSXML3 does support the full XPATH 1.0 language but not by default. The follow should be enough to fix:-
dom.SetProperty "SelectionLanguage", "XPath"
Marvin's answer includes this line when using MSXML4 but it isn't really necessary since XPath is the default selection language on 4 and above.
However I use the word should above advisedly. I've often come across servers that have been compromised by a third-party application which also include a distribution of MSXML2 but install it incorrectly. They cause "Microsoft.XMLDOM" and the non version specific "MSXML2.DOMDocument" to return an MSXML2.dll implementation instead of MSXML3 implementations.
I therefore normally recommend that the best ProgID to use is "MSXML2.DOMDocument.3.0" since you know exactly what you are getting. In addition MSXML3.dll is guaranteed to be installed on all currently supported Windows OSes out of the box. Also MSXML3 remained compatible with bugs in the MSXML2 implentation when the DOM Document is invoked using an older progID. Using the version specific ProgID causes MSXML3 to conform more strictly to XML standards.
Running on W2K3, using IIS6 i tested the MSXML2.XMLDomDocument.4.0 version.
Dim XMLDom ''# As MSXML2.DOMDocument40
Set XMLDom = CreateObject("MSXML2.DOMDocument.4.0")
Call XMLDom.setProperty("SelectionLanguage", "XPath")
Call XMLDom.loadXML( {document as described above - mistakes in original xml doc)
)
Dim originalQuery ''# As String
originalQuery = "//static[#id=6]/ancestor-or-self::static"
Dim replacementQuery ''# As String
replacementQuery = "//static[descendant::static[#id=6] or #id=6]"
Dim XmlElemList ''# As MSXML2.IXMLDOMNodeList
Set XmlElemList = XMLDom.documentElement.selectNodes(originalQuery)
Dim XmlElemList2 ''# As MSXML2.IXMLDOMNodeList
Set XmlElemList2 = XMLDom.documentElement.selectNodes(replacementQuery)
Dim XmlElem ''# As MSXML2.IXMLDOMElement
Call Response.Write("Using original query : '" & originalQuery & "' (" & XmlElemList.Length & ")<br>")
For Each XmlElem In XmlElemList
Call Response.Write("XmlEntry : " & XmlElem.getAttribute("id") & "<br>")
Call Response.Write("****<br>")
Next
Call Response.Write("Using replacement query : '" & replacementQuery & "' (" & XmlElemList2.Length & ")<br>")
For Each XmlElem In XmlElemList2
Call Response.Write("XmlEntry : " & XmlElem.getAttribute("id") & "<br>")
Call Response.Write("****<br>")
Next

Resources