BLOB/TEXT column needs it's length specified - jdo

While having the following object graph:
public class SecureDetails{
#Persistent(defaultFetchGroup = "true", table = "sc_details_emails")
#Join(column = "sc_details_pk")
#Element(column = "email")
private List<String> emails;
}
I keep receiving this exception while datanucleus attempts to auto create the schema (DEBUG logging level activated and the stacktrace is truncated for briefness sake):
21:09:24 DEBUG (Log4JLogger.java:58)-[main] Creating foreign key constraint : "sc_details_emails_fk1" in catalog "" schema ""
21:09:24 DEBUG (Log4JLogger.java:58)-[main] ALTER TABLE sc_details_emails ADD CONSTRAINT sc_details_emails_fk1 FOREIGN KEY (sc_details_pk) REFERENCES sc_details (sc_details_id)
21:09:24 ERROR (Log4JLogger.java:115)-[main] An exception was thrown while adding/validating class(es) : BLOB/TEXT column 'sc_details_pk' used in key specification without a key length
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: BLOB/TEXT column 'sc_details_pk' used in key specification without a key length
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.Util.getInstance(Util.java:386)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1053)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4096)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4028)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2490)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2651)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2728)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2678)
at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:894)
at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:732)
.
.
.
I tried to specify the annotation parameter serialized with the value false for the #Element annotation one time and for the #Persistence annotation another time, with the value of false but still this didn't resolve the problem. I tried that because I thought datanucleus is constructing binary columns and thats why I have to specify a length. And I even failed to specify a length as I don't know where I should specify it !
edit: Datanucleus creates the whole database from scratch. There are only 3 configuration tables that I query using SQL only and no there is no mapping related to them.
I'm using datanucleus v3.1.3 with MySQL v5.5

Surprisingly, a clean build solved the problem !

So you haven't let DataNucleus create all of the schema and there is a BLOB column somewhere that is inconsistent with the (little) metadata you present. Solution: let DataNucleus generate the schema, or actually present the schema so that people can tell you what is wrong with it.

Related

Is it possible to ignore the column when generating migrations

