Following is a example for Adjacency List + Inheritance. This works as expected but if i try to use it in a another Model Mammut as a relationship it throws me this error:
Traceback (most recent call last):
File "bin/py", line 73, in <module>
exec(compile(__file__f.read(), __file__, "exec"))
File "../adjacency_list.py", line 206, in <module>
create_entries(IntTreeNode)
File "../adjacency_list.py", line 170, in create_entries
mut.nodes.append(node)
File "/home/xxx/.buildout/eggs/SQLAlchemy-0.9.8-py3.4-linux-x86_64.egg/sqlalchemy/orm/dynamic.py", line 304, in append
attributes.instance_dict(self.instance), item, None)
File "/home/xxx/.buildout/eggs/SQLAlchemy-0.9.8-py3.4-linux-x86_64.egg/sqlalchemy/orm/dynamic.py", line 202, in append
self.fire_append_event(state, dict_, value, initiator)
File "/home/xxx/.buildout/eggs/SQLAlchemy-0.9.8-py3.4-linux-x86_64.egg/sqlalchemy/orm/dynamic.py", line 99, in fire_append_event
value = fn(state, value, initiator or self._append_token)
File "/home/xxx/.buildout/eggs/SQLAlchemy-0.9.8-py3.4-linux-x86_64.egg/sqlalchemy/orm/attributes.py", line 1164, in emit_backref_from_collection_append_event
child_impl.append(
AttributeError: '_ProxyImpl' object has no attribute 'append'
The Code:
from sqlalchemy import (Column, ForeignKey, Integer, String, create_engine,
Float)
from sqlalchemy.orm import (Session, relationship, backref, joinedload_all)
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm.collections import attribute_mapped_collection
from sqlalchemy.ext.declarative import declared_attr, AbstractConcreteBase
Base = declarative_base()
class Mammut(Base):
__tablename__ = "mammut"
id = Column(Integer, primary_key=True)
nodes = relationship(
'TreeNode',
backref='mammut',
lazy='dynamic',
cascade="all, delete-orphan",
#viewonly=True
)
class TreeNode(AbstractConcreteBase, Base):
id = Column(Integer, primary_key=True)
name = Column(String(50), nullable=False)
depth = Column(Integer, default=0)
data_type = Column(String(50))
#declared_attr
def mammut_id(cls):
return Column(Integer, ForeignKey('mammut.id'))
#declared_attr
def __tablename__(cls):
return cls.__name__.lower()
#declared_attr
def __mapper_args__(cls):
ret = {}
if cls.__name__ != "TreeNode":
ret = {'polymorphic_identity': cls.__name__,
'concrete': True,
# XXX redundant makes only sense if we use one table
'polymorphic_on': cls.data_type}
return ret
#declared_attr
def parent_id(cls):
_fid = '%s.id' % cls.__name__.lower()
return Column(Integer, ForeignKey(_fid))
#declared_attr
def children(cls):
_fid = '%s.id' % cls.__name__
return relationship(cls.__name__,
# cascade deletions
cascade="all, delete-orphan",
# many to one + adjacency list - remote_side
# is required to reference the 'remote'
# column in the join condition.
backref=backref("parent", remote_side=_fid),
# children will be represented as a dictionary
# on the "name" attribute.
collection_class=attribute_mapped_collection(
'name'),
)
def get_path(self, field):
if self.parent:
return self.parent.get_path(field) + [getattr(self, field)]
else:
return [getattr(self, field)]
#property
def name_path(self):
# XXX there is no way to query for it except we add a function with a
# cte (recursive query) to our database see [1] for it
# https://stackoverflow.com/questions/14487386/sqlalchemy-recursive-hybrid-property-in-a-tree-node
return '/'.join(self.get_path(field='name'))
def __init__(self, name, value=None, parent=None):
self.name = name
self.parent = parent
self.depth = 0
self.value = value
if self.parent:
self.depth = self.parent.depth + 1
def __repr__(self):
ret = "%s(name=%r, id=%r, parent_id=%r, value=%r, depth=%r, " \
"name_path=%s data_type=%s)" % (
self.__class__.__name__,
self.name,
self.id,
self.parent_id,
self.value,
self.depth,
self.name_path,
self.data_type
)
return ret
def dump(self, _indent=0):
return " " * _indent + repr(self) + \
"\n" + \
"".join([
c.dump(_indent + 1)
for c in self.children.values()]
)
class IntTreeNode(TreeNode):
value = Column(Integer)
class FloatTreeNode(TreeNode):
value = Column(Float)
miau = Column(String(50), default='zuff')
def __repr__(self):
ret = "%s(name=%r, id=%r, parent_id=%r, value=%r, depth=%r, " \
"name_path=%s data_type=%s miau=%s)" % (
self.__class__.__name__,
self.name,
self.id,
self.parent_id,
self.value,
self.depth,
self.name_path,
self.data_type,
self.miau
)
return ret
if __name__ == '__main__':
engine = create_engine('sqlite:///', echo=True)
def msg(msg, *args):
msg = msg % args
print("\n\n\n" + "-" * len(msg.split("\n")[0]))
print(msg)
print("-" * len(msg.split("\n")[0]))
msg("Creating Tree Table:")
Base.metadata.create_all(engine)
session = Session(engine)
def create_entries(Cls):
node = Cls('rootnode', value=2)
Cls('node1', parent=node)
Cls('node3', parent=node)
node2 = Cls('node2')
Cls('subnode1', parent=node2)
node.children['node2'] = node2
Cls('subnode2', parent=node.children['node2'])
msg("Created new tree structure:\n%s", node.dump())
msg("flush + commit:")
# XXX this throws the error
mut = Mammut()
mut.nodes.append(node)
session.add(mut)
session.add(node)
session.commit()
msg("Tree After Save:\n %s", node.dump())
Cls('node4', parent=node)
Cls('subnode3', parent=node.children['node4'])
Cls('subnode4', parent=node.children['node4'])
Cls('subsubnode1', parent=node.children['node4'].children['subnode3'])
# remove node1 from the parent, which will trigger a delete
# via the delete-orphan cascade.
del node.children['node1']
msg("Removed node1. flush + commit:")
session.commit()
msg("Tree after save:\n %s", node.dump())
msg("Emptying out the session entirely, "
"selecting tree on root, using eager loading to join four levels deep.")
session.expunge_all()
node = session.query(Cls).\
options(joinedload_all("children", "children",
"children", "children")).\
filter(Cls.name == "rootnode").\
first()
msg("Full Tree:\n%s", node.dump())
# msg("Marking root node as deleted, flush + commit:")
# session.delete(node)
# session.commit()
create_entries(IntTreeNode)
create_entries(FloatTreeNode)
nodes = session.query(TreeNode).filter(
TreeNode.name == "rootnode").all()
for idx, n in enumerate(nodes):
msg("Full (%s) Tree:\n%s" % (idx, n.dump()))
concrete inheritance can be very difficult, and AbstractConcreteBase itself has bugs in 0.9 which get in the way of elaborate mappings like this from being used.
Using 1.0 (not released, use git master), I can get the major elements going as follows:
from sqlalchemy import Column, String, Integer, create_engine, ForeignKey, Float
from sqlalchemy.orm import Session, relationship
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm.collections import attribute_mapped_collection
from sqlalchemy.ext.declarative import declared_attr, AbstractConcreteBase
Base = declarative_base()
class Mammut(Base):
__tablename__ = "mammut"
id = Column(Integer, primary_key=True)
nodes = relationship(
'TreeNode',
lazy='dynamic',
back_populates='mammut',
)
class TreeNode(AbstractConcreteBase, Base):
id = Column(Integer, primary_key=True)
name = Column(String)
#declared_attr
def __tablename__(cls):
if cls.__name__ == 'TreeNode':
return None
else:
return cls.__name__.lower()
#declared_attr
def __mapper_args__(cls):
return {'polymorphic_identity': cls.__name__, 'concrete': True}
#declared_attr
def parent_id(cls):
return Column(Integer, ForeignKey(cls.id))
#declared_attr
def mammut_id(cls):
return Column(Integer, ForeignKey('mammut.id'))
#declared_attr
def mammut(cls):
return relationship("Mammut", back_populates="nodes")
#declared_attr
def children(cls):
return relationship(
cls,
back_populates="parent",
collection_class=attribute_mapped_collection('name'),
)
#declared_attr
def parent(cls):
return relationship(
cls, remote_side="%s.id" % cls.__name__,
back_populates='children')
class IntTreeNode(TreeNode):
value = Column(Integer)
class FloatTreeNode(TreeNode):
value = Column(Float)
miau = Column(String(50), default='zuff')
e = create_engine("sqlite://", echo=True)
Base.metadata.create_all(e)
session = Session(e)
root = IntTreeNode(name='root')
IntTreeNode(name='n1', parent=root)
n2 = IntTreeNode(name='n2', parent=root)
IntTreeNode(name='n2n1', parent=n2)
m1 = Mammut()
m1.nodes.append(n2)
m1.nodes.append(root)
session.add(root)
session.commit()
session.close()
root = session.query(TreeNode).filter_by(name='root').one()
print root.children
I'm having hard time understanding what the following means in scala:
f: Int => Int
Is the a function?
What is the difference between f: Int => Intand def f(Int => Int)?
Thanks
Assuming f: Int => Int is a typo of val f: Int => Int,
and def f(Int => Int) is a typo of def f(i: Int): Int.
val f: Int => Int means that a value f is Function1[Int, Int].
First, A => B equals to =>[A, B].
This is just a shortcut writing, for example:
trait Foo[A, B]
val foo: Int Foo String // = Foo[Int, String]
Second, =>[A, B] equals to Function1[A, B].
This is called "type alias", defined like:
type ~>[A, B] = Foo[A, B]
val foo: Int ~> String // = Foo[Int, String]
def f(i: Int): Int is a method, not a function.
But a value g is Function1[Int, Int] where val g = f _ is defined.
f: Int => Int
means that type of f is Int => Int.
Now what does that mean? It means that f is a function which gets an Int and returns an Int.
You can define such a function with
def f(i: Int): Int = i * 2
or with
def f: Int => Int = i => i * 2
or even with
def f: Int => Int = _ * 2
_ is a placeholder used for designating the argument. In this case the type of the parameter is already defined in Int => Int so compiler knows what is the type of this _.
The following is again equivalent to above definitions:
def f = (i:Int) => i * 2
In all cases type of f is Int => Int.
=>
So what is this arrow?
If you see this arrow in type position (i.e. where a type is needed) it designates a function.
for example in
val func: String => String
But if you see this arrow in an anonymous function it separates the parameters from body of the function. For example in
i => i * 2
To elaborate just slightly on Nader's answer, f: Int => Int will frequently appear in a parameter list for a high order function, so
def myHighOrderFunction(f : Int => Int) : String = {
// ...
"Hi"
}
is a dumb high order function, but shows how you say that myOrderFunction takes as a parameter, f, which is a function that maps an int to an int.
So I might legally call it like this for example:
myHighOrderFunction(_ * 2)
A much more illustrative example comes from Odersky's Programming Scala:
object FileMatcher {
private def filesHere = (new java.io.File(".")).listFiles
private def filesMatching(matcher: String => Boolean) =
for (file <- filesHere if matcher(file.getName))
yield file
def filesEnding(query: String) = filesMatching(_.endsWith(query))
def filesContaining(query: String) = filesMatching(_.contains(query))
def filesRegex(query: String) = filesMatching(_.matches(query))
}
Here filesMatching is a high order function, and we define three other functions that call it passing in different anonymous functions to do different kinds of matching.
Hope that helps.
This code works fine when there are records matching the WHERE clause:
val pinfo = SQL("SELECT * FROM tableName WHERE id={id}").on("id" -> "scala")
pinfo().map { row =>
println("have something")// runs when selected
}
What is going to happen when nothing is selected?
I'd like to print the following when no records are selected from MySQL.
println("nothing is selected")//if no row comes
SQL(...)() returns a Stream[SqlRow] and streams have the isEmpty method:
val pinfo: Stream[SqlRow] = SQL("SELECT * FROM tableName WHERE id={id}").on("id" -> "scala")()
if(!pinfo.isEmpty) pinfo.map { row => println("have something") }
else println("nothing is selected")
Also from the REPL:
scala> 1 #:: 2 #:: empty
res0: scala.collection.immutable.Stream[Int] = Stream(1, ?)
scala> res0.isEmpty
res1: Boolean = false
scala> empty
res2: scala.collection.immutable.Stream[Nothing] = Stream()
scala> res2.isEmpty
res3: Boolean = true
You can also parse it as a Option[T], and then handle the case there is no value within this optional result.
val i: Option[Int] = SQL"SELECT int FROM test".as(scalar[String].singleOpt)
If I have the following type and function:
object M {
type X[Boolean] = Int => Boolean
def retrieveVal(x: X[Boolean]) : Boolean = //retrieve the Boolean value of x
}
How would I go about retrieving and returning the boolean value?
That is a peculiar type alias. It has a formal type parameter (the name of which is irrelevant and hence the choice of Boolean is misleading) that defines a function from Int to that arbitrary type. You then define a method, retrieveVal that takes a particular kind of X that happens to be X[Boolean] (here Boolean is an actual type parameter and hence is the Boolean we're familiar with) and returns some Boolean. However, the function x passed as an argument requires an Int argument and there is none in evidence.
So, if your retrieveVal were defined like this instead:
def retrieveVal(i: Int, x: X[Boolean]): Boolean = ...
you could define it like this:
def retrieveVal(i: Int, x: X[Boolean]): Boolean = x(i)
To wit:
scala> type X[Boolean] = Int => Boolean
defined type alias X
scala> def retrieveVal(i: Int, x: X[Boolean]): Boolean = x(i)
retrieveVal: (i: Int, x: Int => Boolean)Boolean
scala> retrieveVal(23, i => i % 2 == 0)
res0: Boolean = false
Forgive me if this has already been asked elsewhere. I have a Scala syntax question involving function-values and implicit parameters.
I'm comfortable using implicits with Scala's currying feature. For instance if I had a sum function and wanted to make the second argument an implicit:
scala> def sum(a: Int)(implicit b: Int) = a + b
sum: (a: Int)(implicit b: Int)Int
Is there a way to do this using the function-value syntax? Ignoring the implicit for a moment, I typically write curried function-values like this:
scala> val sum2 = (a: Int) => (b: Int) => a + b
sum: (Int) => (Int) => Int = <function1>
However, the function signature in the second approach is much different (the currying is being expressed explicitly). Just adding the implicit keyword to b doesn't make much sense and the compiler complains as well:
scala> val sum2 = (a: Int) => (implicit b: Int) => a + b
<console>:1: error: '=>' expected but ')' found.
val sum2 = (a: Int) => (implicit b: Int) => a + b
^
Furthermore partially-applying sum from the very first approach to get a function-value causes problems as well:
scala> val sumFunction = sum _
<console>:14: error: could not find implicit value for parameter b: Int
val sumFunction = sum _
^
This leads me to believe that functions that have implicit parameters must have said parameters determined when the function-value is created, not when the function-value is applied later on. Is this really the case? Can you ever use an implicit parameter with a function-value?
Thanks for the help!
scala> val sum2 = (a: Int) => {implicit b: Int => a + b}
sum2: (Int) => (Int) => Int = <function1>
This will just make b an implicit value for the scope of the function body, so you can call methods that expect an implicit Int.
I don't think you can have implicit arguments for functions since then it is unclear what the function is. Is it Int => Int or () => Int?
The closest I found is:
scala> case class Foo(implicit b: Int) extends (Int => Int) {def apply(a: Int) = a + b}
defined class Foo
scala> implicit val b = 3
b: Int = 3
scala> Foo()
res22: Foo = <function1>
scala> res22(2)
res23: Int = 5
In this snippet
scala> val sum2 = (a: Int) => (b: Int) => a + b
sum: (Int) => (Int) => Int = <function1>
Note that the precise type of sum2 is Function1[Int, Function1[Int, Int]]. It could also be written as
val sum2 = new Function1[Int, Function1[Int, Int]] {
def apply(a: Int) = new Function1[Int, Int] {
def apply(b: Int) = a + b
}
}
Now, if you try to make b implicit, you get this:
scala> val sum2 = new Function1[Int, Function1[Int, Int]] {
| def apply(a: Int) = new Function1[Int, Int] {
| def apply(implicit b: Int) = a + b
| }
| }
<console>:8: error: object creation impossible, since method apply in trait Function1 of type (v1: Int)Int is not defined
def apply(a: Int) = new Function1[Int, Int] {
^
Or, in other words, Function's interfaces do not have implicit parameters, so anything with an implicit parameter is not a Function.
Try overloading the apply method.
scala> val sum = new Function1[Int, Function1[Int, Int]] {
| def apply(a: Int) = (b: Int) => a + b
| def apply(a: Int)(implicit b: Int) = a + b
|}
sum: java.lang.Object with (Int) => (Int) => Int{def apply(a:Int)(implicit b: Int): Int} = <function1>
scala> sum(2)(3)
res0: Int = 5
scala> implicit val b = 10
b: Int = 10
scala> sum(2)
res1: Int = 12