Negative string size (or size too big)

Witam,

mam problem z przechwyceniem wyniku bazy danych i zapisaniu go do tablicy:

def print_result_array result_array = Array.new while row=@sth.fetch_array do result_array.push(row) end puts result_array.size return result_array end
Przy wywolaniu tej metody mam blad:

negative string size (or size too big)
/usr/local/rvm/gems/ruby-1.9.3-p0@sp_qas/gems/dbd-odbc-0.2.5/lib/dbd/odbc/statement.rb:41:in fetch' /usr/local/rvm/gems/ruby-1.9.3-p0@sp_qas/gems/dbd-odbc-0.2.5/lib/dbd/odbc/statement.rb:41:infetch’
/usr/local/rvm/gems/ruby-1.9.3-p0@sp_qas/gems/rails-dbi-0.1.2/lib/dbi/handles/statement.rb:259:in `fetch_array’

Uzywam ruby ruby 1.9.3p0 (2011-10-30 revision 33570) [x86_64-linux]

Problem w tym ze w rubym 1.9.2-p290 nie mialem bledow jak te, Googlowalem ale nie moge nic pomocnego wyszukac. To chyba nie jest problem z rozmiarem tablicy poniewaz nie sa to zapytania z duza iloscia wierszy jako rezultat wynikowy.

[quote=wlodi]Uzywam ruby ruby 1.9.3p0 (2011-10-30 revision 33570) [x86_64-linux]

Problem w tym ze w rubym 1.9.2-p290 nie mialem bledow jak te, Googlowalem ale nie moge nic pomocnego wyszukac. To chyba nie jest problem z rozmiarem tablicy poniewaz nie sa to zapytania z duza iloscia wierszy jako rezultat wynikowy.[/quote]
Sprawdz czy pod 1.9.3-p194 problem nadal wystepuje.

Najlepiej spróbuj na najnowszej wersji 1.9.3. Jeżeli zaczęło się sypać tylko po zmianie wersji, to możesz też spróbować odinstalować gema ze sterownikami do bazdy i zainstalować ponownie, o ile gem używa native extensions.

zamiast require ‘odbc’
dodalem require ‘odbc_utf8’ i rozwiazalo problem

Znalazlem niestety dosc dziwny problem w metodzie tej wypisuje sobie zawartosci wierszy:

[code] def self.print_result_array
result_array = Array.new
while row=@sth.fetch_array do
result_array.push(row)
print “Zawartosc wiersza: #{row}”
end
print “Rozmiar tablicy: #{result_array.size}”
@sth.finish
return result_array
end

Pierwszy raz metoda ta zwrocila zawartosc poprawnie:

Zawartosc wiersza: [“2011-09-29”, “789”]
Rozmiar tablicy: 241

Ale kolejny raz:
Zawartosc wiersza: ["", “789”]
Rozmiar tablicy: 241Z[/code]
Pierwsza kolumna tablicy ma wartosc null. jak to jest mozliwe?

Sprawdzilem i faktycznie w dla wszystkich zapytan brakuje zawartosci pojedynczej losowej kolumny.

Postaram sie to lepiej opisac:

W zadaniu wykonuje metode klasy Report co 5 minut:

scheduler.every '5m' do report = Report.new report.generate_report(:daily) end
Metoda klasy Report:

[code]def generate_report(name)
#stworzenie folderu dla wynikow
path = create_folder(name)

#zwraca wszystkie skrypty ktore maja byc uruchomione
scripts = Script.find_scripts(name)

# polaczenie z baza Exasol za pomoca driver ODBC 
@connection = Exasol.new
@connection.connect(EXA_CONFIG['username'], EXA_CONFIG['password'])

# metoda klasy Report jest tutaj wywolywana dla obiektu
self.prepare_results_for_scripts(scripts, path)

#rozlaczenie z baza 
@connection.disconnect

end[/code]
metoda prepare_results_for_scripts

def prepare_results_for_scripts(scripts, path) scripts.find_each do |script| begin self.process_script(script, path) rescue DBI::DatabaseError => e admin_email = "wlodi@jamaicans.com" err_message = "An error occured with script: " + "#{script.title} - " + "#{e.errstr}" AlertMailer.send_alert(admin_email, err_message).deliver next end end end
metoda process_script klasy Report:

def process_script(script, path) users = User.find_script_users(script) report_title = script.title if script.email_form? name_of_columns, result_array = self.return_database_result(script) User.send_html_emails(users, name_of_columns, result_array, report_title) else report_attachment_name, path_to_excel_file = self.create_excel_file(script, path) User.send_excel_emails(users, report_attachment_name, path_to_excel_file, report_title) end end
metoda return_database_results

def return_database_result(script) @connection.execute_query(script) name_of_columns = @connection.print_column_names result_array = @connection.print_result_array return name_of_columns, result_array end
klasa Exasol

[code]require ‘odbc_utf8’

class Exasol

def connect(login, password)
begin
#connect to the Exasol Server
@dbh = DBI.connect(‘DBI:ODBC:EXA’, login, password)
rescue DBI::DatabaseError => e
admin_email = "lukasz.wlodarczyk@sponsorpay.com"
puts “An error occured”
puts “Error code: #{e.err}”
puts “Error message: #{e.errstr}”
err_message = “#{e.errstr}”
AlertMailer.send_alert(admin_email, err_message).deliver
end
end

def disconnect
#disconnect from server
puts “Disconnecting …”
@dbh.disconnect if @dbh
end

def execute_query(query)
q = Script.find(query.id)
@sth = @dbh.prepare(q.query)
@sth.execute
end

def print_column_names
@column_array = Array.new
@column_array.push(@sth.column_names)
return @column_array
end

def return_number_of_headers
return @sth.column_names.size
end

def print_result_array
result_array = Array.new
row = Array.new
puts “Poczatek: #{row} - #{@sth.object_id}”
while row=@sth.fetch_array do
result_array.push(row)
print “Zawartosc wiersza: #{row}”
end
print “Rozmiar tablicy: #{result_array.size}”
@sth.finish
return result_array
end

end[/code]
Niestety przy drugim uruchomieniu taska zwraca nil dla pierwszej kolumny:
22320560
Poczatek: [] - 24287760
Zawartosc wiersza: ["", “579”]Zawartosc wiersza: ["", “1”]Zawartosc wiersza:

A przy pierwszym jest OK:
19591740
Poczatek: [] - 24454140
Zawartosc wiersza: [“2011-10-10”, “579”]Zawartosc wiersza: [“2012-01-10”, “1”]

Spotkaliscie sie kiedys z czyms podobnym ?

A za trzecim razem co zwraca?

To samo, czyli pusta pierwsza kolumne

Niestety nie moglem znalezc problemu. Metoda print_result_array za drugim, trzecim i kolejnym razem zwraca pierwsza kolumne pusta. Proces ten za drugin razem powinien zwocic taka sama wartosc jak za pierwszym. Najpierw wykonuje polaczenie z baza, wykonuje query w bazie i zapisuje content z bazy w tablicy result_array - zapisujac go albo w excel file albo zwracam rezultat w postaci tablicy html.

Na dodatek teraz dostaje blad przy wiekszych zapytaniach do bazy:

failed to allocate memory /usr/local/rvm/gems/ruby-1.9.3-p0@sp_qas/gems/dbd-odbc-0.2.5/lib/dbd/odbc/statement.rb:41:in `fetch' /usr/local/rvm/gems/ruby-1.9.3-p0@sp_qas/gems/dbd-odbc-0.2.5/lib/dbd/odbc/statement.rb:41:in `fetch' /usr/local/rvm/gems/ruby-1.9.3-p0@sp_qas/gems/rails-dbi-0.1.2/lib/dbi/handles/statement.rb:259:in `fetch_array' /home/lukasz/Projects/qas_refactoring/qas/lib/exasol.rb:35:in `print_result_array' /home/lukasz/Projects/qas_refactoring/qas/lib/report.rb:85:in `return_database_result' /home/lukasz/Projects/qas_refactoring/qas/lib/report.rb:62:in `create_excel_file' /home/lukasz/Projects/qas_refactoring/qas/lib/report.rb:47:in `process_script' /home/lukasz/Projects/qas_refactoring/qas/lib/report.rb:29:in `block in prepare_results_for_scripts
Problem w tym ze musze gdzies zapisac wynik aby moc go pozniej zapisac w Excelu lub wyswietlic w html’u

