Gossamer Forum
Home : Products : Gossamer Links : Development, Plugins and Globals :

'VARCHAR' is not a supported type

Quote Reply
'VARCHAR' is not a supported type
This probably belongs with my other post titled "How to "Include" a .def file",
but I didn't want it to look like I have gotten a reply to that question, cause I haven't (yet) <g>

When supplying a hash of hashes to $creator->cols (\%HoH);, I get the following error:
GT::SQL::Creator (24307): 'VARCHAR' is not a supported type at GT::SQL::Driver::column_sql line 537.

Why the error on VARCHAR?

The file I am trying to #include and feed to $creator->cols object is basically a def file formatted like this:
Code:
ZipCode => { pos => 1, type => 'VARCHAR', size => '5', not_null => 1, default => ''},
City => { pos => 2, type => 'VARCHAR', size => '35', not_null => 0, default => ''},
...
State => { pos => 3, type => 'CHAR', size => '2', not_null => 0, default => '' }

Then in my plugin ZipCodeSearch.pm file I have:
Code:
my $error;
my %HoH = ();
my (@def,$lastchar, @pairs, $pairs, $pairname, $pairvalue, $key, $value);
my $zipcode_table_name = 'ZipCodes';
my $creator = $DB->creator ($zipcode_table_name);

my $formatname = $CFG->{admin_root_path} ."/Plugins/ZipCodeData/". $IN->param('data_format_file');
open (DEF, "$formatname") || return $GT::SQL::error;
@def = <DEF>;
close DEF;

foreach (@def) {
$_ =~ s/\n//g; # Remove newline ?
$_ =~ s/\t//g; # Remove tabs ?
$_ =~ s/ //g; # Remove spaces ?

$lastchar = substr ($_, (length $_) - 1, 1);
if($lastchar eq ',') {
$_ = substr($_, 0, -1);
}

$_ =~ s/=>/\|/; # ZipCode | { pos => 1, type => 'VARCHAR', size => '5', not_null => 1, default => ''}
$_ =~ s/{//; # ZipCode | pos => 1, type => 'VARCHAR', size => '5', not_null => 1, default => ''}
$_ =~ s/}//; # ZipCode | pos => 1, type => 'VARCHAR', size => '5', not_null => 1, default => ''

@pairs = split /\|/, $_;
$pairname = $pairs[0]; # ZipCode
$pairvalue = $pairs[1]; # pos => 1, type => 'VARCHAR', size => '5', not_null => 1, default => ''

for $pairvalue ( split /,/, $pairvalue) {
($key, $value) = split /\=>/, $pairvalue;
$HoH{$pairname}{$key} = $value;
print "Column/key = value: $pairname/$key = $value<br>";
}
}

$creator->cols (\%HoH);
$creator->pk('ZipCode','Latitude','Longitude');

if (! $creator->create('force')) {
$GT::SQL::errcode ||= ''; #silence -w warning.
$GT::SQL::errcode eq 'TBLEXISTS' ? ($error = "Could not create table ZipCodes (table already exists)\n") :
($error = "Could not create table ZipCodes: $GT::SQL::error)");
}

$creator->load_table();

$creator->save_schema();

I could really use some help with this. I swear I am passing a "hash of hashes" to the creator->cols object.
I have spent days doing this, and all I am trying to do is read in a file and create a table from it. Unsure
My perl is getting better. I am a complete rookie. I think I got hashes understood though.

FYI, I tried just feeding the file directly to creator->cols(), but was getting other errors such as:
$creator->cols (%{$def}); # Can't use string when strict refs in use
$creator->cols (%{%def}); # wrong arg, must be a hash of hashes
$creator->cols (%{@def}); # Can't coerce array into hash

Thanks for any help,
Chris
RGB World, Inc. - Software &amp; Web Development.
rgbworld.com
Quote Reply
Re: [rgbworld] 'VARCHAR' is not a supported type In reply to
Well, I have it working, albiet not very pretty. <g>

