String mit NULL-Value in SQLite schreiben

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
Benutzeravatar
noisefloor
User
Beiträge: 3843
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

wie kann man eine String mit NULL Value (also \x00) in einen SQLite BLOB-Feld schreiben?

Der String kommt vom Lesen einer Datei im Binär-Modus, also z.B.

Code: Alles auswählen

with open('bild.jpg','rb') as f:
    data = f.read()
Schreibt man dann "data" so in in eine BLOB-Feld, klappt der Schreibvorgang nur bis zum 1. "\x00". Also wenn der String mit "\xff\xd8\xff\xe0\x00\x10JFIF" wird nur bis "\xe0" geschrieben und dann nicht mehr.

Eine Fehlermeldung wird nicht ausgegeben, d.h. das Schreiben (und auch Lesen) des "gekürzten" Strings klappt.

AFAIK liegt das daran, dass \x00 standardmäßig als Dateienden angesehen wird, d.h. Python "denkt" an dieser Stelle: "das war's".

Gruß, noisefloor
BlackJack

@noisefloor: \0 ist nicht das Ende von Dateien, sondern von Zeichenketten. SQLite weiss nicht dass Deine Zeichenkette keine Zeichenkette sein soll. Du musst sie explizit in `sqlite3.Binary` "wrappen".

Code: Alles auswählen

In [368]: db = sqlite.connect(':memory:')

In [369]: c = db.cursor()

In [370]: c.execute('create table test (blob data)')
Out[370]: <sqlite3.Cursor object at 0x9c810e0>

In [371]: c.execute('insert into test values (?)', ('abc\0def',))
Out[371]: <sqlite3.Cursor object at 0x9c810e0>

In [372]: c.execute('insert into test values (?)', (sqlite.Binary('abc\0def'),))
Out[372]: <sqlite3.Cursor object at 0x9c810e0>

In [373]: db.commit()

In [374]: c.execute('select * from test')
Out[374]: <sqlite3.Cursor object at 0x9c810e0>

In [375]: c.fetchall()
Out[375]: [(u'abc',), (<read-write buffer ptr 0x9d21d60, size 7 at 0x9d21d40>,)]

In [376]: a = _[-1][0]

In [377]: str(a)
Out[377]: 'abc\x00def'
Benutzeravatar
noisefloor
User
Beiträge: 3843
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

THX. :-)

Wo findet man so Hinweise? In der SQLite Online-Doku von Python steht so was nicht...

Code: Alles auswählen

dir(sqlite3)
listet zwar Binary auf, ein

Code: Alles auswählen

help(sqlite.binary)
ist IMHO aber eher kryptisch als hilfreich...

Gruß, noisefloor
BlackJack

@noisefloor: Das ist keine "Eigenentwicklung" von den Entwicklern des `sqlite`-Moduls -- die haben einfach den eingebauten `buffer`-Typ an den Namen `Binary` gebunden. Die Kritik an der Doku müsste man also bei den Python-Entwicklern loswerden.

Code: Alles auswählen

In [420]: sqlite.Binary
Out[420]: <type 'buffer'>

In [421]: buffer
Out[421]: <type 'buffer'>

In [422]: sqlite.Binary is buffer
Out[422]: True
Antworten