I'll try my best to explain the problem... after executing:
delete edge SOME_EDGE from (select from SourceNode where foo=bar) to (select from TargetNode where foo=bar)
When the last reference of an edge is deleted, the type name still persists in SomeClass with an empty list, ie:
"out_SOME_EDGE": []
Similar with in_SOME_EDGE and the inverse relationship.
Then when executing a query:
select from SourceNode where out_SOME_EDGE is not null
those classes with empty list references are still returned.
Obviously
select from SourceNode where out_SOME_EDGE=[]
doesn't do anything. How can I locate and/or remove these obsolete/empty edge references?
update SourceNode remove out_SOME_EDGE where out_SOME_EDGE is not null
update TargetNode remove in_SOME_EDGE where in_SOME_EDGE is not null
works, of course, but isn't the best way to go since TargetNode could still have valid references.
The deeper I get into trying to find a solution the more it seems like it's a bug that vertices are allowed to have edges with empty reference lists, or that those edges aren't removed when the last target reference is removed.
The empty list means that there are no relationship (In/Out)
I think that that the delete edge command doesn't remove the field if the last reference is removed.
Try this to locate empty relationship
select from SourceNode where out_SOME_EDGE is not null or out_SOME_EDGE.size() = 0
The collection remains to host new items. If you want to set it to null execute this:
update V out_SOME_EDGE = NULL where out_SOME_EDGE.size() = 0
Or, better, to completely remove the property instead of setting it to null execute this:
update V remove out_SOME_EDGE where out_SOME_EDGE.size() = 0
Related
I’m looking to use frappe.db.delete to remove the most recently modified record in a custom table, Warehouse Locations. I want to limit the delete to only one record that matches some filters.
The table is a child table, if that matters.
I am not clear on how to filter one record, based on the “modified” value. I tried:
frappe.db.delete(‘Warehouse Locations’,
{“warehouse”: warehouse,
“parent”: item_code,
“shelf”: shelf,
“modified”:("=",last_record_to_keep[0].modified)})
I am getting a syntax error when I run the above query.
First, filter out the record to be deleted using ORM by running
record = frappe.get_list('Warehouse Locations', order_by='-modified')[0]
Once you filtered it out, you can delete it using frappe.db.delete.
frappe.db.delete('Warehouse Locations', record)
I think the solution answered by #ChillarAnand is helpful.
Instead, I would like to give a different way to solve the problem you faced.
Per your question, the goal is to delete only one record from Warehouse Locations (Child Table).
# 1. Get the parent document for the warehouse location.
parent_doc = frappe.get_doc("Doctype", docname)
# 2. iterate through the child table rows to find the row meet your filter
# and assign to row_to_detele for late use or you can delete straight away
row_to_delete = ""
for row in parent_doc.warehouse_locations:
if row.modified == last_record_to_keep[0].modified:
row_to_delete = row.name
break
# 3. to remove the child table from the parent doc method
parent_doc.remove(row_to_delete)
For the document of parent_doc.remove(), you can find it through the below github path: https://github.com/frappe/frappe/blob/6b91ade73c07dc1c070ed137cf54a29a3e7b0993/frappe/model/base_document.py#L210 (7 Oct, 2021)
I try to edit a postgresql entry and immediately delete it. The goal is that the field to be updated is used as a trigger parameter that logs the operation.
If I use a stored function, everything is working correctly. But if I use CTE I can not delete the record.
with tmp as (
update users set by_user_id = '0004' where id = '0006' returning id
)
delete from users
using tmp
where users.id = tmp.id;
http://sqlfiddle.com/#!17/b677a/1
Per the documentation:
Trying to update the same row twice in a single statement is not supported. Only one of the modifications takes place, but it is not easy (and sometimes not possible) to reliably predict which one. This also applies to deleting a row that was already updated in the same statement: only the update is performed.
I have a unique constraint on edge:
CREATE CLASS hasAssignee extends E
CREATE PROPERTY hasAssignee.out LINK Assignable
CREATE PROPERTY hasAssignee.in LINK User
CREATE INDEX UniqueHasAssignee ON hasAssignee(out,in) UNIQUE
I want to multiple create edges if they don't yet exist in one query. If they do exist, then either replace them, or simply don't add them. Something like that, but without possibility of errors:
CREATE EDGE hasAssignee FROM ( SELECT FROM Project WHERE id=:id ) TO ( SELECT FROM User WHERE login in :login )
UPSERT from what I've noticed can deal with only one edge at a time (at least I couldn't produce query parsable by studio)
I see a few possibe solutions (but I don't see anything like it in docs):
something like CREATE IFNOTEXISTS
Soft indexes, that don't throw an error, simply don't create additional edges
Remove unique index, create duplicates, and somehow remove duplicates after each query (?)
Is it possible to do something like that in orientdb? Should I fill out a request?
There is an open feature request for this:
https://github.com/orientechnologies/orientdb/issues/4436
My suggestion is to vote on it
I'm loading a subset of the parent records and the child records into a dataset then setting datarelations and foreignkeyconstraints, so when I am building the dataadapter select stmt for the child records, I must make sure that only the child records whose parent is present is loaded to avoid referential integrity errors. Since the subset of the ParentTable has been loaded into a dataset I tried:
daChild = new OleDBDataAdapter(CreateOledbCommand("select * from Childtable where ChildKey in (ds.tables(""ParentTable""))",dconn))
But got an "undefined function 'ds.tables' in expression" error at runtime.
So, I tried to create a one column table to pass to the IN clause, like this:
Dim MyDataView as DataView = New DataView(ds.tables("ParentTable"))
Dim MyTempParentTable as DataTable = MyDataView.ToTable(False, "ParentKey")
daChild = New OleDbDataAdapter(CreateOledbCommand("select * from ChildTable where ChildKey in (MyTempParentTable)", dconn))
I checked in the debugger, and MyTempParentTable is, in fact, a one column table containing the key of the ParentTable. I thought that the IN clause could take a one column datatable as valid input. Apparently not, as I am getting a "No value given for one or more required parameters" error at runtime.
I'm just about out of ideas. All my google searching came up with for the IN clause was something like IN (value1, value2, value3...) and doesn't give any examples for the IN clause containing a more complex expression.
Can anyone clue me in on what I'm missing, or maybe a different way to accomplish this? I'm trying to get the IN clause to work because I'm thinking that it is the most efficient way to do this... Maybe it's not... Thanks for any help.
I haven't found an answer to the question about why the IN clause didn't work, but just in case anybody else has this issue I will post my workaround.
I load the parent records as usual, but my dataadapter select stmt for the child records has a "WHERE 1=0" so that zero records are initially loaded. When a new parent record is displayed I then determine if the child records for that parent are already loaded into the dataset, if not, I load them in. Bottom line is that I don't pre-load the child records, rather, I load them "on demand". This solution is working well for me.
When I try to query:
select out('teaches') from Course
OrientDB returns empty lists, while the edges that I'm trying to find do exist.
Also, in the graph editor, the edges options won't show up anymore:
Normally, I can choose edges by hovering over the arrows. Now it doesn't do anything.
I've noticed that this started to happen when I started indexing my edges with a unique hash key. Does this have anything to do with it?
I'm using OrientDB version 2.0.5.
Apparently, it didn't work because I was using an UPDATE command.
UPDATE teaches SET in = #12:1, out = #13:1 UPSERT WHERE in = #12:1 AND out = #13:1 will create the edge (record) if it does not yet exist, but you won't be able to query it.
CREATE EDGE teaches from #13:1 to #12:1 does work and you will be able to query it.
Not sure whether this can be considered a bug...