Insert records into embedded field of OrientDB class from select - sql

I am evaluating OrientDB database.
I have two document classes imported from a relational database.
class Order with properties (ID: integer, OrderItems: EmbeddedList of OrderItem)
and
class OrderItem with properties (ID: integer, OrderID: integer, PropA: string)
Both classes are filled with data from the database (except field Order.OrderItems).
Now I would like to insert data from class OrderItem into class Order based on OrderID.
I have tried SQL like
update Order set OrderItems = (select from OrderItem where OrderID = Order.ID)
without success, with error like
The field 'Order.OrderItems' has been declared as EMBEDDEDLIST but the value is document with the valid RecordId ...
I do understand that embedded record should not have RecordId so I have tried
update Order set OrderItems = (select PropA from OrderItem where OrderID = Order.ID)
without success, with error like
The field 'Order.OrderItems' has been declared as EMBEDDEDLIST with linked class 'OrderItem' but the record has no class ...
I have also tried
update Order
set OrderItems = (select #class, PropA from OrderItem where OrderID = Order.ID)
without success.
Is there any other way (OrientDB 2.1.4) ...
Ales

I have found the solution
update Order
set OrderItems = (select $current.exclude('#rid') from OrderItem where $parent.$current.ID = OrderID)

Related

How to filter table with entity from other tables related by many to many relationship using GORM?

I have Product table which is connected with the other two tables Categorie & AttributeValue using many to many relationships. I am using GORM as an ORM. go struct for those tables are like bellow.
type Product struct {
ProductID int `gorm:"column:product_id;primary_key" json:"product_id"`
Name string `gorm:"column:name" json:"name"`
Categories []Category `gorm:"many2many:product_category;foreignkey:product_id;association_foreignkey:category_id;association_jointable_foreignkey:category_id;jointable_foreignkey:product_id;"`
AttributeValues []AttributeValue `gorm:"many2many:product_attribute;foreignkey:product_id;association_foreignkey:attribute_value_id;association_jointable_foreignkey:attribute_value_id;jointable_foreignkey:product_id;"`
}
type Category struct {
CategoryID int `gorm:"column:category_id;primary_key" json:"category_id"`
Name string `gorm:"column:name" json:"name"`
Products []Product `gorm:"many2many:product_category;foreignkey:category_id;association_foreignkey:product_id;association_jointable_foreignkey:product_id;jointable_foreignkey:category_id;"`
}
type AttributeValue struct {
AttributeValueID int `gorm:"column:attribute_value_id;primary_key" json:"attribute_value_id"`
AttributeID int `gorm:"column:attribute_id" json:"attribute_id"`
Value string `gorm:"column:value" json:"value"`
Products []Product `gorm:"many2many:product_attribute;foreignkey:attribute_value_id;association_foreignkey:product_id;association_jointable_foreignkey:product_id;jointable_foreignkey:attribute_value_id;"`
}
If I want to query Product table by category I can do it like bellow which will return all products in a category with category_id 3.
cat := model.Category{}
s.db.First(&cat, "category_id = ?", 3)
products := []*model.Product{}
s.db.Model(&cat).Related(&products, "Products")
If I want to query the Product table by both Category & AttributeValue how can I do that? Suppose I want to find all the products that are in category with category_id 3 and has AttributeValue with attribute_value_id 2?
I found some ways to query products based on category and AttributeValue. The best way I got is like bellow
products := []*model.Product{}
s.db.Joins("INNER JOIN product_attribute ON product_attribute.product_id = " +
"product.product_id AND product_attribute.attribute_value_id in (?)", 2).
Joins("INNER JOIN product_category ON product_category.product_id = " +
"product.product_id AND product_category.category_id in (?)", 3).
Find(&products)
After executing this, products slice will be populated with all the products that are in the category with category_id 3 and has AttributeValue with attribute_value_id 2. We can pass slice of string if we need to find products in multiple Category & AttributeValue.

SQL "Conditional" where clause

I have a table that I'm populating via a queue and I am unable to alter the structure of the table.
Issue:
The table contains four identifiers - SKU, Department, Class, and Subclass - and I need to return other fields from the table in order of the first condition met below:
if the SKU exists in the table then get the values for the sku
else if the Department/Class/Subclass of the SKU exists in the table get
values
else if the Department/Class of the SKU exists in the table
get values
else if the Department of the SKU exists in the table get
values.
else there are no applicable values for the SKU (I don't
think this happens)
I'm populating report fields in a java application from this table and I don't want to write four queries to check each of these cases. I don't believe I'm able to do any procedural SQL so I need to do this via a native sql query.
Any help is appreciated.
I had to alter the query a bit. The query below works:
Select dept, class, subclass,
case
when sku = :sku then 1
when dept = :dept and class = :class and subclass = :subclass then 2
when dept = :dept and class = :class then 3
when dept = :dept then 4
end as priority,
field1, field2, field3, field4, field5
From schema.table
where sku = :sku
or (dept = :dept and class = :class and subclass = :class)
or (dept = :dept and class = :class and subclass is null)
or (dept = :dept and class is null and subclass is null)
order by priority asc
;
So you pass 4 parameeters (SKU, Department, Class, and Subclass) in the query and need value fields for the parameters.
select
case
when sku=:sku then 1
when Department=:Department and Class=:Class and Subclass=:Subclass then 2
when Department=:Department and Class=:Class then 3
when Department=:Department then 4
end as priority,
<value field here>
from the_table t
where sku=:sku
or Department=:Department
or Class=:Class
or Subclass=:Subclass
order by priority
The first line of the query is what you need. How to extract the first line depends on DB you use

Delete category and its children / grandchildren

Using ObjectContext. I'm wanting to do this by passing an SQL query via the ExecuteStoreCommand since I don't fancy retrieving all relevant entities just for the sake of deleting them after.
The Category table is as so:
CatID | CatName | ParentID
Where CatID is the primary key to the ParentID FK
I am wishing to delete a category and also all those that
are under it. Can be 2+ levels deep of sub cats, so different ParentID's
Thought I could do it as below and just set "cascade" on delete option
for the foreign key in the database, but it won't let me and it does not appear to want to
cascade delete down by using the CatID - ParentID relationship and the query gets
stopped by this very FK constraint.
public RedirectToRouteResult DelCat(int CatID)
{
if (CatID != 0)
{
_db.ExecuteStoreCommand("DELETE FROM Categories WHERE CatID={0}", CatID);
_db.SaveChanges();
}
return RedirectToAction("CatManage");
}
Recursive CTE allCategories produces list of all categories in hierarchy. Delete part, obviously, deletes them all.
; with allCategories as (
select CatID
from Categories
where CatID = #CatID_to_delete
union all
select Categories.CatID
from allCategories
inner join Categories
on allCategories.CatID = Categories.ParentID
)
delete Categories
from Categories
inner join allCategories
on Categories.CatID = allCategories.CatID
Try it with select * from allCategories, though, to check first.
There is TEST # Sql Fiddle.
Why not just send two statements in your batch?
DELETE Categories WHERE ParentID = {0};
DELETE Categories WHERE CatID = {0};
If the framework you're using "won't let you" do that, then do this right: put your logic in a stored procedure, and call the stored procedure.

Trying to make a function that updates one table and deletes data from another using psql

I'm working on a project for my class and we were told to make a function that will delete data pertaining to a specific cart number and updates the products table. The function only has one input which is the cart number. Here is what I have:
create function clear_cart(text) returns void as
$$
update products
set qtyonhand = qtyonhand + (select qty from cart where cart_id = $1)
where id in (select product_id from cart where cart_id = $1);
delete from cart where cart_id = $1;
$$ language sql;
I've been testing the queries in by directly putting them into psql, and the error I can't seem to get around is on:
set qtyonhand = qtyonhand + (select qty from cart where cart_id = $1)
It returns multiple values into a field that only accepts one. I've tried looking elsewhere, but I'm not sure where I can find subqueries similar to what I'm trying to do. Any help would be appreciated.
Just in case, here is what the project says:
Parameters: cart_id char
Returns: none
Description: Remove all all items from the specified cart. Adjust the inventory quantities of the products appropriately.
You didn't show us your datamodel, but from the statements you have given, I'd assume you want something like this:
update products
set qtyonhand = qtyonhand + t.qty
from (select product_id,
qty
from cart
where cart_id = $1) t
where products.id = t.product_id;
This assumes that the cart table only holds a single row for each product. If that is not the case you'll get that "sub-select returns more than one row as well".
In that case you'll need to apply an aggregate function:
update products
set qtyonhand = qtyonhand + t.total_qty
from (select product_id,
sum(qty) as total_qty
from cart
where cart_id = $1
group by product_id) t
where products.id = t.product_id;
You could probably do this with just an UPDATE statement by using something like ON UPDATE CASCADE declared in your table.
So if you have this declared in a table called child. Fk is a reference to a table parent, when that parent gets updated it drops the row in child.
FOREIGN KEY (parent_id)
REFERENCES parent(id)
ON UPDATE CASCADE

NHibernate, how to map a property to a subselect

I currently have a legacy system that uses SPs exclusively for access to the DB. My domain object looks something like this:
public class User : EntityBase
{
public virtual string Name {get;set;}
public virtual string CreatedBy {get;set;}
public virtual DateTime CreatedDate {get;set;}
}
The SP I have that mapped this looked like this:
CREATE PROCEDURE getUser
{
#ID int
}
select
Name
,(SELECT TOP 1 UserName FROM AuditTrail WHERE EntityID = [User].[ID] AND EntityName = 'User' AND AuditActionID = 1 ORDER BY DateStamp) AS CreatedBy
,(SELECT TOP 1 DateStamp FROM AuditTrail WHERE EntityID = [User].[ID] AND EntityName = 'User' AND AuditActionID = 1 ORDER BY DateStamp) AS CreatedDate
FROM [User]
WHERE [User].ID = #ID
So, as you can see, the audit information is separated from the entity itself on the database and the CreatedBy/CreatedOn (and ModifiedBy/ModifiedOn) are stored in a separate table called AuditTrail. the AuditActionID field on the table specifies if it was a create/update.
How can I setup this mapping with NHibernate? I looked into JOIN but it doesn't give me the option to restrict by the additional values (and a join isn't what I want).
Also, if this is possible in Fluent NHibernate, that's a bonus but I'm fine with trying just standard NHibernate mapping config if it gets me there.
UPDATE:
I have found one way to do this, but I'm not a fan. I have setup a SQLQuery that reads the data and maps it back to an object. It works, but I'd love to do this via mapping. Is it even possible since the "values" from the database I'm mapping to is a subselect and not editable?
Solution:
Thanks to the tip from Diego, this was the final solution I found (using Fluent NHibernate, in my ClassMap file):
Map(x => x.CreatedBy).Formula("(SELECT TOP 1 AuditTrail.UserName FROM AuditTrail WHERE AuditTrail.EntityID = [ID] AND AuditTrail.EntityName = 'User' AND AuditTrail.AuditActionID = 1 ORDER BY AuditTrail.DateStamp)");
Map(x => x.CreatedDate).Formula("(SELECT TOP 1 AuditTrail.DateStamp FROM AuditTrail WHERE AuditTrail.EntityID = [ID] AND AuditTrail.EntityName = 'User' AND AuditTrail.AuditActionID = 1 ORDER BY AuditTrail.DateStamp)");
Thanks,
M
You can specify the select clause as the formula for your property.