2008-10-23 9 views
5

मेरे पास कुछ कोड है जो डेटाबेस में सम्मिलन से पहले कुछ डेटा mysql enum में सुनिश्चित करने की आवश्यकता है।मैं पर्ल में MySQL enum मानों को कैसे निकालें?

sub enum_values { 
    my ($self, $schema, $table, $column) = @_; 

    # don't eval to let the error bubble up 
    my $columns = $schema->storage->dbh->selectrow_hashref(
     "SHOW COLUMNS FROM `$table` like ?", 
     {}, 
     $column 
    ); 

    unless ($columns) { 
     X::Internal::Database::UnknownColumn->throw(
      column => $column, 
      table => $table, 
     ); 
    } 

    my $type = $columns->{Type} or X::Panic->throw(
     details => "Could not determine type for $table.$column", 
    ); 

    unless ($type =~ /\Aenum\((.*)\)\z/) { 
     X::Internal::Database::IncorrectTypeForColumn->throw(
      type_wanted => 'enum', 
      type_found => $type, 
     ); 
    } 
    $type = $1; 

    require Text::CSV_XS; 
    my $csv = Text::CSV_XS->new; 
    $csv->parse($type) or X::Panic->throw(
     details => "Could not parse enum CSV data: ".$csv->error_input, 
    ); 
    return map { /\A'(.*)'\z/; $1 }$csv->fields; 
} 

हम DBIx::Class उपयोग कर रहे हैं: स्पष्ट तरीका मैं ऐसा करने का मिल गया है निम्नलिखित कोड है। निश्चित रूप से इसे पूरा करने का एक बेहतर तरीका है? (ध्यान दें कि हमारे तालिका से $ तालिका सारणी आ रही है, किसी बाहरी स्रोत से नहीं। इस प्रकार, कोई सुरक्षा समस्या नहीं है)।

उत्तर

13

इतनी वीर होने की आवश्यकता नहीं है।

my $sth = $dbh->column_info(undef, undef, 'mytable', '%'); 

foreach my $col_info ($sth->fetchrow_hashref) 
{ 
    if($col_info->{'TYPE_NAME'} eq 'ENUM') 
    { 
    # The mysql_values key contains a reference to an array of valid enum values 
    print "Valid enum values for $col_info->{'COLUMN_NAME'}: ", 
      join(', ', @{$col_info->{'mysql_values'}}), "\n"; 
    } 
    ... 
} 
+0

अच्छा :-)। हालांकि किसी को एक स्पष्ट जगह पर दस्तावेज करना चाहिए। –

+0

उत्कृष्ट। आपका बहुत बहुत धन्यवाद! – Ovid

+0

एफडब्ल्यूआईडब्ल्यू, मैंने गुलाब :: डीबी :: ऑब्जेक्ट से उस जवाब को खींच लिया, जो आत्मनिरीक्षण और स्वचालित रूप से MySQL enums, Postgres array कॉलम, और कई अन्य प्रकारों को कॉन्फ़िगर करेगा। इसका कोड उत्तर का एक अच्छा स्रोत है जब डीबीडी :: * दस्तावेज़ कम हो जाते हैं। –

3

मैं कहूंगा कि टेक्स्ट :: सीएसवी_एक्सएस का उपयोग करना एक ओवरकिल हो सकता है, जब तक कि आपके पास enums में अल्पविराम की तरह अजीब चीजें हों (वैसे भी यदि आप मुझसे पूछें तो एक बुरा विचार)। मैं शायद इसके बजाय इसका उपयोग करूंगा।

my @fields = $type =~/' ([^']+) ' (?:,|\z) /msgx; 

इसके अलावा, मुझे नहीं लगता कि शॉर्टकट हैं।

+0

हम बहुत सख्त कमी है कि हम नामकरण की परंपरा के बारे में पालन करने की कोशिश की क्या ज़रूरत है ताकि एक अच्छा सरलीकरण की तरह लगता है। धन्यवाद! – Ovid

+0

यद्यपि एक छोटा सुधार हालांकि: यह enum में एक अल्पविराम को संभालेगा, हालांकि यह एक एस्ट्रोफ़े को संभाल नहीं पाएगा। –

0

मैं दिन में कुछ समय बिताया #dbix पूछ: DBD::mysql की एक यथोचित आधुनिक संस्करण का उपयोग करना, हैश DBI के column info विधि द्वारा वापस कुंजी mysql_values में मान्य enum मूल्यों के एक पूर्व विभाजन संस्करण शामिल मैग्नेट पर एक ही सवाल पर क्लास चैनल और उत्तर की इस कमी के पार आया।

my $cfg = new Config::Simple($rc_file); 
my $mysql = $cfg->get_block('mysql'); 
my $dsn = 
    "DBI:mysql:database=$mysql->{database};". 
    "host=$mysql->{hostname};port=$mysql->{port}"; 

my $schema = 
    DTSS::CDN::Schema->connect($dsn, $mysql->{user}, $mysql->{password}); 

my $valid_enum_values = 
    $schema->source('Cdnurl')->column_info('scheme')->{extra}->{list}; 

और अब मुझे आईआरसी लॉग एक दीवार के खिलाफ मेरे सिर की धड़कन:

यहाँ डॉ; जब से मैं इस सवाल का जवाब मिल गया है और किसी और इसलिए अभी तक किया है लगता है, मैं टी एल नीचे प्रतिलेख चस्पा करेंगे
14:40 < cj> is there a cross-platform way to get the valid values of an 
      enum? 
15:11 < cj> it looks like I could add 'InflateColumn::Object::Enum' to the 
      __PACKAGE__->load_components(...) list for tables with enum 
      columns 
15:12 < cj> and then call values() on the enum column 
15:13 < cj> but how do I get dbic-dump to add 
      'InflateColumn::Object::Enum' to 
      __PACKAGE__->load_components(...) for only tables with enum 
      columns? 
15:20 < cj> I guess I could just add it for all tables, since I'm doing 
      the same for InflateColumn::DateTime 
15:39 < cj> hurm... is there a way to get a column without making a 
      request to the db? 
15:40 < cj> I know that we store in the DTSS::CDN::Schema::Result::Cdnurl 
      class all of the information that I need to know about the 
      scheme column before any request is issued 
15:42 <@ilmari> cj: for Pg and mysql Schema::Loader will add the list of 
       valid values to the ->{extra}->{list} column attribute 
15:43 <@ilmari> cj: if you're using some other database that has enums, 
       patches welcome :) 
15:43 <@ilmari> or even just a link to the documentation on how to extract 
       the values 
15:43 <@ilmari> and a willingness to test if it's not a database I have 
       access to 
15:43 < cj> thanks, but I'm using mysql. if I were using sqlite for this 
      project, I'd probably oblige :-) 
15:44 <@ilmari> cj: to add components to only some tables, use 
       result_components_map 
15:44 < cj> and is there a way to get at those attributes without making a 
      query? 
15:45 < cj> can we do $schema->resultset('Cdnurl') without having it issue 
      a query, for instance? 
15:45 <@ilmari> $result_source->column_info('colname')->{extra}->{list} 
15:45 < cj> and $result_source is $schema->resultset('Cdnurl') ? 
15:45 <@ilmari> dbic never issues a query until you start retrieving the 
       results 
15:45 < cj> oh, nice. 
15:46 <@ilmari> $schema->source('Cdnurl') 
15:46 <@ilmari> the result source is where the result set gets the results 
       from when they are needed 
15:47 <@ilmari> names have meanings :)