myBatis Callable Statement - java Date Issue - mybatis

I was using mybatis-3.1.1 and there was no issue in the following code.
DAO Implementation
#Override
public ItunesPriorityReportDates getWeeklyPriorityDates(Date reportRunDate){
ItunesPriorityReportDates itunesPriorityReportDates = new ItunesPriorityReportDates();
Map<String,Object> weeklyPriorityDatesParamMap = new HashMap<>();
weeklyPriorityDatesParamMap.put("reportRunDate", reportRunDate);
log.debug("Report Run Date : " + reportRunDate);
this.getItunesAnalysisMapper().getWeeklyPriorityDates(weeklyPriorityDatesParamMap);
itunesPriorityReportDates.setAriaWeekStartDate((Date)weeklyPriorityDatesParamMap.get("ariaWeekStartDate"));
itunesPriorityReportDates.setAriaWeekEndDate((Date)weeklyPriorityDatesParamMap.get("ariaWeekEndDate"));
itunesPriorityReportDates.setitunesAccountPeriodStartDate((Date)weeklyPriorityDatesParamMap.get("itunesAccountPeriodStartDate"));
itunesPriorityReportDates.setitunesAccountPeriodEndDate((Date)weeklyPriorityDatesParamMap.get("itunesAccountPeriodEndDate"));
return itunesPriorityReportDates;
}
Mapper
public ItunesPriorityReportDates getWeeklyPriorityDates(Map<String,Object> weeklyPriorityDatesParamMap);
Mapper XML.
<select id="getWeeklyPriorityDates" parameterType="java.util.HashMap" statementType="CALLABLE">
{CALL external_reporting.itunes_sales.get_weekly_priority_dates(#{reportRunDate mode=IN, jdbcType=DATE},
#{ariaWeekStartDate mode=OUT, jdbcType=DATE},
#{ariaWeekEndDate mode=OUT, jdbcType=DATE},
#{itunesAccountPeriodStartDate mode=OUT, jdbcType=DATE},
#{itunesAccountPeriodEndDate mode=OUT, jdbcType=DATE}
)
}
</select>
After upgrading to mybatis-3.2.5 now it is passing null as DATE to Oracle procedure.
Can you please help me with this? Not sure whether I have to update my mapper XML and include something to tell it to parse correctly.
I am using java.util.Date in java.
Thanks
Chirag

Got solution from Eduardo Macarron (myBatis developer)
I got it. It is an interesting finding. Have a look at the expression you posted.
{reportRunDate mode=IN, jdbcType=DATE},
There is no comma separating the property name and the mode!
What is happening is that 3.0 and 3.1 admitted using an space as a separator, though that was undocumented, untested and at least in my case unknown :)
3.2 parsing code was improved and now it supports a well defined grammar:
Inline parameter expression parser. Supported grammar (simplified):
inline-parameter = (propertyName | expression) oldJdbcType attributes
propertyName = /expression language's property navigation path/
expression = '(' /expression language's expression/ ')'
oldJdbcType = ':' /any valid jdbc type/
attributes = (',' attribute)*
attribute = name '=' value
And the space is not a valid separator (so properties can in fact be called "input date").
This change was unwanted but was introduced in 3.2 one year ago so I am afraid we cannot go back.
I hope you just missed the comma and that was not intentional. Sorry!

Related

Ontology annotation type is missing in saved ontology file

I'm using OWL API 4.1. I add annotation with type XSD:string like that:
OWLAnnotationProperty annotationProperty = this.getDf().getOWLAnnotationProperty(annotationPropertyIri);
OWLLiteral lit = this.df.getOWLLiteral(annotationValue, range);
OWLAnnotation annotation = df.getOWLAnnotation(annotationProperty, lit);
this.getMng().applyChange(new AddOntologyAnnotation(this.getOnt(), annotation));
... I checked that here lit="test"^^xsd:string. But after I saved ontology (in ttl format) - there in no type ending - ^^xsd:string:
...
<http://semanticweb.rocks/whole-dataset-name/wheat-02> a owl:Ontology ;
dc:description """test""" ;
dc:source """http://mail.ru"""^^xsd:anyURI .
...
If I use other type (e.g. xsd:anyURI ) instead of ^^xsd:string the ending ^^xsd:anyURI is presented.
What is matter with ^^xsd:string?
The xsd:string type can be skipped for string literals, when there is no language tag. A literal typed with xsd:string is identical to a plain literal with no language tag.
If you load the ontology back into an OWLOntology, I expect you to see a test^^xsd:string literal attached to the ontology.