Czy znacie moze jakis inny sposob dla tego problemu? Oto moja metoda print result array:

def self.print_result_array result_array = Array.new while row=@sth.fetch_array do result_array.push(row) end @sth.finish return result_array end
Problem ten zaczyna sie w wierszu while row=@sth.fetch_array do

[quote=wlodi]“failed to allocate memory”

Problem w tym ze musze gdzies zapisac wynik aby moc go pozniej zapisac w Excelu lub wyswietlic w html’u[/quote]
Musisz zastosować jakąś paginację - wczytanie całej bazy do pamięci zazwyczaj właśnie tak się kończy. Wywołuj zapytanie zwracające tylko część rekordów - np. ORDER BY id LIMIT 1000 OFFSET ...., a każdy kawałek też od razu zapisuj do pliku (nie do pamięci, tylko pchaj od razu w strumień).

Dzieki Arsen, wlasnie to poprawiam i postaram sie dane zapisywac bezposrednio w pliku.

Cos jest nie tak, poczatkowo gdy probowalem uruchomic zapytanie z ponad 3000 wierszami powodowalo to blad: failed to allcoate memory

Teraz to samo query przy limicie 100 wierszy daje ten sam rezultat. Dopiero przy limicie 10 dalo oczekiwany rezultat.

Moja aplikacja bedzie przetwarzac zapisane w bazie rozne zapytania SQL. Problem z tym ze nie do wszystkich moge zastosowac limit i offset a gdy probuje bezposrednio zapisac w pliku wynik metoda fetch_array i fetch zwracaja blad failed to allocate memory. select_all wogole nie dziala - zwaraca takie same wiersze i w dodatku tylko 10.

