2013-03-20 15 views
5

Mam następujący model w Django:Django - Oracle błąd wewnętrzny

class Event(models.Model): 
    # some fields 
    start_date = models.DateField() 
    end_date = models.DateField() 

Używam Oracle Database 10g z Django 1.5 i cx_Oracle 5.1.2. Chodzi tu przy próbie utworzenia nowego obiektu w interfejsie administratora (picking daty z kalendarza), jest następujący błąd podniesiony:

ORA-01843: not a valid month 

syncdb stworzył DATE pole w Oracle dla start_date i end_date. Czy to wygląda jak błąd backendu, czy robię coś nie tak?

Mam inne modele z DateTimeField() i działają dobrze, gdy utrzymuję nowe obiekty, problem wygląda na sam z siebie DateField.

UPDATE: Sprawdziłem realizacji zaplecza, aw backends/oracle/base.py linii 513 do 516:

cursor.execute(
    "ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS'" 
    " NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF'" 
    + (" TIME_ZONE = 'UTC'" if settings.USE_TZ else '')) 

Wykonanie tego komunikatu umożliwia INSERT mieć wartości literalne dla DATE dziedzinach. Sprawdziłem zapytanie generowane przez backend i wstawia ono '2013-03-20' w start_date i end_date. Data pasuje do NLS_DATE_FORMAT, więc to teoretycznie powinno działać!

UPDATE: Uważam, że moja sprawa to related to cx_oracle.

UPDATE: Ponieważ ja wciąż nie ma jednoznacznej odpowiedzi (chociaż jestem prawie pewien, że to cx_Oracle który jest przyczyną tego problemu), zmieniłem DateField do DateTimeField co przekłada się na Oracle TIMESTAMP i działa perfekcyjnie.

+0

Więc po prostu być jasne, jesteś sprawdzanie tabel Oracle SYS dla SQL jest prowadzony i widząc coś takiego 'TO_DATE (" 2013- 03-20 ',' RRRR-MM-DD ') 'we wkładce?Z twojego pytania wygląda ono jak "NLS_DATE_FORMAT =" RRRR-MM-DD HH24: MI: SS' ", które różni się od rzeczywistej wstawki, chociaż nie wiem, jaki byłby efekt w tym kontekście. – woemler

+0

Nie, ze względu na ustawienie zestawienia sesji zmian "NLS_DATE_FORMAT", można wstawić datę jako literał bez znaku to_date, co ma miejsce, gdy sprawdzam wykonywany SQL. – abstractpaper

+0

Czy umieścisz odpowiedni SQL uruchamiany na serwerze, który powoduje błąd "ORA-01843"? – woemler

Odpowiedz

-2

Przyczyną błędu jest wpisanie daty, ale część miesiąca daty nie była prawidłowym miesiącem. Oracle wydaje rozwiązania tego problemu.

- Ponownie wprowadź wartość daty albo za pomocą maski formatu MONTH lub MON. Poprawne wartości dla miesiąca są:

January 
February 
March 
....... 
//and soon 

LUB

Jan 
Feb 
Mar 
....... 
//and soon 

- jeśli powyższa uchwała nie powiodła się, należy to_date function zamiast.

to_date(string1, [ format_mask ], [ nls_language ]) 
1

podstawie jtiai problemu description, zrobiłem następujące obejścia - przed wywołaniem jakiegokolwiek problematycznego SQL-a (np Oracle 10.5.0.2 i 11.2.0.1, cx_Oracle 5.1.2), reset NLS_DATE_FORMAT/NLS_TIMESTAMP_FORMAT ponownie - odbywa się w django/db/backendy/oracle/base.py w metodzie def execute(...):

--- base.py 2013-10-31 12:19:24.000000000 +0100 
+++ base_new.py 2013-10-31 12:20:32.000000000 +0100 
@@ -707,6 +707,18 @@ 
     query = convert_unicode(query % tuple(args), self.charset) 
     self._guess_input_sizes([params]) 
     try: 
+   # BUG-WORKAROUND: ulr1-131031 
+   # https://stackoverflow.com/a/17269719/565525 
+   # It's actually a bug in the Oracle 10.5.0.2 and 11.2.0.1. Bug can be reproduced as following: 
+   #  - set NLS_TIMESTAMP_FORMAT in session. 
+   #  - Run any implicit or explicit TO_DATE conversion with unicode data. 
+   #  - **Next implicit or explicit TO_TIMESTAMP with unicode data will trigger internal reset of timestamp format.** 
+   #  - All consecutive TO_TIMESTAMP will fail and TO_CHAR of timestamp will produce invalid output. 
+   self.cursor.execute(
+    "ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS'" 
+    " NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF'" 
+    + (" TIME_ZONE = 'UTC'" if settings.USE_TZ else '')) 
+ 
      return self.cursor.execute(query, self._param_generator(params)) 
     except Database.IntegrityError as e: 
      six.reraise(utils.IntegrityError, utils.IntegrityError(*tuple(e.args)), sys.exc_info()[2])