Groovy sql.rows returns org.postgresql.util.PSQLException: No hstore extension installed

I am using Groovy Sql in Grails with named parameters to get results from a Postgres DB. My statement is generated dynamically, i.e. concatenated to become the final statement, with the params being added to a map as I go along.
sqlWhere += " AND bar = :namedParam1"
paramsMap.namedParam1 = "blah"
For readability, I am using the groovy string syntax which allows me to write my sql statement over multiple lines, like this:
sql = """
SELECT *
FROM foo
WHERE 1=1
${sqlWhere}
"""
The expression is evaluated as a string containing the linebreaks as \n:
SELECT *\n ...
This is not a problem when I pass params like this
results = sql.rows(sqlString, paramsMap)
but it does become one if paramsMap is empty (which happens since AND bar = :namedParam1 is not always concatenated into the query). I then get an error
org.postgresql.util.PSQLException: No hstore extension installed
which does not really seem to relate to the true nature of the problem. I have for now fixed this with an if...else
if (sqlQuery.params.size() > 0) {
results = sql.rows(sqlString, paramsMap)
} else {
results = sql.rows(sqlString.replace('\n',' '))
}
But this seems a bit weird (especially since it does not work if I use the replace in the if-branch as well).
My question is: why do I really get this error message and is there a better way to prevent it from occuring?
It's certainly a bug in groovy.sql.SQL implementation. The method rows() can't deal with an empty map passed as params. As a workaround, you can test for it and pass an empty list instead.
def paramsMap = [:]
...
if (paramsMap.isEmpty())
paramsMap= []
Issue created at https://issues.apache.org/jira/browse/GROOVY-8082

Zend_Framework 1.12 SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax

Before anything I am aware of the multiple questions asked concerning this exception. I have looked through them but have not found an answer for my particular problem. Most of the questions use the Zend_Db_Table::getDefaultAdapter(); , and I am not using that. Instead I am using an Application_Model_DbTable_Name and am left wondering if it´s possible to do so.
Also, I do have access since that´s the first thing I checked when I saw the error. The database is local and I access it with the same user/password through MySqlWorkBench.
My goal is to delete a row when two columns meet the criteria set in the controller action, like so:
public function deleteAction(){
$request = $this->getRequest();
$this->_validateDigit($request->getParam('id'));
// _validateDigit(..) checks that the variable is numeric and if it´s not it redirects to
// an error page
$db = new Application_Model_DbTable_BecasPerfiles();
$select = $db->select();
$select->where('unidad=?', $this->_getUnit())
->where('id=?', (int) $request->getParam('id'));
$db->delete($select->getPart(Zend_Db_Select::WHERE));
$this->_redirect('/profile/view-profiles/unit/'.$this->_getUnit());
}
private function _getUnit()
{
return Zend_Registry::getInstance()['session']->unit;
//unit is nothing but a string
}
Here is my DbTable class (real simple):
class Application_Model_DbTable_BecasPerfiles extends Zend_Db_Table_Abstract
{
protected $_name = 'becas_perfiles';
}
Here is the error that spits out:
Message: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in
your SQL syntax; check the manual that corresponds to your MySQL server version for
the right syntax to use near 'AND (id=7))' at line 1
Here is what calls my attention AND (id=7)), see the extra parenthesis? where is that coming from?
Here is the result of var_dump($select->getPart(Zend_Db_Select::WHERE));
array(2) { [0]=> string(33) "(unidad='Galería de Arte ULPGC')" [1]=> string(10) "AND (id=7)" }
Just for the fun of it, I tried switching the order of the where clause:
$select->where('id=?', (int) $request->getParam('id'))
->where('unidad=?', $this->_getUnit());
Here is the output:
Message: SQLSTATE[42000]: ...
syntax to use near 'AND (unidad='Galería de Arte ULPGC'))' at line 1
There it is again, AND (unidad='Galería de Arte ULPGC')) that second parenthesis. I don´t really know if that´s the problem (but I figure it is because otherwise I don´t know what could posssibly be wrong).
I tried just using one where condition (like id), and it deleted just fine. I´d really appreciate your help, thank you!
The problem here is that there is a mismatch between what getPart() returns and what delete() expects.
As you already pointed out, var_dump($select->getPart(Zend_Db_Select::WHERE)); also returns the logical operators in the where statement, but the delete() operator either expects an array in the form "field => value" or a string containing the full where clause.
So the simplest (untested) approach to fix your problem would be to pass $db->delete(implode(' ', $select->getPart(Zend_Db_Select::WHERE))); so that delete() receives a fully qualified where clause as string instead of an array it cannot handle.

