on August 21, 2010
Topics: Google Query Language, General Patton and an apprentice at our software startup.
Google as you know allows its employees to take 20% of their time to do their own pet projects: 80% for the company and 20% for their own.
Our company? Yes, our ratio is almost the reverse, especially for the interns and the apprentices. They take 80% of their time to do their own pet projects and their own learning: 20% for the company and 80% for their own. So, they put in about 2 hours per day, out of 10 hours working time (10 hours include 2 hour lunch time and other breaks!)
Even then, I wonder, "Is this apprentice wasting our time?"
And General Patton? The famous American WW II tank commander? What does he have to do with software?
The answer: a lot.
If impatient, just go leap to the conclusion.
Example 1
from google.appengine.ext import db
from models.tutor import Residence
import inspect
query = db.GqlQuery("SELECT * FROM Residence WHERE "
"dimensions IN :mydimensions "
"AND locations IN :mylocs "
"AND rent < :myrent "
"AND gender = :mygender"
,
mydimensions =["30x60", ],
mylocs = ['W', "W"],
myrent = 41,
mygender= "M"
)
print inspect.getmembers(query)
which gives the following result:
[('__class__', ),
('__delattr__', ),
('__dict__', {'_namespace': None, '_proto_query': , '_kwds': {'mylocs': ['W', 'W'], 'mydimensions': ['30x60'],
'myrent': 41, 'mygender': 'M'}, '_args': [], '_model_class': ,
'_keys_only': False, '_cursor': None, '_end_cursor': None, '_compile': True}),
('__doc__', 'A Query class that uses GQL query syntax instead of .filter() etc.'),
('__getattribute__', ),
('__getitem__', bound method GqlQuery.__getitem__ of >), ('__hash__', ),
('__init__', bound method GqlQuery.__init__ of ('__iter__', bound method GqlQuery.__iter__ of google.appengine.ext.db.GqlQuery object at 0xaa7dd6c>>), ('__module__', 'google.appengine.ext.db'),
('__new__', built-in method __new__ of type object at 0x8146a20),
('__reduce__', built-in method __reduce__ of GqlQuery object at 0xaa7dd6c),
('__reduce_ex__', built-in method __reduce_ex__ of GqlQuery object at 0xaa7dd6c),
('__repr__', method-wrapper '__repr__' of GqlQuery object at 0xaa7dd6c),
('__setattr__', method-wrapper '__setattr__' of GqlQuery object at 0xaa7dd6c),
('__str__', method-wrapper '__str__' of GqlQuery object at 0xaa7dd6c), ('__weakref__', None), ('_args', []), ('_compile', True), ('_cursor', None), ('_end_cursor', None),
('_get_query', bound method GqlQuery._get_query of google.appengine.ext.db.GqlQuery object at 0xaa7dd6c),
('_keys_only', False), ('_kwds', {'mylocs': ['W', 'W'],
'mydimensions': ['30x60'], 'myrent': 41, 'mygender': 'M'}), ('_model_class', class 'models.tutor.Residence'),
('_namespace', None),
('_proto_query', google.appengine.ext.gql.GQL object at 0xaa7d6ac),
('bind', bound method GqlQuery.bind of google.appengine.ext.db.GqlQuery object at 0xaa7dd6c),
('count', bound method GqlQuery.count of google.appengine.ext.db.GqlQuery object at 0xaa7dd6c),
('cursor', bound method GqlQuery.cursor of google.appengine.ext.db.GqlQuery object at 0xaa7dd6c),
('fetch', bound method GqlQuery.fetch of google.appengine.ext.db.GqlQuery object at 0xaa7dd6c),
('get', bound method GqlQuery.get of google.appengine.ext.db.GqlQuery object at 0xaa7dd6c),
('is_keys_only', bound method GqlQuery.is_keys_only of google.appengine.ext.db.GqlQuery object at 0xaa7dd6c), ('run', bound method GqlQuery.run of google.appengine.ext.db.GqlQuery object at 0xaa7dd6c), ('with_cursor', bound method GqlQuery.with_cursor of google.appengine.ext.db.GqlQuery object at 0xaa7dd6c)]
Example 2
from google.appengine.ext import db
from models.tutor import Residence
import inspect
query = db.GqlQuery("SELECT * FROM Residence WHERE "
"dimensions IN :mydimensions "
"AND locations IN :mylocs "
"AND rent < :myrent "
"AND gender = :mygender"
,
mydimensions =["30x60", ],
mylocs = ['W', "W"],
myrent = 41,
mygender= "M"
)
print query.__dict__
which gives the following result:
{'_namespace': None, '_proto_query': , '_kwds':
{'mylocs': ['W', 'W'], 'mydimensions': ['30x60'], 'myrent': 41, 'mygender': 'M'}, '_args': [],
'_model_class': class 'models.tutor.Residence', '_keys_only': False, '_cursor': None,
'_end_cursor': None, '_compile': True}
Example 3
from google.appengine.ext import db
from models.tutor import Residence
import inspect
query = db.GqlQuery("SELECT * FROM Residence WHERE "
"dimensions IN :mydimensions "
"AND locations IN :mylocs "
"AND rent < :myrent "
"AND gender = :mygender"
,
mydimensions =["30x60", ],
mylocs = ['W', "W"],
myrent = 41,
mygender= "M"
)
obj1= query.__dict__['_proto_query']
print obj1
which gives the following result:
google.appengine.ext.gql.GQL object at 0xaa7814c
Example 4
from google.appengine.ext import db
from models.tutor import Residence
import inspect
query = db.GqlQuery("SELECT * FROM Residence WHERE "
"dimensions IN :mydimensions "
"AND locations IN :mylocs "
"AND rent < :myrent "
"AND gender = :mygender"
,
mydimensions =["30x60", ],
mylocs = ['W', "W"],
myrent = 41,
mygender= "M"
)
obj1= query.__dict__['_proto_query']
print obj1.__dict__['_GQL__symbols']
which gives the following result:
['SELECT', '*', 'FROM', 'Residence',
'WHERE', 'dimensions', 'IN', ':mydimensions',
'AND', 'locations', 'IN', ':mylocs',
'AND', 'rent', '<', ':myrent',
'AND', 'gender', '=', ':mygender']
which gradually leads to
['SELECT', '*', 'FROM', 'Residence',
'WHERE', 'name', '=', ':myname',
'AND', 'email', '=', ':myemail',
'AND', 'phone', '=', ':myphone',
'AND', 'rent', '=', ':myrent',
'AND', 'neighborhood', '=', ':myneighborhood',
'AND', 'transportation', '=', ':mytransportation',
'AND', 'gender', '=', ':mygender',
'AND', 'race', '=', ':myrace',
'AND', 'dimensions', 'IN', ':mydimensions',
'AND', 'locations', 'IN', ':mylocations',
'ORDER', 'BY', 'email', 'DESC', ',', 'rent', 'ASC']
Conclusion
At one time in WW II, the rumors (which was actually true) went that the German tanks were far stronger than the American tanks. General Patton must have known this before anyone else.
Did he admit the truth? No.
Did he lie and refute the truth? No.
What did he say? He said in effect that
he never intended to use his tanks that way. His tanks were to do something else, not ram/bump/jar into or out-punch/out-slug/out-shoot the opponent tanks. Read more about that here.
The younger software developer wants to look into the nuts and bolts of a tank (a deliberately mixed metaphor).
The older General just wants him to look into the logic of his query in pseudo-code or read the doc for GQL(mixed again).
Engineers and soldiers
programmers and suits
engineers and marketers
Anyway, we gave the apprentice a pat on the back.
Whether he works his 2 hours as Engineer or Soldier, is fine with us.