My project working on Symfony 4.4 and doctrine migrations bundle 3.2.1.
I used the columnDefinition to write a special column:
columnDefinition="VARCHAR(50) GENERATED ALWAYS AS (IF(ISNULL(`cabinet_id`), 'null', `cabinet_id`)) VIRTUAL"
It works perfect, but now, every time when I call doctrine:migrations:diff, migration is trying to change the column for the same:
ALTER TABLE MonitoringReportUpdate CHANGE virtual_null `virtual_null` VARCHAR(50) GENERATED ALWAYS AS (IF(ISNULL(`cabinet_id`), \'null\', `cabinet_id`)) VIRTUAL
And even if I run this alter, and call doctrine:migrations:diff again, I'll see the same query to execute:
ALTER TABLE MonitoringReportUpdate CHANGE virtual_null `virtual_null` VARCHAR(50) GENERATED ALWAYS AS (IF(ISNULL(`cabinet_id`), \'null\', `cabinet_id`)) VIRTUAL
Did I use columnDefinition wrong or maybe it's just a bug? Or is it possible to ignore this column when I call generate migration?
This is something Doctrine is not able to analyze properly so he is not able to consider it "already done", so he is considering it missing each time you generate a diff.
I already had to try such "complex" doctrine column def and i did not found a good workaround.
My best answer would be : There is something bad in your code that generate that kind of needed behavior in your database : avoid it and adapt your code.

How to add properties with a specific type into gremlinpython?

Currently i am trying to import via gremlinpython a large graph from igraph programmatically . I am rather new to gremlin and the endpoints i may use it with. The problem i currently face is that a property in a node/edge can have multiple types. (E.g.: -> Bool or None-type | Int, Long, etc..)
I've noticed no error when importing it into this gremlin-server (is this called Apache TinkerGraph-Server? How should i call this?). It seems that the types of same properties can be arbitrary.
However, when using JanusGraph i receive multiple errors:
gremlin_python.driver.protocol.GremlinServerError: 500: Value [XXX] is not an instance of the expected data type for property key [YYY] and cannot be converted. Expected: class <SomeClass>, found: class <SomeOtherClass>
E.g. executing:
conn = DriverRemoteConnection("ws://localhost:8182/gremlin", "g")
remote_graph = traversal().withRemote(conn)
remote_graph.addV().property("test", 10000).next()
remote_graph.addV().property("test", 100000000000000000000000).next() # <- Causes an error on JanusGraph
It is possible for me to cast some properties into other datatypes (Bool/None-Type-> -1,0,1), so i can avoid this error. But i am not sure how i should handle the above provided example. Is there a way to explicitly set the type (for at least numeric types) of a property, so that the server knows to store it e.g. as a Long/BigInt instead of as a Int? Especially since in python3 there is no distincion between long(/bigint) and int anymore.
So specifically is there something like the following?:
E.g. executing:
remote_graph.addV().property("test", 10000).asLong().next()
remote_graph.addV().property("test", 10000, <Type: Long>).next()
Gremlin does have a special class for ensuring a Java Long. You can just do long(10000) given the appropriate import like: from gremlin_python.statics import long

OpenJpa2.0 How to map Oracle sys.XMLTYPE column to String

I changed Change in persistence.xml
I also changed column definition (columnDefinition="XDB.XMLType") for xml fields
I checked OpenJpa(http://openjpa.208410.n2.nabble.com/Oracle-XMLType-fetch-problems-td6208344.html) site and IBM (http://www.ibm.com/support/knowledgecenter/SS7J6S_7.5.0/com.ibm.wsadapters.jca.jdbc.doc/env/doc/rjdb_problemsolutions.html)
My env is OpenJpa 2.0 and WAS 7
its throwing exception
org.apache.openjpa.persistence.PersistenceException: ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at "SYS.XMLTYPE", line 169
Please suggest without changing OpenJpa2.0 as its part of IBM WebSphere Application Server V7.0 how can i handle sys.XMLTYPE data, i am migrating my application from db2 to Oracle in same environment.
Writing XML data can be tricky some times! Getting the correct drivers and things defined properly can have its challenges. I can not say exactly what you need to do given the lack of info on your domain model and such, but let me give some general things to look for. First, there is an XML test in the OpenJPA test framework if you want to make reference to it. It can be seen publicly here:
https://apache.googlesource.com/openjpa/+/refs/heads/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/oracle/
Or, another test using an "XMLValueHandler" (likely this is beyond the scope of what you are looking for):
https://apache.googlesource.com/openjpa/+/refs/heads/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/xmlmapping/query/
Second, (stating the obvious) I assume you have a column in Oracle defined as "XMLTYPE". Also, I see you are using schema SYS. I'm sure you are aware but this is a system/admin schema......just for sanity sake you might want to first get things running using a non-system/admin schema just so we don't get hung up with any issues with your OpenJPA client not having the correct permissions.
Next, you need the following definition:
#Lob #Basic
#Column(name = "ANXMLCOLUMN", columnDefinition="XMLCOLUMN XMLType")
private String anXMLString;
The #Lob I think will be necessary if you are using data greater than 4000 chars (this was mentioned in one of the comments). To start I'd use a very small set of data (a couple characters), once that works, then experiment with > 4k.
Next, make sure to use the correct JDBC driver. The last time I experimented with an XMLType I used the Oracle JDBC 11.2.0.2 driver.
Finally, you might need to use the property "openjpa.jdbc.DBDictionary" with value "oracle(supportsSetClob=true,maxEmbeddedClobSize=-1)". Again, experiment with this AND look at the OpenJPA documentation on these properties to determine if they are necessary in your scenario. I think the supportsSetClob=true will only be necessary for older version (pre-2.2.x) of OpenJPA. You might also need to use property "openjpa.jdbc.SchemaFactory" with value "native". I would suggest you first try without either or these two properties. If that doesn't help, then experiment with these two properties. I know this is vague, but I don't know what your DDL or domain model looks like so I have to keep in vague.
Thanks,
Heath Thomann

Binding data with pragma query

I'm starting to develop a website with Laravel/SQLite.
I need to display some information from my database structure, so I'm trying to use PRAGMA statements that SQLite provides.
My question is : can I use the binding tool with pragma queries ?
The bad-old school method works fine :
DB::select('PRAGMA table_info(\''.$value->name.'\')');
If I try to use binding :
DB::select('PRAGMA table_info( ? )', array($value->name));
I get this error :
SQLSTATE[HY000]: General error: 1 near "?": syntax error (SQL: PRAGMA table_info( migrations ))
I don't see in documentation if binding with DB's specific queries is allowed or not. I don't think so, but I don't find any documentation of the binding tool, so maybe I've done a mistake.
Parameters are placeholders for an expression.
A table name (whether in a PRAGMA or in any other statement) is not an expression but an identifer, so it cannot be bound to a parameter.

XQuery Update: insert or replace depending if node exists not possible?

I am trying to build simple XML database (inside BaseX or eXist-db), but I have trouble figuring how to modify values in document :
content is simple as this for test :
<p>
<pl>
<id>6></id>
</pl>
</p>
I am trying to build something like function which would insert element into <pl> if that element is not present or replace it if it is present. But XQuery is giving me troubles yet :
When I try it head-on with if-then-else logic :
if (exists(/p/pl[id=6]/name)=false)
then insert node <name>thenname</name> into /p/pl[id=6]
else replace value of node /p/pl[id=6]/name with 'elsename'
I get error Error: [XUDY0027] Replace target must not be empty. Clearly I am confused, why the else part is evaluated in both cases, thus the error.
When I empty out the else part :
if (exists(/p/pl[id=6]/name)=true)
then insert node <name>thenname</name> into /p/pl[id=6]
else <dummy/>
Then I get Error: [XUST0001] If expression: no updating expression allowed.
When I try through declaring updating function, even then it reports error :
declare namespace testa='test';
declare updating function testa:bid($a, $b)
{
if (exists(/p/pl[id=6]/name)=true)
then insert node <name>thenname</name> into /p/pl[id=6]
else <dummy/>
};
testa:bid(0,0)
Error: [XUST0001] If expression: no updating expression allowed.
I've got these errors from BaseX 6.5.1 package.
So how can I modify values in a simple fashion if possible ?
If I call insert straight, the there could be multiple elements of same value.
If I call replace it will fail when the node does not exist.
If I delete the node before insert/replace then I could destroy sub-nodes which I don't want.
In most SQL databases, these are quite simple task (like MYSQL 'replace' command).
#Qiqi: #Alejandro is right. Your if expression is incorrect XQuery syntax:
if (exists(/p/pl[id=6]/name))
then insert node <name>thenname</name> into /p/pl[id=6]
else replace value of node /p/pl[id=6]/name with 'elsename'
Note that eXist-db's XQuery Update functionality is currently an eXist-specific implementation, so in eXist (currently) 1.4.x and 1.5dev, you'll want:
if (exists(/p/pl[id=6]/name))
then update insert <name>thenname</name> into /p/pl[id=6]
else update value /p/pl[id=6]/name with 'elsename'
This eXist-specific XQuery Update syntax is documented on http://exist-db.org/update_ext.html. This syntax was developed before the W3C XQuery Update spec had reached its current state. The eXist team plans to make eXist fully compliant with the W3C spec soon, but in the meantime the docs above should help you achieve what you need to if you use eXist.
Note too that your example code contains a typo inside the pl and id elements. The valid XML version would be:
<p>
<pl>
<id>6</id>
</pl>
</p>

Resources