From 4dc42faab3734ccad7dd8951d6f190e9868dc37f Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Sun, 17 Jul 2005 01:17:33 +0000 Subject: [PATCH] basic eager loading --- lib/sqlalchemy/engine.py | 26 +++++++++++++++++ lib/sqlalchemy/mapper.py | 62 ++++++++++------------------------------ lib/sqlalchemy/sql.py | 4 +++ test/mapper.py | 1 - 4 files changed, 45 insertions(+), 48 deletions(-) diff --git a/lib/sqlalchemy/engine.py b/lib/sqlalchemy/engine.py index 0814caf573..6ea026159e 100644 --- a/lib/sqlalchemy/engine.py +++ b/lib/sqlalchemy/engine.py @@ -132,3 +132,29 @@ class SQLEngine(schema.SchemaEngine): def log(self, msg): print msg + + +class ResultProxy: + def __init__(self, cursor): + self.cursor = cursor + metadata = cursor.description + self.props = {} + i = 0 + for item in metadata: + self.props[item[0]] = i + self.props[i] = i + i+=1 + + def fetchone(self): + row = self.cursor.fetchone() + if row is not None: + return RowProxy(self, row) + else: + return None + +class RowProxy: + def __init__(self, parent, row): + self.parent = parent + self.row = row + def __getitem__(self, key): + return self.row[self.parent.props[key]] diff --git a/lib/sqlalchemy/mapper.py b/lib/sqlalchemy/mapper.py index 2a178b56b6..ed0ebe3b04 100644 --- a/lib/sqlalchemy/mapper.py +++ b/lib/sqlalchemy/mapper.py @@ -36,14 +36,16 @@ addressmapper = Mapper(Address, addresses, properties = { import sqlalchemy.sql as sql import sqlalchemy.schema as schema +import sqlalchemy.engine as engine class Mapper(object): - def __init__(self, class_, selectable, properties = None, identitymap = None): + def __init__(self, class_, selectable, table = None, properties = None, identitymap = None): self.class_ = class_ - self.selectable = selectable - self.table = self._find_table(selectable) - + if table is None: + self.table = self._find_table(selectable) + else: + self.table = table self.props = {} for column in self.selectable.columns: @@ -60,15 +62,15 @@ class Mapper(object): def instances(self, cursor): result = [] - cursor = ResultProxy(cursor) + cursor = engine.ResultProxy(cursor) localmap = IdentityMap() while True: row = cursor.fetchone() if row is None: break - identitykey = localmap.get_key(row, self.class_, self.table, self.selectable) - if not localmap.map.has_key(identitykey): + identitykey = self._identity_key(row) + if not localmap.has_key(identitykey): instance = self._create(row, identitykey, localmap) result.append(instance) else: @@ -104,6 +106,8 @@ class Mapper(object): class TableFinder(sql.ClauseVisitor): def visit_table(self, table): + if hasattr(self, 'table'): + raise "Mapper can only create object instances against a single-table identity - specify the 'table' argument to the Mapper constructor" self.table = table def _find_table(self, selectable): @@ -131,8 +135,8 @@ class Mapper(object): return None for key, prop in self.props.iteritems(): prop.execute(instance, key, row, identitykey, localmap, False) - self.identitymap.map[identitykey] = instance - localmap.map[identitykey] = instance + self.identitymap[identitykey] = instance + localmap[identitykey] = instance return instance @@ -176,46 +180,10 @@ class EagerLoader(MapperProperty): subinstance = self.mapper._create(row, identitykey, localmap) list.append(subinstance) -class ResultProxy: - def __init__(self, cursor): - self.cursor = cursor - metadata = cursor.description - self.props = {} - i = 0 - for item in metadata: - self.props[item[0]] = i - self.props[i] = i - i+=1 - - def fetchone(self): - row = self.cursor.fetchone() - print "row: " + repr(row) - if row is not None: - return RowProxy(self, row) - else: - return None - -class RowProxy: - def __init__(self, parent, row): - self.parent = parent - self.row = row - def __getitem__(self, key): - return self.row[self.parent.props[key]] - -class IdentityMap(object): - def __init__(self): - self.map = {} - self.keystereotypes = {} - - def has_key(self, key): - return self.map.has_key(key) +class IdentityMap(dict): def get_key(self, row, class_, table, selectable): return (class_, table, tuple([row[column.label] for column in selectable.primary_keys])) - def get(self, key): - return self.map[key] - - - + _global_identitymap = IdentityMap() diff --git a/lib/sqlalchemy/sql.py b/lib/sqlalchemy/sql.py index 7438408d69..0bd9fa3826 100644 --- a/lib/sqlalchemy/sql.py +++ b/lib/sqlalchemy/sql.py @@ -126,6 +126,10 @@ class ClauseElement(object): c = self.compile(e, bindparams = params) return e.execute(str(c), c.get_params(**params)) + def result(self, **params): + e = self._engine() + c = self.compile(e, bindparams = params) + return e.result(str(c), c.get_params(**params)) class ColumnClause(ClauseElement): """represents a column clause element in a SQL statement.""" diff --git a/test/mapper.py b/test/mapper.py index a2fc249c75..3d0ee0b8ac 100644 --- a/test/mapper.py +++ b/test/mapper.py @@ -99,7 +99,6 @@ class MapperTest(PersistTest): ), identitymap = mapper.IdentityMap()) l = m.select() print repr(l) - print repr(m.identitymap.map) def tearDown(self): -- 2.47.2