Where relation value higher than entity value with Eloquent - eloquent

I have two entities; Part and PartStock. There is a one-to-one relationship between them:
Part model:
public function partStock()
{
return $this->hasOne('App\PartStock');
}
PartStock model:
public function part()
{
return $this->belongsTo('App\Part');
}
How can I write a global scope for Part that has a where filter for values on the PartStock relation and Part entity itself?
So basically:
$query->where('PartStock.count', '>', 'Part.reorder');
parts table:
`id` int(10)
`category_id` int(10)
`description` varchar(255)
`value` varchar(255)
`reorder` int(10)
part_stock table:
`id` int(10)
`part_id` int(10)
`count` int(11)
I can not wrap my head around if it is even possible:
// here I have part reorder, but not the partstock count
$query->where(???, '>', 'reorder');
// here I have partstock count, but not the part reorder
$query->whereHas('partStock', function($q) {
$q->where('count', '>', ???);
});
Can I in a way combine this two scopes?

See Eloquent: Querying Relations.
Part::whereHas('PartStock', function ($query) {
$query->whereRaw('PartStock.count > Part.reorder');
})->get();

Related

Include columns from related table in JPA using ListAll()

I have 2 related tables and i am wondering if it is possible to include other columns (like firstname and surname) from table no1 when i am calling the function ListAll() in table no2? I am using JPA with Session Beans (AbstractFacade) and JSF Pages. Thanks in advance :-)
Table No1
CREATE TABLE cases (
caseid INT AUTO_INCREMENT PRIMARY KEY,
category VARCHAR(32),
descript VARCHAR(512),
isDone TINYINT,
userid INT,
INDEX user_ind(userid),
FOREIGN KEY (userid) REFERENCES USERS(userid)
);
Table 2
CREATE TABLE users (
userid INT NOT NULL AUTO_INCREMENT,
firstname VARCHAR(64) NOT NULL,
surname VARCHAR(64) NOT NULL,
telephone VARCHAR(12),
email VARCHAR(64),
PRIMARY KEY (userid)
);
Entity Controller
#Named(value = "caseController")
#SessionScoped
public class CaseController implements Serializable {
#EJB
CasesFacade casesFacade;
#Inject
CasesBean casesBean;
public List<Cases> getAll() {
return casesFacade.findAll();
}
If i correct understand maybe the good idea will be unpack chosen columns/fields to custom DTO on level repository or in code.

Using Automapper with F# Entity Type Provider

I am looking at Automapper for the first time using F# and the Entity Type Provider. I want to map between the EF Type Provider types and the F# record types that I have created.
The EF Type Provider is based on the following database schema:
CREATE TABLE [dbo].[Address](
[Id] [int] IDENTITY(1,1) NOT NULL,
[FamilyId] [int] NOT NULL,
[State] [varchar](50) NOT NULL,
[County] [varchar](50) NOT NULL,
[City] [varchar](50) NOT NULL,
CONSTRAINT [PK_Address] PRIMARY KEY CLUSTERED ([Id] ASC)
CREATE TABLE [dbo].[Child](
[Id] [int] IDENTITY(1,1) NOT NULL,
[FamilyId] [int] NOT NULL,
[FirstName] [varchar](50) NOT NULL,
[Gender] [varchar](50) NOT NULL,
[Grade] [int] NOT NULL,
CONSTRAINT [PK_Child] PRIMARY KEY CLUSTERED ([Id] ASC)
CREATE TABLE [dbo].[Family](
[Id] [int] IDENTITY(1,1) NOT NULL,
[LastName] [varchar](50) NOT NULL,
[IsRegistered] [bit] NOT NULL,
CONSTRAINT [PK_Family] PRIMARY KEY CLUSTERED ([Id] ASC)
CREATE TABLE [dbo].[Parent](
[Id] [int] IDENTITY(1,1) NOT NULL,
[FamilyId] [int] NOT NULL,
[FirstName] [varchar](50) NOT NULL,
CONSTRAINT [PK_Parent] PRIMARY KEY CLUSTERED ([Id] ASC)
CREATE TABLE [dbo].[Pet](
[Id] [int] IDENTITY(1,1) NOT NULL,
[ChildId] [int] NOT NULL,
[GivenName] [varchar](50) NOT NULL,
CONSTRAINT [PK_Pet] PRIMARY KEY CLUSTERED ([Id] ASC)
ALTER TABLE [dbo].[Address] WITH CHECK ADD CONSTRAINT [FK_Address_Family] FOREIGN KEY([FamilyId])
REFERENCES [dbo].[Family] ([Id])
ALTER TABLE [dbo].[Address] CHECK CONSTRAINT [FK_Address_Family]
ALTER TABLE [dbo].[Child] WITH CHECK ADD CONSTRAINT [FK_Child_Family] FOREIGN KEY([FamilyId])
REFERENCES [dbo].[Family] ([Id])
ALTER TABLE [dbo].[Child] CHECK CONSTRAINT [FK_Child_Family]
ALTER TABLE [dbo].[Parent] WITH CHECK ADD CONSTRAINT [FK_Parent_Family] FOREIGN KEY([FamilyId])
REFERENCES [dbo].[Family] ([Id])
ALTER TABLE [dbo].[Parent] CHECK CONSTRAINT [FK_Parent_Family]
ALTER TABLE [dbo].[Pet] WITH CHECK ADD CONSTRAINT [FK_Pet_Child] FOREIGN KEY([ChildId])
REFERENCES [dbo].[Child] ([Id])
ALTER TABLE [dbo].[Pet] CHECK CONSTRAINT [FK_Pet_Child]
I then created a comparable set of types in F#:
type Pet = {Id:int; GivenName:string}
type Child = {Id:int; FirstName:string; Gender:string; Grade:int; Pets: Pet list}
type Address = {Id:int; State:string; County:string; City:string}
type Parent = {Id:int; FirstName:string}
type Family = {Id:int; Parents:Parent list; Children: Child list; Address:Address}
The only real difference is that the foreign key is not explicit in the record types.
When I use Automapper on the Address type, it works as expected:
Mapper.CreateMap<EntityConnection.ServiceTypes.Address, Address>()
let context = EntityConnection.GetDataContext()
let addressQuery = query {for address in context.Addresses do select address}
let address = Seq.head addressQuery
let address' = Mapper.Map<Address>(address)
val address' : Address = {Id = 1;
State = "WA";
County = "King";
City = "Seattle";}
But when I try and do the same with the entire graph,
Mapper.CreateMap<EntityConnection.ServiceTypes.Pet, Pet>()
Mapper.CreateMap<EntityConnection.ServiceTypes.Child, Child>()
Mapper.CreateMap<EntityConnection.ServiceTypes.Address, Address>()
Mapper.CreateMap<EntityConnection.ServiceTypes.Parent, Parent>()
Mapper.CreateMap<EntityConnection.ServiceTypes.Family, Family>()
let context = EntityConnection.GetDataContext()
let familyQuery = query {for family in context.Families do select family}
let family = Seq.head familyQuery
let family' = Mapper.Map<Family>(family)
I get this exception:
System.ArgumentException: Type needs to have a constructor with 0 args or only optional args
Parameter name: type
I am wondering if it is b/c EF is lazy loading so the remaining types are not being evaluated? has anyone seen this before?
The error is pretty straight forward. None of your classes have a constructor that takes 0 arguments.
F# creates default constructors for you so the default constructor on your class has multiple arguments in it. For example:
type Pet = {Id:int; GivenName:string}
as a c# class would have this as it's definition.
public class Pet
{
public int Id { get; private set; }
public string GivenName { get; private set; }
public Pet(int id, string givenName)
{
Id = id;
GivenName = givenName;
}
}
Note the lack of a parameterless constructor. That's where your error is coming from.
You can fix it by flagging your type as CLIMutable
[<CLIMutable>]
type Pet = {Id:int; GivenName:string}

Passing CAST(foo AS type) as a relationship condition in DBIx::Class

For historical reasons, we have a table at work that has integer values in a text field that correspond to the ID's in another table. Example:
CREATE TABLE things (
id INTEGER,
name VARCHAR,
thingy VARCHAR
);
CREATE TABLE other_things (
id INTEGER,
name VARCHAR,
);
So a "thing" has-one "other thing", but rather than being set up sensibly, the join field is a varchar, and called "thingy".
So in Postgres, I can do this to join the two tables:
SELECT t.id, t.name, ot.name FROM things t
JOIN other_things ot ON CAST(t.thingy AS int) = ot.id
How can I represent this relationship in DBIx::Class? Here's an example of one thing I've tried:
package MySchema::Thing;
__PACKAGE__->has_one(
'other_thing',
'MySchema::OtherThing',
{ 'foreign.id' => 'CAST(self.thingy AS int)' },
);
nwellnhof was close, but to get the literal SQL to SQL::Abstract, I had to do a coderef like so:
__PACKAGE__->has_one(
'other_thing',
'MySchema::OtherThing',
sub {
my $args = shift;
return {
qq{$args->{'foreign_alias'}.id} => { q{=} => \qq{CAST($args->{'self_alias'}.dept AS int)} },
};
},
);
Using Literal SQL should do the trick:
__PACKAGE__->has_one(
'other_thing',
'MySchema::OtherThing',
{ 'foreign.id' => { '=', \'CAST(self.thingy AS int)' } },
);
I'd change the datatype of the field.
If that's not possible you could add another field of type int and a trigger that casts the varchar to an int and stores it in the int field that you then use for the joins to improve performance.

How to map inheritance discriminator as composite key in Entity Framework?

Is it possible to map a one to one relationship using the parent key and a discriminator value? I know that code first does not like the discriminator property on the concrete class and to reference it only in the Map method.
FlightTypes { Inbound = 1, Outbound = 2}
public class Transaction
- int TransactionId
- int? InboundFlightId
- InboundTransactionFlight InboundFlight
- int? OutboundFlightId
- OutboundTransactionFlight OutboundFlight
public abstract class TransactionFlight
- TransactionFlightId
public class InboundTransactionFlight : Flight
- List<Transaction> InboundFor
public class OutboundTransactionFlight : Flight
- List<Transaction> OutboundFor
Entity<InboundTransactionFlight>().Map(m => m.Requires("FlightTypeId").HasValue(1));
Entity<OutboundTransactionFlight>().Map(m => m.Requires("FlightTypeId").HasValue(2));
/* this is what is currently generated */
CREATE TABLE Transactions (
TransactionId int NOT NULL,
InboundFlightId int NULL,
OutboundFlightId int NULL
)
CREATE TABLE TransactionFlights (
TransactionFlightId int NOT NULL,
FlightTypeId int NOT NULL,
...
CONSTRAINT PK_TransactionFlights PRIMARY KEY CLUSTERED ( TransactionFlightId )
)
/* is it possible to generate/map this and keep inheritance? */
CREATE TABLE Transactions (
TransactionId int NOT NULL,
)
CREATE TABLE TransactionFlights (
TransactionId int NOT NULL,
FlightTypeId int NOT NULL,
...
CONSTRAINT PK_TransactionFlights PRIMARY KEY CLUSTERED ( TransactionId, FlightTypeId )
)
Thanks.
As I know it is not possible because EF doesn't allow using discriminator column in any other mapping. Also your target mapping will demand that your transaction class also has FlightTypeId property (class must have properties for the whole key) but it would break the meaning of the inheritance because you would be able to change the value of that property and make your inheritance inconsistent.

Cannot refresh row as parent is missing. Zend Framework

i am getting the error "Cannot refresh row as parent is missing" when I try to save. Here is my code
abstract class Webapp_Model_Resource_Db_Table_Abstract
extends Zend_Db_Table_Abstract
{
/**
* Save a row to the database
*
*
* #param array $info The data to insert/update
* #param Zend_DB_Table_Row $row Optional The row to use
* #return mixed The primary key
*/
public function saveRow($info, $row = null)
{
if (null === $row) {
$row = $this->createRow();
}
$columns = $this->info('cols');
foreach ($columns as $column) {
if (array_key_exists($column, $info)) {
$row->$column = $info[$column];
}
}
return $row->save();
}
}
when I call the saveRow() method, I pass in the $_POST values ($form->getValues())
I have reused this class with my other modules in the same application but now I am getting this error and I am not sure why. My table is pretty straight forward:
CREATE TABLE `news` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`headline` varchar(100) DEFAULT NULL,
`snippet` varchar(500) DEFAULT NULL,
`full_text` text,
`author` varchar(100) DEFAULT NULL,
`publish_from` date DEFAULT NULL COMMENT 'Publish date',
`publish_to` date DEFAULT NULL COMMENT 'Take it down or mark as draft after this date',
`datecreated` timestamp NULL DEFAULT NULL COMMENT 'First created on',
`revised` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Timestamp for the last time it was revised',
`draft` tinyint(1) DEFAULT '0' COMMENT 'Should not be published',
`departments_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=214 DEFAULT CHARSET=utf8 COMMENT='Stores news articles';
Anyone know what I am doing wrong?
::::::::::::::ADDTION:::::::::::::
public function saveNews($post,$defaults = array())
{
//get the form
$form = $this->getForm('article' . ucfirst($validator));
//validate
if(!$form->isValid($post)) {
return false;
}
//get fitered values
$data = $form->getValues();
//apply defaults
foreach($defaults as $col => $value) {
$data[$col] = $value;
}
//get the article if it exists
$article = array_key_exists('id', $data) ?
$this->getNewsById($data['id']) : null;
return $this->saveRow($data, $article);
}
When you pass an empty value for the primary key, Zend seems to return this value instead of the inserted auto-increment value - even though a new row is created properly with an auto-increment value, the inserted value will not be returned.
Maybe your problem is related to this. If so, try unsetting the id field prior to saving.
You have to tell DbTable that there is a Auto Incrementing Primary Key by setting $_sequence either to true or the Sequence Name.
15.5.4.1. Using a Table with an Auto-incrementing Key
Check your $info array. Probably you have some empty value for your primary key there.
So array_key_exists($column, $info) returns true and you assign an empty primary key to your row. And this causes the error as the row with this key does not exist.
try
if (array_key_exists($column, $info) and $column != 'YOUR_PRIMARY_KEY_NAME')
{
$row->$column = $info[$column];
}
In my case the problem was missing AUTO_INCREMENT.
Could you post the function:
$this->getNewsById($id)
There is your problem...