ArangoDB 3.2 unique constraint violation _id or _key - arangodb

I just read the issue from arangoDB github [1.1] Feature request: On unique constrain violation exceptions include ids or keys that were involved #342 (https://github.com/arangodb/arangodb/issues/342) because it is exactly what I was searching for.
Apparently this issue is already closed because it has been implemented in ArangoDB 3.2, however I do not find the way to retrieve the id or key from a unique constraint violation error.
For example I call the following AQL query on a collection with a Hash Index on "projectName" attribute.
# first insert - everything OK
INSERT {"projectName":"test","startDate":"now"} IN projects
RETURN NEW
# second insert - will give unique constraint violation error
INSERT {"projectName":"test","startDate":"tomorrow"} IN projects
RETURN NEW
Therefore the error that I get is: AQL: unique constraint violated (while executing). Errors: {u'code': 409, u'errorNum': 1210, u'errorMessage': u'AQL: unique constraint violated (while executing)', u'error': True}
with no _key or _id or something that tells me with which document do I have a unique constraint violation. Based on the closed issue it should be possible but I don't see how, or maybe I just understood it wrong.
Note: A similar question was posted in Determining which unique constraint caused INSERT failure in ArangoDB but I think it was answered before the release of ArangoDB 3.2
I am using ArangoDB 3.2.3
Thanks

It looks like that the index details are still omitted when triggering a unique constraint violation from within AQL. In this case it will only show/return a generic "unique constraint violated", but not indicate which index caused it.
This is unintentional, and there is now a pull request to fix this:
https://github.com/arangodb/arangodb/pull/3330

Related

jOOQ: How to resolve `Ambiguous match found for <column>` when joining across multiple tables?

The following jOOQ query spits out a SQL warning in my logs about: Fields Ambiguous match found for id
db.select(FORWARDED_MESSAGE.SES_MESSAGE_ID).
from(FORWARDED_MESSAGE).
where(
FORWARDED_MESSAGE.FORWARDED.lt( DSL.currentTimestamp().subtract(
FORWARDED_MESSAGE.mailMapping().mailKeyword().mailDomain().account().
MESSAGE_RETENTION_DAYS ))).
fetch(FORWARDED_MESSAGE.SES_MESSAGE_ID);
The SQL generated appears to be correct, but I don't want the warning polluting my logs (and I want to know if jOOQ is warning me about something important that I need to be aware of).
Some context about the schema tables:
forwarded_message doesn't have a primary key
mail_domain uses a natural PK named "domain"
mail_mapping, mail_keyword and account all have a PK named id
I tried the following, but it fails saying Key ambiguous between tables:
db.select(FORWARDED_MESSAGE.SES_MESSAGE_ID).
from(FORWARDED_MESSAGE).
join(MAIL_MAPPING).onKey().
join(MAIL_KEYWORD).onKey().
join(MAIL_DOMAIN).onKey().
join(ACCOUNT).onKey().
where(
FORWARDED_MESSAGE.FORWARDED.lt(
DSL.currentTimestamp().subtract(ACCOUNT.MESSAGE_RETENTION_DAYS) )).
fetch(FORWARDED_MESSAGE.SES_MESSAGE_ID);
jOOQ version is 3.13.4, DB is postgres, using pgjdbc 42.2.14.
The Question:
How do I resolve the Fields Ambiguous match found warning?
Note: this is not a dupe of How to resolve ambiguous match when chaining generated Jooq classes because that was about a sub-classing ambiguity - this question is about simple chaining of joins (across tables that do have duplicate PK columns).
I was able to make the warning go away by re-writing the query to the join().onKey() style, but specifying the join foreign keys explicitly.
It's a bit verbose, but it seems to work:
db.select(FORWARDED_MESSAGE.SES_MESSAGE_ID).
from(FORWARDED_MESSAGE).
join(MAIL_MAPPING).
onKey(Keys.FORWARDED_MESSAGE__FORWARDED_MESSAGE_MAIL_MAPPING_ID_FKEY).
join(MAIL_KEYWORD).onKey(Keys.MAIL_MAPPING__MAIL_MAPPING_MAIL_KEYWORD_ID_FKEY).
join(MAIL_DOMAIN).onKey(Keys.MAIL_KEYWORD__MAIL_KEYWORD_DOMAIN_FKEY).
join(ACCOUNT).onKey(Keys.MAIL_DOMAIN__MAIL_DOMAIN_MAIL_DOMAIN_ACCOUNT_ID_FKEY).
where(
FORWARDED_MESSAGE.FORWARDED.lt(
DSL.currentTimestamp().subtract(ACCOUNT.MESSAGE_RETENTION_DAYS) )).
fetch(FORWARDED_MESSAGE.SES_MESSAGE_ID);
Not sure why this is much different from the FORWARDED_MESSAGE.mailMapping()...account() style. But it works and the generated SQL is cleaner.

web2py-sqlform can't check unique=True that use with requires=IS_LENGTH()

