Fixed #7783 -- Made introspection of nullable columns more robust with Postgres.
Thanks bthomas AT ncorcle DOT com for the report and initial patch, and Claude Paroz for the final, complete patch. git-svn-id: http://code.djangoproject.com/svn/django/trunk@17508 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
4b81d790a8
commit
ccc0e122d4
|
@ -34,8 +34,16 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
|
||||||
|
|
||||||
def get_table_description(self, cursor, table_name):
|
def get_table_description(self, cursor, table_name):
|
||||||
"Returns a description of the table, with the DB-API cursor.description interface."
|
"Returns a description of the table, with the DB-API cursor.description interface."
|
||||||
|
# As cursor.description does not return reliably the nullable property,
|
||||||
|
# we have to query the information_schema (#7783)
|
||||||
|
cursor.execute("""
|
||||||
|
SELECT column_name, is_nullable
|
||||||
|
FROM information_schema.columns
|
||||||
|
WHERE table_name = %s""", [table_name])
|
||||||
|
null_map = dict(cursor.fetchall())
|
||||||
cursor.execute("SELECT * FROM %s LIMIT 1" % self.connection.ops.quote_name(table_name))
|
cursor.execute("SELECT * FROM %s LIMIT 1" % self.connection.ops.quote_name(table_name))
|
||||||
return cursor.description
|
return [tuple([item for item in line[:6]] + [null_map[line[0]]==u'YES'])
|
||||||
|
for line in cursor.description]
|
||||||
|
|
||||||
def get_relations(self, cursor, table_name):
|
def get_relations(self, cursor, table_name):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -5,7 +5,7 @@ class Reporter(models.Model):
|
||||||
first_name = models.CharField(max_length=30)
|
first_name = models.CharField(max_length=30)
|
||||||
last_name = models.CharField(max_length=30)
|
last_name = models.CharField(max_length=30)
|
||||||
email = models.EmailField()
|
email = models.EmailField()
|
||||||
facebook_user_id = models.BigIntegerField()
|
facebook_user_id = models.BigIntegerField(null=True)
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return u"%s %s" % (self.first_name, self.last_name)
|
return u"%s %s" % (self.first_name, self.last_name)
|
||||||
|
|
|
@ -78,6 +78,14 @@ class IntrospectionTests(TestCase):
|
||||||
['IntegerField', 'CharField', 'CharField', 'CharField', 'BigIntegerField']
|
['IntegerField', 'CharField', 'CharField', 'CharField', 'BigIntegerField']
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_get_table_description_nullable(self):
|
||||||
|
cursor = connection.cursor()
|
||||||
|
desc = connection.introspection.get_table_description(cursor, Reporter._meta.db_table)
|
||||||
|
self.assertEqual(
|
||||||
|
[r[6] for r in desc],
|
||||||
|
[False, False, False, False, True]
|
||||||
|
)
|
||||||
|
|
||||||
# Regression test for #9991 - 'real' types in postgres
|
# Regression test for #9991 - 'real' types in postgres
|
||||||
@skipUnlessDBFeature('has_real_datatype')
|
@skipUnlessDBFeature('has_real_datatype')
|
||||||
def test_postgresql_real_type(self):
|
def test_postgresql_real_type(self):
|
||||||
|
|
Loading…
Reference in New Issue