--- nfo/perl/libs/DBD/CSV.pm 2002/11/13 18:50:19 1.1 +++ nfo/perl/libs/DBD/CSV.pm 2002/11/15 07:26:25 1.2 @@ -115,6 +115,28 @@ sub open_table ($$$$$) { my($self, $data, $table, $createMode, $lockMode) = @_; + + # remember some attributes if scanning starts below + $data->{Database}->{_cache}->{csv_tables}->{$table}->{'col_names'} = $data->{Database}->{csv_tables}->{$table}->{'col_names'} + if $data->{Database}->{csv_tables}->{$table}->{'col_names'}; + +SCAN: + if ($data->{f_stmt}->{command} eq 'SELECT' && $data->{Database}->{scan}) { + # get rules from builtin rulebase if requested + $data->{Database}->{'scan'} = _get_rules_autoscan() if $data->{Database}->{'scan'} == 1; + delete $data->{Database}->{csv_tables}->{$table}; + # rules left on stack? + if (my $rule = shift @{$data->{Database}->{'scan'}}) { + $data->{Database}->{scan_count}++; + # merge csv-options to table metadata: + # foreach (keys %{$rule}) { $data->{Database}->{csv_tables}->{$table}->{$_} = $rule->{$_}; } + # overwrite table metadata, (re-)set csv-options: + $data->{Database}->{csv_tables}->{$table} = $rule; + } else { + die "Missing first row or scanrule not applied"; + } + } + my $dbh = $data->{Database}; my $tables = $dbh->{csv_tables}; if (!exists($tables->{$table})) { @@ -138,6 +160,9 @@ exists($meta->{'escape_char'}) ? $meta->{'escape_char'} : exists($dbh->{'csv_escape_char'}) ? $dbh->{'csv_escape_char'} : '"'; + $opts{'always_quote'} = + exists($meta->{'always_quote'}) ? $meta->{'always_quote'} : + exists($dbh->{'csv_always_quote'}) ? $dbh->{'csv_always_quote'} : 0; $csv = $meta->{csv} = $class->new(\%opts); } my $file = $meta->{file} || $table; @@ -168,7 +193,16 @@ } if ($skipRows--) { if (!($array = $tbl->fetch_row($data))) { - die "Missing first row"; + if ($data->{Database}->{'scan'}) { + # if requested, try to help figuring out delimiters (just with SELECTs) + $data->{Database}->{'scan_running'} = 1; + goto SCAN; + } + my $die_msg = ''; + if ($data->{f_stmt}->{command} ne 'SELECT') { + $die_msg = ' - Note: scan does only work with a successful SELECT prior using ' . $data->{f_stmt}->{command}; + } + die "Missing first row" . $die_msg; } $tbl->{col_names} = $array; while ($skipRows--) { @@ -176,6 +210,32 @@ } } $tbl->{first_row_pos} = $tbl->{fh}->tell(); + $tbl->{size} = ($tbl->{fh}->stat)[7]; + + # checkpoint: did we already slurp to the end of the file? + # is this correct to be assumed as an error + # since it shouldn't occour while mungling with the first line(s)? + if ( $tbl->{first_row_pos} == $tbl->{size} ) { + $data->{Database}->{'scan_running'} = 1; + $tbl->{fh}->setpos(0); + goto SCAN; + } + + # scan successful? + if ($dbh->{'scan_running'}) { + #print "matched rule: ", $dbh->{scan_count}, "\n"; + # merge back cached attributes to local metadata + foreach (keys %{$dbh->{_cache}->{csv_tables}->{$table}}) { + $meta->{col_names} = $dbh->{_cache}->{csv_tables}->{$table}->{$_}; + } + # patch csv options from table metadata into the scope of the Text::CSV_XS object + if ($data->{f_stmt}->{command} eq 'INSERT' || $data->{f_stmt}->{command} eq 'UPDATE') { + my $rule = $data->{Database}->{csv_tables}->{$table}; + foreach (keys %{$rule}) { $tbl->{csv_csv} = $rule->{$_}; } + } + } + + my $array; if (exists($meta->{col_names})) { $array = $tbl->{col_names} = $meta->{col_names}; } elsif (!$tbl->{col_names} || !@{$tbl->{col_names}}) {