sqlform don't show error message when data have same value it accepted then error appear
error1
detail
ps. my goal is to create a field that contain 13 figure number which not same as other
i try delete requires=IS_LENGTH(maxsize=13,minsize=13) then the sqlform work fine but which these method i can't check either string is equal 13 or not
db.define_table('person',
Field('h_id_card',unique=True,requires=IS_LENGTH(maxsize=13,minsize=13))
)
def add():
form = SQLFORM(db.person).process()
return locals()
i expected sqlform will show error message instead of accepted
this is what i expect
From the book:
Notice that requires=... is enforced at the level of forms, required=True is enforced at the level of the DAL (insert), while notnull, unique and ondelete are enforced at the level of the database. While they sometimes may seem redundant, it is important to maintain the distinction when programming with the DAL.
Because unique=True translates to the UNIQUE SQL statement, when an insert/update violates the uniqueness constraint, you simply get an error from the database, which generates an exception in the database driver, which ultimately generates an exception in your app code if you don't catch it.
If you instead want to enable form validation for the uniqueness requirement, you should use the IS_NOT_IN_DB validator:
Field('h_id_card',
requires=[IS_LENGTH(maxsize=13, minsize=13), IS_NOT_IN_DB(db, 'person.h_id_card')])

ArangoError: unique constraint violated

My logging picked up an occurrence of the below error.
Its a very simple insert into an edge collection but the _key that was autogenerated already existed in that collection.
Details:
Save in an edge collection via a FOXX app.
Error: ArangoError: unique constraint violated - in index 0 of type primary over [“_key”]; conflicting key: 13647205
Arangodb version: 3.3.9 using RocksDB

I do not want my updates to do an add if entity does not exist

I want to be able to provide an UPDATE method to my users that will update the record they specify based on RowKey but it will NOT ADD it if the RowKey they pass in does not exist.
My reasoning is that if they mistakenly send in an invalid RowKey, I do not want them unknowingly ending up with a new entity vs. having updated the one they intended to update in the first place.
Here is the gist of the code I have (but that Adds/inserts the entity if it does not exist):
' p below is the entity obj (Inherits from TableServiceEntity)
' PartitionKey and RowKey are set to values of entity to update
MyBase.AttachTo(_tableName, p)
MyBase.UpdateObject(p)
MyBase.SaveChangesWithRetries(Services.Client.SaveChangesWithOptions.Batch)
My issue is that I was expecting to get some exception thrown when SaveChanges executed and no entity with matching PK and RK was found. Instead the entity with the new PK, RK combination is added.
How can I structure my code so that only an UPDATE is done and no ADD if PK, RK is not existent?
I believe if you call the three argument version of AttachTo(), you will get the desired behavior.
MyBase.AttachTo(_tableName, p, "*");
But I haven't actually tried it.
Rather than catching an error when you try to update and item that doesn't exists (I believe breischl is right about how to avoid that) the easiest thing to do would be to run a query to check if it does actually exist first.

Subsonic BatchQuery.Queue causing 'Can't decide which property to consider the key...' exception

I'm just getting started with Subsonic 3.0 ActiveRecord and am trying to implement a batch query like the one in the SubSonic docs. I'm using a batch so I can query a User and a list of the users Orders in one shot.
When I call the BatchQuery.Queue() method, adding my "select user" query, SubSonic throws the following exception:
System.InvalidOperationException : Can't decide which property to consider the Key - you can create one called 'ID' or mark one with SubSonicPrimaryKey attribute
The code is as follows:
var db = new MyDB();
var userQuery = from u in db.Users //gets user by uid
where u.uid == 1
select u;
var provider = ProviderFactory.GetProvider();
var batch = new BatchQuery(provider);
batch.Queue(userQuery); //exception here
//create and add "select users orders" query here...
First things first - Why this error? My SubSonic Users object knows it's PK. "uid" is the PK in the database and the generated code reflects this. And I thought SubSonicPrimaryKey attribute was for the SimpleRepository? Is this way of batching not for ActiveRecord?
I could ask a number of other questions, but I'll leave it at that. If anyone can help me figure out what is going on and how to issue 2 batched queries I'd be grateful!
Edit - after further investigation
I ran through the source code with the debugger. Adam is correct - the ToSchemaTable() method in Objects.cs is apparently building out my schema and failing to find a PK. At the very end, it tries to find a column property named "ID" and flags this as the PK, otherwise it throws the exception. I added a check for "UID" and this works!
Still... I'm confused. I'm admittedly a bit lost after peeling back layer after layer of the source, but it seems like this portion of code is trying to build up a schema for my table and completely ignoring my generated User class - which quite nicely identifies which column/property is the PK! It doesn't seem quite right that I'd be required to name all keys "ID" w/ ActiveRecord.
I think the answer you're looking for is that this is a really stupid bug on my part. I'm hoping to push another build next week and if you could put this on the issue list I'd really appreciate it. My apologies...
SubSonic expects your primary key to be called Id so it's getting confused. SubSonicPrimaryKey is for simple repository but I assume where that exception is being thrown is shared between the different templates. If you rename your PK to Id or id or ID your query will work.

Resources