sqlobject-discuss Mailing List for SQLObject (Page 435)
SQLObject is a Python ORM.
Brought to you by:
ianbicking,
phd
You can subscribe to this list here.
| 2003 |
Jan
|
Feb
(2) |
Mar
(43) |
Apr
(204) |
May
(208) |
Jun
(102) |
Jul
(113) |
Aug
(63) |
Sep
(88) |
Oct
(85) |
Nov
(95) |
Dec
(62) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2004 |
Jan
(38) |
Feb
(93) |
Mar
(125) |
Apr
(89) |
May
(66) |
Jun
(65) |
Jul
(53) |
Aug
(65) |
Sep
(79) |
Oct
(60) |
Nov
(171) |
Dec
(176) |
| 2005 |
Jan
(264) |
Feb
(260) |
Mar
(145) |
Apr
(153) |
May
(192) |
Jun
(166) |
Jul
(265) |
Aug
(340) |
Sep
(300) |
Oct
(469) |
Nov
(316) |
Dec
(235) |
| 2006 |
Jan
(236) |
Feb
(156) |
Mar
(229) |
Apr
(221) |
May
(257) |
Jun
(161) |
Jul
(97) |
Aug
(169) |
Sep
(159) |
Oct
(400) |
Nov
(136) |
Dec
(134) |
| 2007 |
Jan
(152) |
Feb
(101) |
Mar
(115) |
Apr
(120) |
May
(129) |
Jun
(82) |
Jul
(118) |
Aug
(82) |
Sep
(30) |
Oct
(101) |
Nov
(137) |
Dec
(53) |
| 2008 |
Jan
(83) |
Feb
(139) |
Mar
(55) |
Apr
(69) |
May
(82) |
Jun
(31) |
Jul
(66) |
Aug
(30) |
Sep
(21) |
Oct
(37) |
Nov
(41) |
Dec
(65) |
| 2009 |
Jan
(69) |
Feb
(46) |
Mar
(22) |
Apr
(20) |
May
(39) |
Jun
(30) |
Jul
(36) |
Aug
(58) |
Sep
(38) |
Oct
(20) |
Nov
(10) |
Dec
(11) |
| 2010 |
Jan
(24) |
Feb
(63) |
Mar
(22) |
Apr
(72) |
May
(8) |
Jun
(13) |
Jul
(35) |
Aug
(23) |
Sep
(12) |
Oct
(26) |
Nov
(11) |
Dec
(30) |
| 2011 |
Jan
(15) |
Feb
(44) |
Mar
(36) |
Apr
(26) |
May
(27) |
Jun
(10) |
Jul
(28) |
Aug
(12) |
Sep
|
Oct
|
Nov
(17) |
Dec
(16) |
| 2012 |
Jan
(12) |
Feb
(31) |
Mar
(23) |
Apr
(14) |
May
(10) |
Jun
(26) |
Jul
|
Aug
(2) |
Sep
(2) |
Oct
(1) |
Nov
|
Dec
(6) |
| 2013 |
Jan
(4) |
Feb
(5) |
Mar
|
Apr
(4) |
May
(13) |
Jun
(7) |
Jul
(5) |
Aug
(15) |
Sep
(25) |
Oct
(18) |
Nov
(7) |
Dec
(3) |
| 2014 |
Jan
(1) |
Feb
(5) |
Mar
|
Apr
(3) |
May
(3) |
Jun
(2) |
Jul
(4) |
Aug
(5) |
Sep
|
Oct
(11) |
Nov
|
Dec
(62) |
| 2015 |
Jan
(8) |
Feb
(3) |
Mar
(15) |
Apr
|
May
|
Jun
(6) |
Jul
|
Aug
(6) |
Sep
|
Oct
|
Nov
|
Dec
(19) |
| 2016 |
Jan
(2) |
Feb
|
Mar
(2) |
Apr
(4) |
May
(3) |
Jun
(7) |
Jul
(14) |
Aug
(13) |
Sep
(6) |
Oct
(2) |
Nov
(3) |
Dec
|
| 2017 |
Jan
(6) |
Feb
(14) |
Mar
(2) |
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
(1) |
Sep
|
Oct
(4) |
Nov
(3) |
Dec
|
| 2018 |
Jan
|
Feb
(1) |
Mar
|
Apr
|
May
|
Jun
(1) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| 2019 |
Jan
|
Feb
(1) |
Mar
|
Apr
(44) |
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
|
Nov
|
Dec
(1) |
| 2020 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
|
Dec
(1) |
| 2021 |
Jan
|
Feb
(1) |
Mar
|
Apr
|
May
|
Jun
(3) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| 2022 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
|
Nov
|
Dec
(1) |
| 2023 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(1) |
Sep
|
Oct
(1) |
Nov
(2) |
Dec
|
| 2024 |
Jan
|
Feb
|
Mar
|
Apr
(4) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(1) |
| 2025 |
Jan
|
Feb
(1) |
Mar
(1) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(1) |
Dec
(2) |
|
From: Michal K. <mi...@fr...> - 2003-04-13 15:40:16
|
...
># If not defined, "Unreadable attribute" error occurs...
> def _get_passwd(self):
> self._SO_get_passwd()
At least one mystery solved. Forfot to return something in
above method...
Mike
------------------------------------------------------------------------
Michal Kaukic (mi...@fr...)
Dept. of Math. Methods, Fac. of Manag. & Informatics
University of Zilina, Slovak Republic
|
|
From: Michal K. <mi...@fr...> - 2003-04-13 14:44:39
|
Hi, Ian and all,
I am Mathematician, no CS man at all, but I like generality
and clarity. So, SQLObject captured my attention.
Now I am trying to rethink our system for student exams agenda
in terms of SQLObject (current implementation is in Python/Webware
with psycopg PostgreSQL driver).
First, my understanding of SQLObject internals is very limited.
Or, maybe, I am pushing SQLObject beyond its current limits...
But my current work with SQLObject is like "debug thrice, write once" :-)
Despite this, I like it. So here are my remarks:
1. From PostgreSQL 7.3 documentation:
"Note: Prior to PostgreSQL 7.3, serial implied UNIQUE. This is no longer
automatic. If you wish a serial column to be UNIQUE or a PRIMARY KEY it
must now be specified, same as with any other data type."
So, I think, it will be useful to add this information to SQLObject
documentation (Using SQLObject/Declaring the Class).
In DBConnection.py, it is already O.K.
2. I refactored database tables several times to make them more
"SQLObject compliant". In one of attempts I choosed column names
like "Passwd" and got db. column name: "_passwd", which I not liked :-(
Users should not be trapped like that, if they are strictly using
proposed naming conventions. But for me, this happens.
Maybe, splitWords from util.py can be written like that:
def splitWords(s):
res = _translateRE.sub(lambda x: '_%s' % x.group(0).lower(), s)
if s[0].isupper():
return res[1:]
return res
3. Say, we have the following code fragment:
# ------------------------------ here begins ------------------
from SQLObject import *
from md5 import md5
# ...
class Student(SQLObject):
_idName='student_id'
_cacheValues=False
_columns=['name',
'surname',
'group',
Col('passwd',default=''),
Col('contact',default='')]
def _set_passwd(self,pwstr):
# This fails, self has (as yet) no attribute "id",
# which I can understand, but don't like
#
#if not pwstr:
# print self.__dict__
# pstr=str(self.__dict__['id'])
cryptpwd=md5(pstr).hexdigest()
print cryptpwd # I see, it is O.K
self._SO_set_passwd(cryptpwd)
# If not defined, "Unreadable attribute" error occurs...
def _get_passwd(self):
self._SO_get_passwd()
# ---------------------------- here ends ----------------------
This code used to work for me as generator of all kinds of troubles...
----------------------------------------
A. Trouble with creating Student object:
SQL statement for creating table is:
CREATE TABLE "student" (
"student_id" SERIAL PRIMARY KEY,
"name" varchar(20) NOT NULL,
"surname" varchar(20) NOT NULL,
"group" varchar(7) NOT NULL),
"passwd" varchar(32) DEFAULT '' NOT NULL,
"contact" varchar(128) DEFAULT '');
This will implicitly create the sequence "student_student_id"
for primary key.
But DBConnection.py, line 439 (checked yesterday) states:
c.execute('SELECT nextval(\'%s_id_seq\')' % table)
Should be the idName not involved in that?
Maybe:
c.execute('SELECT nextval(\'%s_%s_seq\')' % (table,idName)) ?
In my case, student_id_seq was expected, but student_student_id_seq
was the reality.
---------------------------------
B. Troubles with passwd attribute.
Let us create the student:
>>> S=Student.new(name='Milan',surname='Frco',group='5Z023',passwd='frc')
But what we see is:
>>> S
<Student 15007 name='Milan' ... group='5Z023' passwd=None contact=''>
The resulting query seems pretty O.K.:
INSERT INTO student (passwd, meno, priezv, skupina, contact, student_id)
VALUES ('f964379c80b1ab8b890cf40876fbd0aa', 'Milan', 'Frco',
'5Z023', '', 15007).
But, it seems like S.passwd has nothing in common with attribute
generated by "_set_passwd" method.
Without "_get_passwd" defined, we get "Unreadable attribute" error.
If we execute:
>>> S.passwd="caramba"
(Query is O.K., in database it IS updated.)
But, we still have passwd=None in S (also retrieving as S.passwd).
How can it be, I wonder...
But, also if I retrieve (in another Python commandline session)
the Student object with student_id=15007,
>>> P=Student(15007)
I still get "None" for password, although corresponding query
(SELECT passwd FROM student WHERE student_id = 15007) in psql
gives the right, MD5-encrypted password.
I had a goodwill to follow the first example in docs
(Customizing the Objects/Overriding Column Attributes),
but somewhere, something, goes wrong.
(Also, maybe, in second example form docs,
there should be the call:
"self._SO_set_phoneNumber(value)"
instead of
"self._SO_set_phoneNumber(self, value)".)
I will be very grateful, if someone can explain this behaviour and
suggest some way of creating "Student" with MD5-encrypted passwd
(even better - with initial value as the MD5-encrypted string
representation of "student_id").
------------------------------------
C. What we find, trying "destroy"...
Now, we want to delete the abovementioned object S from database.
I suppose (looking into source :-), the method "destroy" can do this:
>>> S.destroy()
>>> S
AssertionError: Student with id 15007 has become obsolete
So far, so good.
>>> del S
>>> S = Student(15007)
>>> S
.... (most of Traceback removed)
File "/usr/local/lib/python2.2/site-packages/SQLObject/SQLObject.py",
line 652, in _SO_getValue
return results[0]
TypeError: unsubscriptable object
This is the behaviour (in PostgreSQL/psycopg) if we retrieve any object
with nonexisting "id". Maybe, it would be better to make assertion like:
---------------------
(file SQLObject.py, lines 651,...):
self._SO_writeLock.release()
assert results != None, "%s with id %s is not in the database" \
% (self.__class__.__name__, self.id)
return results[0]
---------------------
Now, accessing S gives:
"AssertionError: Student with id 15007 is not in the database."
which is more to my liking.
That's all for now. Sorry for long posting...
Mike
|
|
From: Peter W. <pwi...@th...> - 2003-04-13 08:01:31
|
Hi, I've had a few discussions with some of the HTML folks I work with a some of them were a little wary of them dealing with Python code in the templates so I've been looking at the possibility of hooking other template engines into Draco that don't need Python code - these guys are used to various template kits sitting on top of Perl CGI's. Not having done a lot of Python before I had a quick look around and found what seems to be a nice simple template tool in SimpleTAL (http://www.owlfish.com/software/simpleTAL/). I've been able to plug it into Draco with a minimum of fuss, just a new import statement and a few lines changed to dracohandler.py, I've made no attempt at this stage to support multiple types of templates and switch between them but doing that would be quite simple I'd think. Also the really simple change I did knocks out support for tag rewriters but could be put back in easily I'm sure. Does this sound like something that could make sense in Draco - with a config option of some sort to choose the template engine to use. from simpletal import simpleTAL, simpleTALES and at line 471 (needs to have support for using normal Draco templates as well) if template: #environment = DracoEnvironment() context = simpleTALES.Context() if handler: #environment.update(handler) for key,value in handler.items(): context.addGlobal(key, value) response.addHeader('Cache-Control', 'no-cache') #rewriters = rewritemanager.rewriters() #parser = Parser(document, opener, environment, rewriters) #output = parser.parse() response.setBuffering(1) #response.write(output) templateFile = opener.open(document) template = simpleTAL.compileHTMLTemplate(templateFile) templateFile.close() template.expand(context, response) This takes a template that looks like: <html> <body> <h1 tal:content="title">Title</h1> <h2 tal:condition="username">Welcome back <b tal:replace="username">Username here</b></h2> <p> Links for today are: <ul> <li tal:repeat="news hotItems"><a href="http://www.sample.org/" tal:attributes="href news/link" tal:content="news/title">News item</a></li> </ul> </p> </body> </html> and when the __handler__.py has something like: def test(self, path, args): self["title"] = "Daily links" self["username"] = "peter w" self["hotItems"] = [ {"link": "http://www.yahoo.com", "title": "Yahoo!"}, {"link": "http://www.google.com", "title": "Google"}, {"link": "http://www.apple.com", "title": "Apple"} ] it generates: <html> <body> <h1>Daily links</h1> <h2>Welcome back peter w</h2> <p> Links for today are: <ul> <li><a href="http://www.yahoo.com">Yahoo!</a></li><li><a href="http://www.google.com">Google</a></li><li><a href="http://www.apple.com">Apple</a></li> </ul> </p> </body> </html> Interesting? regards, -- peter w. |
|
From: Matt M. <ma...@mo...> - 2003-04-13 07:25:23
|
Hello,
I have just checked out SQLObject from CVS and installed it on my
debian system (python2.3). I get the following when I attempt to run
the test program.
>>> p = Person.new(firstName="John", lastName="Doe", username="johnd")
Traceback (most recent call last):
File "people.py", line 161, in ?
runTest(test1)
File "people.py", line 159, in runTest
exec line[4:]
File "<string>", line 1, in ?
File "/usr/lib/python2.3/site-packages/SQLObject/SQLObject.py", line 665, in new
inst = cls(None)
File "/usr/lib/python2.3/site-packages/SQLObject/SQLObject.py", line 292, in __new__
inst = object.__new__(cls, id)
TypeError: default __new__ takes no parameters
Any idea what could be causing this?
Thanks,
Matt
|
|
From: Luke O. <lu...@me...> - 2003-04-12 22:17:33
|
Hi all -
Well, we've identified a few things that are merely
'irritations' at this point, but will become serious
trouble for our use of SQLObject in the future.
First problem: The inability of classRegistry/needSet to
import classes that aren't explicitly imported. For
example, if we have three classes "ProductSaved", "Product"
and "ProductType", and we're only dealing with
"ProductSaved" instances in a given class, accessing
"savedProductInstance.product.type" throws an exception (no
attribute _SO_class_ProductType), because ProductType is
not imported by either ProductSaved or Product (just
referenced by name as a foreignKey in Product).
Is the best solution to this just to do an import of all
classes referred to in a class (even if just by name) in
the class file? ie, Product would import ProductType? This
seems to be working for us, but should probably be
explicitly mentioned in the docs if it's the best way.
(Yes, I know such access breaks Law of Demeter or whatever,
but I believe the above example is a fairly reasonable one.
:)
Second problem, and one I don't have a solution for right
now: the interpreter-global uniqueness required of class
names for classRegistry. We don't run many instances of
Webware/Webkit for multiple sites, just run them as
multiple contexts. This makes two sites who have separate
"Product" objects conflict, but it seems to be a very
realistic problem...
Possible high-level solutions I can think of right now:
making class registry be keyed by the class modules'
__file__ attribute or similar (not fully thought through, I
realize this won't work because of needSet's now-ambiguous
names....)
Or having the ability to create specific classRegistrys,
sort of like having multiple object Stores. Haven't fully
thought this through, but my first thought is to simply add
another class-level or module-level attribute called
"_registry". The SQLObject classRegistry/needset would now
become dictionaries of dicationaries/lists, with a default
registry key called perhaps "__global" or some other
unlikely name. So needSet/setNeedSet would check the class
for the _registry variable, and search within the specified
sub-keyed areas only.
Not sure I explained that too well. classRegistry would now
look like (for my multiple Product example):
{
'__global': {},
'site1': {'Product': ...},
'site2': {'Product': ...}
}
based on the two Product classes specifying site1 or site2
as their registry.
Thoughts?
- Luke
|
|
From: Bud P. B. <bu...@si...> - 2003-04-12 07:55:44
|
Ian,
I thought more about my "higher-level" types and believe what I really
need are two hooks:
* afterLoad() that is called just after the object has been created from
data from the DBMS
* beforeStore() that is called just before storing data in the DBMS
By default, these don't do anything and need to be overloaded if one
wants to use them.
The following example shows how to apply this to my problem:
assume _columns contains
...
FloatCol('_ptX'),
FloatCol('_ptY'),
...
so with
def afterLoad(self):
point = Point(self._ptX, self._ptY)
I could really treat my data as being of type Point...
To make sure that storage is consistent, I'd need
def beforeStore(self):
self._ptX = self.point.x()
self._ptY = self.point.y()
The same approach obviously also solves the phoneNumber type
example...
Note that some of the attributes are probably not for direct use. I
indicated that by preceding their name with an underscore... But
maybe there is a way of having a keyword argument to Col called
'hidden' or similar such that I can only access it from the above
hook routines???
My intuition says that implementing these two hooks may be quite
straight forward or that they already exist. Can you give me some
more insight on this?
many thanks
--b
/-----------------------------------------------------------------
| Bud P. Bruegger, Ph.D.
| Sistema (www.sistema.it)
| Via U. Bassi, 54
| 58100 Grosseto, Italy
| +39-0564-411682 (voice and fax)
\-----------------------------------------------------------------
|
|
From: Ian B. <ia...@co...> - 2003-04-11 19:31:50
|
Okay, I got all confused because both of your first and last names start in B, and when I was first skimming through this I thought one of you was arguing with yourself. But no... anyway, to interject, I still don't feel there's a good use case for multiple keys (except legacy schemas) On Fri, 2003-04-11 at 08:44, Bud P.Bruegger wrote: > If this is your comments table, there are no problems. However, the > problem I try to illustrate uses the following table: > > CREATE TABLE ProjectWorkerComment( > project_id INT, > worker_id INT, > comment_id INT, > PRIMARY KEY (project_id, worker_id, comment_id), > FOREIGN KEY (project_id, worker_id) REFERENCES ProjectWorker); In this example you should have a join, in the spirit of RelatedJoin. Project would have a workerComment method that would return a list of (worker, comment) tuples, and Worker and Comment would have similar methods. So long as a table only contains references to other tables, it should be represented by a Join of some sort, the rows of that table should not be Python objects. After looking through examples, I feel increasingly confident that this intuition is correct -- rows without content of their own are derivative, and should be treated as such. Ian |
|
From: Ian B. <ia...@co...> - 2003-04-11 19:25:21
|
On Thu, 2003-04-10 at 10:02, Bud P.Bruegger wrote:
> Another thought on the relationship of alternateID and notNull:
>
> Doesn't the former imply the latter? If so, maybe the interface can
> be simplified.
Yes, the two should go together.
> Also, considering that SQLObject kind of hides the SQL and attempts a
> pythonic touch and feel, I don't like the term "notNull" since Null
> really comes from SQL world. NotNone would be more pythonic (but
> ugly), but what about "required"?
No, to me NOT NULL is not the same as required. "Required" can be
interpreted both as if the column has a default, and if NULL is
allowed. And then it could get confused with other requirements, like a
requirement like first_name can't be empty (''). The empty string in
many cases is just as ambiguous as NULL.
I know NULL is special in SQL, but I don't treat it as all that special,
and I know many other people don't either. notNone would be okay,
though I don't mind the SQL analog that comes through in notNull. I
*don't* feel NULL is the absence of a value in a general sense -- what
it means is contextual, just like None.
> And a change of topic:
> Just for completeness, it would be nice to also add Col keyword
> argument check, for example check="price > 0", and a special
> attribute _checks, for example _checks=[check("marriageDate >
> birthDate")], to access Check constraints of SQL. (See
> http://www.postgresql.org/docs/view.php?version=7.3&idoc=1&file=ddl-constraints.html#AEN1793).
I'm reluctant to add direct hooks for table creation. If you want close
control over your schemas it's still better to construct them manually
-- maybe at some point SQLObject will be more complete, but I don't want
to add things simply to force it to be complete.
In this case the check argument is an opaque hook to the schema creation
-- SQLObject can't understand what your asking, it can only pass it on
to the database. That's something I want to avoid.
Ian
|
|
From: Luke O. <lu...@me...> - 2003-04-11 18:15:21
|
I second Edmund's comments: GlobalIDs have a few specific purposes (which I personally try to avoid :)), but in the discussion of SQLObject being specially aware / making internal use of them, I'm opposed. - Luke Quoting Edmund Lian <el...@in...>: > > On 04/11/2003 01:47:59 PM Bud P.Bruegger wrote: > > >But what do you think of Globally Unique IDs? > > Seems unavoidable in certain situations--e.g., > implementing an access > control mechanism where you want to grant/revoke rights > to all sorts of > data scattered across all sorts of tables in a consistent > way. I've had to > do this myself, and I use triggers and rules to > generate/delete the global > IDs. > > I've yet to see a need to have global IDs in any other > situation though. > Use of global IDs seems to arise mostly when one tries to > force an RDBMS to > behave like an object store. > > ...Edmund. > > > > ------------------------------------------------------- > This SF.net email is sponsored by: Etnus, makers of > TotalView, The debugger > for complex code. Debugging C/C++ programs can leave you > feeling lost and > disoriented. TotalView can help you find your way. > Available on major UNIX > and Linux platforms. Try it free. www.etnus.com > _______________________________________________ > sqlobject-discuss mailing list > sql...@li... > https://lists.sourceforge.net/lists/listinfo/sqlobject-discuss > -- Many people are hamstrung by things like affection for fellow employees, honesty, desire to appear to be a "nice person," and other crippling limitations not suffered by the truly powerful and successful. |
|
From: Edmund L. <el...@in...> - 2003-04-11 17:55:35
|
On 04/11/2003 01:47:59 PM Bud P.Bruegger wrote: >But what do you think of Globally Unique IDs? Seems unavoidable in certain situations--e.g., implementing an access control mechanism where you want to grant/revoke rights to all sorts of data scattered across all sorts of tables in a consistent way. I've had to do this myself, and I use triggers and rules to generate/delete the global IDs. I've yet to see a need to have global IDs in any other situation though. Use of global IDs seems to arise mostly when one tries to force an RDBMS to behave like an object store. ...Edmund. |
|
From: Bud P. B. <bu...@si...> - 2003-04-11 17:48:55
|
On Fri, 11 Apr 2003 13:37:49 -0400 "Edmund Lian" <el...@in...> wrote: > >> > Another thought in this context is that PostgreSQL already inserts an > >> > object id column for every table. But maybe it's not a good idea to > >> > use since other dbms don't have equivalents... > > This is a really bad idea. OIDs are not preserved across db dumps, and are > optional in PG 7.3 and above, I think. > > ...Edmund. Edmund, point taken. I felt it was too implementation dependent myself when I thought of it. But what do you think of Globally Unique IDs? --b |
|
From: Edmund L. <el...@in...> - 2003-04-11 17:41:22
|
On 04/11/2003 04:45:37 AM Ian wrote: >Oh, I forgot to reply to this too. This is definitely on my mind. I >also wrote FunFormKit (funformkit.sf.net), which is a form >rendering/validation library. I'll be the first to admit it's too >complex, and I've wanted to reimplement it for some time... now my focus >is on reimplementing it with SQLObject in mind (though without any >actual ties). It probably wouldn't be that hard to do this rendering >right now with FFK -- Luke has mentioned at least using some stuff from >FFK with SQLObject -- but SQLObject's design makes me happy, and I want >the entire system to make me happy, and FFK doesn't do that for me. Amen. Definitely needs to be refactored/rewritten! It's very hard to extend/maintain in its current form. But, the interface to the Webware servlet is simple (at least for v0.4 and above), which is what made me use it instead of FormKit. ...Edmund. |
|
From: Edmund L. <el...@in...> - 2003-04-11 17:38:04
|
Ian Bicking <ia...@co...> wrote: >> > Another thought in this context is that PostgreSQL already inserts an >> > object id column for every table. But maybe it's not a good idea to >> > use since other dbms don't have equivalents... This is a really bad idea. OIDs are not preserved across db dumps, and are optional in PG 7.3 and above, I think. ...Edmund. |
|
From: Edmund L. <el...@in...> - 2003-04-11 17:34:34
|
On 04/10/2003 02:06:44 AM Ian Bicking wrote:
>On Thu, 2003-04-10 at 00:38, Edmund Lian wrote:
>> Composite keys are used an awful lot in any schema of moderate
complexity,
>> and they are important (when used with foreign key constraints) for
>> enforcing relational integrity. If the aim is for SQLObject to support
>> complex projects, then composite key support would be pretty important.
>
>Can you describe some situations where they'd be used? For instance, if
>either key was modified at any time that'd cause a lot of problems for
>SQLObject. If not, then what would be the problem with a third simple
>ID/PRIMARY KEY column?
Hmmm... Here's a contrived example that typifies how I use them.
create table category (
name varchar(100),
--
constraint category_pk
primary key (name)
);
create table item (
name varchar(100),
--
constraint item_pk
primary key (name)
);
create table category_item_map (
category varchar(100),
item varchar (100),
--
constraint category_item_pk
primary key (category, item),
constraint category_item_category_fk
foreign key (category) references category (name)
on update cascade
on delete cascade,
constraint category_item_item_fk
foreign key (item) references item (name)
on update cascade
on delete cascade
);
The argument against using real rather than surrogate primary keys (which
is what you are doing) is typically that primary keys have business
meaning, and that changing them becomes difficult because the changes in
one table must be somehow cascade through all the other tables that use the
primary keys of one table as foreign keys.
There are really two separate issues here. Let's look at the first
one--that it is bad to have primary keys which have business meaning. Yes,
they do have business meaning, because they are integrity constraints.
That's what you want. Without integrity constraints, the data in the DB has
no meaning.
Constraints are to data as are grammar is to words. Without grammar, a page
of written text would be just a jumble of words. You derive meaning from
written text only if the reader and writer agree to certain rules of
grammar, which constrains the words to have certain order, roles, etc. To
push the point further, consider three words: "eat", "I", and "meat".
Without grammatical constraints, and of the following is possible:
meat eat I
eat meat I
meat I eat
meat eat I
I meat eat
I eat meat
Now suppose we agree to some constraints--grammatical rules. The rules we
agree to are:
Phrases must be in subject-verb-object order
Action words are verbs
Pronouns are subject nouns
+ a few other rules which I won't bore you with.
Once we constrain the words with grammar, the only valid combination is: I
eat meat
So, it is critically important to have constraints in the DB. They
determine the semantics of the data almost completely. To use surrogate
keys instead of real keys weakens the integrity constraints substantially.
The second issue--that real primary keys are troublesome because when the
business meaning changes, they have to be changed, and this is tough to do.
This argument might be true in Oracle, but it is not true in PostgreSQL and
a few other databases that support the "on update cascade" clause in
foreign key constraints.
With the table definitions I have above, an update or deletion to a primary
key in the category or item table cascade through to all the tables that
use the updated primary key as a foreign key. This is so very nice, and is
one reason why I say that Oracle is actually more backward than PostgreSQL
in some respects.
...Edmund.
|
|
From: Bud P. B. <bu...@si...> - 2003-04-11 17:32:09
|
Ian, just ran a quick test for the check constraint that I added for EnumCol for postgres and it seems to work. all changes that I made are in the attached diff and listed in the changes file. (It seems that you changed two lines in Col.py between two of my checkouts from CVS--but you'll recognize those, I'm sure) let me know how these changes look --b /----------------------------------------------------------------- | Bud P. Bruegger, Ph.D. | Sistema (www.sistema.it) | Via U. Bassi, 54 | 58100 Grosseto, Italy | +39-0564-411682 (voice and fax) \----------------------------------------------------------------- |
|
From: Bud P. B. <bu...@si...> - 2003-04-11 13:45:47
|
On Fri, 11 Apr 2003 08:23:51 -0500 Brad Bollenbach <br...@bb...> wrote: > In either case, this will not affect anything in comments, because > this is a table that would probably look like: > > Comments > comment_id > comment_desc > ... > etc. If this is your comments table, there are no problems. However, the problem I try to illustrate uses the following table: CREATE TABLE ProjectWorkerComment( project_id INT, worker_id INT, comment_id INT, PRIMARY KEY (project_id, worker_id, comment_id), FOREIGN KEY (project_id, worker_id) REFERENCES ProjectWorker); It may not be a realistic example, but I was attempting to quickly think of something to add additional levels to the hierarchy of composite foreign key relationships. If you have such a hierachy, changing relationships at a higher level (for business logic reasons) implies that you change the composite keys of all related tables at lower levels. --b |
|
From: Brad B. <br...@bb...> - 2003-04-11 13:24:36
|
On 04/11/03 15:08, Bud P. Bruegger wrote: > On Fri, 11 Apr 2003 07:58:45 -0500 > Brad Bollenbach <br...@bb...> wrote: > > > There's no implication in there that they do carry business > > meaning. I.e. project_id and worker_id could easily be integers (and > > each table could later have a name column, e.g. project_name, > > worker_name, etc.) > > Hmmm. you're right! > > But assume there are other tables referencing ProjectWorker; say > ProjectWorkerComment. Assume, they also use composite keys: > > project_id > worker_id > comment_id > > (where (project_id, worker_id) is a foreign key referencing > ProjectWorker > > Then, if you reassign the project to another worker, you also have to > change the composite key of the related comments. > > So you could say that the business meaning is not in the key itself > but in the relationships you define in terms of the keys... Hmmmm, I don't see the problem here. You have two options when assigning a different worker to the project: 1. A simple update on worker_id, in which case all previous comments in your comments table will now look like they refer to that new worker_id (which may or may not be what you want). 2. Inserting a new row into ProjectWorker, which provides separation between the comments related to each worker who's done work on the project. In either case, this will not affect anything in comments, because this is a table that would probably look like: Comments comment_id comment_desc ... etc. It doesn't care what kind of update-fu you do on the composite key of ProjectWorker (and ProjectWorker probably doesn't care either, unless -- of course -- the update tries to duplicate an existing project/worker pair). -- Brad Bollenbach BBnet.ca |
|
From: Bud P. B. <bu...@si...> - 2003-04-11 13:09:21
|
On Fri, 11 Apr 2003 07:58:45 -0500 Brad Bollenbach <br...@bb...> wrote: > There's no implication in there that they do carry business > meaning. I.e. project_id and worker_id could easily be integers (and > each table could later have a name column, e.g. project_name, > worker_name, etc.) Hmmm. you're right! But assume there are other tables referencing ProjectWorker; say ProjectWorkerComment. Assume, they also use composite keys: project_id worker_id comment_id (where (project_id, worker_id) is a foreign key referencing ProjectWorker Then, if you reassign the project to another worker, you also have to change the composite key of the related comments. So you could say that the business meaning is not in the key itself but in the relationships you define in terms of the keys... --b |
|
From: Brad B. <br...@bb...> - 2003-04-11 12:59:30
|
On 04/11/03 09:45, Bud P. Bruegger wrote: > On Thu, 10 Apr 2003 18:22:11 -0500 > Brad Bollenbach <br...@bb...> wrote: > > > Project > > project_id PK > > ... > > > > Worker > > worker_id PK > > ... > > > > ProjectWorker > > project_id FK > > worker_id FK > > (together they're the PK) > > hourly_rate > > ... > > > > and so on. > > But in my experience, it gets hard if these keys have to change--and > since they carry business meaning, it is not always inevitable (people > even in rare cases change social security numbers...). For example, > assume you reassign a project to another worker... If there is a key > without any business meaning whatsoever, changing is MUCH easier... There's no implication in there that they do carry business meaning. I.e. project_id and worker_id could easily be integers (and each table could later have a name column, e.g. project_name, worker_name, etc.) -- Brad Bollenbach BBnet.ca |
|
From: Ian B. <ia...@co...> - 2003-04-11 08:44:50
|
On Thu, 2003-04-10 at 16:10, Steve Holden wrote: > I'd also like to hear ideas about a possible "web form rendering" mixin that > allows a collection of columns to be input from, or populate, a form in a > web page. Oh, I forgot to reply to this too. This is definitely on my mind. I also wrote FunFormKit (funformkit.sf.net), which is a form rendering/validation library. I'll be the first to admit it's too complex, and I've wanted to reimplement it for some time... now my focus is on reimplementing it with SQLObject in mind (though without any actual ties). It probably wouldn't be that hard to do this rendering right now with FFK -- Luke has mentioned at least using some stuff from FFK with SQLObject -- but SQLObject's design makes me happy, and I want the entire system to make me happy, and FFK doesn't do that for me. It's hard, though, because FFK is fairly advanced -- more advanced than any other form processor I've seen (though I haven't done a survey of alternatives in some time). I want my new system to be just as advanced, but a high bar can feel stifling (excuse the mixed metaphor). Ian |
|
From: Frank B. <fb...@fo...> - 2003-04-11 08:31:17
|
Hallo, Ian Bicking hat gesagt: // Ian Bicking wrote: > That's a bug bug, not a version bug. It's fixed in CVS. Thanks a lot Ian, now with current CVS everything (that I use) seems to be working fine on python 2.2.0 except the installation. This might be a broken Suse-rpm, but "cp -r build/lib/SQLObject /usr/lib/python2.2/site-packages" was all that's needed. I'm really impressed with the ease of use that SQLObject gives. It saves a h*ll of a lot of typing and JustWorks(tm) for my project. This is a survey application with Webware, where website users get asked how they like the website. So far only the "add questions and answers" editing interface is done, but it just took me a couple of hours to hack this together thanks to SQLObject. I'm sure, the real survey will be done just as fast. In this project, performance will be not that important, because we only have a handful of data, but I wonder how good the performance with really big databaseses would be? Doesn't SO issue rather plenty of selects so that performance might drop if lots of data is involved? Also what would be a preferred way of pooling database connections for SO in Webware? Does Webware's datapool make sense in the context of SQLObject? I fear, that every SQLObject I use creates and drops its own database connection, which would be bad for performance. ciao -- Frank Barknecht _ ______footils.org__ |
|
From: Bud P. B. <bu...@si...> - 2003-04-11 07:58:10
|
On 10 Apr 2003 13:26:27 -0500 Ian Bicking <ia...@co...> wrote: > On Thu, 2003-04-10 at 12:14, Bud P.Bruegger wrote: > > Maybe, it would be possible to add yet another subclass to Col that > > has an "sqlType" keyword attribute and simply passes on what is > > written there to the DBMS. This would allow to take advantage of > > "advanced" types that some DBMS provide. > > If your class has a sqlRepr() method, then that will be called to get > the SQL representation. I should name that __sql_repr__ or something, > though... > > Anyway, that's the hook you want. > > Ian great! I'll have to look into this more closely... thanks --b |
|
From: Bud P. B. <bu...@si...> - 2003-04-11 07:56:13
|
On 10 Apr 2003 13:32:09 -0500 Ian Bicking <ia...@co...> wrote: > > Hmmm... I'm not clear here. You mean that the fields have subfields, > like some_table.some_point.x ? Yes. Say I have the attribute "location" of type "Point" in the say "Office" class. A Point is basically specified by a coordinate pair (x/y or lat/long or whatever). Currently, I could define Point as a subclass of SQLObject and join Point and Office--but since an office is always in a single location, this would degenerate into 1:1 relationships that are rather inefficient... So if one could define 1:1 relationships that cause an "inlining" of the attributes or the related object, that would be great. > You could add something to SQLBuilder to > use this in queries fairly easily. For actual retrieval, it's up to > either some (not-yet-implemented) Constraint system to handle it, or the > database adapter. And the sqlRepr method I mentioned in the other > email. /----------------------------------------------------------------- | Bud P. Bruegger, Ph.D. | Sistema (www.sistema.it) | Via U. Bassi, 54 | 58100 Grosseto, Italy | +39-0564-411682 (voice and fax) \----------------------------------------------------------------- |
|
From: Bud P. B. <bu...@si...> - 2003-04-11 07:47:53
|
On 11 Apr 2003 01:37:10 -0500 Ian Bicking <ia...@co...> wrote: > > Site > > site_id PK > > ... > > > > User > > user_id PK > > ... > > > > UserSite > > user_id FK > > site_id FK > > (together they're the PK) > > ... > > This seems like a many-to-many relation, which SQLObject doesn't > represent as a Python object, and which doesn't require any ID. The difference to many-to-many relationships (in my understanding) is that the "breakup" table has many more columns than just necessary for linking. --b /----------------------------------------------------------------- | Bud P. Bruegger, Ph.D. | Sistema (www.sistema.it) | Via U. Bassi, 54 | 58100 Grosseto, Italy | +39-0564-411682 (voice and fax) \----------------------------------------------------------------- |
|
From: Bud P. B. <bu...@si...> - 2003-04-11 07:46:30
|
On Thu, 10 Apr 2003 18:22:11 -0500 Brad Bollenbach <br...@bb...> wrote: > Project > project_id PK > ... > > Worker > worker_id PK > ... > > ProjectWorker > project_id FK > worker_id FK > (together they're the PK) > hourly_rate > ... > > and so on. But in my experience, it gets hard if these keys have to change--and since they carry business meaning, it is not always inevitable (people even in rare cases change social security numbers...). For example, assume you reassign a project to another worker... If there is a key without any business meaning whatsoever, changing is MUCH easier... --b |