The fix to the previous error was to add yet another substitution.
This one removes the single quotes from the pair values.
$creator->cols (\%HoH); Now accepts my hash of hashes. Yeah!

Code:
$_ =~ s/'//g; # ZipCode | pos => 1, type => VARCHAR, size => 5, not_null => 1, default =>

I hope someone understands what I accomplished. I am reading in a psuedo def file, and
using that to send to creator->cols().

Someone please tell me that I can't just load a 'real' def file and pass it to creator->cols().
I have this sinking feeling that I may have invented another wheel.

Oh, and don't laugh at my perl substitutions (unless your going to help clean them up ) Cool

Thanks,
Chris
RGB World, Inc. - Software &amp; Web Development.
rgbworld.com
Quote Reply
Re: [rgbworld] 'VARCHAR' is not a supported type In reply to
Or, rather than that big mess, I could do this. <g>

This code creates/recreates the ZipCode table using a "predefined" table def
which is selected from a dropdown menu by the User who is doing data importing. whew

It's amazing what you can do when you find the right tools that are available!
Code:
my $table_name = 'ZipCodes';
my $creator = $DB->creator ($table_name);
my $src_file = $CFG->{admin_root_path} ."/Plugins/ZipCodeData/". $IN->param('data_format_file');
my $def = GT::Config->load($src_file);
my $col_defs = $def->{cols};
$creator->cols ($col_defs);

if (! $creator->create('force')) {
$GT::SQL::errcode eq ($error = "Could not create table ZipCodes: $GT::SQL::error");
}

$creator->load_table(); # Creates a schema based on an existing sql table and saves it.

Then I just import the data to the database.

What classes do I use to import?

I currently have a working import, I am sure there's probably a better way than this.
Maybe GT::SQL::Editor import?
Code:
my $col_count = 0;
my $col_names = "";
my @column_names = $DB->table('ZipCodes')->ordered_columns;

foreach (@column_names) {
$col_names .= "$_,";
$col_count++;
}
$col_names = substr($col_names, 0, - 1);

my $db_delim = ',';
my $prefix_plus_table = $DB->prefix . $table_name;
my $zipcode_table = $DB->table($table_name) || return $GT::SQL::error;
my $filename = $CFG->{admin_root_path} ."/Plugins/ZipCodeData/". $IN->param('zipcode_data_file');

my (@db, $fields, @fields);
open (DB, "$filename") || return $GT::SQL::error;
chomp ($fields = <DB> );
@fields = split /$db_delim/, $fields;
@db = <DB>;
close DB;

my $row = 1;
my ($sth, $i, @item, %item, $insert_name, $insert_value);
foreach (@db) {
$i = 0;
$_ =~ s/\"//g;
$_ =~ s/\n//;
$_ =~ s/\r//;
@item = split /$db_delim/, $_;
%item = map { $fields[$i++] => $_ } @item;
$insert_name = "ZipID,"; # for auto increment
$insert_value = "'',";

foreach (@fields) {
$insert_name .= "$_,";
$insert_value .= $zipcode_table->quote($item{$_}) . ",";
}
$insert_value = substr($insert_value, 0, - 1);
print "$row) $insert_value <br>";
$sth = $zipcode_table->prepare ("INSERT INTO $prefix_plus_table ($col_names) VALUES ($insert_value)");
$sth->execute();
$row++;
}

$sth->finish;

The data file is typically like this, so I skip 1st row. Also, I am taking
the fieldnames from the def, not the first row of this csv file.
"zip","city","state","latitude","longitude","timezone","dst"
"53140","Kenosha","WI","42.60217","-87.82979","-6","1"
"53141","Kenosha","WI","42.58098","-87.662878","-6","1"


Thanks for reading if there's anyone out there
Wink

Chris
RGB World, Inc. - Software &amp; Web Development.
rgbworld.com