Find Table object in query - sqlalchemy

Using sqlalchemy 0.7.2
Is there a way to find the table class from the query object? For example:
q = session.query(Customers)
how can I find Customers in q? Possible? Not Possible?

Yes. You need column_descriptions.
It's a long road to the table, though. sqlalchemy.orm.Query.column_descriptions returns a list of dicts, describing each query entity as it was given to query. in your example, there's only one entity, so you need the first item from that list. And since you're interested in the type of the query entity, rather than its' structure, you want the "type" key from that list:
q_entity = q.column_descriptions[0]['type']
assert q_entity == Customer
Accessing the table for the mapped class requires snooping around in the mapper subsystem. for that, you should use manager_of_class. The table is accessible from the manager through the mapper.mapped_table attribute:
from sqlalchemy.orm.attribute import manager_of_class
q_table = manager_of_class(q_entity).mapper.mapped_table
Resist the urge to skip strait to the mapper through Customer.__mapper__, or even Customer.__table__; That's specific to sqlalchemy.ext.declarative, and won't work with classes that are mapped by other means.

Related

Grails criteria projections - return whole table AND the projections

I want to know if I can have a single createCriteria() call, that returns me the whole table, and some specified joined columns.
Something like this:
SELECT table1.*, table2.property1,table2.property2 FROM table1 WHERE ... INNER JOIN table2.
I have a code similar to this:
MyDomainClass.createCriteria().list{
createAlias("relationedObject", "relationedObjectAlias")
condition1(...)
condition2(...)
condition3(...)
projections{
property("relationedObjectAlias.nestedProperty")
property("someProperty")
property("anotherProperty")
}
}
It returns me an array of arrays, containing these 3 properties listed inside the projections closure. But what should I do to receive the whole MyDomainClass object row, AND the projections?
What I really need, actually, is an array containing the whole MyDomainClass object, and the nestedProperty from the relationedObject.
I know I could just do another createCriteria() call, without specifying the projections, and manually "join" them in code, but this looks ugly to me... any ideas?
I'm using grails 2.5.5
I don't think there is a way in Hibernate to accomplish what you are doing so (nothing in the documentation that I've seen) and since you are using a HibernateCriteriaBuilder, I would say no.
I think your alternative would be to have all of your domain class's properties defined within your projection, depending on how many properties are involved you could do this manually or with some help:
import org.codehaus.groovy.grails.commons.DefaultGrailsDomainClass
import org.hibernate.criterion.CriteriaSpecification
...
def propertyNames = new DefaultGrailsDomainClass(MyDomainClass.class).
getPersistentProperties().
findAll{ p -> !p.isOneToMany() }*.
name
MyDomainClass.createCriteria().list{
createAlias("relationedObject", "relationedObjectAlias")
condition1(...)
condition2(...)
condition3(...)
resultTransformer(CriteriaSpecification.ALIAS_TO_ENTITY_MAP)
projections{
property("relationedObjectAlias.nestedProperty")
propertyNames.each{ pn ->
property(pn, pn)
}
}
}
I would not call it pretty but it may work for your situation; I tested it on several of my domain objects and it worked successfully. I'm using DefaultGrailsDomainClass because getPersistentProperties() is a method on a non-static method and I don't want to rely on any particular instance. I'm excluding any collections based on my own testing.
Rather than relying on an returned array and the position of properties within that array, I'm using the ALIAS_TO_ENTITY_MAP result transformer to return a map. I think this is generally a good idea anyways, especially when dealing with larger result sets; and I think it's absolutely critical if gathering the properties in an automated fashion. This does require the property(<String>, <String>) method call as opposed to just the `property()', with the 2nd argument being the map key.

How do I get a related Model instance by PK from an ORM Model?

I have an SQLAlchemy model class model, a string denoting an attribute/column attr that corresponds to an ORM relationship with another model class othermodel, and a private key or id string of such an othermodel.
I would like to find the object othermodel.get(id) to store it in a newly constructed instance, using like setattr(model(), attr, ???) – but I don't have that othermodel accessible in a variable. How do I get that?
I assume I can use some kind of introspection on model or its new instance, but how?
Digging through
model's attributes, I found a copy of othermodel in
getattr(model, attr).comparator.property.argument
turning my assignment into
setattr(model(), attr, getattr(model, attr).comparator.property.argument.get(id))
Quite a mouthful!
This looks reasonable for the moment, but I am quite sure I am missing a more obvious way to access it.

Will manual Linq-To-Sql mapping with Expressions work?

I have this problem:
The Vehicle type derives from the EntityObject type which has the property "ID".
I think i get why L2S can't translate this into SQL- it does not know that the WHERE clause should include WHERE VehicleId == value. VehicleId btw is the PK on the table, whereas the property in the object model, as above, is "ID".
Can I even win on this with an Expression tree? Because it seems easy enough to create an Expression to pass to the SingleOrDefault method but will L2S still fail to translate it?
I'm trying to be DDD friendly so I don't want to decorate my domain model objects with ColumnAttributes etc. I am happy however to customize my L2S dbml file and add Expression helpers/whatever in my "data layer" in the hope of keeping this ORM-business far from my domain model.
Update:
I'm not using the object initialization syntax in my select statement. Like this:
private IQueryable<Vehicle> Vehicles()
{
return from vehicle in _dc
select new Vehicle() { ID = vehicle.VehicleId };
}
I'm actually using a constructor and from what I've read this will cause the above problem. This is what I'm doing:
private IQueryable<Vehicle> Vehicles()
{
return from vehicle in _dc
select new Vehicle(vehicle.VehicleId);
}
I understand that L2S can't translate the expression tree from the screen grab above because it does not know the mappings which it would usually infer from the object initialization syntax. How can I get around this? Do I need to build a Expression with the attribute bindings?
I have decided that this is not possible from further experience.
L2S simply can not create the correct WHERE clause when a parameterized ctor is used in the mapping projection. It's the initializer syntax in conventional L2S mapping projections which gives L2S the context it needs.
Short answer - use NHibernate.
Short answer: Don't.
I once tried to apply the IQueryable<.IEntity> to Linq2Sql. I got burned bad.
As you said. L2S (and EF too in this regard) doesn't know that ID is mapped to the column VehicleId. You could get around this by refactoring your Vehicle.ID to Vehicle.VehicleID. (Yes, they work if they are the same name). However I still don't recommend it.
Use L2S with the object it provided. Masking an extra layer over it while working with IQueryable ... is bad IMO (from my experience).
Otherway is to do .ToList() after you have done the select statement. This loads all the vehicles into your memory. Then you do the .Where statment against Linq 2 Object collections. Ofcourse this won't be as effecient as L2S handles all of the query and causes larger memory usage.
Long story short. Don't use Sql IQueryable with any object other than the ones it was originally designed for. It just doesn't work (well).

How to map more than one table to a class with SQLAlchemy

I'm new to sqlalchemy and am trying to map several tables to a class.
The tables are constructed like so:
Types
-typeID
-typeName
-groupID
...
TypeAttributes
-typeID
-attributeID
-attributeValueInt
-attributeValueFloat
The idea is to have sqlalchemy map a from TypeAttributes to normal class attributes.
As added complexity attributeValueInt and attributeValueFloat are exclusive. By which I mean each attributeID will have either an int or a float assossiated and the other will be null.
Any ideas how this could be done? or advice on a better way to do it (I have no control over the Database itself).
Have a look at this question: How to map one class against multiple tables with SQLAlchemy?

applying separation of concerns

I wonder if you think that there is a need to refactor this class.( regarding separation of concern)
publi class CSVLIstMapping<T>
{
void ReadMappingFromAttirbutes();
void GetDataFromList();
}
ReadMappingFromAttributes - Reads the mapping from the type T and stores it in the class. Has a name of the list to use and a number of csvMappingColumns which contains the name of the property to set the value in and the name of csvcolumns.
GetObjectsFromList - uses a CVSListreader ( which is passed in via the constructor) to get the data from all row's as KeyValuePair ( Key = csvcolumnName , value = actually value) and after that it uses the mappinginformation( listname and csvMappingColumns ) to set the data in the object.
I cant decide if this class has 2 concerns or one. First I felt that it had two and started to refactor out the conversion from rows to object to another object. But after this it felt awkward to use the functionality, as I first had to create a mappingretriver, and after that I had to retrive the rows and pass it in together with the mapping to the "mapper" to convert the objects from the rows
/w
Sounds like two concerns to me: parsing and mapping/binding. I'd separate them. CSV parsing should be a well-defined problem. And you should care about more than mere mapping. What about validation? If you parse a date string, don't you want to make sure that it's valid before you bind it to an object attribute? I think you should.
Rule of thumb: if it's awkward, it's wrong.
I have to say I'm finding it hard to understand what you've written there, but I think it's likely that you need to refactor the class: the names seem unclear, any method called GetFoo() should really not be returning void, and it may be possible that the whole ReadMappingFromAttribute should just be constructor logic.