A może masz uszkodzoną pamięć albo się komputer przegrzewa? Pisałeś wcześniej, że “Sprawdzilem i faktycznie w dla wszystkich zapytan brakuje zawartosci pojedynczej losowej kolumny.”

To moze byc przyczyna, wczesniej bez problemu aplikacja ta zapisywala w pliku rezultat z ponad 3000 wierszami.

Hej, po dluzszej analizie doszedlem do przyczyny bledu, nie jest to problem z pamiecia:

negative allocation size (or too big)

Powoduja ta wartosci w bazie danych takie jak naprzyklad .

Nie wiem za bardzo jak rozpoznac ta wartosc i zapisac ja jakos String w excelu

def self.execute_query(query) result = [] q = Script.find(query.id) puts "Processing script: #{q.title}" @sth = @dbh.execute(q.query) while row=@sth.fetch_array do puts row result.push(row) end col_names = @sth.column_names @sth.finish return result, col_names end

Czym mozna to jakos przechwycic? Najprosciej to mozna uzyc funkcji nvl i zapisywac null jako 0 w wynikowym SQL ale czy jest mozliwe jakies obejscie na poziomie programu?

Hej, ponawiam pytanie,

jak przechwycic i obsluzyc wyjatek ktory pojawia sie w metodzie:

@sth = @dbh.execute(q.query) while row=@sth.fetch_array do puts row result.push(row) end
“negative allocation size (or too big)”

jedynie wtedy kiedy wartoscia danego rekordu jest wartosc ?