How to refactor parts of an EF select

Let's say I have the following EF code:
context.Employees.Select(e => e
{
FullName = e.FirstName + " " + e.LastName,
StartDate = e.StartDate,
... // Grab other data
};
Now maybe I notice that I construct the full name in multiple places, but would like in centralized. Is it possible to refactor this?
If I make it a method or a Func, I get EF errors, because it can't translate it into SQL.
NOTE: This is a simple example, assume it can get much more complicated with "Select"s, "Where"s, whatever in the assignment, so adding a ToList and then running additional code would be suboptimal and does not fit the definition of refactoring since I would have to change functionality and not just make it more maintainable.
One solution is to use the AsExpandable method from LinqKit:
Expression<Func<Employee,string>> fullName = e => e.FirstName + " " + e.LastName;
context.Employees.AsExpandable().Select(e => e
{
FullName = fullName.Compile().Invoke(e),
StartDate = e.StartDate,
... // Grab other data
};
From the linked article:
Compile is an inbuilt method in the Expression class. It converts the
Expression into a plain Func which
satisfies the compiler. Of course, if this method actually ran, we'd
end up with compiled IL code instead of an expression tree, and LINQ
to SQL or Entity Framework would throw an exception. But here's the
clever part: Compile never actually runs; nor does LINQ to SQL or
Entity Framework ever get to see it. The call to Compile gets stripped
out entirely by a special wrapper that was created by calling
AsExpandable, and substituted for a correct expression tree.
Alternatively, you could look into creating an Model Defined Function with Entity Framework. There's also the Microsoft.Linq.Translations library if you want to define a FullName property on the Employee class itself.
I think the better centralized way to do it in the entity class itself. You can add ReadOnly property to your entity class which should be NotMapped to the database to return required formatted data.
Public class Employee
{
//...
public string fullName{get { return FirstName + " " + LastName;}}
}

Xml attribute rendering oddness

Using 2.9.0.1
<b time={None}>Hello</b>
=>
<b >Hello</b>
i.e. there is a space after the b in the starting tag.
This makes no sense from an XML perspective.
Is this "feature" supposed to happen?
Thanks.
It happens because of toString implementation of scala.xml.Elem, to be more specific
in object scala.xml.MetaInf method buildString which looks like following:
def buildString(sb: StringBuilder): StringBuilder = {
sb.append(' ')
toString1(sb)
next.buildString(sb)
}
So it's firstly adds a white space to string representation of element, and only after that appends next attribute, so if an attribute is present as class member but doesn't have any string representation you'll end up with one extra space before closing bracket
Actually, it is allowed. See Extensible Markup Language (XML) 1.0 (Fifth Edition), 3.1 Start-Tags, End-Tags, and Empty-Element Tags. From there:
STag ::= '<' Name (S Attribute)* S? '>'
Where S is whitespace and Attribute is an attribute definition. The same is true for end elements:
ETag ::= '</' Name S? '>'
So this is allowed. Whether or not it's what you want is another thing :-)