Merge 'trunk' into 'DBIx-Class-current'
David Jack Olrik [Sat, 3 Mar 2007 17:58:21 +0000 (17:58 +0000)]
r27233@ip-37-237 (orig r3005):  castaway | 2007-01-05 10:25:11 +0100
add inflatecolumn fixes to Changes

r27496@ip-37-237 (orig r3007):  castaway | 2007-01-09 22:20:55 +0100
todoify collapse test

r27497@ip-37-237 (orig r3008):  castaway | 2007-01-09 22:42:59 +0100
Up version to 0.07004

r27498@ip-37-237 (orig r3009):  castaway | 2007-01-09 22:44:39 +0100
0.07004

r27499@ip-37-237 (orig r3010):  castaway | 2007-01-10 18:54:19 +0100
Skip .orig files in dist

r27500@ip-37-237 (orig r3011):  castaway | 2007-01-10 20:37:23 +0100
oops, remove .orig files etc

r27546@ip-37-237 (orig r3053):  zarquon | 2007-01-23 11:15:05 +0100
minor doc improvement to clarify how to do joins
r27720@ip-37-237 (orig r3058):  zarquon | 2007-01-24 22:48:07 +0100
explained a cryptic error message
r27732@ip-37-237 (orig r3064):  castaway | 2007-01-29 17:28:12 +0100
Make POD a little more obvious about component order
 --This line, and those below, will be ignored--

M    DateTime.pm

r27738@ip-37-237 (orig r3070):  jester | 2007-02-01 00:59:06 +0100
Doc cleanup in Ordered.pm
r27740@ip-37-237 (orig r3072):  castaway | 2007-02-02 20:48:53 +0100
POD updates

r27741@ip-37-237 (orig r3073):  ash | 2007-02-03 22:33:19 +0100
Made ->update not change the hashref passed in (with test.)
r27743@ip-37-237 (orig r3075):  ash | 2007-02-05 13:29:52 +0100
Backed out my r3073, and doc'd the fact that it takes a hashref that might be changed
r27744@ip-37-237 (orig r3076):  castaway | 2007-02-05 14:56:35 +0100
Add _accessor example, thanks to grinktt3n

r27745@ip-37-237 (orig r3077):  castaway | 2007-02-05 15:23:22 +0100
Fix overload example

r27747@ip-37-237 (orig r3079):  grink1tt3n | 2007-02-06 20:40:00 +0100
Added;
FAQ-fetch-a-formatted-column.txt
FAQ-store-JSON-in-a-column.txt

r27762@ip-37-237 (orig r3094):  castaway | 2007-02-08 09:25:54 +0100
Argh! Fix spurious example

r27765@ip-37-237 (orig r3097):  castaway | 2007-02-13 15:00:21 +0100
Improve resultset_attributes docs

r27766@ip-37-237 (orig r3098):  grink1tt3n | 2007-02-14 08:16:40 +0100
Fleshed out the JSON inflated column example with a corresponding YAML example. Added a cautionary warning against overuse. Added a link to InflateColumn.

r27767@ip-37-237 (orig r3099):  grink1tt3n | 2007-02-14 09:39:26 +0100
Added how to '.. fetch a single (or topmost) row?' to the FAQ

r27768@ip-37-237 (orig r3100):  zarquon | 2007-02-14 09:44:18 +0100
improved docs for as attrib
r27769@ip-37-237 (orig r3101):  zarquon | 2007-02-14 11:05:51 +0100
pointed out ambiguity of as attribs
r27967@ip-37-237 (orig r3107):  castaway | 2007-03-03 13:15:03 +0100
Fix to $filename from Carl Vincent

100 files changed:
Build.PL
Changes
MANIFEST.SKIP
Makefile.PL
lib/DBIx/Class.pm
lib/DBIx/Class/AccessorGroup.pm [deleted file]
lib/DBIx/Class/Componentised.pm
lib/DBIx/Class/Core.pm
lib/DBIx/Class/DB.pm
lib/DBIx/Class/InflateColumn.pm
lib/DBIx/Class/InflateColumn/File.pm [new file with mode: 0644]
lib/DBIx/Class/Manual/Cookbook.pod
lib/DBIx/Class/Manual/DocMap.pod
lib/DBIx/Class/Manual/FAQ.pod
lib/DBIx/Class/Ordered.pm
lib/DBIx/Class/Relationship/Accessor.pm
lib/DBIx/Class/ResultClass/HashRefInflator.pm [new file with mode: 0644]
lib/DBIx/Class/ResultSet.pm
lib/DBIx/Class/ResultSetColumn.pm
lib/DBIx/Class/ResultSource.pm
lib/DBIx/Class/ResultSource/Table.pm
lib/DBIx/Class/ResultSourceHandle.pm [new file with mode: 0644]
lib/DBIx/Class/ResultSourceProxy.pm
lib/DBIx/Class/ResultSourceProxy/Table.pm
lib/DBIx/Class/Row.pm
lib/DBIx/Class/Schema.pm
lib/DBIx/Class/Schema/Versioned.pm [new file with mode: 0644]
lib/DBIx/Class/Serialize/Storable.pm [deleted file]
lib/DBIx/Class/Storage.pm
lib/DBIx/Class/Storage/DBI.pm
lib/DBIx/Class/Storage/DBI/Cursor.pm
lib/DBIx/Class/Storage/DBI/DB2.pm
lib/DBIx/Class/Storage/DBI/MSSQL.pm
lib/DBIx/Class/Storage/DBI/NoBindVars.pm
lib/DBIx/Class/Storage/DBI/ODBC.pm
lib/DBIx/Class/Storage/DBI/ODBC/DB2_400_SQL.pm
lib/DBIx/Class/Storage/DBI/Oracle.pm
lib/DBIx/Class/Storage/DBI/Pg.pm
lib/DBIx/Class/Storage/DBI/SQLite.pm
lib/DBIx/Class/Storage/DBI/mysql.pm
lib/DBIx/Class/Storage/Statistics.pm
lib/SQL/Translator/Parser/DBIx/Class.pm
t/03podcoverage.t
t/100populate.t [new file with mode: 0644]
t/19quotes.t
t/19quotes_newstyle.t
t/31stats.t
t/33storage_reconnect.t [new file with mode: 0644]
t/34exception_action.t [new file with mode: 0644]
t/35disable_sth_caching.t [new file with mode: 0644]
t/39load_namespaces_1.t [new file with mode: 0644]
t/39load_namespaces_2.t [new file with mode: 0644]
t/39load_namespaces_3.t [new file with mode: 0644]
t/39load_namespaces_4.t [new file with mode: 0644]
t/40resultsetmanager.t
t/55storage_stress.t [new file with mode: 0644]
t/60core.t
t/63register_class.t [new file with mode: 0644]
t/65multipk.t
t/68inflate.t
t/68inflate_resultclass_hashrefinflator.t [new file with mode: 0644]
t/71mysql.t
t/72pg.t
t/73oracle.t
t/745db2.t
t/746db2_400.t
t/74mssql.t
t/81transactions.t
t/86sqlt.t
t/87ordered.t
t/93nobindvars.t [new file with mode: 0644]
t/94versioning.t [new file with mode: 0644]
t/95sql_maker_quote.t
t/96file_column.t [new file with mode: 0644]
t/bindtype_columns.t [new file with mode: 0644]
t/cdbi-sweet-t/08pager.t
t/lib/DBICNSTest/OtherRslt/D.pm [new file with mode: 0644]
t/lib/DBICNSTest/RSBase.pm [new file with mode: 0644]
t/lib/DBICNSTest/RSet/A.pm [new file with mode: 0644]
t/lib/DBICNSTest/RSet/C.pm [new file with mode: 0644]
t/lib/DBICNSTest/Result/A.pm [new file with mode: 0644]
t/lib/DBICNSTest/Result/B.pm [new file with mode: 0644]
t/lib/DBICNSTest/ResultSet/A.pm [new file with mode: 0644]
t/lib/DBICNSTest/ResultSet/C.pm [new file with mode: 0644]
t/lib/DBICNSTest/Rslt/A.pm [new file with mode: 0644]
t/lib/DBICNSTest/Rslt/B.pm [new file with mode: 0644]
t/lib/DBICTest.pm
t/lib/DBICTest/Schema.pm
t/lib/DBICTest/Schema/Artist.pm
t/lib/DBICTest/Schema/ArtistSourceName.pm
t/lib/DBICTest/Schema/Employee.pm
t/lib/DBICTest/Schema/FileColumn.pm [new file with mode: 0644]
t/lib/DBICTest/Schema/FourKeys.pm
t/lib/DBICTest/Schema/LinerNotes.pm
t/lib/DBICTest/Schema/NoPrimaryKey.pm
t/lib/DBICTest/Schema/OneKey.pm
t/lib/DBICTest/Schema/Serialized.pm
t/lib/DBICVersionNew.pm [new file with mode: 0644]
t/lib/DBICVersionOrig.pm [new file with mode: 0644]
t/lib/sqlite.sql

index 2ba9d22..a919ccc 100644 (file)
--- a/Build.PL
+++ b/Build.PL
@@ -1,32 +1,3 @@
-use strict;
-use Module::Build;
-
-my %arguments = (
-    create_makefile_pl => 'passthrough',
-    license            => 'perl',
-    module_name        => 'DBIx::Class',
-    requires           => {
-        'Cwd'                       => 3.19,
-        'Data::Page'                => 2.00,
-        'Scalar::Util'              => 0,
-        'SQL::Abstract'             => 1.20,
-        'SQL::Abstract::Limit'      => 0.101,
-        'Class::C3'                 => 0.13,
-        'Storable'                  => 0,
-        'Class::Data::Accessor'     => 0.01,
-       'Carp::Clan'                => 0,
-        'DBI'                       => 1.40,
-        'Module::Find'              => 0,
-        'Class::Inspector'          => 0,
-    },
-    build_requires      => {
-        'DBD::SQLite'               => 1.11,
-    },
-    create_makefile_pl => 'passthrough',
-    create_readme      => 1,
-    test_files         => [ glob('t/*.t'), glob('t/*/*.t') ],
-    script_files       => [ glob('script/*') ],
-);
-
-Module::Build->new(%arguments)->create_build_script;
-
+# Dear Distribution Packager. This use of require is intentional.
+# Module::Install detects Build.PL usage and acts accordingly.
+require 'Makefile.PL';
diff --git a/Changes b/Changes
index eb87d1b..bcc8a45 100644 (file)
--- a/Changes
+++ b/Changes
@@ -22,7 +22,6 @@ Revision history for DBIx::Class
         - fix quote tests for recent versions of SQLite
         - added reference implementation of Manual::Example
         - backported column_info_from_storage accessor from -current, but
-          defaults true instead of false in 0.07xxx
         - fixed inflate_datetime.t tests/stringify under older Test::More
         - minor fixes for many-to-many relationship helpers
         - cleared up Relationship docs, and fixed some typos
index fa93767..eaa6bc0 100644 (file)
@@ -25,6 +25,7 @@
 \.tmp$
 \.old$
 \.bak$
+\..*?\.sw[po]$
 \#$
 \b\.#
 
index 192903a..b9eeb22 100644 (file)
@@ -1,31 +1,31 @@
-# Note: this file was auto-generated by Module::Build::Compat version 0.03
-    
-    unless (eval "use Module::Build::Compat 0.02; 1" ) {
-      print "This module requires Module::Build to install itself.\n";
-      
-      require ExtUtils::MakeMaker;
-      my $yn = ExtUtils::MakeMaker::prompt
-       ('  Install Module::Build now from CPAN?', 'y');
-      
-      unless ($yn =~ /^y/i) {
-       die " *** Cannot install without Module::Build.  Exiting ...\n";
-      }
-      
-      require Cwd;
-      require File::Spec;
-      require CPAN;
-      
-      # Save this 'cause CPAN will chdir all over the place.
-      my $cwd = Cwd::cwd();
-      
-      CPAN::Shell->install('Module::Build::Compat');
-      CPAN::Shell->expand("Module", "Module::Build::Compat")->uptodate
-       or die "Couldn't install Module::Build, giving up.\n";
-      
-      chdir $cwd or die "Cannot chdir() back to $cwd: $!";
-    }
-    eval "use Module::Build::Compat 0.02; 1" or die $@;
-    
-    Module::Build::Compat->run_build_pl(args => \@ARGV);
-    require Module::Build;
-    Module::Build::Compat->write_makefile(build_class => 'Module::Build');
+use inc::Module::Install 0.64;
+
+name     'DBIx-Class';
+all_from 'lib/DBIx/Class.pm';
+perl_version '5.006001';
+
+requires 'Cwd'                       => 3.19; 
+requires 'Data::Page'                => 2.00;
+requires 'Scalar::Util'              => 0;
+requires 'SQL::Abstract'             => 1.20;
+requires 'SQL::Abstract::Limit'      => 0.101;
+requires 'Class::C3'                 => 0.13;
+requires 'Storable'                  => 0;
+requires 'Carp::Clan'                => 0;
+requires 'DBI'                       => 1.40;
+requires 'Module::Find'              => 0;
+requires 'Class::Inspector'          => 0;
+requires 'Class::Accessor::Grouped'  => 0.03;
+
+# Perl 5.8.0 doesn't have utf8::is_utf8()
+requires 'Encode'                    => 0 if ($] <= 5.008000);  
+
+build_requires 'DBD::SQLite'         => 1.11;
+
+install_script 'script/dbicadmin';
+
+tests "t/*.t t/*/*.t";
+
+auto_install;
+
+WriteAll;
index bc103a3..3ccd2af 100644 (file)
@@ -4,9 +4,14 @@ use strict;
 use warnings;
 
 use vars qw($VERSION);
-use base qw/DBIx::Class::Componentised Class::Data::Accessor/;
+use base qw/DBIx::Class::Componentised Class::Accessor::Grouped/;
+
+sub mk_classdata { 
+    my $self = shift;
+    $self->mk_group_accessors('inherited', $_[0]); 
+    $self->set_inherited(@_) if @_ > 1;
+}
 
-sub mk_classdata { shift->mk_classaccessor(@_); }
 sub component_base_class { 'DBIx::Class' }
 
 # Always remember to do all digits for the version even if they're 0
@@ -180,6 +185,8 @@ andyg: Andy Grundman <andy@hybridized.org>
 
 ank: Andres Kievsky
 
+ash: Ash Berlin <ash@cpan.org>
+
 blblack: Brandon L. Black <blblack@gmail.com>
 
 bluefeet: Aran Deltac <bluefeet@cpan.org>
@@ -210,6 +217,8 @@ konobi: Scott McWhirter
 
 LTJake: Brian Cassidy <bricas@cpan.org>
 
+ned: Neil de Carteret
+
 nigel: Nigel Metheringham <nigelm@cpan.org>
 
 ningu: David Kamholz <dkamholz@cpan.org>
@@ -234,6 +243,8 @@ Todd Lipcon
 
 typester: Daisuke Murase <typester@cpan.org>
 
+victori: Victor Igumnov <victori@cpan.org>
+
 wdh: Will Hawes
 
 willert: Sebastian Willert <willert@cpan.org>
diff --git a/lib/DBIx/Class/AccessorGroup.pm b/lib/DBIx/Class/AccessorGroup.pm
deleted file mode 100644 (file)
index 56bcf1b..0000000
+++ /dev/null
@@ -1,342 +0,0 @@
-package DBIx::Class::AccessorGroup;
-
-use strict;
-use warnings;
-
-use Carp::Clan qw/^DBIx::Class/;
-
-=head1 NAME
-
-DBIx::Class::AccessorGroup -  Lets you build groups of accessors
-
-=head1 SYNOPSIS
-
-=head1 DESCRIPTION
-
-This class lets you build groups of accessors that will call different
-getters and setters.
-
-=head1 METHODS
-
-=head2 mk_group_accessors
-
-=over 4
-
-=item Arguments: $group, @fieldspec
-
-Returns: none
-
-=back
-
-Creates a set of accessors in a given group.
-
-$group is the name of the accessor group for the generated accessors; they
-will call get_$group($field) on get and set_$group($field, $value) on set.
-
-@fieldspec is a list of field/accessor names; if a fieldspec is a scalar
-this is used as both field and accessor name, if a listref it is expected to
-be of the form [ $accessor, $field ].
-
-=cut
-
-sub mk_group_accessors {
-  my ($self, $group, @fields) = @_;
-
-  $self->_mk_group_accessors('make_group_accessor', $group, @fields);
-  return;
-}
-
-
-{
-    no strict 'refs';
-    no warnings 'redefine';
-
-    sub _mk_group_accessors {
-        my($self, $maker, $group, @fields) = @_;
-        my $class = ref $self || $self;
-
-        # So we don't have to do lots of lookups inside the loop.
-        $maker = $self->can($maker) unless ref $maker;
-
-        foreach my $field (@fields) {
-            if( $field eq 'DESTROY' ) {
-                carp("Having a data accessor named DESTROY  in ".
-                             "'$class' is unwise.");
-            }
-
-            my $name = $field;
-
-            ($name, $field) = @$field if ref $field;
-
-            my $accessor = $self->$maker($group, $field);
-            my $alias = "_${name}_accessor";
-
-            #warn "$class $group $field $alias";
-
-            *{$class."\:\:$name"}  = $accessor;
-              #unless defined &{$class."\:\:$field"}
-
-            *{$class."\:\:$alias"}  = $accessor;
-              #unless defined &{$class."\:\:$alias"}
-        }
-    }
-}
-
-=head2 mk_group_ro_accessors
-
-=over 4
-
-=item Arguments: $group, @fieldspec
-
-Returns: none
-
-=back
-
-Creates a set of read only accessors in a given group. Identical to
-<L:/mk_group_accessors> but accessors will throw an error if passed a value
-rather than setting the value.
-
-=cut
-
-sub mk_group_ro_accessors {
-    my($self, $group, @fields) = @_;
-
-    $self->_mk_group_accessors('make_group_ro_accessor', $group, @fields);
-}
-
-=head2 mk_group_wo_accessors
-
-=over 4
-
-=item Arguments: $group, @fieldspec
-
-Returns: none
-
-=back
-
-Creates a set of write only accessors in a given group. Identical to
-<L:/mk_group_accessors> but accessors will throw an error if not passed a
-value rather than getting the value.
-
-=cut
-
-sub mk_group_wo_accessors {
-    my($self, $group, @fields) = @_;
-
-    $self->_mk_group_accessors('make_group_wo_accessor', $group, @fields);
-}
-
-=head2 make_group_accessor
-
-=over 4
-
-=item Arguments: $group, $field
-
-Returns: $sub (\CODE)
-
-=back
-
-Returns a single accessor in a given group; called by mk_group_accessors
-for each entry in @fieldspec.
-
-=cut
-
-sub make_group_accessor {
-    my ($class, $group, $field) = @_;
-
-    my $set = "set_$group";
-    my $get = "get_$group";
-
-    # Build a closure around $field.
-    return sub {
-        my $self = shift;
-
-        if(@_) {
-            return $self->$set($field, @_);
-        }
-        else {
-            return $self->$get($field);
-        }
-    };
-}
-
-=head2 make_group_ro_accessor
-
-=over 4
-
-=item Arguments: $group, $field
-
-Returns: $sub (\CODE)
-
-=back
-
-Returns a single read-only accessor in a given group; called by
-mk_group_ro_accessors for each entry in @fieldspec.
-
-=cut
-
-sub make_group_ro_accessor {
-    my($class, $group, $field) = @_;
-
-    my $get = "get_$group";
-
-    return sub {
-        my $self = shift;
-
-        if(@_) {
-            my $caller = caller;
-            croak("'$caller' cannot alter the value of '$field' on ".
-                        "objects of class '$class'");
-        }
-        else {
-            return $self->$get($field);
-        }
-    };
-}
-
-=head2 make_group_wo_accessor
-
-=over 4
-
-=item Arguments: $group, $field
-
-Returns: $sub (\CODE)
-
-=back
-
-Returns a single write-only accessor in a given group; called by
-mk_group_wo_accessors for each entry in @fieldspec.
-
-=cut
-
-sub make_group_wo_accessor {
-    my($class, $group, $field) = @_;
-
-    my $set = "set_$group";
-
-    return sub {
-        my $self = shift;
-
-        unless (@_) {
-            my $caller = caller;
-            croak("'$caller' cannot access the value of '$field' on ".
-                        "objects of class '$class'");
-        }
-        else {
-            return $self->$set($field, @_);
-        }
-    };
-}
-
-=head2 get_simple
-
-=over 4
-
-=item Arguments: $field
-
-Returns: $value
-
-=back
-
-Simple getter for hash-based objects which returns the value for the field
-name passed as an argument.
-
-=cut
-
-sub get_simple {
-  my ($self, $get) = @_;
-  return $self->{$get};
-}
-
-=head2 set_simple
-
-=over 4
-
-=item Arguments: $field, $new_value
-
-Returns: $new_value
-
-=back
-
-Simple setter for hash-based objects which sets and then returns the value
-for the field name passed as an argument.
-
-=cut
-
-sub set_simple {
-  my ($self, $set, $val) = @_;
-  return $self->{$set} = $val;
-}
-
-=head2 get_component_class
-
-=over 4
-
-=item Arguments: $name
-
-Returns: $component_class
-
-=back
-
-Returns the class name for a component; returns an object key if called on
-an object, or attempts to return classdata referenced by _$name if called
-on a class.
-
-=cut
-
-sub get_component_class {
-  my ($self, $get) = @_;
-  if (ref $self) {
-      return $self->{$get};
-  } else {
-      $get = "_$get";
-      return $self->can($get) ? $self->$get : undef;
-  }
-}
-
-=head2 set_component_class
-
-=over 4
-
-=item Arguments: $name, $new_component_class
-
-Returns: $new_component_class
-
-=back
-
-Sets a component class name; attempts to require the class before setting
-but does not error if unable to do so. Sets an object key of the given name
-if called or an object or classdata called _$name if called on a class.
-
-=cut
-
-sub set_component_class {
-  my ($self, $set, $val) = @_;
-  eval "require $val";
-  if ($@) {
-      my $val_path = $val;
-      $val_path =~ s{::}{/}g;
-      carp $@ unless $@ =~ /^Can't locate $val_path\.pm/;
-  }
-  if (ref $self) {
-      return $self->{$set} = $val;
-  } else {
-      $set = "_$set";
-      return $self->can($set) ?
-        $self->$set($val) :
-        $self->mk_classdata($set => $val);
-  }
-}
-
-1;
-
-=head1 AUTHORS
-
-Matt S. Trout <mst@shadowcatsystems.co.uk>
-
-=head1 LICENSE
-
-You may distribute this code under the same terms as Perl itself.
-
-=cut
-
index 2b3bf83..ecfe177 100644 (file)
@@ -6,7 +6,7 @@ use warnings;
 
 use Class::C3;
 use Class::Inspector;
-use Carp::Clan qw/DBIx::Class/;
+use Carp::Clan qw/^DBIx::Class/;
 
 sub inject_base {
   my ($class, $target, @to_inject) = @_;
index 7c48181..92dd74c 100644 (file)
@@ -7,14 +7,12 @@ no warnings 'qw';
 use base qw/DBIx::Class/;
 
 __PACKAGE__->load_components(qw/
-  Serialize::Storable
   Relationship
   InflateColumn
   PK::Auto
   PK
   Row
-  ResultSourceProxy::Table
-  AccessorGroup/);
+  ResultSourceProxy::Table/);
 
 1;
 
@@ -50,8 +48,6 @@ The core modules currently are:
 
 =item L<DBIx::Class::ResultSourceProxy::Table>
 
-=item L<DBIx::Class::AccessorGroup>
-
 =back
 
 =head1 AUTHORS
index 007c82a..9d80916 100644 (file)
@@ -8,6 +8,11 @@ use DBIx::Class::Schema;
 use DBIx::Class::Storage::DBI;
 use DBIx::Class::ClassResolver::PassThrough;
 use DBI;
+use Scalar::Util;
+
+unless ($INC{"DBIx/Class/CDBICompat.pm"}) {
+  warn "IMPORTANT: DBIx::Class::DB is DEPRECATED AND *WILL* BE REMOVED. DO NOT USE.\n";
+}
 
 __PACKAGE__->load_components(qw/ResultSetProxy/);
 
@@ -23,29 +28,15 @@ sub storage { shift->schema_instance(@_)->storage; }
 
 DBIx::Class::DB - (DEPRECATED) classdata schema component
 
-=head1 SYNOPSIS
-
-  package MyDB;
-
-  use base qw/DBIx::Class/;
-  __PACKAGE__->load_components('DB');
-
-  __PACKAGE__->connection('dbi:...', 'user', 'pass', \%attrs);
-
-  package MyDB::MyTable;
-
-  use base qw/MyDB/;
-  __PACKAGE__->load_components('Core'); # just load this in MyDB if it will
-                                        # always be there
-
-  ...
-
 =head1 DESCRIPTION
 
 This class is designed to support the Class::DBI connection-as-classdata style
 for DBIx::Class. You are *strongly* recommended to use a DBIx::Class::Schema
 instead; DBIx::Class::DB will not undergo new development and will be moved
-to being a CDBICompat-only component before 1.0.
+to being a CDBICompat-only component before 1.0. In order to discourage further
+use, documentation has been removed as of 0.08000
+
+=begin HIDE_BECAUSE_THIS_CLASS_IS_DEPRECATED
 
 =head1 METHODS
 
@@ -150,13 +141,43 @@ native L<DBIx::Class::ResultSet> system.
 =cut
 
 sub resultset_instance {
-  my $class = ref $_[0] || $_[0];
-  my $source = $class->result_source_instance;
+  $_[0]->result_source_instance->resultset
+}
+
+sub result_source_instance {
+  my $class = shift;
+  $class = ref $class || $class;
+  __PACKAGE__->mk_classdata(qw/_result_source_instance/)
+    unless __PACKAGE__->can('_result_source_instance');
+
+  
+  return $class->_result_source_instance(@_) if @_;
+
+  my $source = $class->_result_source_instance;
+  return {} unless Scalar::Util::blessed($source);
+
   if ($source->result_class ne $class) {
-    $source = $source->new($source);
-    $source->result_class($class);
+    # Remove old source instance so we dont get deep recursion
+    #$DB::single = 1;
+    # Need to set it to a non-undef value so that it doesn't just fallback to
+    # a parent class's _result_source_instance
+    #$class->_result_source_instance({});
+    #$class->table($class);
+    #$source = $class->_result_source_instance;
+
+    $DB::single = 1;
+    $source = $source->new({ 
+        %$source, 
+        source_name  => $class,
+        result_class => $class
+    } );
+    $class->_result_source_instance($source);
+    if (my $coderef = $class->can('schema_instance')) {
+        $coderef->($class)->register_class($class, $class);
+    }
   }
-  return $source->resultset;
+  return $source;
 }
 
 =head2 resolve_class
@@ -177,6 +198,8 @@ Alias for L<txn_commit>
 
 Alias for L<txn_rollback>
 
+=end HIDE_BECAUSE_THIS_CLASS_IS_DEPRECATED
+
 =head1 AUTHORS
 
 Matt S. Trout <mst@shadowcatsystems.co.uk>
index 84f86b8..721894f 100644 (file)
@@ -164,93 +164,6 @@ sub store_inflated_column {
   return $self->{_inflated_column}{$col} = $inflated;
 }
 
-=head2 get_column
-
-Gets a column value in the same way as L<DBIx::Class::Row/get_column>. If there
-is an inflated value stored that has not yet been deflated, it is deflated
-when the method is invoked.
-
-=cut
-
-sub get_column {
-  my ($self, $col) = @_;
-  if (exists $self->{_inflated_column}{$col}
-        && !exists $self->{_column_data}{$col}) {
-    $self->store_column($col, $self->_deflated_column($col, $self->{_inflated_column}{$col})); 
-  }
-  return $self->next::method($col);
-}
-
-=head2 get_columns 
-
-Returns the get_column info for all columns as a hash,
-just like L<DBIx::Class::Row/get_columns>.  Handles inflation just
-like L</get_column>.
-
-=cut
-
-sub get_columns {
-  my $self = shift;
-  if (exists $self->{_inflated_column}) {
-    foreach my $col (keys %{$self->{_inflated_column}}) {
-      $self->store_column($col, $self->_deflated_column($col, $self->{_inflated_column}{$col}))
-       unless exists $self->{_column_data}{$col};
-    }
-  }
-  return $self->next::method;
-}
-
-=head2 has_column_loaded
-
-Like L<DBIx::Class::Row/has_column_loaded>, but also returns true if there
-is an inflated value stored.
-
-=cut
-
-sub has_column_loaded {
-  my ($self, $col) = @_;
-  return 1 if exists $self->{_inflated_column}{$col};
-  return $self->next::method($col);
-}
-
-=head2 update
-
-Updates a row in the same way as L<DBIx::Class::Row/update>, handling
-inflation and deflation of columns appropriately.
-
-=cut
-
-sub update {
-  my ($class, $attrs, @rest) = @_;
-  foreach my $key (keys %{$attrs||{}}) {
-    if (ref $attrs->{$key} && $class->has_column($key)
-          && exists $class->column_info($key)->{_inflate_info}) {
-      $class->set_inflated_column($key, delete $attrs->{$key});
-    }
-  }
-  return $class->next::method($attrs, @rest);
-}
-
-=head2 new
-
-Creates a row in the same way as L<DBIx::Class::Row/new>, handling
-inflation and deflation of columns appropriately.
-
-=cut
-
-sub new {
-  my ($class, $attrs, @rest) = @_;
-  my $inflated;
-  foreach my $key (keys %{$attrs||{}}) {
-    $inflated->{$key} = delete $attrs->{$key} 
-      if ref $attrs->{$key} && $class->has_column($key)
-         && exists $class->column_info($key)->{_inflate_info};
-  }
-  my $obj = $class->next::method($attrs, @rest);
-  $obj->{_inflated_column} = $inflated if $inflated;
-  return $obj;
-}
-
 =head1 SEE ALSO
 
 =over 4
diff --git a/lib/DBIx/Class/InflateColumn/File.pm b/lib/DBIx/Class/InflateColumn/File.pm
new file mode 100644 (file)
index 0000000..b7bda60
--- /dev/null
@@ -0,0 +1,201 @@
+package DBIx::Class::InflateColumn::File;
+
+use strict;
+use warnings;
+use base 'DBIx::Class';
+use File::Path;
+use File::Copy;
+use IO::File;
+
+__PACKAGE__->load_components(qw/InflateColumn/);
+
+
+sub register_column {
+  my ($self, $column, $info, @rest) = @_;
+  $self->next::method($column, $info, @rest);
+  return unless defined($info->{is_file_column});
+    $self->inflate_column(
+      $column =>
+        {
+          inflate => $self->_inflate_file_column,
+          deflate => sub {
+              my ( $file, @column_names ) = $self->_load_file_column_information;
+              $self->_save_file_column( $file, $self, @column_names );
+          },
+        }
+    );
+}
+
+
+sub delete {
+    my ( $self, @rest ) = @_;
+
+    my @column_names = $self->columns;
+    for (@column_names) {
+        if ( $self->column_info($_)->{is_file_column} ) {
+            my $path =
+              File::Spec->catdir( $self->column_info($_)->{file_column_path},
+                $self->id );
+            rmtree( [$path], 0, 0 );
+        }
+    }
+
+    my $ret = $self->next::method(@rest);
+
+    return $ret;
+}
+
+sub _inflate_file_column {
+    my $self = shift;
+
+    my @column_names = $self->columns;
+    for(@column_names) {
+        if ( $self->column_info($_)->{is_file_column} ) {
+            # make sure everything checks out
+            unless (defined $self->$_) {
+                # if something is wrong set it to undef
+                $self->$_(undef);
+                next;
+            }
+            my $fs_file =
+              File::Spec->catfile( $self->column_info($_)->{file_column_path}, 
+                $self->id, $self->$_ );
+            $self->$_({handle => new IO::File($fs_file, "r"), filename => $self->$_});
+        }
+    }
+}
+
+sub _load_file_column_information {
+    my $self = shift;
+
+    my $file;
+    my @column_names;
+
+    @column_names = $self->columns;
+    for (@column_names) {
+        if ( $self->column_info($_)->{is_file_column} ) {
+            # make sure everything checks out
+            unless ((defined $self->$_) ||
+             (defined $self->$_->{filename} && defined $self->$_->{handle})) {
+                # if something is wrong set it to undef
+                $self->$_(undef);
+                next;
+            }
+            $file->{$_} = $self->$_;
+            $self->$_( $self->$_->{filename} );
+        }
+    }
+
+    return ( $file, @column_names );
+}
+
+sub _save_file_column {
+    my ( $self, $file, $ret, @column_names ) = @_;
+
+    for (@column_names) {
+        if ( $ret->column_info($_)->{is_file_column} ) {
+            next unless (defined $ret->$_);
+            my $file_path =
+              File::Spec->catdir( $ret->column_info($_)->{file_column_path},
+                $ret->id );
+            mkpath [$file_path];
+            
+            my $outfile =
+              File::Spec->catfile( $file_path, $file->{$_}->{filename} );
+            File::Copy::copy( $file->{$_}->{handle}, $outfile );
+        
+            $self->_file_column_callback($file->{$_},$ret,$_);
+        }
+    }
+}
+
+=head1 METHODS
+
+=cut
+
+
+=head2 _file_column_callback ($file,$ret,$target)
+
+method made to be overridden for callback purposes.
+
+=cut
+
+sub _file_column_callback {
+    my ($self,$file,$ret,$target) = @_;
+}
+
+=head1 NAME
+
+DBIx::Class::InflateColumn::File -  map files from the Database to the filesystem.
+
+=head1 DESCRIPTION
+
+InflateColumn::File
+
+=head1 SYNOPSIS
+
+In your L<DBIx::Class> table class:
+
+    __PACKAGE__->load_components( "PK::Auto", "InflateColumn::File", "Core" );
+    
+    # define your columns
+    __PACKAGE__->add_columns(
+        "id",
+        {
+            data_type         => "integer",
+            is_auto_increment => 1,
+            is_nullable       => 0,
+            size              => 4,
+        },
+        "filename",
+        {
+            data_type           => "varchar",
+            is_file_column      => 1,
+            file_column_path    =>'/tmp/uploaded_files',
+            # or for a Catalyst application 
+            # file_column_path  => MyApp->path_to('root','static','files'),
+            default_value       => undef,
+            is_nullable         => 1,
+            size                => 255,
+        },
+    );
+    
+
+In your L<Catalyst::Controller> class:
+
+FileColumn requires a hash that contains L<IO::File> as handle and the file's name as name.
+
+    my $entry = $c->model('MyAppDB::Articles')->create({ 
+        subject => 'blah',
+        filename => { 
+            handle => $c->req->upload('myupload')->fh, 
+            filename => $c->req->upload('myupload')->basename 
+        },
+        body => '....'
+    });
+    $c->stash->{entry}=$entry;
+    
+
+And Place the following in your TT template
+    
+    Article Subject: [% entry.subject %]
+    Uploaded File: 
+    <a href="/static/files/[% entry.id %]/[% entry.filename.filename %]">File</a>
+    Body: [% entry.body %]
+    
+The file will be stored on the filesystem for later retrieval.
+Calling delete on your resultset will delete the file from the filesystem.
+Retrevial of the record automatically inflates the column back to the set hash with the IO::File handle and filename.
+
+=head1 AUTHOR
+
+Victor Igumnov
+
+=head1 LICENSE
+
+This library is free software, you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
+
+1;
index e95a95c..bd92f43 100644 (file)
@@ -494,7 +494,7 @@ To order C<< $book->pages >> by descending page_number.
 =head2 Transactions
 
 As of version 0.04001, there is improved transaction support in
-L<DBIx::Class::Storage::DBI> and L<DBIx::Class::Schema>.  Here is an
+L<DBIx::Class::Storage> and L<DBIx::Class::Schema>.  Here is an
 example of the recommended way to use it:
 
   my $genus = $schema->resultset('Genus')->find(12);
@@ -912,7 +912,7 @@ method.
 
 =head2 Profiling
 
-When you enable L<DBIx::Class::Storage::DBI>'s debugging it prints the SQL
+When you enable L<DBIx::Class::Storage>'s debugging it prints the SQL
 executed as well as notifications of query completion and transaction
 begin/commit.  If you'd like to profile the SQL you can subclass the
 L<DBIx::Class::Storage::Statistics> class and write your own profiling
@@ -1107,42 +1107,18 @@ B<Test File> test.pl
 
 DBIx::Class is not built for speed, it's built for convenience and
 ease of use, but sometimes you just need to get the data, and skip the
-fancy objects. Luckily this is also fairly easy using
-C<inflate_result>:
-
-  # Define a class which just returns the results as a hashref:
-  package My::HashRefInflator;
-
-  ## $me is the hashref of cols/data from the immediate resultsource
-  ## $prefetch is a deep hashref of all the data from the prefetched
-  ##   related sources.
-
-  sub mk_hash {
-     my ($me, $rest) = @_;
-
-     return { %$me, 
-        map { ($_ => mk_hash(@{$rest->{$_}})) } keys %$rest
-     };
-  }
-
-  sub inflate_result {
-     my ($self, $source, $me, $prefetch) = @_;
-     return mk_hash($me, $prefetch); 
-  }
-
-  # Change the object inflation to a hashref for just this resultset:
-  $rs->result_class('My::HashRefInflator');
-
-  my $datahashref = $rs->next;
-  foreach my $col (keys %$datahashref) {
-     if(!ref($datahashref->{$col})) {
-        # It's a plain value
-     }
-     elsif(ref($datahashref->{$col} eq 'HASH')) {
-        # It's a related value in a hashref
-     }
-  }
-
+fancy objects.
+  
+To do this simply use L<DBIx::Class::ResultClass::HashRefInflator>.
+  
+ my $rs = $schema->resultset('CD');
+ $rs->result_class('DBIx::Class::ResultClass::HashRefInflator');
+ my $hash_ref = $rs->find(1);
+  
+Wasn't that easy?
+  
 =head2 Want to know if find_or_create found or created a row?
 
 Just use C<find_or_new> instead, then check C<in_storage>:
index 8d425bb..5820d03 100644 (file)
@@ -64,6 +64,8 @@ DBIx::Class::Manual::DocMap - What documentation do we have?
 
 =item L<DBIx::Class::Row> - Dealing with actual data.
 
+=item L<DBIx::Class::Storage> - Basic Storage stuff.
+
 =item L<DBIx::Class::Storage::DBI> - Storage using L<DBI> and L<SQL::Abstract>.
 
 =back
index 2ff72ee..df0f773 100644 (file)
@@ -376,7 +376,7 @@ to work around this issue.
 
 =item See the SQL statements my code is producing?
 
-Turn on debugging! See L<DBIx::Class::Storage::DBI> for details of how
+Turn on debugging! See L<DBIx::Class::Storage> for details of how
 to turn on debugging in the environment, pass your own filehandle to
 save debug to, or create your own callback.
 
index 35ceba4..88e1110 100644 (file)
@@ -17,7 +17,6 @@ Create a table for your ordered data.
     name TEXT NOT NULL,
     position INTEGER NOT NULL
   );
-  # Optional: group_id INTEGER NOT NULL
 
 In your Schema or DB class add "Ordered" to the top 
 of the component list.
@@ -29,7 +28,6 @@ each row.
 
   package My::Item;
   __PACKAGE__->position_column('position');
-  __PACKAGE__->grouping_column('group_id'); # optional
 
 That's it, now you can change the position of your objects.
 
@@ -54,6 +52,10 @@ That's it, now you can change the position of your objects.
   $item->move_first();
   $item->move_last();
   $item->move_to( $position );
+  $item->move_to_group( 'groupname' );
+  $item->move_to_group( 'groupname', $position );
+  $item->move_to_group( {group_id=>'groupname', 'other_group_id=>'othergroupname'} );
+  $item->move_to_group( {group_id=>'groupname', 'other_group_id=>'othergroupname'}, $position );
 
 =head1 DESCRIPTION
 
@@ -127,6 +129,7 @@ is this sibling.
 sub first_sibling {
     my( $self ) = @_;
     return 0 if ($self->get_column($self->position_column())==1);
+
     return ($self->result_source->resultset->search(
         {
             $self->position_column => 1,
@@ -290,11 +293,72 @@ sub move_to {
         $self->_grouping_clause(),
     });
     my $op = ($from_position>$to_position) ? '+' : '-';
-    $rs->update({ $position_column => \"$position_column $op 1" });
+    $rs->update({ $position_column => \"$position_column $op 1" });  #" Sorry, GEdit bug
+    $self->{_ORDERED_INTERNAL_UPDATE} = 1;
     $self->update({ $position_column => $to_position });
     return 1;
 }
 
+
+
+=head2 move_to_group
+
+  $item->move_to_group( $group, $position );
+
+Moves the object to the specified position of the specified
+group, or to the end of the group if $position is undef.
+1 is returned on success, and 0 is returned if the object is
+already at the specified position of the specified group.
+
+$group may be specified as a single scalar if only one 
+grouping column is in use, or as a hashref of column => value pairs
+if multiple grouping columns are in use.
+
+=cut
+
+sub move_to_group {
+    my( $self, $to_group, $to_position ) = @_;
+
+    # if we're given a string, turn it into a hashref
+    unless (ref $to_group eq 'HASH') {
+        $to_group = {($self->_grouping_columns)[0] => $to_group};
+    }
+
+    my $position_column = $self->position_column;
+    #my @grouping_columns = $self->_grouping_columns;
+
+    return 0 if ( ! defined($to_group) );
+    return 0 if ( defined($to_position) and $to_position < 1 );
+    return 0 if ( $self->_is_in_group($to_group) 
+                    and ((not defined($to_position)) 
+                            or (defined($to_position) and $self->$position_column==$to_position)
+                        )
+                    );
+
+    # Move to end of current group and adjust siblings
+    $self->move_last;
+
+    $self->set_columns($to_group);
+    my $new_group_count = $self->result_source->resultset->search({$self->_grouping_clause()})->count();
+    if (!defined($to_position) or $to_position > $new_group_count) {
+        $self->{_ORDERED_INTERNAL_UPDATE} = 1;
+        $self->update({ $position_column => $new_group_count + 1 });
+    }
+    else {
+        my @between = ($to_position, $new_group_count);
+
+        my $rs = $self->result_source->resultset->search({
+            $position_column => { -between => [ @between ] },
+            $self->_grouping_clause(),
+        });
+        $rs->update({ $position_column => \"$position_column + 1" }); #"
+        $self->{_ORDERED_INTERNAL_UPDATE} = 1;
+        $self->update({ $position_column => $to_position });
+    }
+
+    return 1;
+}
+
 =head2 insert
 
 Overrides the DBIC insert() method by providing a default 
@@ -311,6 +375,53 @@ sub insert {
     return $self->next::method( @_ );
 }
 
+=head2 update
+
+Overrides the DBIC update() method by checking for a change
+to the position and/or group columns.  Movement within a
+group or to another group is handled by repositioning
+the appropriate siblings.  Position defaults to the end
+of a new group if it has been changed to undef.
+
+=cut
+
+sub update {
+    my $self = shift;
+
+    if ($self->{_ORDERED_INTERNAL_UPDATE}) {
+        delete $self->{_ORDERED_INTERNAL_UPDATE};
+        return $self->next::method( @_ );
+    }
+
+    $self->set_columns($_[0]) if @_ > 0;
+    my %changes = $self->get_dirty_columns;
+    $self->discard_changes;
+
+    my $pos_col = $self->position_column;
+
+    # if any of our grouping columns have been changed
+    if (grep {$_} map {exists $changes{$_}} $self->_grouping_columns ) {
+
+        # create new_group by taking the current group and inserting changes
+        my $new_group = {$self->_grouping_clause};
+        foreach my $col (keys %$new_group) {
+            if (exists $changes{$col}) {
+                $new_group->{$col} = $changes{$col};
+                delete $changes{$col}; # don't want to pass this on to next::method
+            }
+        }
+
+        $self->move_to_group(
+            $new_group,
+            exists($changes{$pos_col}) ? delete($changes{$pos_col}) : $self->$pos_col
+        );
+    }
+    elsif (exists $changes{$pos_col}) {
+        $self->move_to(delete $changes{$pos_col});
+    }
+    return $self->next::method( \%changes );
+}
+
 =head2 delete
 
 Overrides the DBIC delete() method by first moving the object 
@@ -337,16 +448,52 @@ by the collection column.  If the collection column is not
 defined then this will return an empty list.
 
 =cut
-
 sub _grouping_clause {
     my( $self ) = @_;
+    return map {  $_ => $self->get_column($_)  } $self->_grouping_columns();
+}
+
+
+
+=head2 _get_grouping_columns
+
+Returns a list of the column names used for grouping, regardless of whether
+they were specified as an arrayref or a single string, and returns ()
+if there is no grouping.
+
+=cut
+sub _grouping_columns {
+    my( $self ) = @_;
     my $col = $self->grouping_column();
-    if ($col) {
-        return ( $col => $self->get_column($col) );
+    if (ref $col eq 'ARRAY') {
+        return @$col;
+    } elsif ($col) {
+        return ( $col );
+    } else {
+        return ();
     }
-    return ();
 }
 
+
+
+=head2 _is_in_group($other)
+
+    $item->_is_in_group( {user => 'fred', list => 'work'} )
+
+Returns true if the object is in the group represented by hashref $other
+=cut
+sub _is_in_group {
+    my ($self, $other) = @_;
+    my $current = {$self->_grouping_clause};
+    return 0 unless (ref $other eq 'HASH') and (keys %$current == keys %$other);
+    for my $key (keys %$current) {
+        return 0 unless exists $other->{$key};
+        return 0 if $current->{$key} ne $other->{$key};
+    }
+    return 1;
+}
+
+
 1;
 __END__
 
index b77ce00..b20eb16 100644 (file)
@@ -62,39 +62,4 @@ sub add_relationship_accessor {
   }
 }
 
-sub new {
-  my ($class, $attrs, @rest) = @_;
-  my ($related, $info);
-  foreach my $key (keys %{$attrs||{}}) {
-    next unless $info = $class->relationship_info($key);
-    $related->{$key} = delete $attrs->{$key}
-      if ref $attrs->{$key}
-         && $info->{attrs}{accessor}
-         && $info->{attrs}{accessor} eq 'single';
-  }
-  my $obj = $class->next::method($attrs, @rest);
-  if ($related) {
-    $obj->{_relationship_data} = $related;
-    foreach my $rel (keys %$related) {
-      $obj->set_from_related($rel, $related->{$rel});
-    }
-  }
-  return $obj;
-}
-
-sub update {
-  my ($obj, $attrs, @rest) = @_;
-  my $info;
-  foreach my $key (keys %{$attrs||{}}) {
-    next unless $info = $obj->relationship_info($key);
-    if (ref $attrs->{$key} && $info->{attrs}{accessor}
-        && $info->{attrs}{accessor} eq 'single') {
-      my $rel = delete $attrs->{$key};
-      $obj->set_from_related($key => $rel);
-      $obj->{_relationship_data}{$key} = $rel;
-    }
-  }
-  return $obj->next::method($attrs, @rest);
-}
-
 1;
diff --git a/lib/DBIx/Class/ResultClass/HashRefInflator.pm b/lib/DBIx/Class/ResultClass/HashRefInflator.pm
new file mode 100644 (file)
index 0000000..ca6741e
--- /dev/null
@@ -0,0 +1,76 @@
+package DBIx::Class::ResultClass::HashRefInflator;
+
+=head1 NAME
+
+DBIx::Class::ResultClass::HashRefInflator
+
+=head1 SYNOPSIS
+
+ my $rs = $schema->resultset('CD');
+
+ $rs->result_class('DBIx::Class::ResultClass::HashRefInflator');
+
+=head1 DESCRIPTION
+
+DBIx::Class is not built for speed: it's built for convenience and
+ease of use. But sometimes you just need to get the data, and skip the
+fancy objects. That is what this class provides.
+
+There are two ways of using this class.
+
+=over
+
+=item *
+
+Specify C<< $rs->result_class >> on a specific resultset to affect only that
+resultser (and any chained off of it); or
+
+=item *
+
+Specify C<< __PACKAGE__->result_class >> on your source object to force all
+uses of that result source to be inflated to hash-refs - this approach is not
+recomended
+
+=back
+
+=head1 METHODS
+
+=head2 inflate_result
+
+Inflates the result and prefetched data into a hash-ref using L<mk_hash>.
+
+=cut
+
+sub inflate_result {
+    my ($self, $source, $me, $prefetch) = @_;
+
+    return mk_hash($me, $prefetch);
+}
+
+=head2 mk_hash
+
+This does all the work of inflating the (pre)fetched data.
+
+=cut
+
+sub mk_hash {
+    my ($me, $rest) = @_;
+
+    # $me is the hashref of cols/data from the immediate resultsource
+    # $rest is a deep hashref of all the data from the prefetched
+    # related sources.
+
+    # to avoid emtpy has_many rels contain one empty hashref
+    return if (not keys %$me);
+
+    return { %$me,
+        map {
+          ( $_ =>
+             ref($rest->{$_}[0]) eq 'ARRAY' ? [ map { mk_hash(@$_) } @{$rest->{$_}} ]
+                                            : mk_hash( @{$rest->{$_}} )
+          )
+        } keys %$rest
+    };
+}
+
+1;
index 6c1066c..a56285c 100644 (file)
@@ -10,10 +10,10 @@ use Carp::Clan qw/^DBIx::Class/;
 use Data::Page;
 use Storable;
 use DBIx::Class::ResultSetColumn;
+use DBIx::Class::ResultSourceHandle;
 use base qw/DBIx::Class/;
 
-__PACKAGE__->load_components(qw/AccessorGroup/);
-__PACKAGE__->mk_group_accessors('simple' => qw/result_source result_class/);
+__PACKAGE__->mk_group_accessors('simple' => qw/result_class _source_handle/);
 
 =head1 NAME
 
@@ -85,7 +85,8 @@ sub new {
   return $class->new_result(@_) if ref $class;
 
   my ($source, $attrs) = @_;
-  #weaken $source;
+  $source = $source->handle 
+    unless $source->isa('DBIx::Class::ResultSourceHandle');
   $attrs = { %{$attrs||{}} };
 
   if ($attrs->{page}) {
@@ -97,8 +98,8 @@ sub new {
   $attrs->{alias} ||= 'me';
 
   my $self = {
-    result_source => $source,
-    result_class => $attrs->{result_class} || $source->result_class,
+    _source_handle => $source,
+    result_class => $attrs->{result_class} || $source->resolve->result_class,
     cond => $attrs->{where},
     count => undef,
     pager => undef,
@@ -239,7 +240,7 @@ sub search_rs {
         : $having);
   }
 
-  my $rs = (ref $self)->new($self->result_source, $new_attrs);
+  my $rs = (ref $self)->new($self->_source_handle, $new_attrs);
   if ($rows) {
     $rs->set_cache($rows);
   }
@@ -743,7 +744,7 @@ sub next {
 sub _construct_object {
   my ($self, @row) = @_;
   my $info = $self->_collapse_result($self->{_attrs}{as}, \@row);
-  my @new = $self->result_class->inflate_result($self->result_source, @$info);
+  my @new = $self->result_class->inflate_result($self->_source_handle, @$info);
   @new = $self->{_attrs}{record_filter}->(@new)
     if exists $self->{_attrs}{record_filter};
   return @new;
@@ -919,7 +920,7 @@ sub _count { # Separated out so pager can get the full count
   # offset, order by and page are not needed to count. record_filter is cdbi
   delete $attrs->{$_} for qw/rows offset order_by page pager record_filter/;
 
-  my $tmp_rs = (ref $self)->new($self->result_source, $attrs);
+  my $tmp_rs = (ref $self)->new($self->_source_handle, $attrs);
   my ($count) = $tmp_rs->cursor->next;
   return $count;
 }
@@ -1110,9 +1111,9 @@ sub update {
     unless ref $values eq 'HASH';
 
   my $cond = $self->_cond_for_update_delete;
-
+   
   return $self->result_source->storage->update(
-    $self->result_source->from, $values, $cond
+    $self->result_source, $values, $cond
   );
 }
 
@@ -1162,7 +1163,7 @@ sub delete {
 
   my $cond = $self->_cond_for_update_delete;
 
-  $self->result_source->storage->delete($self->result_source->from, $cond);
+  $self->result_source->storage->delete($self->result_source, $cond);
   return 1;
 }
 
@@ -1230,7 +1231,7 @@ attribute set on the resultset (10 by default).
 
 sub page {
   my ($self, $page) = @_;
-  return (ref $self)->new($self->result_source, { %{$self->{attrs}}, page => $page });
+  return (ref $self)->new($self->_source_handle, { %{$self->{attrs}}, page => $page });
 }
 
 =head2 new_result
@@ -1260,11 +1261,9 @@ sub new_result {
   my %new = (
     %{ $self->_remove_alias($values, $alias) },
     %{ $self->_remove_alias($collapsed_cond, $alias) },
-    -result_source => $self->result_source,
   );
 
-  my $obj = $self->result_class->new(\%new);
-  return $obj;
+  return $self->result_class->new(\%new,$self->_source_handle);
 }
 
 # _collapse_cond
@@ -1558,7 +1557,7 @@ sub related_resultset {
     my $rel_obj = $self->result_source->relationship_info($rel);
 
     $self->throw_exception(
-      "search_related: result source '" . $self->result_source->name .
+      "search_related: result source '" . $self->_source_handle->source_moniker .
         "' has no such relationship $rel")
       unless $rel_obj;
     
@@ -1567,7 +1566,7 @@ sub related_resultset {
     my $join_count = $seen->{$rel};
     my $alias = ($join_count > 1 ? join('_', $rel, $join_count) : $rel);
 
-    $self->result_source->schema->resultset($rel_obj->{class})->search_rs(
+    $self->_source_handle->schema->resultset($rel_obj->{class})->search_rs(
       undef, {
         %{$self->{attrs}||{}},
         join => undef,
@@ -1608,7 +1607,7 @@ sub _resolved_attrs {
   return $self->{_attrs} if $self->{_attrs};
 
   my $attrs = { %{$self->{attrs}||{}} };
-  my $source = $self->{result_source};
+  my $source = $self->result_source;
   my $alias = $attrs->{alias};
 
   $attrs->{columns} ||= delete $attrs->{cols} if exists $attrs->{cols};
@@ -1740,6 +1739,16 @@ sub _merge_attr {
   }
 }
 
+sub result_source {
+    my $self = shift;
+
+    if (@_) {
+        $self->_source_handle($_[0]->handle);
+    } else {
+        $self->_source_handle->resolve;
+    }
+}
+
 =head2 throw_exception
 
 See L<DBIx::Class::Schema/throw_exception> for details.
@@ -1748,7 +1757,7 @@ See L<DBIx::Class::Schema/throw_exception> for details.
 
 sub throw_exception {
   my $self=shift;
-  $self->result_source->schema->throw_exception(@_);
+  $self->_source_handle->schema->throw_exception(@_);
 }
 
 # XXX: FIXME: Attributes docs need clearing up
@@ -1770,8 +1779,8 @@ Which column(s) to order the results by. This is currently passed
 through directly to SQL, so you can give e.g. C<year DESC> for a
 descending order on the column `year'.
 
-Please note that if you have quoting enabled (see
-L<DBIx::Class::Storage/quote_char>) you will need to do C<\'year DESC' > to
+Please note that if you have C<quote_char> enabled (see
+L<DBIx::Class::Storage::DBI/connect_info>) you will need to do C<\'year DESC' > to
 specify an order. (The scalar ref causes it to be passed as raw sql to the DB,
 so you will need to manually quote things as appropriate.)
 
index 49b8456..876a3c1 100644 (file)
@@ -35,12 +35,8 @@ passed as params. Used internally by L<DBIx::Class::ResultSet/get_column>.
 sub new {
   my ($class, $rs, $column) = @_;
   $class = ref $class if ref $class;
-
-  my $object_ref = { _column => $column,
-                    _parent_resultset => $rs };
-  
-  my $new = bless $object_ref, $class;
-  $new->throw_exception("column must be supplied") unless ($column);
+  my $new = bless { _column => $column, _parent_resultset => $rs }, $class;
+  $new->throw_exception("column must be supplied") unless $column;
   return $new;
 }
 
@@ -64,7 +60,6 @@ one value.
 
 sub next {
   my $self = shift;
-    
   $self->{_resultset} = $self->{_parent_resultset}->search(undef, {select => [$self->{_column}], as => [$self->{_column}]}) unless ($self->{_resultset});
   my ($row) = $self->{_resultset}->cursor->next;
   return $row;
@@ -111,8 +106,7 @@ resultset (or C<undef> if there are none).
 =cut
 
 sub min {
-  my $self = shift;
-  return $self->func('MIN');
+  return shift->func('MIN');
 }
 
 =head2 max
@@ -133,8 +127,7 @@ resultset (or C<undef> if there are none).
 =cut
 
 sub max {
-  my $self = shift;
-  return $self->func('MAX');
+  return shift->func('MAX');
 }
 
 =head2 sum
@@ -155,8 +148,7 @@ the resultset. Use on varchar-like columns at your own risk.
 =cut
 
 sub sum {
-  my $self = shift;
-  return $self->func('SUM');
+  return shift->func('SUM');
 }
 
 =head2 func
@@ -180,9 +172,7 @@ value. Produces the following SQL:
 =cut
 
 sub func {
-  my $self = shift;
-  my $function = shift;
-
+  my ($self,$function) = @_;
   my ($row) = $self->{_parent_resultset}->search(undef, {select => {$function => $self->{_column}}, as => [$self->{_column}]})->cursor->next;
   return $row;
 }
index dbbe1ad..54374f1 100644 (file)
@@ -4,19 +4,21 @@ use strict;
 use warnings;
 
 use DBIx::Class::ResultSet;
+use DBIx::Class::ResultSourceHandle;
 use Carp::Clan qw/^DBIx::Class/;
 use Storable;
 
 use base qw/DBIx::Class/;
-__PACKAGE__->load_components(qw/AccessorGroup/);
 
 __PACKAGE__->mk_group_accessors('simple' => qw/_ordered_columns
   _columns _primaries _unique_constraints name resultset_attributes
-  schema from _relationships column_info_from_storage source_name/);
+  schema from _relationships column_info_from_storage source_info/);
 
-__PACKAGE__->mk_group_accessors('component_class' => qw/resultset_class
+__PACKAGE__->mk_group_accessors('inherited' => qw/resultset_class
   result_class/);
 
+__PACKAGE__->mk_group_ro_accessors('simple' => qw/source_name/);
+
 =head1 NAME
 
 DBIx::Class::ResultSource - Result source object
@@ -46,9 +48,7 @@ sub new {
   my ($class, $attrs) = @_;
   $class = ref $class if ref $class;
 
-  my $new = { %{$attrs || {}}, _resultset => undef };
-  bless $new, $class;
-
+  my $new = bless { %{$attrs || {}} }, $class;
   $new->{resultset_class} ||= 'DBIx::Class::ResultSet';
   $new->{resultset_attributes} = { %{$new->{resultset_attributes} || {}} };
   $new->{_ordered_columns} = [ @{$new->{_ordered_columns}||[]}];
@@ -56,14 +56,22 @@ sub new {
   $new->{_relationships} = { %{$new->{_relationships}||{}} };
   $new->{name} ||= "!!NAME NOT SET!!";
   $new->{_columns_info_loaded} ||= 0;
-  if(!defined $new->column_info_from_storage) {
-      $new->{column_info_from_storage} = 1
-  }
   return $new;
 }
 
 =pod
 
+=head2 source_info
+
+Stores a hashref of per-source metadata.  No specific key names
+have yet been standardized, the examples below are purely hypothetical
+and don't actually accomplish anything on their own:
+
+  __PACKAGE__->source_info({
+    "_tablespace" => 'fast_disk_array_3',
+    "_engine" => 'InnoDB',
+  });
+
 =head2 add_columns
 
   $table->add_columns(qw/col1 col2 col3/);
@@ -223,13 +231,10 @@ sub column_info {
 
 =head2 column_info_from_storage
 
-Enables or disables the on-demand automatic loading of the above
-column metadata from storage as neccesary.  Defaults to true in the
-current release, but will default to false in future releases starting
-with 0.08000.  This is *deprecated*, and should not be used.  It will
-be removed before 1.0.
+Enables the on-demand automatic loading of the above column
+metadata from storage as neccesary.  This is *deprecated*, and
+should not be used.  It will be removed before 1.0.
 
-  __PACKAGE__->column_info_from_storage(0);
   __PACKAGE__->column_info_from_storage(1);
 
 =head2 columns
@@ -965,12 +970,6 @@ sub resultset {
     'call it on the schema instead.'
   ) if scalar @_;
 
-  # disabled until we can figure out a way to do it without consistency issues
-  #
-  #return $self->{_resultset}
-  #  if ref $self->{_resultset} eq $self->resultset_class;
-  #return $self->{_resultset} =
-
   return $self->resultset_class->new(
     $self, $self->{resultset_attributes}
   );
@@ -996,6 +995,20 @@ its class name.
   # from your schema...
   $schema->resultset('Books')->find(1);
 
+=head2 handle
+
+Obtain a new handle to this source. Returns an instance of a 
+L<DBIx::Class::ResultSourceHandle>.
+
+=cut
+
+sub handle {
+    return new DBIx::Class::ResultSourceHandle({
+        schema         => $_[0]->schema,
+        source_moniker => $_[0]->source_name
+    });
+}
+
 =head2 throw_exception
 
 See L<DBIx::Class::Schema/"throw_exception">.
index 1e56359..cf263d1 100644 (file)
@@ -5,8 +5,6 @@ use warnings;
 
 use DBIx::Class::ResultSet;
 
-use Carp qw/croak/;
-
 use base qw/DBIx::Class/;
 __PACKAGE__->load_components(qw/ResultSource/);
 
diff --git a/lib/DBIx/Class/ResultSourceHandle.pm b/lib/DBIx/Class/ResultSourceHandle.pm
new file mode 100644 (file)
index 0000000..60118b8
--- /dev/null
@@ -0,0 +1,76 @@
+package DBIx::Class::ResultSourceHandle;
+
+use strict;
+use warnings;
+use Storable;
+
+use base qw/DBIx::Class/;
+
+use overload
+    q/""/ => sub { __PACKAGE__ . ":" . shift->source_moniker; },
+    fallback => 1;
+
+__PACKAGE__->mk_group_accessors('simple' => qw/schema source_moniker/);
+
+=head1 NAME
+
+DBIx::Class::ResultSourceHandle
+
+=head1 DESCRIPTION
+
+This module removes fixed link between Rows/ResultSets and the actual source
+objects, which gets round the following problems
+
+=over 4
+
+=item *
+
+Needing to keep C<$schema> in scope, since any objects/result_sets
+will have a C<$schema> object through their source handle
+
+=item *
+
+Large output when using Data::Dump(er) since this class can be set to
+stringify to almost nothing
+
+=item *
+
+Closer to being aboe to do a Serialize::Storable that doesn't require class-based connections
+
+=back
+
+=head1 METHODS
+
+=head2 new
+
+=cut
+
+sub new {
+    my ($class, $data) = @_;
+
+    $class = ref $class if ref $class;
+
+    bless $data, $class;
+}
+
+=head2 resolve
+
+Resolve the moniker into the actual ResultSource object
+
+=cut
+
+sub resolve { return $_[0]->schema->source($_[0]->source_moniker) }
+
+sub STORABLE_freeze {
+    my ($self, $cloning) = @_;
+    my $to_serialize = { %$self };
+    delete $to_serialize->{schema};
+    return (Storable::freeze($to_serialize));
+}
+
+sub STORABLE_thaw {
+    my ($self, $cloning,$ice) = @_;
+    %$self = %{ Storable::thaw($ice) };
+}
+
+1;
index 1ae920e..696c9a5 100644 (file)
@@ -5,11 +5,28 @@ use strict;
 use warnings;
 
 use base qw/DBIx::Class/;
+use Scalar::Util qw/blessed/;
+use Carp::Clan qw/^DBIx::Class/;
 
 sub iterator_class  { shift->result_source_instance->resultset_class(@_) }
 sub resultset_class { shift->result_source_instance->resultset_class(@_) }
 sub result_class { shift->result_source_instance->result_class(@_) }
-sub source_name { shift->result_source_instance->source_name(@_) }
+sub source_info { shift->result_source_instance->source_info(@_) }
+
+sub set_inherited_ro_instance {
+    my $self = shift;
+
+    croak "Cannot set @{[shift]} on an instance" if blessed $self;
+
+    return $self->set_inherited(@_);
+}
+
+sub get_inherited_ro_instance {
+    return shift->get_inherited(@_);
+}
+
+__PACKAGE__->mk_group_accessors('inherited_ro_instance' => 'source_name');
+
 
 sub resultset_attributes {
   shift->result_source_instance->resultset_attributes(@_);
index f70f2bc..ce78cb8 100644 (file)
@@ -4,10 +4,10 @@ use strict;
 use warnings;
 
 use base qw/DBIx::Class::ResultSourceProxy/;
-__PACKAGE__->load_components(qw/AccessorGroup/);
 
-__PACKAGE__->mk_group_accessors('component_class' => 'table_class');
-__PACKAGE__->table_class('DBIx::Class::ResultSource::Table');
+use DBIx::Class::ResultSource::Table;
+
+__PACKAGE__->mk_classdata(table_class => 'DBIx::Class::ResultSource::Table');
 
 __PACKAGE__->mk_classdata('table_alias'); # FIXME: Doesn't actually do
                                           # anything yet!
@@ -53,7 +53,12 @@ sub table {
         source_name => undef,
     });
   }
-  $class->mk_classdata('result_source_instance' => $table);
+
+  $class->mk_classdata('result_source_instance')
+    unless $class->can('result_source_instance');
+
+  $class->result_source_instance($table);
+
   if ($class->can('schema_instance')) {
     $class =~ m/([^:]+)$/;
     $class->schema_instance->register_class($class, $class);
index e6e5ebc..a26d34c 100644 (file)
@@ -6,9 +6,7 @@ use warnings;
 use base qw/DBIx::Class/;
 use Carp::Clan qw/^DBIx::Class/;
 
-__PACKAGE__->load_components(qw/AccessorGroup/);
-
-__PACKAGE__->mk_group_accessors('simple' => 'result_source');
+__PACKAGE__->mk_group_accessors('simple' => qw/_source_handle/);
 
 =head1 NAME
 
@@ -32,23 +30,46 @@ Creates a new row object from column => value mappings passed as a hash ref
 =cut
 
 sub new {
-  my ($class, $attrs) = @_;
+  my ($class, $attrs, $source) = @_;
   $class = ref $class if ref $class;
 
   my $new = { _column_data => {} };
   bless $new, $class;
 
+  $new->_source_handle($source) if $source;
+
   if ($attrs) {
     $new->throw_exception("attrs must be a hashref")
       unless ref($attrs) eq 'HASH';
+    
+    my ($related,$inflated);
+    foreach my $key (keys %$attrs) {
+      if (ref $attrs->{$key}) {
+        my $info = $class->relationship_info($key);
+        if ($info && $info->{attrs}{accessor}
+          && $info->{attrs}{accessor} eq 'single')
+        {
+          $new->set_from_related($key, $attrs->{$key});        
+          $related->{$key} = $attrs->{$key};
+          next;
+        }
+        elsif ($class->has_column($key)
+          && exists $class->column_info($key)->{_inflate_info})
+        {
+          $inflated->{$key} = $attrs->{$key};
+          next;
+        }
+      }
+      $new->throw_exception("No such column $key on $class")
+        unless $class->has_column($key);
+      $new->store_column($key => $attrs->{$key});          
+    }
     if (my $source = delete $attrs->{-result_source}) {
       $new->result_source($source);
     }
-    foreach my $k (keys %$attrs) {
-      $new->throw_exception("No such column $k on $class")
-        unless $class->has_column($k);
-      $new->store_column($k => $attrs->{$k});
-    }
+
+    $new->{_relationship_data} = $related if $related;
+    $new->{_inflated_column} = $inflated if $inflated;
   }
 
   return $new;
@@ -69,13 +90,13 @@ L<DBIx::Class::ResultSet/create>).
 sub insert {
   my ($self) = @_;
   return $self if $self->in_storage;
-  $self->{result_source} ||= $self->result_source_instance
+  my $source = $self->result_source;
+  $source ||=  $self->result_source($self->result_source_instance)
     if $self->can('result_source_instance');
-  my $source = $self->{result_source};
   $self->throw_exception("No result_source set on this object; can't insert")
     unless $source;
-  #use Data::Dumper; warn Dumper($self);
-  $source->storage->insert($source->from, { $self->get_columns });
+
+  $source->storage->insert($source, { $self->get_columns });
   $self->in_storage(1);
   $self->{_dirty_columns} = {};
   $self->{related_resultsets} = {};
@@ -118,11 +139,33 @@ sub update {
   my $ident_cond = $self->ident_condition;
   $self->throw_exception("Cannot safely update a row in a PK-less table")
     if ! keys %$ident_cond;
-  $self->set_columns($upd) if $upd;
+
+  if ($upd) {
+    foreach my $key (keys %$upd) {
+      if (ref $upd->{$key}) {
+        my $info = $self->relationship_info($key);
+        if ($info && $info->{attrs}{accessor}
+          && $info->{attrs}{accessor} eq 'single')
+        {
+          my $rel = delete $upd->{$key};
+          $self->set_from_related($key => $rel);
+          $self->{_relationship_data}{$key} = $rel;          
+        } 
+        elsif ($self->has_column($key)
+          && exists $self->column_info($key)->{_inflate_info})
+        {
+          $self->set_inflated_column($key, delete $upd->{$key});          
+        }
+      }
+    }
+    $self->set_columns($upd);    
+  }
   my %to_update = $self->get_dirty_columns;
   return $self unless keys %to_update;
   my $rows = $self->result_source->storage->update(
-               $self->result_source->from, \%to_update, $self->{_orig_ident} || $ident_cond);
+               $self->result_source, \%to_update,
+               $self->{_orig_ident} || $ident_cond
+             );
   if ($rows == 0) {
     $self->throw_exception( "Can't update ${self}: row not found" );
   } elsif ($rows > 1) {
@@ -139,8 +182,8 @@ sub update {
   $obj->delete
 
 Deletes the object from the database. The object is still perfectly
-usable, but C<-E<gt>in_storage()> will now return 0 and the object must
-reinserted using C<-E<gt>insert()> before C<-E(<gt>update()> can be used
+usable, but C<< ->in_storage() >> will now return 0 and the object must
+reinserted using C<< ->insert() >> before C<< ->update() >> can be used
 on it. If you delete an object in a class with a C<has_many>
 relationship, all the related objects will be deleted as well. To turn
 this behavior off, pass C<cascade_delete => 0> in the C<$attr>
@@ -161,7 +204,7 @@ sub delete {
               unless exists $self->{_column_data}{$column};
     }
     $self->result_source->storage->delete(
-      $self->result_source->from, $ident_cond);
+      $self->result_source, $ident_cond);
     $self->in_storage(undef);
   } else {
     $self->throw_exception("Can't do class delete without a ResultSource instance")
@@ -177,9 +220,10 @@ sub delete {
 
   my $val = $obj->get_column($col);
 
-Gets a column value from a row object. Currently, does not do
-any queries; the column must have already been fetched from
-the database and stored in the object.
+Gets a column value from a row object. Does not do any queries; the column 
+must have already been fetched from the database and stored in the object. If 
+there is an inflated value stored that has not yet been deflated, it is deflated
+when the method is invoked.
 
 =cut
 
@@ -187,6 +231,10 @@ sub get_column {
   my ($self, $column) = @_;
   $self->throw_exception( "Can't fetch data as class method" ) unless ref $self;
   return $self->{_column_data}{$column} if exists $self->{_column_data}{$column};
+  if (exists $self->{_inflated_column}{$column}) {
+    return $self->store_column($column,
+      $self->_deflated_column($column, $self->{_inflated_column}{$column}));   
+  }
   $self->throw_exception( "No such column '${column}'" ) unless $self->has_column($column);
   return undef;
 }
@@ -205,6 +253,7 @@ database (or set locally).
 sub has_column_loaded {
   my ($self, $column) = @_;
   $self->throw_exception( "Can't call has_column data as class method" ) unless ref $self;
+  return 1 if exists $self->{_inflated_column}{$column};
   return exists $self->{_column_data}{$column};
 }
 
@@ -218,6 +267,12 @@ Does C<get_column>, for all column values at once.
 
 sub get_columns {
   my $self = shift;
+  if (exists $self->{_inflated_column}) {
+    foreach my $col (keys %{$self->{_inflated_column}}) {
+      $self->store_column($col, $self->_deflated_column($col, $self->{_inflated_column}{$col}))
+        unless exists $self->{_column_data}{$col};
+    }
+  }
   return %{$self->{_column_data}};
 }
 
@@ -334,9 +389,17 @@ Called by ResultSet to inflate a result from storage
 
 sub inflate_result {
   my ($class, $source, $me, $prefetch) = @_;
-  #use Data::Dumper; print Dumper(@_);
+
+  my ($source_handle) = $source;
+
+  if ($source->isa('DBIx::Class::ResultSourceHandle')) {
+      $source = $source_handle->resolve
+  } else {
+      $source_handle = $source->handle
+  }
+
   my $new = {
-    result_source => $source,
+    _source_handle => $source_handle,
     _column_data => $me,
     _in_storage => 1
   };
@@ -436,6 +499,18 @@ sub is_column_changed {
 
 Accessor to the ResultSource this object was created from
 
+=cut
+
+sub result_source {
+    my $self = shift;
+
+    if (@_) {
+        $self->_source_handle($_[0]->handle);
+    } else {
+        $self->_source_handle->resolve;
+    }
+}
+
 =head2 register_column
 
   $column_info = { .... };
index 3ab14fd..58a59db 100644 (file)
@@ -5,6 +5,8 @@ use warnings;
 
 use Carp::Clan qw/^DBIx::Class/;
 use Scalar::Util qw/weaken/;
+use File::Spec;
+require Module::Find;
 
 use base qw/DBIx::Class/;
 
@@ -12,6 +14,7 @@ __PACKAGE__->mk_classdata('class_mappings' => {});
 __PACKAGE__->mk_classdata('source_registrations' => {});
 __PACKAGE__->mk_classdata('storage_type' => '::DBI');
 __PACKAGE__->mk_classdata('storage');
+__PACKAGE__->mk_classdata('exception_action');
 
 =head1 NAME
 
@@ -91,10 +94,15 @@ moniker.
 
 sub register_source {
   my ($self, $moniker, $source) = @_;
+
+  %$source = %{ $source->new( { %$source, source_name => $moniker }) };
+
   my %reg = %{$self->source_registrations};
   $reg{$moniker} = $source;
   $self->source_registrations(\%reg);
+
   $source->schema($self);
+
   weaken($source->{schema}) if ref($self);
   if ($source->result_class) {
     my %map = %{$self->class_mappings};
@@ -103,6 +111,19 @@ sub register_source {
   }
 }
 
+sub _unregister_source {
+    my ($self, $moniker) = @_;
+    my %reg = %{$self->source_registrations}; 
+
+    my $source = delete $reg{$moniker};
+    $self->source_registrations(\%reg);
+    if ($source->result_class) {
+        my %map = %{$self->class_mappings};
+        delete $map{$source->result_class};
+        $self->class_mappings(\%map);
+    }
+}
+
 =head2 class
 
 =over 4
@@ -253,10 +274,6 @@ sub load_classes {
       }
     }
   } else {
-    eval "require Module::Find;";
-    $class->throw_exception(
-      "No arguments to load_classes and couldn't load Module::Find ($@)"
-    ) if $@;
     my @comp = map { substr $_, length "${class}::"  }
                  Module::Find::findallmod($class);
     $comps_for{$class} = \@comp;
@@ -277,9 +294,10 @@ sub load_classes {
           }
         }
         $class->ensure_class_loaded($comp_class);
-        $comp_class->source_name($comp) unless $comp_class->source_name;
 
-        push(@to_register, [ $comp_class->source_name, $comp_class ]);
+        $comp = $comp_class->source_name || $comp;
+#  $DB::single = 1;
+        push(@to_register, [ $comp, $comp_class ]);
       }
     }
   }
@@ -291,7 +309,165 @@ sub load_classes {
   }
 }
 
-=head2 compose_connection
+=head2 load_namespaces
+
+=over 4
+
+=item Arguments: %options?
+
+=back
+
+This is an alternative to L</load_classes> above which assumes an alternative
+layout for automatic class loading.  It assumes that all result
+classes are underneath a sub-namespace of the schema called C<Result>, any
+corresponding ResultSet classes are underneath a sub-namespace of the schema
+called C<ResultSet>.
+
+Both of the sub-namespaces are configurable if you don't like the defaults,
+via the options C<result_namespace> and C<resultset_namespace>.
+
+If (and only if) you specify the option C<default_resultset_class>, any found
+Result classes for which we do not find a corresponding
+ResultSet class will have their C<resultset_class> set to
+C<default_resultset_class>.
+
+C<load_namespaces> takes care of calling C<resultset_class> for you where
+neccessary if you didn't do it for yourself.
+
+All of the namespace and classname options to this method are relative to
+the schema classname by default.  To specify a fully-qualified name, prefix
+it with a literal C<+>.
+
+Examples:
+
+  # load My::Schema::Result::CD, My::Schema::Result::Artist,
+  #    My::Schema::ResultSet::CD, etc...
+  My::Schema->load_namespaces;
+
+  # Override everything to use ugly names.
+  # In this example, if there is a My::Schema::Res::Foo, but no matching
+  #   My::Schema::RSets::Foo, then Foo will have its
+  #   resultset_class set to My::Schema::RSetBase
+  My::Schema->load_namespaces(
+    result_namespace => 'Res',
+    resultset_namespace => 'RSets',
+    default_resultset_class => 'RSetBase',
+  );
+
+  # Put things in other namespaces
+  My::Schema->load_namespaces(
+    result_namespace => '+Some::Place::Results',
+    resultset_namespace => '+Another::Place::RSets',
+  );
+
+If you'd like to use multiple namespaces of each type, simply use an arrayref
+of namespaces for that option.  In the case that the same result
+(or resultset) class exists in multiple namespaces, the latter entries in
+your list of namespaces will override earlier ones.
+
+  My::Schema->load_namespaces(
+    # My::Schema::Results_C::Foo takes precedence over My::Schema::Results_B::Foo :
+    result_namespace => [ 'Results_A', 'Results_B', 'Results_C' ],
+    resultset_namespace => [ '+Some::Place::RSets', 'RSets' ],
+  );
+
+=cut
+
+# Pre-pends our classname to the given relative classname or
+#   class namespace, unless there is a '+' prefix, which will
+#   be stripped.
+sub _expand_relative_name {
+  my ($class, $name) = @_;
+  return if !$name;
+  $name = $class . '::' . $name if ! ($name =~ s/^\+//);
+  return $name;
+}
+
+# returns a hash of $shortname => $fullname for every package
+#  found in the given namespaces ($shortname is with the $fullname's
+#  namespace stripped off)
+sub _map_namespaces {
+  my ($class, @namespaces) = @_;
+
+  my @results_hash;
+  foreach my $namespace (@namespaces) {
+    push(
+      @results_hash,
+      map { (substr($_, length "${namespace}::"), $_) }
+      Module::Find::findallmod($namespace)
+    );
+  }
+
+  @results_hash;
+}
+
+sub load_namespaces {
+  my ($class, %args) = @_;
+
+  my $result_namespace = delete $args{result_namespace} || 'Result';
+  my $resultset_namespace = delete $args{resultset_namespace} || 'ResultSet';
+  my $default_resultset_class = delete $args{default_resultset_class};
+
+  $class->throw_exception('load_namespaces: unknown option(s): '
+    . join(q{,}, map { qq{'$_'} } keys %args))
+      if scalar keys %args;
+
+  $default_resultset_class
+    = $class->_expand_relative_name($default_resultset_class);
+
+  for my $arg ($result_namespace, $resultset_namespace) {
+    $arg = [ $arg ] if !ref($arg) && $arg;
+
+    $class->throw_exception('load_namespaces: namespace arguments must be '
+      . 'a simple string or an arrayref')
+        if ref($arg) ne 'ARRAY';
+
+    $_ = $class->_expand_relative_name($_) for (@$arg);
+  }
+
+  my %results = $class->_map_namespaces(@$result_namespace);
+  my %resultsets = $class->_map_namespaces(@$resultset_namespace);
+
+  my @to_register;
+  {
+    no warnings 'redefine';
+    local *Class::C3::reinitialize = sub { };
+    use warnings 'redefine';
+
+    foreach my $result (keys %results) {
+      my $result_class = $results{$result};
+      $class->ensure_class_loaded($result_class);
+      $result_class->source_name($result) unless $result_class->source_name;
+
+      my $rs_class = delete $resultsets{$result};
+      my $rs_set = $result_class->resultset_class;
+      if($rs_set && $rs_set ne 'DBIx::Class::ResultSet') {
+        if($rs_class && $rs_class ne $rs_set) {
+          warn "We found ResultSet class '$rs_class' for '$result', but it seems "
+             . "that you had already set '$result' to use '$rs_set' instead";
+        }
+      }
+      elsif($rs_class ||= $default_resultset_class) {
+        $class->ensure_class_loaded($rs_class);
+        $result_class->resultset_class($rs_class);
+      }
+
+      push(@to_register, [ $result_class->source_name, $result_class ]);
+    }
+  }
+
+  foreach (sort keys %resultsets) {
+    warn "load_namespaces found ResultSet class $_ with no "
+      . 'corresponding Result class';
+  }
+
+  Class::C3->reinitialize;
+  $class->register_class(@$_) for (@to_register);
+
+  return;
+}
+
+=head2 compose_connection (DEPRECATED)
 
 =over 4
 
@@ -301,6 +477,12 @@ sub load_classes {
 
 =back
 
+DEPRECATED. You probably wanted compose_namespace.
+
+Actually, you probably just wanted to call connect.
+
+=for hidden due to deprecation
+
 Calls L<DBIx::Class::Schema/"compose_namespace"> to the target namespace,
 calls L<DBIx::Class::Schema/connection> with @db_info on the new schema,
 then injects the L<DBix::Class::ResultSetProxy> component and a
@@ -315,43 +497,50 @@ more information.
 
 =cut
 
-sub compose_connection {
-  my ($self, $target, @info) = @_;
-  my $base = 'DBIx::Class::ResultSetProxy';
-  eval "require ${base};";
-  $self->throw_exception
-    ("No arguments to load_classes and couldn't load ${base} ($@)")
-      if $@;
-
-  if ($self eq $target) {
-    # Pathological case, largely caused by the docs on early C::M::DBIC::Plain
-    foreach my $moniker ($self->sources) {
-      my $source = $self->source($moniker);
+{
+  my $warn;
+
+  sub compose_connection {
+    my ($self, $target, @info) = @_;
+
+    warn "compose_connection deprecated as of 0.08000" unless $warn++;
+
+    my $base = 'DBIx::Class::ResultSetProxy';
+    eval "require ${base};";
+    $self->throw_exception
+      ("No arguments to load_classes and couldn't load ${base} ($@)")
+        if $@;
+  
+    if ($self eq $target) {
+      # Pathological case, largely caused by the docs on early C::M::DBIC::Plain
+      foreach my $moniker ($self->sources) {
+        my $source = $self->source($moniker);
+        my $class = $source->result_class;
+        $self->inject_base($class, $base);
+        $class->mk_classdata(resultset_instance => $source->resultset);
+        $class->mk_classdata(class_resolver => $self);
+      }
+      $self->connection(@info);
+      return $self;
+    }
+  
+    my $schema = $self->compose_namespace($target, $base);
+    {
+      no strict 'refs';
+      *{"${target}::schema"} = sub { $schema };
+    }
+  
+    $schema->connection(@info);
+    foreach my $moniker ($schema->sources) {
+      my $source = $schema->source($moniker);
       my $class = $source->result_class;
-      $self->inject_base($class, $base);
+      #warn "$moniker $class $source ".$source->storage;
+      $class->mk_classdata(result_source_instance => $source);
       $class->mk_classdata(resultset_instance => $source->resultset);
-      $class->mk_classdata(class_resolver => $self);
+      $class->mk_classdata(class_resolver => $schema);
     }
-    $self->connection(@info);
-    return $self;
+    return $schema;
   }
-
-  my $schema = $self->compose_namespace($target, $base);
-  {
-    no strict 'refs';
-    *{"${target}::schema"} = sub { $schema };
-  }
-
-  $schema->connection(@info);
-  foreach my $moniker ($schema->sources) {
-    my $source = $schema->source($moniker);
-    my $class = $source->result_class;
-    #warn "$moniker $class $source ".$source->storage;
-    $class->mk_classdata(result_source_instance => $source);
-    $class->mk_classdata(resultset_instance => $source->resultset);
-    $class->mk_classdata(class_resolver => $schema);
-  }
-  return $schema;
 }
 
 =head2 compose_namespace
@@ -470,8 +659,10 @@ C<::DBI::Sybase::MSSQL>.
 
 Instantiates a new Storage object of type
 L<DBIx::Class::Schema/"storage_type"> and passes the arguments to
-$storage->connect_info. Sets the connection in-place on the schema. See
-L<DBIx::Class::Storage::DBI/"connect_info"> for more information.
+$storage->connect_info. Sets the connection in-place on the schema.
+
+See L<DBIx::Class::Storage::DBI/"connect_info"> for DBI-specific syntax,
+or L<DBIx::Class::Storage> in general.
 
 =cut
 
@@ -485,9 +676,10 @@ sub connection {
   $self->throw_exception(
     "No arguments to load_classes and couldn't load ${storage_class} ($@)"
   ) if $@;
-  my $storage = $storage_class->new;
+  my $storage = $storage_class->new($self);
   $storage->connect_info(\@info);
   $self->storage($storage);
+  $self->on_connect() if($self->can('on_connect'));
   return $self;
 }
 
@@ -509,138 +701,83 @@ information.
 
 sub connect { shift->clone->connection(@_) }
 
-=head2 txn_begin
-
-Begins a transaction (does nothing if AutoCommit is off). Equivalent to
-calling $schema->storage->txn_begin. See
-L<DBIx::Class::Storage::DBI/"txn_begin"> for more information.
+=head2 txn_do
 
-=cut
+=over 4
 
-sub txn_begin { shift->storage->txn_begin }
+=item Arguments: C<$coderef>, @coderef_args?
 
-=head2 txn_commit
+=item Return Value: The return value of $coderef
 
-Commits the current transaction. Equivalent to calling
-$schema->storage->txn_commit. See L<DBIx::Class::Storage::DBI/"txn_commit">
-for more information.
+=back
 
-=cut
+Executes C<$coderef> with (optional) arguments C<@coderef_args> atomically,
+returning its result (if any). Equivalent to calling $schema->storage->txn_do.
+See L<DBIx::Class::Storage/"txn_do"> for more information.
 
-sub txn_commit { shift->storage->txn_commit }
+This interface is preferred over using the individual methods L</txn_begin>,
+L</txn_commit>, and L</txn_rollback> below.
 
-=head2 txn_rollback
+=cut
 
-Rolls back the current transaction. Equivalent to calling
-$schema->storage->txn_rollback. See
-L<DBIx::Class::Storage::DBI/"txn_rollback"> for more information.
+sub txn_do {
+  my $self = shift;
 
-=cut
+  $self->storage or $self->throw_exception
+    ('txn_do called on $schema without storage');
 
-sub txn_rollback { shift->storage->txn_rollback }
+  $self->storage->txn_do(@_);
+}
 
-=head2 txn_do
+=head2 txn_begin
 
-=over 4
+Begins a transaction (does nothing if AutoCommit is off). Equivalent to
+calling $schema->storage->txn_begin. See
+L<DBIx::Class::Storage::DBI/"txn_begin"> for more information.
 
-=item Arguments: C<$coderef>, @coderef_args?
+=cut
 
-=item Return Value: The return value of $coderef
+sub txn_begin {
+  my $self = shift;
 
-=back
+  $self->storage or $self->throw_exception
+    ('txn_begin called on $schema without storage');
 
-Executes C<$coderef> with (optional) arguments C<@coderef_args> atomically,
-returning its result (if any). If an exception is caught, a rollback is issued
-and the exception is rethrown. If the rollback fails, (i.e. throws an
-exception) an exception is thrown that includes a "Rollback failed" message.
+  $self->storage->txn_begin;
+}
 
-For example,
+=head2 txn_commit
 
-  my $author_rs = $schema->resultset('Author')->find(1);
-  my @titles = qw/Night Day It/;
+Commits the current transaction. Equivalent to calling
+$schema->storage->txn_commit. See L<DBIx::Class::Storage::DBI/"txn_commit">
+for more information.
 
-  my $coderef = sub {
-    # If any one of these fails, the entire transaction fails
-    $author_rs->create_related('books', {
-      title => $_
-    }) foreach (@titles);
+=cut
 
-    return $author->books;
-  };
+sub txn_commit {
+  my $self = shift;
 
-  my $rs;
-  eval {
-    $rs = $schema->txn_do($coderef);
-  };
+  $self->storage or $self->throw_exception
+    ('txn_commit called on $schema without storage');
 
-  if ($@) {                                  # Transaction failed
-    die "something terrible has happened!"   #
-      if ($@ =~ /Rollback failed/);          # Rollback failed
+  $self->storage->txn_commit;
+}
 
-    deal_with_failed_transaction();
-  }
+=head2 txn_rollback
 
-In a nested transaction (calling txn_do() from within a txn_do() coderef) only
-the outermost transaction will issue a L<DBIx::Class::Schema/"txn_commit"> on
-the Schema's storage, and txn_do() can be called in void, scalar and list
-context and it will behave as expected.
+Rolls back the current transaction. Equivalent to calling
+$schema->storage->txn_rollback. See
+L<DBIx::Class::Storage::DBI/"txn_rollback"> for more information.
 
 =cut
 
-sub txn_do {
-  my ($self, $coderef, @args) = @_;
+sub txn_rollback {
+  my $self = shift;
 
   $self->storage or $self->throw_exception
-    ('txn_do called on $schema without storage');
-  ref $coderef eq 'CODE' or $self->throw_exception
-    ('$coderef must be a CODE reference');
-
-  my (@return_values, $return_value);
-
-  $self->txn_begin; # If this throws an exception, no rollback is needed
-
-  my $wantarray = wantarray; # Need to save this since the context
-                             # inside the eval{} block is independent
-                             # of the context that called txn_do()
-  eval {
-
-    # Need to differentiate between scalar/list context to allow for
-    # returning a list in scalar context to get the size of the list
-    if ($wantarray) {
-      # list context
-      @return_values = $coderef->(@args);
-    } elsif (defined $wantarray) {
-      # scalar context
-      $return_value = $coderef->(@args);
-    } else {
-      # void context
-      $coderef->(@args);
-    }
-    $self->txn_commit;
-  };
+    ('txn_rollback called on $schema without storage');
 
-  if ($@) {
-    my $error = $@;
-
-    eval {
-      $self->txn_rollback;
-    };
-
-    if ($@) {
-      my $rollback_error = $@;
-      my $exception_class = "DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION";
-      $self->throw_exception($error)  # propagate nested rollback
-        if $rollback_error =~ /$exception_class/;
-
-      $self->throw_exception(
-        "Transaction aborted: $error. Rollback failed: ${rollback_error}"
-      );
-    } else {
-      $self->throw_exception($error); # txn failed but rollback succeeded
-    }
-  }
-
-  return $wantarray ? @return_values : $return_value;
+  $self->storage->txn_rollback;
 }
 
 =head2 clone
@@ -666,6 +803,7 @@ sub clone {
     my $new = $source->new($source);
     $clone->register_source($moniker => $new);
   }
+  $clone->storage->set_schema($clone) if $clone->storage;
   return $clone;
 }
 
@@ -681,7 +819,12 @@ Pass this method a resultsource name, and an arrayref of
 arrayrefs. The arrayrefs should contain a list of column names,
 followed by one or many sets of matching data for the given columns. 
 
-Each set of data is inserted into the database using
+In void context, C<insert_bulk> in L<DBIx::Class::Storage::DBI> is used
+to insert the data, as this is a fast method. However, insert_bulk currently
+assumes that your datasets all contain the same type of values, using scalar
+references in a column in one row, and not in another will probably not work.
+
+Otherwise, each set of data is inserted into the database using
 L<DBIx::Class::ResultSet/create>, and a arrayref of the resulting row
 objects is returned.
 
@@ -700,15 +843,50 @@ sub populate {
   my ($self, $name, $data) = @_;
   my $rs = $self->resultset($name);
   my @names = @{shift(@$data)};
-  my @created;
-  foreach my $item (@$data) {
-    my %create;
-    @create{@names} = @$item;
-    push(@created, $rs->create(\%create));
+  if(defined wantarray) {
+    my @created;
+    foreach my $item (@$data) {
+      my %create;
+      @create{@names} = @$item;
+      push(@created, $rs->create(\%create));
+    }
+    return @created;
   }
-  return @created;
+  $self->storage->insert_bulk($self->source($name), \@names, $data);
 }
 
+=head2 exception_action
+
+=over 4
+
+=item Arguments: $code_reference
+
+=back
+
+If C<exception_action> is set for this class/object, L</throw_exception>
+will prefer to call this code reference with the exception as an argument,
+rather than its normal <croak> action.
+
+Your subroutine should probably just wrap the error in the exception
+object/class of your choosing and rethrow.  If, against all sage advice,
+you'd like your C<exception_action> to suppress a particular exception
+completely, simply have it return true.
+
+Example:
+
+   package My::Schema;
+   use base qw/DBIx::Class::Schema/;
+   use My::ExceptionClass;
+   __PACKAGE__->exception_action(sub { My::ExceptionClass->throw(@_) });
+   __PACKAGE__->load_classes;
+
+   # or:
+   my $schema_obj = My::Schema->connect( .... );
+   $schema_obj->exception_action(sub { My::ExceptionClass->throw(@_) });
+
+   # suppress all exceptions, like a moron:
+   $schema_obj->exception_action(sub { 1 });
+
 =head2 throw_exception
 
 =over 4
@@ -718,13 +896,14 @@ sub populate {
 =back
 
 Throws an exception. Defaults to using L<Carp::Clan> to report errors from
-user's perspective.
+user's perspective.  See L</exception_action> for details on overriding
+this method's behavior.
 
 =cut
 
 sub throw_exception {
-  my ($self) = shift;
-  croak @_;
+  my $self = shift;
+  croak @_ if !$self->exception_action || !$self->exception_action->(@_);
 }
 
 =head2 deploy (EXPERIMENTAL)
@@ -738,12 +917,17 @@ sub throw_exception {
 Attempts to deploy the schema to the current storage using L<SQL::Translator>.
 
 Note that this feature is currently EXPERIMENTAL and may not work correctly
-across all databases, or fully handle complex relationships.
+across all databases, or fully handle complex relationships. Saying that, it
+has been used successfully by many people, including the core dev team.
 
 See L<SQL::Translator/METHODS> for a list of values for C<$sqlt_args>. The most
 common value for this would be C<< { add_drop_table => 1, } >> to have the SQL
 produced include a DROP TABLE statement for each table created.
 
+Additionally, the DBIx::Class parser accepts a C<sources> parameter as a hash 
+ref or an array ref, containing a list of source to deploy. If present, then 
+only the sources listed will get deployed.
+
 =cut
 
 sub deploy {
@@ -756,16 +940,41 @@ sub deploy {
 
 =over 4
 
-=item Arguments: \@databases, $version, $directory, $sqlt_args
+=item Arguments: \@databases, $version, $directory, $preversion, $sqlt_args
 
 =back
 
 Creates an SQL file based on the Schema, for each of the specified
-database types, in the given directory.
+database types, in the given directory. Given a previous version number,
+this will also create a file containing the ALTER TABLE statements to
+transform the previous schema into the current one. Note that these
+statements may contain DROP TABLE or DROP COLUMN statements that can
+potentially destroy data.
+
+The file names are created using the C<ddl_filename> method below, please
+override this method in your schema if you would like a different file
+name format. For the ALTER file, the same format is used, replacing
+$version in the name with "$preversion-$version".
+
+If no arguments are passed, then the following default values are used:
+
+=over 4
+
+=item databases  - ['MySQL', 'SQLite', 'PostgreSQL']
+
+=item version    - $schema->VERSION
+
+=item directory  - './'
+
+=item preversion - <none>
+
+=back
 
 Note that this feature is currently EXPERIMENTAL and may not work correctly
 across all databases, or fully handle complex relationships.
 
+WARNING: Please check all SQL files created, before applying them.
+
 =cut
 
 sub create_ddl_dir {
@@ -777,19 +986,30 @@ sub create_ddl_dir {
 
 =head2 ddl_filename (EXPERIMENTAL)
 
-  my $filename = $table->ddl_filename($type, $dir, $version)
+=over 4
+
+=item Arguments: $directory, $database-type, $version, $preversion
+
+=back
+
+  my $filename = $table->ddl_filename($type, $dir, $version, $preversion)
+
+This method is called by C<create_ddl_dir> to compose a file name out of
+the supplied directory, database type and version number. The default file
+name format is: C<$dir$schema-$version-$type.sql>.
 
-Creates a filename for a SQL file based on the table class name.  Not
-intended for direct end user use.
+You may override this method in your schema if you wish to use a different
+format.
 
 =cut
 
 sub ddl_filename {
-    my ($self, $type, $dir, $version) = @_;
+    my ($self, $type, $dir, $version, $pversion) = @_;
 
     my $filename = ref($self);
     $filename =~ s/::/-/g;
-    $filename = "$dir$filename-$version-$type.sql";
+    $filename = File::Spec->catfile($dir, "$filename-$version-$type.sql");
+    $filename =~ s/$version/$pversion-$version/ if($pversion);
 
     return $filename;
 }
diff --git a/lib/DBIx/Class/Schema/Versioned.pm b/lib/DBIx/Class/Schema/Versioned.pm
new file mode 100644 (file)
index 0000000..91e78aa
--- /dev/null
@@ -0,0 +1,303 @@
+package DBIx::Class::Version::Table;
+use base 'DBIx::Class';
+use strict;
+use warnings;
+
+__PACKAGE__->load_components(qw/ Core/);
+__PACKAGE__->table('SchemaVersions');
+
+__PACKAGE__->add_columns
+    ( 'Version' => {
+        'data_type' => 'VARCHAR',
+        'is_auto_increment' => 0,
+        'default_value' => undef,
+        'is_foreign_key' => 0,
+        'name' => 'Version',
+        'is_nullable' => 0,
+        'size' => '10'
+        },
+      'Installed' => {
+          'data_type' => 'VARCHAR',
+          'is_auto_increment' => 0,
+          'default_value' => undef,
+          'is_foreign_key' => 0,
+          'name' => 'Installed',
+          'is_nullable' => 0,
+          'size' => '20'
+          },
+      );
+__PACKAGE__->set_primary_key('Version');
+
+package DBIx::Class::Version;
+use base 'DBIx::Class::Schema';
+use strict;
+use warnings;
+
+__PACKAGE__->register_class('Table', 'DBIx::Class::Version::Table');
+
+
+# ---------------------------------------------------------------------------
+package DBIx::Class::Schema::Versioned;
+
+use strict;
+use warnings;
+use base 'DBIx::Class';
+use POSIX 'strftime';
+use Data::Dumper;
+
+__PACKAGE__->mk_classdata('_filedata');
+__PACKAGE__->mk_classdata('upgrade_directory');
+__PACKAGE__->mk_classdata('backup_directory');
+
+sub on_connect
+{
+    my ($self) = @_;
+    my $vschema = DBIx::Class::Version->connect(@{$self->storage->connect_info()});
+    my $vtable = $vschema->resultset('Table');
+    my $pversion;
+
+    if(!$self->exists($vtable))
+    {
+#        $vschema->storage->debug(1);
+        $vschema->storage->ensure_connected();
+        $vschema->deploy();
+        $pversion = 0;
+    }
+    else
+    {
+        my $psearch = $vtable->search(undef, 
+                                      { select => [
+                                                   { 'max' => 'Installed' },
+                                                   ],
+                                            as => ['maxinstall'],
+                                        })->first;
+        $pversion = $vtable->search({ Installed => $psearch->get_column('maxinstall'),
+                                  })->first;
+        $pversion = $pversion->Version if($pversion);
+    }
+#    warn("Previous version: $pversion\n");
+    if($pversion eq $self->VERSION)
+    {
+        warn "This version is already installed\n";
+        return 1;
+    }
+
+## use IC::DT?    
+
+    if(!$pversion)
+    {
+        $vtable->create({ Version => $self->VERSION,
+                          Installed => strftime("%Y-%m-%d %H:%M:%S", gmtime())
+                          });
+        ## If we let the user do this, where does the Version table get updated?
+        warn "No previous version found, calling deploy to install this version.\n";
+        $self->deploy();
+        return 1;
+    }
+
+    my $file = $self->ddl_filename(
+                                   $self->storage->sqlt_type,
+                                   $self->upgrade_directory,
+                                   $self->VERSION
+                                   );
+    if(!$file)
+    {
+        # No upgrade path between these two versions
+        return 1;
+    }
+
+     $file = $self->ddl_filename(
+                                 $self->storage->sqlt_type,
+                                 $self->upgrade_directory,
+                                 $self->VERSION,
+                                 $pversion,
+                                 );
+#    $file =~ s/@{[ $self->VERSION ]}/"${pversion}-" . $self->VERSION/e;
+    if(!-f $file)
+    {
+        warn "Upgrade not possible, no upgrade file found ($file)\n";
+        return;
+    }
+
+    my $fh;
+    open $fh, "<$file" or warn("Can't open upgrade file, $file ($!)");
+    my @data = split(/;\n/, join('', <$fh>));
+    close($fh);
+    @data = grep { $_ && $_ !~ /^-- / } @data;
+    @data = grep { $_ !~ /^(BEGIN TRANACTION|COMMIT)/m } @data;
+
+    $self->_filedata(\@data);
+
+    ## Don't do this yet, do only on command?
+    ## If we do this later, where does the Version table get updated??
+    warn "Versions out of sync. This is " . $self->VERSION . 
+        ", your database contains version $pversion, please call upgrade on your Schema.\n";
+#    $self->upgrade($pversion, $self->VERSION);
+}
+
+sub exists
+{
+    my ($self, $rs) = @_;
+
+    my $c = eval {
+        $rs->search({ 1, 0 })->count;
+    };
+    return 0 if $@ || !defined $c;
+
+    return 1;
+}
+
+sub backup
+{
+    my ($self) = @_;
+    ## Make each ::DBI::Foo do this
+    $self->storage->backup($self->backup_directory());
+}
+
+sub upgrade
+{
+    my ($self) = @_;
+
+    ## overridable sub, per default just run all the commands.
+
+    $self->backup();
+
+    $self->run_upgrade(qr/create/i);
+    $self->run_upgrade(qr/alter table .*? add/i);
+    $self->run_upgrade(qr/alter table .*? (?!drop)/i);
+    $self->run_upgrade(qr/alter table .*? drop/i);
+    $self->run_upgrade(qr/drop/i);
+#    $self->run_upgrade(qr//i);
+
+    my $vschema = DBIx::Class::Version->connect(@{$self->storage->connect_info()});
+    my $vtable = $vschema->resultset('Table');
+    $vtable->create({ Version => $self->VERSION,
+                      Installed => strftime("%Y-%m-%d %H:%M:%S", gmtime())
+                      });
+}
+
+
+sub run_upgrade
+{
+    my ($self, $stm) = @_;
+#    print "Reg: $stm\n";
+    my @statements = grep { $_ =~ $stm } @{$self->_filedata};
+#    print "Statements: ", join("\n", @statements), "\n";
+    $self->_filedata([ grep { $_ !~ /$stm/i } @{$self->_filedata} ]);
+
+    for (@statements)
+    {
+        $self->storage->debugfh->print("$_\n") if $self->storage->debug;
+#        print "Running \n>>$_<<\n";
+        $self->storage->dbh->do($_) or warn "SQL was:\n $_";
+    }
+
+    return 1;
+}
+
+1;
+
+=head1 NAME
+
+DBIx::Class::Versioning - DBIx::Class::Schema plugin for Schema upgrades
+
+=head1 SYNOPSIS
+
+  package Library::Schema;
+  use base qw/DBIx::Class::Schema/;   
+  # load Library::Schema::CD, Library::Schema::Book, Library::Schema::DVD
+  __PACKAGE__->load_classes(qw/CD Book DVD/);
+
+  __PACKAGE__->load_components(qw/+DBIx::Class::Schema::Versioned/);
+  __PACKAGE__->upgrade_directory('/path/to/upgrades/');
+  __PACKAGE__->backup_directory('/path/to/backups/');
+
+  sub backup
+  {
+    my ($self) = @_;
+    # my special backup process
+  }
+
+  sub upgrade
+  {
+    my ($self) = @_;
+
+    ## overridable sub, per default just runs all the commands.
+
+    $self->run_upgrade(qr/create/i);
+    $self->run_upgrade(qr/alter table .*? add/i);
+    $self->run_upgrade(qr/alter table .*? (?!drop)/i);
+    $self->run_upgrade(qr/alter table .*? drop/i);
+    $self->run_upgrade(qr/drop/i);
+    $self->run_upgrade(qr//i);   
+  }
+
+=head1 DESCRIPTION
+
+This module is a component designed to extend L<DBIx::Class::Schema>
+classes, to enable them to upgrade to newer schema layouts. To use this
+module, you need to have called C<create_ddl_dir> on your Schema to
+create your upgrade files to include with your delivery.
+
+A table called I<SchemaVersions> is created and maintained by the
+module. This contains two fields, 'Version' and 'Installed', which
+contain each VERSION of your Schema, and the date+time it was installed.
+
+If you would like to influence which levels of version change need
+upgrades in your Schema, you can override the method C<ddl_filename>
+in L<DBIx::Class::Schema>. Return a false value if there is no upgrade
+path between the two versions supplied. By default, every change in
+your VERSION is regarded as needing an upgrade.
+
+The actual upgrade is called manually by calling C<upgrade> on your
+schema object. Code is run at connect time to determine whether an
+upgrade is needed, if so, a warning "Versions out of sync" is
+produced.
+
+NB: At the moment, SQLite upgrading is rather spotty, as SQL::Translator::Diff
+returns SQL statements that SQLite does not support.
+
+
+=head1 METHODS
+
+=head2 backup
+
+This is an overwritable method which is called just before the upgrade, to
+allow you to make a backup of the database. Per default this method attempts
+to call C<< $self->storage->backup >>, to run the standard backup on each
+database type. 
+
+This method should return the name of the backup file, if appropriate.
+
+C<backup> is called from C<upgrade>, make sure you call it, if you write your
+own <upgrade> method.
+
+=head2 upgrade
+
+This is an overwritable method used to run your upgrade. The freeform method
+allows you to run your upgrade any way you please, you can call C<run_upgrade>
+any number of times to run the actual SQL commands, and in between you can
+sandwich your data upgrading. For example, first run all the B<CREATE>
+commands, then migrate your data from old to new tables/formats, then 
+issue the DROP commands when you are finished.
+
+=head2 run_upgrade
+
+ $self->run_upgrade(qr/create/i);
+
+Runs a set of SQL statements matching a passed in regular expression. The
+idea is that this method can be called any number of times from your
+C<upgrade> method, running whichever commands you specify via the
+regex in the parameter.
+
+=head2 upgrade_directory
+
+Use this to set the directory your upgrade files are stored in.
+
+=head2 backup_directory
+
+Use this to set the directory you want your backups stored in.
+
+=head1 AUTHOR
+
+Jess Robinson <castaway@desert-island.demon.co.uk>
diff --git a/lib/DBIx/Class/Serialize/Storable.pm b/lib/DBIx/Class/Serialize/Storable.pm
deleted file mode 100644 (file)
index 7ccd2b0..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-package DBIx::Class::Serialize::Storable;
-use strict;
-use warnings;
-use Storable;
-
-sub STORABLE_freeze {
-    my ($self,$cloning) = @_;
-    my $to_serialize = { %$self };
-    delete $to_serialize->{result_source};
-    return (Storable::freeze($to_serialize));
-}
-
-sub STORABLE_thaw {
-    my ($self,$cloning,$serialized) = @_;
-    %$self = %{ Storable::thaw($serialized) };
-    $self->result_source($self->result_source_instance)
-      if $self->can('result_source_instance');
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-    DBIx::Class::Serialize::Storable - hooks for Storable freeze/thaw
-
-=head1 SYNOPSIS
-
-    # in a table class definition
-    __PACKAGE__->load_components(qw/Serialize::Storable/);
-
-    # meanwhile, in a nearby piece of code
-    my $cd = $schema->resultset('CD')->find(12);
-    # if the cache uses Storable, this will work automatically
-    $cache->set($cd->ID, $cd);
-
-=head1 DESCRIPTION
-
-This component adds hooks for Storable so that row objects can be
-serialized. It assumes that your row object class (C<result_class>) is
-the same as your table class, which is the normal situation.
-
-=head1 HOOKS
-
-The following hooks are defined for L<Storable> - see the
-documentation for L<Storable/Hooks> for detailed information on these
-hooks.
-
-=head2 STORABLE_freeze
-
-The serializing hook, called on the object during serialization. It
-can be inherited, or defined in the class itself, like any other
-method.
-
-=head2 STORABLE_thaw
-
-The deserializing hook called on the object during deserialization.
-
-=head1 AUTHORS
-
-David Kamholz <dkamholz@cpan.org>
-
-=head1 LICENSE
-
-You may distribute this code under the same terms as Perl itself.
-
-=cut
index 735006c..9a58b94 100644 (file)
-package # hide from PAUSE
-    DBIx::Class::Storage;
+package DBIx::Class::Storage;
 
 use strict;
 use warnings;
 
-sub new { die "Virtual method!" }
-sub debug { die "Virtual method!" }
-sub debugcb { die "Virtual method!" }
-sub debugfh { die "Virtual method!" }
-sub debugobj { die "Virtual method!" }
-sub cursor { die "Virtual method!" }
-sub disconnect { die "Virtual method!" }
+use base qw/DBIx::Class/;
+
+use Scalar::Util qw/weaken/;
+use Carp::Clan qw/^DBIx::Class/;
+
+__PACKAGE__->mk_group_accessors('simple' => qw/debug debugobj schema/);
+
+package # Hide from PAUSE
+    DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION;
+
+use overload '"' => sub {
+  'DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION'
+};
+
+sub new {
+  my $class = shift;
+  my $self = {};
+  return bless $self, $class;
+}
+
+package DBIx::Class::Storage;
+
+=head1 NAME
+
+DBIx::Class::Storage - Generic Storage Handler
+
+=head1 DESCRIPTION
+
+A base implementation of common Storage methods.  For specific
+information about L<DBI>-based storage, see L<DBIx::Class::Storage::DBI>.
+
+=head1 METHODS
+
+=head2 new
+
+Arguments: $schema
+
+Instantiates the Storage object.
+
+=cut
+
+sub new {
+  my ($self, $schema) = @_;
+
+  $self = ref $self if ref $self;
+
+  my $new = {};
+  bless $new, $self;
+
+  $new->set_schema($schema);
+  $new->debugobj(new DBIx::Class::Storage::Statistics());
+
+  my $fh;
+
+  my $debug_env = $ENV{DBIX_CLASS_STORAGE_DBI_DEBUG}
+                  || $ENV{DBIC_TRACE};
+
+  if (defined($debug_env) && ($debug_env =~ /=(.+)$/)) {
+    $fh = IO::File->new($1, 'w')
+      or $new->throw_exception("Cannot open trace file $1");
+  } else {
+    $fh = IO::File->new('>&STDERR');
+  }
+
+  $new->debugfh($fh);
+  $new->debug(1) if $debug_env;
+
+  $new;
+}
+
+=head2 set_schema
+
+Used to reset the schema class or object which owns this
+storage object, such as during L<DBIx::Class::Schema/clone>.
+
+=cut
+
+sub set_schema {
+  my ($self, $schema) = @_;
+  $self->schema($schema);
+  weaken($self->{schema}) if ref $self->{schema};
+}
+
+=head2 connected
+
+Returns true if we have an open storage connection, false
+if it is not (yet) open.
+
+=cut
+
 sub connected { die "Virtual method!" }
+
+=head2 disconnect
+
+Closes any open storage connection unconditionally.
+
+=cut
+
+sub disconnect { die "Virtual method!" }
+
+=head2 ensure_connected
+
+Initiate a connection to the storage if one isn't already open.
+
+=cut
+
 sub ensure_connected { die "Virtual method!" }
-sub on_connect_do { die "Virtual method!" }
-sub connect_info { die "Virtual method!" }
-sub sql_maker { die "Virtual method!" }
+
+=head2 throw_exception
+
+Throws an exception - croaks.
+
+=cut
+
+sub throw_exception {
+  my $self = shift;
+
+  $self->schema->throw_exception(@_) if $self->schema;
+  croak @_;
+}
+
+=head2 txn_do
+
+=over 4
+
+=item Arguments: C<$coderef>, @coderef_args?
+
+=item Return Value: The return value of $coderef
+
+=back
+
+Executes C<$coderef> with (optional) arguments C<@coderef_args> atomically,
+returning its result (if any). If an exception is caught, a rollback is issued
+and the exception is rethrown. If the rollback fails, (i.e. throws an
+exception) an exception is thrown that includes a "Rollback failed" message.
+
+For example,
+
+  my $author_rs = $schema->resultset('Author')->find(1);
+  my @titles = qw/Night Day It/;
+
+  my $coderef = sub {
+    # If any one of these fails, the entire transaction fails
+    $author_rs->create_related('books', {
+      title => $_
+    }) foreach (@titles);
+
+    return $author->books;
+  };
+
+  my $rs;
+  eval {
+    $rs = $schema->txn_do($coderef);
+  };
+
+  if ($@) {                                  # Transaction failed
+    die "something terrible has happened!"   #
+      if ($@ =~ /Rollback failed/);          # Rollback failed
+
+    deal_with_failed_transaction();
+  }
+
+In a nested transaction (calling txn_do() from within a txn_do() coderef) only
+the outermost transaction will issue a L</txn_commit>, and txn_do() can be
+called in void, scalar and list context and it will behave as expected.
+
+=cut
+
+sub txn_do {
+  my ($self, $coderef, @args) = @_;
+
+  ref $coderef eq 'CODE' or $self->throw_exception
+    ('$coderef must be a CODE reference');
+
+  my (@return_values, $return_value);
+
+  $self->txn_begin; # If this throws an exception, no rollback is needed
+
+  my $wantarray = wantarray; # Need to save this since the context
+                             # inside the eval{} block is independent
+                             # of the context that called txn_do()
+  eval {
+
+    # Need to differentiate between scalar/list context to allow for
+    # returning a list in scalar context to get the size of the list
+    if ($wantarray) {
+      # list context
+      @return_values = $coderef->(@args);
+    } elsif (defined $wantarray) {
+      # scalar context
+      $return_value = $coderef->(@args);
+    } else {
+      # void context
+      $coderef->(@args);
+    }
+    $self->txn_commit;
+  };
+
+  if ($@) {
+    my $error = $@;
+
+    eval {
+      $self->txn_rollback;
+    };
+
+    if ($@) {
+      my $rollback_error = $@;
+      my $exception_class = "DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION";
+      $self->throw_exception($error)  # propagate nested rollback
+        if $rollback_error =~ /$exception_class/;
+
+      $self->throw_exception(
+        "Transaction aborted: $error. Rollback failed: ${rollback_error}"
+      );
+    } else {
+      $self->throw_exception($error); # txn failed but rollback succeeded
+    }
+  }
+
+  return $wantarray ? @return_values : $return_value;
+}
+
+=head2 txn_begin
+
+Starts a transaction.
+
+See the preferred L</txn_do> method, which allows for
+an entire code block to be executed transactionally.
+
+=cut
+
 sub txn_begin { die "Virtual method!" }
+
+=head2 txn_commit
+
+Issues a commit of the current transaction.
+
+=cut
+
 sub txn_commit { die "Virtual method!" }
+
+=head2 txn_rollback
+
+Issues a rollback of the current transaction. A nested rollback will
+throw a L<DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION> exception,
+which allows the rollback to propagate to the outermost transaction.
+
+=cut
+
 sub txn_rollback { die "Virtual method!" }
+
+=head2 sql_maker
+
+Returns a C<sql_maker> object - normally an object of class
+C<DBIC::SQL::Abstract>.
+
+=cut
+
+sub sql_maker { die "Virtual method!" }
+
+=head2 debug
+
+Causes trace information to be emitted on the C<debugobj> object.
+(or C<STDERR> if C<debugobj> has not specifically been set).
+
+This is the equivalent to setting L</DBIC_TRACE> in your
+shell environment.
+
+=head2 debugfh
+
+Set or retrieve the filehandle used for trace/debug output.  This should be
+an IO::Handle compatible ojbect (only the C<print> method is used.  Initially
+set to be STDERR - although see information on the
+L<DBIC_TRACE> environment variable.
+
+=cut
+
+sub debugfh {
+    my $self = shift;
+
+    if ($self->debugobj->can('debugfh')) {
+        return $self->debugobj->debugfh(@_);
+    }
+}
+
+=head2 debugobj
+
+Sets or retrieves the object used for metric collection. Defaults to an instance
+of L<DBIx::Class::Storage::Statistics> that is compatible with the original
+method of using a coderef as a callback.  See the aforementioned Statistics
+class for more information.
+
+=head2 debugcb
+
+Sets a callback to be executed each time a statement is run; takes a sub
+reference.  Callback is executed as $sub->($op, $info) where $op is
+SELECT/INSERT/UPDATE/DELETE and $info is what would normally be printed.
+
+See L<debugobj> for a better way.
+
+=cut
+
+sub debugcb {
+    my $self = shift;
+
+    if ($self->debugobj->can('callback')) {
+        return $self->debugobj->callback(@_);
+    }
+}
+
+=head2 cursor
+
+The cursor class for this Storage object.
+
+=cut
+
+sub cursor { die "Virtual method!" }
+
+=head2 deploy
+
+Deploy the tables to storage (CREATE TABLE and friends in a SQL-based
+Storage class). This would normally be called through
+L<DBIx::Class::Schema/deploy>.
+
+=cut
+
+sub deploy { die "Virtual method!" }
+
+=head2 connect_info
+
+The arguments of C<connect_info> are always a single array reference,
+and are Storage-handler specific.
+
+This is normally accessed via L<DBIx::Class::Schema/connection>, which
+encapsulates its argument list in an arrayref before calling
+C<connect_info> here.
+
+=cut
+
+sub connect_info { die "Virtual method!" }
+
+=head2 select
+
+Handle a select statement.
+
+=cut
+
+sub select { die "Virtual method!" }
+
+=head2 insert
+
+Handle an insert statement.
+
+=cut
+
 sub insert { die "Virtual method!" }
+
+=head2 update
+
+Handle an update statement.
+
+=cut
+
 sub update { die "Virtual method!" }
+
+=head2 delete
+
+Handle a delete statement.
+
+=cut
+
 sub delete { die "Virtual method!" }
-sub select { die "Virtual method!" }
+
+=head2 select_single
+
+Performs a select, fetch and return of data - handles a single row
+only.
+
+=cut
+
 sub select_single { die "Virtual method!" }
+
+=head2 columns_info_for
+
+Returns metadata for the given source's columns.  This
+is *deprecated*, and will be removed before 1.0.  You should
+be specifying the metadata yourself if you need it.
+
+=cut
+
 sub columns_info_for { die "Virtual method!" }
 
+=head1 ENVIRONMENT VARIABLES
 
-package DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION;
+=head2 DBIC_TRACE
 
-use overload '"' => sub {
-  'DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION'
-};
+If C<DBIC_TRACE> is set then trace information
+is produced (as when the L<debug> method is set).
 
-sub new {
-  my $class = shift;
-  my $self = {};
-  return bless $self, $class;
-}
+If the value is of the form C<1=/path/name> then the trace output is
+written to the file C</path/name>.
+
+This environment variable is checked when the storage object is first
+created (when you call connect on your schema).  So, run-time changes 
+to this environment variable will not take effect unless you also 
+re-connect on your schema.
+
+=head2 DBIX_CLASS_STORAGE_DBI_DEBUG
+
+Old name for DBIC_TRACE
+
+=head1 AUTHORS
+
+Matt S. Trout <mst@shadowcatsystems.co.uk>
+
+Andy Grundman <andy@hybridized.org>
+
+=head1 LICENSE
+
+You may distribute this code under the same terms as Perl itself.
+
+=cut
 
 1;
index b5caa90..61fef77 100644 (file)
@@ -3,14 +3,21 @@ package DBIx::Class::Storage::DBI;
 
 use base 'DBIx::Class::Storage';
 
-use strict;
+use strict;    
 use warnings;
 use DBI;
 use SQL::Abstract::Limit;
 use DBIx::Class::Storage::DBI::Cursor;
 use DBIx::Class::Storage::Statistics;
 use IO::File;
-use Carp::Clan qw/DBIx::Class/;
+use Scalar::Util 'blessed';
+
+__PACKAGE__->mk_group_accessors(
+  'simple' =>
+    qw/_connect_info _dbh _sql_maker _sql_maker_opts _conn_pid _conn_tid
+       disable_sth_caching cursor on_connect_do transaction_depth/
+);
+
 BEGIN {
 
 package DBIC::SQL::Abstract; # Would merge upstream, but nate doesn't reply :(
@@ -56,7 +63,6 @@ use Scalar::Util 'blessed';
 sub _find_syntax {
   my ($self, $syntax) = @_;
   my $dbhname = blessed($syntax) ?  $syntax->{Driver}{Name} : $syntax;
-#  print STDERR "Found DBH $syntax >$dbhname< ", $syntax->{Driver}->{Name}, "\n";
   if(ref($self) && $dbhname && $dbhname eq 'DB2') {
     return 'RowNumberOver';
   }
@@ -287,14 +293,6 @@ sub name_sep {
 
 } # End of BEGIN block
 
-use base qw/DBIx::Class/;
-
-__PACKAGE__->load_components(qw/AccessorGroup/);
-
-__PACKAGE__->mk_group_accessors('simple' =>
-  qw/_connect_info _dbh _sql_maker _sql_maker_opts _conn_pid _conn_tid
-     debug debugobj cursor on_connect_do transaction_depth/);
-
 =head1 NAME
 
 DBIx::Class::Storage::DBI - DBI storage handler
@@ -303,49 +301,24 @@ DBIx::Class::Storage::DBI - DBI storage handler
 
 =head1 DESCRIPTION
 
-This class represents the connection to the database
+This class represents the connection to an RDBMS via L<DBI>.  See
+L<DBIx::Class::Storage> for general information.  This pod only
+documents DBI-specific methods and behaviors.
 
 =head1 METHODS
 
-=head2 new
-
 =cut
 
 sub new {
-  my $new = {};
-  bless $new, (ref $_[0] || $_[0]);
+  my $new = shift->next::method(@_);
 
   $new->cursor("DBIx::Class::Storage::DBI::Cursor");
   $new->transaction_depth(0);
-
-  $new->debugobj(new DBIx::Class::Storage::Statistics());
-
-  my $fh;
-
-  my $debug_env = $ENV{DBIX_CLASS_STORAGE_DBI_DEBUG}
-                  || $ENV{DBIC_TRACE};
-
-  if (defined($debug_env) && ($debug_env =~ /=(.+)$/)) {
-    $fh = IO::File->new($1, 'w')
-      or $new->throw_exception("Cannot open trace file $1");
-  } else {
-    $fh = IO::File->new('>&STDERR');
-  }
-  $new->debugfh($fh);
-  $new->debug(1) if $debug_env;
   $new->_sql_maker_opts({});
-  return $new;
-}
-
-=head2 throw_exception
+  $new->{_in_dbh_do} = 0;
+  $new->{_dbh_gen} = 0;
 
-Throws an exception - croaks.
-
-=cut
-
-sub throw_exception {
-  my ($self, $msg) = @_;
-  croak($msg);
+  $new;
 }
 
 =head2 connect_info
@@ -372,6 +345,11 @@ This can be set to an arrayref of literal sql statements, which will
 be executed immediately after making the connection to the database
 every time we [re-]connect.
 
+=item disable_sth_caching
+
+If set to a true value, this option will disable the caching of
+statement handles via L<DBI/prepare_cached>.
+
 =item limit_dialect 
 
 Sets the limit dialect. This is useful for JDBC-bridge among others
@@ -406,6 +384,12 @@ Every time C<connect_info> is invoked, any previous settings for
 these options will be cleared before setting the new ones, regardless of
 whether any options are specified in the new C<connect_info>.
 
+Important note:  DBIC expects the returned database handle provided by 
+a subref argument to have RaiseError set on it.  If it doesn't, things
+might not work very well, YMMV.  If you don't use a subref, DBIC will
+force this setting for you anyways.  Setting HandleError to anything
+other than simple exception object wrapper might cause problems too.
+
 Examples:
 
   # Simple SQLite connection
@@ -443,67 +427,178 @@ Examples:
           quote_char => q{`},
           name_sep => q{@},
           on_connect_do => ['SET search_path TO myschema,otherschema,public'],
+          disable_sth_caching => 1,
       },
     ]
   );
 
+=cut
+
+sub connect_info {
+  my ($self, $info_arg) = @_;
+
+  return $self->_connect_info if !$info_arg;
+
+  # Kill sql_maker/_sql_maker_opts, so we get a fresh one with only
+  #  the new set of options
+  $self->_sql_maker(undef);
+  $self->_sql_maker_opts({});
+
+  my $info = [ @$info_arg ]; # copy because we can alter it
+  my $last_info = $info->[-1];
+  if(ref $last_info eq 'HASH') {
+    for my $storage_opt (qw/on_connect_do disable_sth_caching/) {
+      if(my $value = delete $last_info->{$storage_opt}) {
+        $self->$storage_opt($value);
+      }
+    }
+    for my $sql_maker_opt (qw/limit_dialect quote_char name_sep/) {
+      if(my $opt_val = delete $last_info->{$sql_maker_opt}) {
+        $self->_sql_maker_opts->{$sql_maker_opt} = $opt_val;
+      }
+    }
+
+    # Get rid of any trailing empty hashref
+    pop(@$info) if !keys %$last_info;
+  }
+
+  $self->_connect_info($info);
+}
+
 =head2 on_connect_do
 
 This method is deprecated in favor of setting via L</connect_info>.
 
-=head2 debug
+=head2 dbh_do
 
-Causes SQL trace information to be emitted on the C<debugobj> object.
-(or C<STDERR> if C<debugobj> has not specifically been set).
+Arguments: $subref, @extra_coderef_args?
 
-This is the equivalent to setting L</DBIC_TRACE> in your
-shell environment.
+Execute the given subref using the new exception-based connection management.
 
-=head2 debugfh
+The first two arguments will be the storage object that C<dbh_do> was called
+on and a database handle to use.  Any additional arguments will be passed
+verbatim to the called subref as arguments 2 and onwards.
 
-Set or retrieve the filehandle used for trace/debug output.  This should be
-an IO::Handle compatible ojbect (only the C<print> method is used.  Initially
-set to be STDERR - although see information on the
-L<DBIC_TRACE> environment variable.
+Using this (instead of $self->_dbh or $self->dbh) ensures correct
+exception handling and reconnection (or failover in future subclasses).
+
+Your subref should have no side-effects outside of the database, as
+there is the potential for your subref to be partially double-executed
+if the database connection was stale/dysfunctional.
+
+Example:
+
+  my @stuff = $schema->storage->dbh_do(
+    sub {
+      my ($storage, $dbh, @cols) = @_;
+      my $cols = join(q{, }, @cols);
+      $dbh->selectrow_array("SELECT $cols FROM foo");
+    },
+    @column_list
+  );
 
 =cut
 
-sub debugfh {
-    my $self = shift;
+sub dbh_do {
+  my $self = shift;
+  my $coderef = shift;
+
+  ref $coderef eq 'CODE' or $self->throw_exception
+    ('$coderef must be a CODE reference');
+
+  return $coderef->($self, $self->_dbh, @_) if $self->{_in_dbh_do};
+  local $self->{_in_dbh_do} = 1;
+
+  my @result;
+  my $want_array = wantarray;
 
-    if ($self->debugobj->can('debugfh')) {
-        return $self->debugobj->debugfh(@_);
+  eval {
+    $self->_verify_pid if $self->_dbh;
+    $self->_populate_dbh if !$self->_dbh;
+    if($want_array) {
+        @result = $coderef->($self, $self->_dbh, @_);
     }
-}
+    elsif(defined $want_array) {
+        $result[0] = $coderef->($self, $self->_dbh, @_);
+    }
+    else {
+        $coderef->($self, $self->_dbh, @_);
+    }
+  };
 
-=head2 debugobj
+  my $exception = $@;
+  if(!$exception) { return $want_array ? @result : $result[0] }
 
-Sets or retrieves the object used for metric collection. Defaults to an instance
-of L<DBIx::Class::Storage::Statistics> that is campatible with the original
-method of using a coderef as a callback.  See the aforementioned Statistics
-class for more information.
+  $self->throw_exception($exception) if $self->connected;
 
-=head2 debugcb
+  # We were not connected - reconnect and retry, but let any
+  #  exception fall right through this time
+  $self->_populate_dbh;
+  $coderef->($self, $self->_dbh, @_);
+}
 
-Sets a callback to be executed each time a statement is run; takes a sub
-reference.  Callback is executed as $sub->($op, $info) where $op is
-SELECT/INSERT/UPDATE/DELETE and $info is what would normally be printed.
+# This is basically a blend of dbh_do above and DBIx::Class::Storage::txn_do.
+# It also informs dbh_do to bypass itself while under the direction of txn_do,
+#  via $self->{_in_dbh_do} (this saves some redundant eval and errorcheck, etc)
+sub txn_do {
+  my $self = shift;
+  my $coderef = shift;
 
-See L<debugobj> for a better way.
+  ref $coderef eq 'CODE' or $self->throw_exception
+    ('$coderef must be a CODE reference');
 
-=cut
+  local $self->{_in_dbh_do} = 1;
 
-sub debugcb {
-    my $self = shift;
+  my @result;
+  my $want_array = wantarray;
+
+  my $tried = 0;
+  while(1) {
+    eval {
+      $self->_verify_pid if $self->_dbh;
+      $self->_populate_dbh if !$self->_dbh;
+
+      $self->txn_begin;
+      if($want_array) {
+          @result = $coderef->(@_);
+      }
+      elsif(defined $want_array) {
+          $result[0] = $coderef->(@_);
+      }
+      else {
+          $coderef->(@_);
+      }
+      $self->txn_commit;
+    };
 
-    if ($self->debugobj->can('callback')) {
-        return $self->debugobj->callback(@_);
+    my $exception = $@;
+    if(!$exception) { return $want_array ? @result : $result[0] }
+
+    if($tried++ > 0 || $self->connected) {
+      eval { $self->txn_rollback };
+      my $rollback_exception = $@;
+      if($rollback_exception) {
+        my $exception_class = "DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION";
+        $self->throw_exception($exception)  # propagate nested rollback
+          if $rollback_exception =~ /$exception_class/;
+
+        $self->throw_exception(
+          "Transaction aborted: ${exception}. "
+          . "Rollback failed: ${rollback_exception}"
+        );
+      }
+      $self->throw_exception($exception)
     }
+
+    # We were not connected, and was first try - reconnect and retry
+    # via the while loop
+    $self->_populate_dbh;
+  }
 }
 
 =head2 disconnect
 
-Disconnect the L<DBI> handle, performing a rollback first if the
+Our C<disconnect> method also performs a rollback first if the
 database is not in C<AutoCommit> mode.
 
 =cut
@@ -515,25 +610,21 @@ sub disconnect {
     $self->_dbh->rollback unless $self->_dbh->{AutoCommit};
     $self->_dbh->disconnect;
     $self->_dbh(undef);
+    $self->{_dbh_gen}++;
   }
 }
 
-=head2 connected
-
-Check if the L<DBI> handle is connected.  Returns true if the handle
-is connected.
-
-=cut
-
-sub connected { my ($self) = @_;
+sub connected {
+  my ($self) = @_;
 
   if(my $dbh = $self->_dbh) {
       if(defined $self->_conn_tid && $self->_conn_tid != threads->tid) {
-          return $self->_dbh(undef);
+          $self->_dbh(undef);
+          $self->{_dbh_gen}++;
+          return;
       }
-      elsif($self->_conn_pid != $$) {
-          $self->_dbh->{InactiveDestroy} = 1;
-          return $self->_dbh(undef);
+      else {
+          $self->_verify_pid;
       }
       return ($dbh->FETCH('Active') && $dbh->ping);
   }
@@ -541,12 +632,19 @@ sub connected { my ($self) = @_;
   return 0;
 }
 
-=head2 ensure_connected
+# handle pid changes correctly
+#  NOTE: assumes $self->_dbh is a valid $dbh
+sub _verify_pid {
+  my ($self) = @_;
 
-Check whether the database handle is connected - if not then make a
-connection.
+  return if $self->_conn_pid == $$;
 
-=cut
+  $self->_dbh->{InactiveDestroy} = 1;
+  $self->_dbh(undef);
+  $self->{_dbh_gen}++;
+
+  return;
+}
 
 sub ensure_connected {
   my ($self) = @_;
@@ -572,16 +670,9 @@ sub dbh {
 sub _sql_maker_args {
     my ($self) = @_;
     
-    return ( limit_dialect => $self->dbh, %{$self->_sql_maker_opts} );
+    return ( bindtype=>'columns', limit_dialect => $self->dbh, %{$self->_sql_maker_opts} );
 }
 
-=head2 sql_maker
-
-Returns a C<sql_maker> object - normally an object of class
-C<DBIC::SQL::Abstract>.
-
-=cut
-
 sub sql_maker {
   my ($self) = @_;
   unless ($self->_sql_maker) {
@@ -590,37 +681,6 @@ sub sql_maker {
   return $self->_sql_maker;
 }
 
-sub connect_info {
-  my ($self, $info_arg) = @_;
-
-  if($info_arg) {
-    # Kill sql_maker/_sql_maker_opts, so we get a fresh one with only
-    #  the new set of options
-    $self->_sql_maker(undef);
-    $self->_sql_maker_opts({});
-
-    my $info = [ @$info_arg ]; # copy because we can alter it
-    my $last_info = $info->[-1];
-    if(ref $last_info eq 'HASH') {
-      if(my $on_connect_do = delete $last_info->{on_connect_do}) {
-        $self->on_connect_do($on_connect_do);
-      }
-      for my $sql_maker_opt (qw/limit_dialect quote_char name_sep/) {
-        if(my $opt_val = delete $last_info->{$sql_maker_opt}) {
-          $self->_sql_maker_opts->{$sql_maker_opt} = $opt_val;
-        }
-      }
-
-      # Get rid of any trailing empty hashref
-      pop(@$info) if !keys %$last_info;
-    }
-
-    $self->_connect_info($info);
-  }
-
-  $self->_connect_info;
-}
-
 sub _populate_dbh {
   my ($self) = @_;
   my @info = @{$self->_connect_info || []};
@@ -659,9 +719,15 @@ sub _connect {
   }
 
   eval {
-    $dbh = ref $info[0] eq 'CODE'
-         ? &{$info[0]}
-         : DBI->connect(@info);
+    if(ref $info[0] eq 'CODE') {
+       $dbh = &{$info[0]}
+    }
+    else {
+       $dbh = DBI->connect(@info);
+       $dbh->{RaiseError} = 1;
+       $dbh->{PrintError} = 0;
+       $dbh->{PrintWarn} = 0;
+    }
   };
 
   $DBI::connect_via = $old_connect_via if $old_connect_via;
@@ -673,36 +739,23 @@ sub _connect {
   $dbh;
 }
 
-=head2 txn_begin
-
-Calls begin_work on the current dbh.
-
-See L<DBIx::Class::Schema> for the txn_do() method, which allows for
-an entire code block to be executed transactionally.
-
-=cut
+sub _dbh_txn_begin {
+  my ($self, $dbh) = @_;
+  if ($dbh->{AutoCommit}) {
+    $self->debugobj->txn_begin()
+      if ($self->debug);
+    $dbh->begin_work;
+  }
+}
 
 sub txn_begin {
   my $self = shift;
-  if ($self->{transaction_depth}++ == 0) {
-    my $dbh = $self->dbh;
-    if ($dbh->{AutoCommit}) {
-      $self->debugobj->txn_begin()
-        if ($self->debug);
-      $dbh->begin_work;
-    }
-  }
+  $self->dbh_do($self->can('_dbh_txn_begin'))
+    if $self->{transaction_depth}++ == 0;
 }
 
-=head2 txn_commit
-
-Issues a commit against the current dbh.
-
-=cut
-
-sub txn_commit {
-  my $self = shift;
-  my $dbh = $self->dbh;
+sub _dbh_txn_commit {
+  my ($self, $dbh) = @_;
   if ($self->{transaction_depth} == 0) {
     unless ($dbh->{AutoCommit}) {
       $self->debugobj->txn_commit()
@@ -719,38 +772,36 @@ sub txn_commit {
   }
 }
 
-=head2 txn_rollback
-
-Issues a rollback against the current dbh. A nested rollback will
-throw a L<DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION> exception,
-which allows the rollback to propagate to the outermost transaction.
-
-=cut
-
-sub txn_rollback {
+sub txn_commit {
   my $self = shift;
+  $self->dbh_do($self->can('_dbh_txn_commit'));
+}
 
-  eval {
-    my $dbh = $self->dbh;
-    if ($self->{transaction_depth} == 0) {
-      unless ($dbh->{AutoCommit}) {
-        $self->debugobj->txn_rollback()
-          if ($self->debug);
-        $dbh->rollback;
-      }
+sub _dbh_txn_rollback {
+  my ($self, $dbh) = @_;
+  if ($self->{transaction_depth} == 0) {
+    unless ($dbh->{AutoCommit}) {
+      $self->debugobj->txn_rollback()
+        if ($self->debug);
+      $dbh->rollback;
+    }
+  }
+  else {
+    if (--$self->{transaction_depth} == 0) {
+      $self->debugobj->txn_rollback()
+        if ($self->debug);
+      $dbh->rollback;
     }
     else {
-      if (--$self->{transaction_depth} == 0) {
-        $self->debugobj->txn_rollback()
-          if ($self->debug);
-        $dbh->rollback;
-      }
-      else {
-        die DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION->new;
-      }
+      die DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION->new;
     }
-  };
+  }
+}
 
+sub txn_rollback {
+  my $self = shift;
+
+  eval { $self->dbh_do($self->can('_dbh_txn_rollback')) };
   if ($@) {
     my $error = $@;
     my $exception_class = "DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION";
@@ -760,12 +811,35 @@ sub txn_rollback {
   }
 }
 
-sub _execute {
+# This used to be the top-half of _execute.  It was split out to make it
+#  easier to override in NoBindVars without duping the rest.  It takes up
+#  all of _execute's args, and emits $sql, @bind.
+sub _prep_for_execute {
   my ($self, $op, $extra_bind, $ident, @args) = @_;
+
   my ($sql, @bind) = $self->sql_maker->$op($ident, @args);
-  unshift(@bind, @$extra_bind) if $extra_bind;
+  unshift(@bind,
+    map { ref $_ eq 'ARRAY' ? $_ : [ '!!dummy', $_ ] } @$extra_bind)
+      if $extra_bind;
+  @bind = map { ref $_ ? ''.$_ : $_ } @bind; # stringify args
+
+  return ($sql, @bind);
+}
+
+sub _execute {
+  my ($self, $op, $extra_bind, $ident, $bind_attributes, @args) = @_;
+  
+  if( blessed($ident) && $ident->isa("DBIx::Class::ResultSource") ) {
+    $ident = $ident->from();
+  }
+  
+  my ($sql, @bind) = $self->sql_maker->$op($ident, @args);
+  unshift(@bind,
+    map { ref $_ eq 'ARRAY' ? $_ : [ '!!dummy', $_ ] } @$extra_bind)
+      if $extra_bind;
   if ($self->debug) {
-      my @debug_bind = map { defined $_ ? qq{'$_'} : q{'NULL'} } @bind;
+      my @debug_bind =
+        map { defined ($_ && $_->[1]) ? qq{'$_->[1]'} : q{'NULL'} } @bind;
       $self->debugobj->query_start($sql, @debug_bind);
   }
   my $sth = eval { $self->sth($sql,$op) };
@@ -775,12 +849,34 @@ sub _execute {
       'no sth generated via sql (' . ($@ || $self->_dbh->errstr) . "): $sql"
     );
   }
-  @bind = map { ref $_ ? ''.$_ : $_ } @bind; # stringify args
+
   my $rv;
   if ($sth) {
     my $time = time();
-    $rv = eval { $sth->execute(@bind) };
+    $rv = eval {
+      my $placeholder_index = 1; 
+
+      foreach my $bound (@bind) {
 
+        my $attributes = {};
+        my($column_name, @data) = @$bound;
+
+        if( $bind_attributes ) {
+          $attributes = $bind_attributes->{$column_name}
+          if defined $bind_attributes->{$column_name};
+        }
+
+        foreach my $data (@data)
+        {
+          $data = ref $data ? ''.$data : $data; # stringify args
+
+          $sth->bind_param($placeholder_index, $data, $attributes);
+          $placeholder_index++;
+        }
+      }
+      $sth->execute();
+    };
+  
     if ($@ || !$rv) {
       $self->throw_exception("Error executing '$sql': ".($@ || $sth->errstr));
     }
@@ -788,28 +884,119 @@ sub _execute {
     $self->throw_exception("'$sql' did not generate a statement.");
   }
   if ($self->debug) {
-      my @debug_bind = map { defined $_ ? qq{`$_'} : q{`NULL'} } @bind; 
-      $self->debugobj->query_end($sql, @debug_bind);
+     my @debug_bind =
+       map { defined ($_ && $_->[1]) ? qq{'$_->[1]'} : q{'NULL'} } @bind; 
+     $self->debugobj->query_end($sql, @debug_bind);
   }
   return (wantarray ? ($rv, $sth, @bind) : $rv);
 }
 
 sub insert {
-  my ($self, $ident, $to_insert) = @_;
+  my ($self, $source, $to_insert) = @_;
+  
+  my $ident = $source->from; 
+  my $bind_attributes = $self->source_bind_attributes($source);
+
   $self->throw_exception(
     "Couldn't insert ".join(', ',
       map "$_ => $to_insert->{$_}", keys %$to_insert
     )." into ${ident}"
-  ) unless ($self->_execute('insert' => [], $ident, $to_insert));
+  ) unless ($self->_execute('insert' => [], $source, $bind_attributes, $to_insert));
   return $to_insert;
 }
 
+## Still not quite perfect, and EXPERIMENTAL
+## Currently it is assumed that all values passed will be "normal", i.e. not 
+## scalar refs, or at least, all the same type as the first set, the statement is
+## only prepped once.
+sub insert_bulk {
+  my ($self, $source, $cols, $data) = @_;
+  my %colvalues;
+  my $table = $source->from;
+  @colvalues{@$cols} = (0..$#$cols);
+  my ($sql, @bind) = $self->sql_maker->insert($table, \%colvalues);
+  
+  if ($self->debug) {
+      my @debug_bind = map { defined $_->[1] ? qq{$_->[1]} : q{'NULL'} } @bind;
+      $self->debugobj->query_start($sql, @debug_bind);
+  }
+  my $sth = $self->sth($sql);
+
+#  @bind = map { ref $_ ? ''.$_ : $_ } @bind; # stringify args
+
+  my $rv;
+  
+  ## This must be an arrayref, else nothing works!
+  
+  my $tuple_status = [];
+  
+  ##use Data::Dumper;
+  ##print STDERR Dumper( $data, $sql, [@bind] );
+
+  if ($sth) {
+  
+    my $time = time();
+
+    ## Get the bind_attributes, if any exist
+    my $bind_attributes = $self->source_bind_attributes($source);
+
+    ## Bind the values and execute
+    $rv = eval {
+
+     my $placeholder_index = 1; 
+
+        foreach my $bound (@bind) {
+
+          my $attributes = {};
+          my ($column_name, $data_index) = @$bound;
+
+          if( $bind_attributes ) {
+            $attributes = $bind_attributes->{$column_name}
+            if defined $bind_attributes->{$column_name};
+          }
+
+          my @data = map { $_->[$data_index] } @$data;
+
+          $sth->bind_param_array( $placeholder_index, [@data], $attributes );
+          $placeholder_index++;
+      }
+      $sth->execute_array( {ArrayTupleStatus => $tuple_status} );
+
+    };
+   
+    if ($@ || !defined $rv) {
+      my $errors = '';
+      foreach my $tuple (@$tuple_status) {
+          $errors .= "\n" . $tuple->[1] if(ref $tuple);
+      }
+      $self->throw_exception("Error executing '$sql': ".($@ || $errors));
+    }
+  } else {
+    $self->throw_exception("'$sql' did not generate a statement.");
+  }
+  if ($self->debug) {
+      my @debug_bind = map { defined $_ ? qq{`$_'} : q{`NULL'} } @bind;
+      $self->debugobj->query_end($sql, @debug_bind);
+  }
+  return (wantarray ? ($rv, $sth, @bind) : $rv);
+}
+
 sub update {
-  return shift->_execute('update' => [], @_);
+  my $self = shift @_;
+  my $source = shift @_;
+  my $bind_attributes = $self->source_bind_attributes($source);
+  
+  return $self->_execute('update' => [], $source, $bind_attributes, @_);
 }
 
+
 sub delete {
-  return shift->_execute('delete' => [], @_);
+  my $self = shift @_;
+  my $source = shift @_;
+  
+  my $bind_attrs = {}; ## If ever it's needed...
+  
+  return $self->_execute('delete' => [], $source, $bind_attrs, @_);
 }
 
 sub _select {
@@ -825,7 +1012,8 @@ sub _select {
       ($order ? (order_by => $order) : ())
     };
   }
-  my @args = ('select', $attrs->{bind}, $ident, $select, $condition, $order);
+  my $bind_attrs = {}; ## Future support
+  my @args = ('select', $attrs->{bind}, $ident, $bind_attrs, $select, $condition, $order);
   if ($attrs->{software_limit} ||
       $self->sql_maker->_default_limit_syntax eq "GenericSubQ") {
         $attrs->{software_limit} = 1;
@@ -837,6 +1025,20 @@ sub _select {
   return $self->_execute(@args);
 }
 
+sub source_bind_attributes {
+  my ($self, $source) = @_;
+  
+  my $bind_attributes;
+  foreach my $column ($source->columns) {
+  
+    my $data_type = $source->column_info($column)->{data_type} || '';
+    $bind_attributes->{$column} = $self->bind_attribute_by_data_type($data_type)
+     if $data_type;
+  }
+
+  return $bind_attributes;
+}
+
 =head2 select
 
 =over 4
@@ -855,19 +1057,11 @@ sub select {
   return $self->cursor->new($self, \@_, $attrs);
 }
 
-=head2 select_single
-
-Performs a select, fetch and return of data - handles a single row
-only.
-
-=cut
-
-# Need to call finish() to work round broken DBDs
-
 sub select_single {
   my $self = shift;
   my ($rv, $sth, @bind) = $self->_select(@_);
   my @row = $sth->fetchrow_array;
+  # Need to call finish() to work round broken DBDs
   $sth->finish();
   return @row;
 }
@@ -884,32 +1078,35 @@ Returns a L<DBI> sth (statement handle) for the supplied SQL.
 
 =cut
 
-sub sth {
-  my ($self, $sql) = @_;
-  # 3 is the if_active parameter which avoids active sth re-use
-  return $self->dbh->prepare_cached($sql, {}, 3);
-}
+sub _dbh_sth {
+  my ($self, $dbh, $sql) = @_;
 
-=head2 columns_info_for
+  # 3 is the if_active parameter which avoids active sth re-use
+  my $sth = $self->disable_sth_caching
+    ? $dbh->prepare($sql)
+    : $dbh->prepare_cached($sql, {}, 3);
 
-Returns database type info for a given table column.
+  $self->throw_exception(
+    'no sth generated via sql (' . ($@ || $dbh->errstr) . "): $sql"
+  ) if !$sth;
 
-=cut
+  $sth;
+}
 
-sub columns_info_for {
-  my ($self, $table) = @_;
+sub sth {
+  my ($self, $sql) = @_;
+  $self->dbh_do($self->can('_dbh_sth'), $sql);
+}
 
-  my $dbh = $self->dbh;
+sub _dbh_columns_info_for {
+  my ($self, $dbh, $table) = @_;
 
   if ($dbh->can('column_info')) {
     my %result;
-    local $dbh->{RaiseError} = 1;
-    local $dbh->{PrintError} = 0;
     eval {
       my ($schema,$tab) = $table =~ /^(.+?)\.(.+)$/ ? ($1,$2) : (undef,$table);
       my $sth = $dbh->column_info( undef,$schema, $tab, '%' );
       $sth->execute();
-
       while ( my $info = $sth->fetchrow_hashref() ){
         my %column_info;
         $column_info{data_type}   = $info->{TYPE_NAME};
@@ -952,17 +1149,26 @@ sub columns_info_for {
   return \%result;
 }
 
+sub columns_info_for {
+  my ($self, $table) = @_;
+  $self->dbh_do($self->can('_dbh_columns_info_for'), $table);
+}
+
 =head2 last_insert_id
 
 Return the row id of the last insert.
 
 =cut
 
-sub last_insert_id {
-  my ($self, $row) = @_;
-    
-  return $self->dbh->func('last_insert_rowid');
+sub _dbh_last_insert_id {
+    my ($self, $dbh, $source, $col) = @_;
+    # XXX This is a SQLite-ism as a default... is there a DBI-generic way?
+    $dbh->func('last_insert_rowid');
+}
 
+sub last_insert_id {
+  my $self = shift;
+  $self->dbh_do($self->can('_dbh_last_insert_id'), @_);
 }
 
 =head2 sqlt_type
@@ -973,11 +1179,25 @@ Returns the database driver name.
 
 sub sqlt_type { shift->dbh->{Driver}->{Name} }
 
+=head2 bind_attribute_by_data_type
+
+Given a datatype from column info, returns a database specific bind attribute for
+$dbh->bind_param($val,$attribute) or nothing if we will let the database planner
+just handle it.
+
+Generally only needed for special case column types, like bytea in postgres.
+
+=cut
+
+sub bind_attribute_by_data_type {
+    return;
+}
+
 =head2 create_ddl_dir (EXPERIMENTAL)
 
 =over 4
 
-=item Arguments: $schema \@databases, $version, $directory, $sqlt_args
+=item Arguments: $schema \@databases, $version, $directory, $preversion, $sqlt_args
 
 =back
 
@@ -991,7 +1211,7 @@ across all databases, or fully handle complex relationships.
 
 sub create_ddl_dir
 {
-  my ($self, $schema, $databases, $version, $dir, $sqltargs) = @_;
+  my ($self, $schema, $databases, $version, $dir, $preversion, $sqltargs) = @_;
 
   if(!$dir || !-d $dir)
   {
@@ -1004,14 +1224,18 @@ sub create_ddl_dir
   $sqltargs = { ( add_drop_table => 1 ), %{$sqltargs || {}} };
 
   eval "use SQL::Translator";
-  $self->throw_exception("Can't deploy without SQL::Translator: $@") if $@;
+  $self->throw_exception("Can't create a ddl file without SQL::Translator: $@") if $@;
 
-  my $sqlt = SQL::Translator->new($sqltargs);
+  my $sqlt = SQL::Translator->new({
+#      debug => 1,
+      add_drop_table => 1,
+  });
   foreach my $db (@$databases)
   {
     $sqlt->reset();
     $sqlt->parser('SQL::Translator::Parser::DBIx::Class');
 #    $sqlt->parser_args({'DBIx::Class' => $schema);
+    $sqlt = $self->configure_sqlt($sqlt, $db);
     $sqlt->data($schema);
     $sqlt->producer($db);
 
@@ -1019,24 +1243,97 @@ sub create_ddl_dir
     my $filename = $schema->ddl_filename($db, $dir, $version);
     if(-e $filename)
     {
-      $self->throw_exception("$filename already exists, skipping $db");
+      warn("$filename already exists, skipping $db");
       next;
     }
-    open($file, ">$filename") 
-      or $self->throw_exception("Can't open $filename for writing ($!)");
+
     my $output = $sqlt->translate;
-#use Data::Dumper;
-#    print join(":", keys %{$schema->source_registrations});
-#    print Dumper($sqlt->schema);
     if(!$output)
     {
-      $self->throw_exception("Failed to translate to $db. (" . $sqlt->error . ")");
+      warn("Failed to translate to $db, skipping. (" . $sqlt->error . ")");
       next;
     }
+    if(!open($file, ">$filename"))
+    {
+        $self->throw_exception("Can't open $filename for writing ($!)");
+        next;
+    }
     print $file $output;
     close($file);
+
+    if($preversion)
+    {
+      eval "use SQL::Translator::Diff";
+      if($@)
+      {
+        warn("Can't diff versions without SQL::Translator::Diff: $@");
+        next;
+      }
+
+      my $prefilename = $schema->ddl_filename($db, $dir, $preversion);
+#      print "Previous version $prefilename\n";
+      if(!-e $prefilename)
+      {
+        warn("No previous schema file found ($prefilename)");
+        next;
+      }
+      #### We need to reparse the SQLite file we just wrote, so that 
+      ##   Diff doesnt get all confoosed, and Diff is *very* confused.
+      ##   FIXME: rip Diff to pieces!
+#      my $target_schema = $sqlt->schema;
+#      unless ( $target_schema->name ) {
+#        $target_schema->name( $filename );
+#      }
+      my @input;
+      push @input, {file => $prefilename, parser => $db};
+      push @input, {file => $filename, parser => $db};
+      my ( $source_schema, $source_db, $target_schema, $target_db ) = map {
+        my $file   = $_->{'file'};
+        my $parser = $_->{'parser'};
+
+        my $t = SQL::Translator->new;
+        $t->debug( 0 );
+        $t->trace( 0 );
+        $t->parser( $parser )            or die $t->error;
+        my $out = $t->translate( $file ) or die $t->error;
+        my $schema = $t->schema;
+        unless ( $schema->name ) {
+          $schema->name( $file );
+        }
+        ($schema, $parser);
+      } @input;
+
+      my $diff = SQL::Translator::Diff::schema_diff($source_schema, $db,
+                                                    $target_schema, $db,
+                                                    {}
+                                                   );
+      my $difffile = $schema->ddl_filename($db, $dir, $version, $preversion);
+      print STDERR "Diff: $difffile: $db, $dir, $version, $preversion \n";
+      if(-e $difffile)
+      {
+        warn("$difffile already exists, skipping");
+        next;
+      }
+      if(!open $file, ">$difffile")
+      { 
+        $self->throw_exception("Can't write to $difffile ($!)");
+        next;
+      }
+      print $file $diff;
+      close($file);
+    }
   }
+}
 
+sub configure_sqlt() {
+  my $self = shift;
+  my $tr = shift;
+  my $db = shift || $self->sqlt_type;
+  if ($db eq 'PostgreSQL') {
+    $tr->quote_table_names(0);
+    $tr->quote_field_names(0);
+  }
+  return $tr;
 }
 
 =head2 deployment_statements
@@ -1069,6 +1366,17 @@ sub deployment_statements {
   $type ||= $self->sqlt_type;
   $version ||= $schema->VERSION || '1.x';
   $dir ||= './';
+  my $filename = $schema->ddl_filename($type, $dir, $version);
+  if(-f $filename)
+  {
+      my $file;
+      open($file, "<$filename") 
+        or $self->throw_exception("Can't open $filename ($!)");
+      my @rows = <$file>;
+      close($file);
+      return join('', @rows);
+  }
+
   eval "use SQL::Translator";
   if(!$@)
   {
@@ -1076,36 +1384,22 @@ sub deployment_statements {
     $self->throw_exception($@) if $@;
     eval "use SQL::Translator::Producer::${type};";
     $self->throw_exception($@) if $@;
+
+    # sources needs to be a parser arg, but for simplicty allow at top level 
+    # coming in
+    $sqltargs->{parser_args}{sources} = delete $sqltargs->{sources}
+        if exists $sqltargs->{sources};
+
     my $tr = SQL::Translator->new(%$sqltargs);
     SQL::Translator::Parser::DBIx::Class::parse( $tr, $schema );
     return "SQL::Translator::Producer::${type}"->can('produce')->($tr);
   }
 
-  my $filename = $schema->ddl_filename($type, $dir, $version);
-  if(!-f $filename)
-  {
-#      $schema->create_ddl_dir([ $type ], $version, $dir, $sqltargs);
-      $self->throw_exception("No SQL::Translator, and no Schema file found, aborting deploy");
-      return;
-  }
-  my $file;
-  open($file, "<$filename") 
-      or $self->throw_exception("Can't open $filename ($!)");
-  my @rows = <$file>;
-  close($file);
+  $self->throw_exception("No SQL::Translator, and no Schema file found, aborting deploy");
+  return;
 
-  return join('', @rows);
-  
 }
 
-=head2 deploy
-
-Sends the appropriate statements to create or modify tables to the
-db. This would normally be called through
-L<DBIx::Class::Schema/deploy>.
-
-=cut
-
 sub deploy {
   my ($self, $schema, $type, $sqltargs, $dir) = @_;
   foreach my $statement ( $self->deployment_statements($schema, $type, undef, $dir, { no_comments => 1, %{ $sqltargs || {} } } ) ) {
@@ -1117,7 +1411,7 @@ sub deploy {
       next if($_ =~ /^COMMIT/m);
       next if $_ =~ /^\s+$/; # skip whitespace only
       $self->debugobj->query_start($_) if $self->debug;
-      $self->dbh->do($_) or warn "SQL was:\n $_";
+      $self->dbh->do($_) or warn "SQL was:\n $_"; # XXX exceptions?
       $self->debugobj->query_end($_) if $self->debug;
     }
   }
@@ -1158,14 +1452,9 @@ sub build_datetime_parser {
 }
 
 sub DESTROY {
-  # NOTE: if there's a merge conflict here when -current is pushed
-  #  back to trunk, take -current's version and ignore this trunk one :)
   my $self = shift;
-
-  if($self->_dbh && $self->_conn_pid != $$) {
-    $self->_dbh->{InactiveDestroy} = 1;
-  }
-
+  return if !$self->_dbh;
+  $self->_verify_pid;
   $self->_dbh(undef);
 }
 
@@ -1206,25 +1495,6 @@ For setting, this method is deprecated in favor of L</connect_info>.
 
 =back
 
-=head1 ENVIRONMENT VARIABLES
-
-=head2 DBIC_TRACE
-
-If C<DBIC_TRACE> is set then SQL trace information
-is produced (as when the L<debug> method is set).
-
-If the value is of the form C<1=/path/name> then the trace output is
-written to the file C</path/name>.
-
-This environment variable is checked when the storage object is first
-created (when you call connect on your schema).  So, run-time changes 
-to this environment variable will not take effect unless you also 
-re-connect on your schema.
-
-=head2 DBIX_CLASS_STORAGE_DBI_DEBUG
-
-Old name for DBIC_TRACE
-
 =head1 AUTHORS
 
 Matt S. Trout <mst@shadowcatsystems.co.uk>
index 770608c..c9dedf6 100644 (file)
@@ -43,11 +43,9 @@ sub new {
     args => $args,
     pos => 0,
     attrs => $attrs,
-    pid => $$,
+    _dbh_gen => $storage->{_dbh_gen},
   };
 
-  $new->{tid} = threads->tid if $INC{'threads.pm'};
-  
   return bless ($new, $class);
 }
 
@@ -65,10 +63,10 @@ Advances the cursor to the next row and returns an arrayref of column values.
 
 =cut
 
-sub next {
-  my ($self) = @_;
+sub _dbh_next {
+  my ($storage, $dbh, $self) = @_;
 
-  $self->_check_forks_threads;
+  $self->_check_dbh_gen;
   if ($self->{attrs}{rows} && $self->{pos} >= $self->{attrs}{rows}) {
     $self->{sth}->finish if $self->{sth}->{Active};
     delete $self->{sth};
@@ -76,7 +74,7 @@ sub next {
   }
   return if $self->{done};
   unless ($self->{sth}) {
-    $self->{sth} = ($self->{storage}->_select(@{$self->{args}}))[1];
+    $self->{sth} = ($storage->_select(@{$self->{args}}))[1];
     if ($self->{attrs}{software_limit}) {
       if (my $offset = $self->{attrs}{offset}) {
         $self->{sth}->fetch for 1 .. $offset;
@@ -93,6 +91,11 @@ sub next {
   return @row;
 }
 
+sub next {
+  my ($self) = @_;
+  $self->{storage}->dbh_do($self->can('_dbh_next'), $self);
+}
+
 =head2 all
 
 =over 4
@@ -108,17 +111,22 @@ L<DBIx::Class::ResultSet>.
 
 =cut
 
-sub all {
-  my ($self) = @_;
+sub _dbh_all {
+  my ($storage, $dbh, $self) = @_;
 
-  $self->_check_forks_threads;
-  return $self->SUPER::all if $self->{attrs}{rows};
+  $self->_check_dbh_gen;
   $self->{sth}->finish if $self->{sth}->{Active};
   delete $self->{sth};
-  my ($rv, $sth) = $self->{storage}->_select(@{$self->{args}});
+  my ($rv, $sth) = $storage->_select(@{$self->{args}});
   return @{$sth->fetchall_arrayref};
 }
 
+sub all {
+  my ($self) = @_;
+  return $self->SUPER::all if $self->{attrs}{rows};
+  $self->{storage}->dbh_do($self->can('_dbh_all'), $self);
+}
+
 =head2 reset
 
 Resets the cursor to the beginning of the L<DBIx::Class::ResultSet>.
@@ -128,8 +136,8 @@ Resets the cursor to the beginning of the L<DBIx::Class::ResultSet>.
 sub reset {
   my ($self) = @_;
 
-  $self->_check_forks_threads;
-  $self->{sth}->finish if $self->{sth}->{Active};
+  # No need to care about failures here
+  eval { $self->{sth}->finish if $self->{sth} && $self->{sth}->{Active} };
   $self->_soft_reset;
 }
 
@@ -137,30 +145,25 @@ sub _soft_reset {
   my ($self) = @_;
 
   delete $self->{sth};
-  $self->{pos} = 0;
   delete $self->{done};
+  $self->{pos} = 0;
   return $self;
 }
 
-sub _check_forks_threads {
+sub _check_dbh_gen {
   my ($self) = @_;
 
-  if($INC{'threads.pm'} && $self->{tid} != threads->tid) {
-      $self->_soft_reset;
-      $self->{tid} = threads->tid;
-  }
-
-  if($self->{pid} != $$) {
-      $self->_soft_reset;
-      $self->{pid} = $$;
+  if($self->{_dbh_gen} != $self->{storage}->{_dbh_gen}) {
+    $self->{_dbh_gen} = $self->{storage}->{_dbh_gen};
+    $self->_soft_reset;
   }
 }
 
 sub DESTROY {
   my ($self) = @_;
 
-  $self->_check_forks_threads;
-  $self->{sth}->finish if $self->{sth} && $self->{sth}->{Active};
+  # None of the reasons this would die matter if we're in DESTROY anyways
+  eval { $self->{sth}->finish if $self->{sth} && $self->{sth}->{Active} };
 }
 
 1;
index 8e867e0..4b5051b 100644 (file)
@@ -7,18 +7,15 @@ use base qw/DBIx::Class::Storage::DBI/;
 
 # __PACKAGE__->load_components(qw/PK::Auto/);
 
-sub last_insert_id
-{
-    my ($self) = @_;
+sub _dbh_last_insert_id {
+    my ($self, $dbh, $source, $col) = @_;
 
-    my $dbh = $self->_dbh;
-    my $sth = $dbh->prepare_cached("VALUES(IDENTITY_VAL_LOCAL())", {}, 3);
+    my $sth = $dbh->prepare_cached('VALUES(IDENTITY_VAL_LOCAL())', {}, 3);
     $sth->execute();
 
     my @res = $sth->fetchrow_array();
 
     return @res ? $res[0] : undef;
-                         
 }
 
 sub datetime_parser_type { "DateTime::Format::DB2"; }
index e355ce9..dcfe895 100644 (file)
@@ -5,8 +5,9 @@ use warnings;
 
 use base qw/DBIx::Class::Storage::DBI/;
 
-sub last_insert_id {
-  my( $id ) = $_[0]->_dbh->selectrow_array('SELECT @@IDENTITY' );
+sub _dbh_last_insert_id {
+  my ($self, $dbh, $source, $col) = @_;
+  my ($id) = $dbh->selectrow_array('SELECT @@IDENTITY');
   return $id;
 }
 
index 2388762..2877ee2 100644 (file)
@@ -17,58 +17,32 @@ well, as is the case with L<DBD::Sybase>
 
 =head1 METHODS
 
-=head2 sth
+=head2 connect_info
 
-Uses C<prepare> instead of the usual C<prepare_cached>, seeing as we can't cache very effectively without bind variables.
+We can't cache very effectively without bind variables, so force the C<disable_sth_caching> setting to be turned on when the connect info is set.
 
 =cut
 
-sub sth {
-  my ($self, $sql) = @_;
-  return $self->dbh->prepare($sql);
+sub connect_info {
+    my $self = shift;
+    my $retval = shift->next::method(@_);
+    $self->disable_sth_caching(1);
+    $retval;
 }
 
-=head2 _execute
+=head2 _prep_for_execute
 
-Manually subs in the values for the usual C<?> placeholders before calling L</sth> on the generated SQL.
+Manually subs in the values for the usual C<?> placeholders.
 
 =cut
 
-sub _execute {
-  my ($self, $op, $extra_bind, $ident, @args) = @_;
-  my ($sql, @bind) = $self->sql_maker->$op($ident, @args);
-  unshift(@bind, @$extra_bind) if $extra_bind;
-  if ($self->debug) {
-    my @debug_bind = map { defined $_ ? qq{'$_'} : q{'NULL'} } @bind;
-    $self->debugobj->query_start($sql, @debug_bind);
-  }
+sub _prep_for_execute {
+  my $self = shift;
+  my ($sql, @bind) = $self->next::method(@_);
 
   $sql =~ s/\?/$self->_dbh->quote(shift(@bind))/eg;
 
-  my $sth = eval { $self->sth($sql,$op) };
-
-  if (!$sth || $@) {
-    $self->throw_exception(
-      'no sth generated via sql (' . ($@ || $self->_dbh->errstr) . "): $sql"
-    );
-  }
-
-  my $rv;
-  if ($sth) {
-    my $time = time();
-    $rv = eval { $sth->execute };
-
-    if ($@ || !$rv) {
-      $self->throw_exception("Error executing '$sql': ".($@ || $sth->errstr));
-    }
-  } else {
-    $self->throw_exception("'$sql' did not generate a statement.");
-  }
-  if ($self->debug) {
-    my @debug_bind = map { defined $_ ? qq{`$_'} : q{`NULL'} } @bind;
-    $self->debugobj->query_end($sql, @debug_bind);
-  }
-  return (wantarray ? ($rv, $sth, @bind) : $rv);
+  return ($sql);
 }
 
 =head1 AUTHORS
index f33100c..42466ef 100644 (file)
@@ -7,7 +7,7 @@ use base qw/DBIx::Class::Storage::DBI/;
 sub _rebless {
     my ($self) = @_;
 
-    my $dbh = $self->_dbh;
+    my $dbh = $self->dbh;
     my $dbtype = eval { $dbh->get_info(17) };
     unless ( $@ ) {
         # Translate the backend name into a perl identifier
index c39a622..1df4c21 100644 (file)
@@ -4,11 +4,8 @@ use warnings;
 
 use base qw/DBIx::Class::Storage::DBI::ODBC/;
 
-sub last_insert_id
-{
-    my ($self) = @_;
-
-    my $dbh = $self->_dbh;
+sub _dbh_last_insert_id {
+    my ($self, $dbh, $source, $col) = @_;
 
     # get the schema/table separator:
     #    '.' when SQL naming is active
@@ -26,10 +23,14 @@ sub last_insert_id
 sub _sql_maker_opts {
     my ($self) = @_;
     
-    return {
-        limit_dialect => 'FetchFirst',
-        name_sep => $self->_dbh->get_info(41)
-    };
+    $self->dbh_do(sub {
+        my ($self, $dbh) = @_;
+
+        return {
+            limit_dialect => 'FetchFirst',
+            name_sep => $dbh->get_info(41)
+        };
+    });
 }
 
 1;
index 1cda2e3..77cedf3 100644 (file)
@@ -3,33 +3,34 @@ package DBIx::Class::Storage::DBI::Oracle;
 use strict;
 use warnings;
 
-use Carp qw/croak/;
+use Carp::Clan qw/^DBIx::Class/;
 
 use base qw/DBIx::Class::Storage::DBI::MultiDistinctEmulation/;
 
 # __PACKAGE__->load_components(qw/PK::Auto/);
 
-sub last_insert_id {
-  my ($self,$source,$col) = @_;
+sub _dbh_last_insert_id {
+  my ($self, $dbh, $source, $col) = @_;
   my $seq = ($source->column_info($col)->{sequence} ||= $self->get_autoinc_seq($source,$col));
-  my $sql = "SELECT " . $seq . ".currval FROM DUAL";
-  my ($id) = $self->_dbh->selectrow_array($sql);
+  my $sql = 'SELECT ' . $seq . '.currval FROM DUAL';
+  my ($id) = $dbh->selectrow_array($sql);
   return $id;
 }
 
-sub get_autoinc_seq {
-  my ($self,$source,$col) = @_;
-    
+sub _dbh_get_autoinc_seq {
+  my ($self, $dbh, $source, $col) = @_;
+
   # look up the correct sequence automatically
-  my $dbh = $self->_dbh;
   my $sql = q{
     SELECT trigger_body FROM ALL_TRIGGERS t
     WHERE t.table_name = ?
     AND t.triggering_event = 'INSERT'
     AND t.status = 'ENABLED'
   };
+
   # trigger_body is a LONG
   $dbh->{LongReadLen} = 64 * 1024 if ($dbh->{LongReadLen} < 64 * 1024);
+
   my $sth = $dbh->prepare($sql);
   $sth->execute( uc($source->name) );
   while (my ($insert_trigger) = $sth->fetchrow_array) {
@@ -38,6 +39,12 @@ sub get_autoinc_seq {
   croak "Unable to find a sequence INSERT trigger on table '" . $source->name . "'.";
 }
 
+sub get_autoinc_seq {
+  my ($self, $source, $col) = @_;
+    
+  $self->dbh_do($self->can('_dbh_get_autoinc_seq'), $source, $col);
+}
+
 sub columns_info_for {
   my ($self, $table) = @_;
 
index 5d7a0bf..ea5f6f0 100644 (file)
@@ -3,7 +3,7 @@ package DBIx::Class::Storage::DBI::Pg;
 use strict;
 use warnings;
 
-use DBD::Pg;
+use DBD::Pg qw(:pg_types);
 
 use base qw/DBIx::Class::Storage::DBI/;
 
@@ -13,31 +13,43 @@ use base qw/DBIx::Class::Storage::DBI/;
 warn "DBD::Pg 1.49 is strongly recommended"
   if ($DBD::Pg::VERSION < 1.49);
 
+sub _dbh_last_insert_id {
+  my ($self, $dbh, $seq) = @_;
+  $dbh->last_insert_id(undef, undef, undef, undef, {sequence => $seq});
+}
+
 sub last_insert_id {
   my ($self,$source,$col) = @_;
   my $seq = ($source->column_info($col)->{sequence} ||= $self->get_autoinc_seq($source,$col));
   $self->throw_exception("could not fetch primary key for " . $source->name . ", could not "
     . "get autoinc sequence for $col (check that table and column specifications are correct "
     . "and in the correct case)") unless defined $seq;
-  $self->_dbh->last_insert_id(undef,undef,undef,undef, {sequence => $seq});
+  $self->dbh_do($self->can('_dbh_last_insert_id'), $seq);
+}
+
+sub _dbh_get_autoinc_seq {
+  my ($self, $dbh, $schema, $table, @pri) = @_;
+
+  while (my $col = shift @pri) {
+    my $info = $dbh->column_info(undef,$schema,$table,$col)->fetchrow_hashref;
+    if(defined $info->{COLUMN_DEF} and
+       $info->{COLUMN_DEF} =~ /^nextval\(+'([^']+)'::(?:text|regclass)\)/) {
+      my $seq = $1;
+      # may need to strip quotes -- see if this works
+      return $seq =~ /\./ ? $seq : $info->{TABLE_SCHEM} . "." . $seq;
+    }
+  }
+  return;
 }
 
 sub get_autoinc_seq {
   my ($self,$source,$col) = @_;
     
   my @pri = $source->primary_columns;
-  my $dbh = $self->_dbh;
   my ($schema,$table) = $source->name =~ /^(.+)\.(.+)$/ ? ($1,$2)
     : (undef,$source->name);
-  while (my $col = shift @pri) {
-    my $info = $dbh->column_info(undef,$schema,$table,$col)->fetchrow_hashref;
-    if (defined $info->{COLUMN_DEF} and $info->{COLUMN_DEF} =~
-      /^nextval\(+'([^']+)'::(?:text|regclass)\)/)
-    {
-       my $seq = $1;
-      return $seq =~ /\./ ? $seq : $info->{TABLE_SCHEM} . "." . $seq; # may need to strip quotes -- see if this works
-    }
-  }
+
+  $self->dbh_do($self->can('_dbh_get_autoinc_seq'), $schema, $table, @pri);
 }
 
 sub sqlt_type {
@@ -46,6 +58,21 @@ sub sqlt_type {
 
 sub datetime_parser_type { return "DateTime::Format::Pg"; }
 
+sub bind_attribute_by_data_type {
+  my ($self,$data_type) = @_;
+
+  my $bind_attributes = {
+    bytea => { pg_type => DBD::Pg::PG_BYTEA },
+  };
+  if( defined $bind_attributes->{$data_type} ) {
+    return $bind_attributes->{$data_type};
+  }
+  else {
+    return;
+  }
+}
+
 1;
 
 =head1 NAME
index 091b5e7..02a3c51 100644 (file)
@@ -2,11 +2,47 @@ package DBIx::Class::Storage::DBI::SQLite;
 
 use strict;
 use warnings;
+use POSIX 'strftime';
+use File::Copy;
+use File::Spec;
 
 use base qw/DBIx::Class::Storage::DBI::MultiDistinctEmulation/;
 
-sub last_insert_id {
-  return $_[0]->dbh->func('last_insert_rowid');
+sub _dbh_last_insert_id {
+  my ($self, $dbh, $source, $col) = @_;
+  $dbh->func('last_insert_rowid');
+}
+
+sub backup
+{
+  my ($self, $dir) = @_;
+  $dir ||= './';
+
+  ## Where is the db file?
+  my $dsn = $self->connect_info()->[0];
+
+  my $dbname = $1 if($dsn =~ /dbname=([^;]+)/);
+  if(!$dbname)
+  {
+    $dbname = $1 if($dsn =~ /^dbi:SQLite:(.+)$/i);
+  }
+  $self->throw_exception("Cannot determine name of SQLite db file") 
+    if(!$dbname || !-f $dbname);
+
+#  print "Found database: $dbname\n";
+#  my $dbfile = file($dbname);
+  my ($vol, $dbdir, $file) = File::Spec->splitpath($dbname);
+#  my $file = $dbfile->basename();
+  $file = strftime("%y%m%d%h%M%s", localtime()) . $file; 
+  $file = "B$file" while(-f $file);
+
+  mkdir($dir) unless -f $dir;
+  my $backupfile = File::Spec->catfile($dir, $file);
+
+  my $res = copy($dbname, $backupfile);
+  $self->throw_exception("Backup failed! ($!)") if(!$res);
+
+  return $backupfile;
 }
 
 1;
index 8c14b1b..8ecdfca 100644 (file)
@@ -7,8 +7,9 @@ use base qw/DBIx::Class::Storage::DBI/;
 
 # __PACKAGE__->load_components(qw/PK::Auto/);
 
-sub last_insert_id {
-  return $_[0]->_dbh->{mysql_insertid};
+sub _dbh_last_insert_id {
+  my ($self, $dbh, $source, $col) = @_;
+  $dbh->{mysql_insertid};
 }
 
 sub sqlt_type {
index 3b9d7d6..5d0ba47 100644 (file)
@@ -1,7 +1,9 @@
 package DBIx::Class::Storage::Statistics;
 use strict;
+use warnings;
+
+use base qw/Class::Accessor::Grouped/;
 
-use base qw/DBIx::Class::AccessorGroup Class::Data::Accessor/;
 __PACKAGE__->mk_group_accessors(simple => qw/callback debugfh/);
 
 =head1 NAME
index d8af4d6..edf6224 100644 (file)
@@ -26,10 +26,11 @@ use base qw(Exporter);
 # We're working with DBIx::Class Schemas, not data streams.
 # -------------------------------------------------------------------
 sub parse {
-    my ($tr, $data) = @_;
-    my $args        = $tr->parser_args;
-    my $dbixschema  = $args->{'DBIx::Schema'} || $data;
-    $dbixschema   ||= $args->{'package'};
+    my ($tr, $data)   = @_;
+    my $args          = $tr->parser_args;
+    my $dbixschema    = $args->{'DBIx::Schema'} || $data;
+    $dbixschema     ||= $args->{'package'};
+    my $limit_sources = $args->{'sources'};
     
     die 'No DBIx::Schema' unless ($dbixschema);
     if (!ref $dbixschema) {
@@ -46,7 +47,23 @@ sub parse {
 
     my %seen_tables;
 
-    foreach my $moniker ($dbixschema->sources)
+    my @monikers = $dbixschema->sources;
+    if ($limit_sources) {
+        my $ref = ref $limit_sources || '';
+        die "'sources' parameter must be an array or hash ref" unless $ref eq 'ARRAY' || ref eq 'HASH';
+
+        # limit monikers to those specified in 
+        my $sources;
+        if ($ref eq 'ARRAY') {
+            $sources->{$_} = 1 for (@$limit_sources);
+        } else {
+            $sources = $limit_sources;
+        }
+        @monikers = grep { $sources->{$_} } @monikers;
+    }
+
+
+    foreach my $moniker (@monikers)
     {
         #eval "use $tableclass";
         #print("Can't load $tableclass"), next if($@);
@@ -91,6 +108,9 @@ sub parse {
         }
 
         my @rels = $source->relationships();
+
+        my %created_FK_rels;
+
         foreach my $rel (@rels)
         {
             my $rel_info = $source->relationship_info($rel);
@@ -120,12 +140,22 @@ sub parse {
                     $on_update = $otherrelationship->{'attrs'}->{cascade_copy} ? 'CASCADE' : '';
                 }
 
+                # Make sure we dont create the same foreign key constraint twice
+                my $key_test = join("\x00", @keys);
+
                 #Decide if this is a foreign key based on whether the self
                 #items are our primary columns.
 
                 # If the sets are different, then we assume it's a foreign key from
                 # us to another table.
-                if (!$source->compare_relationship_keys(\@keys, \@primary)) {
+                # OR: If is_foreign_key attr is explicity set on one the local columns
+                if ( ! exists $created_FK_rels{$rel_table}->{$key_test} 
+                    && 
+                    ( !$source->compare_relationship_keys(\@keys, \@primary) ||
+                      grep { $source->column_info($_)->{is_foreign_key} } @keys 
+                    )
+                   ) {
+                    $created_FK_rels{$rel_table}->{$key_test} = 1;
                     $table->add_constraint(
                                 type             => 'foreign_key',
                                 name             => "fk_$keys[0]",
index aacbf18..2530be2 100644 (file)
@@ -58,7 +58,7 @@ my $exceptions = {
     'DBIx::Class::Relationship::ProxyMethods'           => { skip => 1 },
     'DBIx::Class::ResultSetProxy'                       => { skip => 1 },
     'DBIx::Class::ResultSourceProxy'                    => { skip => 1 },
-    'DBIx::Class::Storage'                              => { skip => 1 },
+    'DBIx::Class::Storage::DBI'                         => { skip => 1 },
     'DBIx::Class::Storage::DBI::DB2'                    => { skip => 1 },
     'DBIx::Class::Storage::DBI::MSSQL'                  => { skip => 1 },
     'DBIx::Class::Storage::DBI::MultiDistinctEmulation' => { skip => 1 },
diff --git a/t/100populate.t b/t/100populate.t
new file mode 100644 (file)
index 0000000..7b89395
--- /dev/null
@@ -0,0 +1,10085 @@
+use strict;
+use warnings;  
+
+use Test::More;
+use lib qw(t/lib);
+use DBICTest;
+
+plan tests => 22;
+
+# perl -le'my $letter = 'a'; for my $i (4..10000) { $letter++; print "[ $i, \"$letter\" ]," }' > tests.txt
+
+my $schema = DBICTest->init_schema();
+$schema->populate('Artist', [
+[ qw/artistid name/ ],
+[ 4, "b" ],
+[ 5, "c" ],
+[ 6, "d" ],
+[ 7, "e" ],
+[ 8, "f" ],
+[ 9, "g" ],
+[ 10, "h" ],
+[ 11, "i" ],
+[ 12, "j" ],
+[ 13, "k" ],
+[ 14, "l" ],
+[ 15, "m" ],
+[ 16, "n" ],
+[ 17, "o" ],
+[ 18, "p" ],
+[ 19, "q" ],
+[ 20, "r" ],
+[ 21, "s" ],
+[ 22, "t" ],
+[ 23, "u" ],
+[ 24, "v" ],
+[ 25, "w" ],
+[ 26, "x" ],
+[ 27, "y" ],
+[ 28, "z" ],
+[ 29, "aa" ],
+[ 30, "ab" ],
+[ 31, "ac" ],
+[ 32, "ad" ],
+[ 33, "ae" ],
+[ 34, "af" ],
+[ 35, "ag" ],
+[ 36, "ah" ],
+[ 37, "ai" ],
+[ 38, "aj" ],
+[ 39, "ak" ],
+[ 40, "al" ],
+[ 41, "am" ],
+[ 42, "an" ],
+[ 43, "ao" ],
+[ 44, "ap" ],
+[ 45, "aq" ],
+[ 46, "ar" ],
+[ 47, "as" ],
+[ 48, "at" ],
+[ 49, "au" ],
+[ 50, "av" ],
+[ 51, "aw" ],
+[ 52, "ax" ],
+[ 53, "ay" ],
+[ 54, "az" ],
+[ 55, "ba" ],
+[ 56, "bb" ],
+[ 57, "bc" ],
+[ 58, "bd" ],
+[ 59, "be" ],
+[ 60, "bf" ],
+[ 61, "bg" ],
+[ 62, "bh" ],
+[ 63, "bi" ],
+[ 64, "bj" ],
+[ 65, "bk" ],
+[ 66, "bl" ],
+[ 67, "bm" ],
+[ 68, "bn" ],
+[ 69, "bo" ],
+[ 70, "bp" ],
+[ 71, "bq" ],
+[ 72, "br" ],
+[ 73, "bs" ],
+[ 74, "bt" ],
+[ 75, "bu" ],
+[ 76, "bv" ],
+[ 77, "bw" ],
+[ 78, "bx" ],
+[ 79, "by" ],
+[ 80, "bz" ],
+[ 81, "ca" ],
+[ 82, "cb" ],
+[ 83, "cc" ],
+[ 84, "cd" ],
+[ 85, "ce" ],
+[ 86, "cf" ],
+[ 87, "cg" ],
+[ 88, "ch" ],
+[ 89, "ci" ],
+[ 90, "cj" ],
+[ 91, "ck" ],
+[ 92, "cl" ],
+[ 93, "cm" ],
+[ 94, "cn" ],
+[ 95, "co" ],
+[ 96, "cp" ],
+[ 97, "cq" ],
+[ 98, "cr" ],
+[ 99, "cs" ],
+[ 100, "ct" ],
+[ 101, "cu" ],
+[ 102, "cv" ],
+[ 103, "cw" ],
+[ 104, "cx" ],
+[ 105, "cy" ],
+[ 106, "cz" ],
+[ 107, "da" ],
+[ 108, "db" ],
+[ 109, "dc" ],
+[ 110, "dd" ],
+[ 111, "de" ],
+[ 112, "df" ],
+[ 113, "dg" ],
+[ 114, "dh" ],
+[ 115, "di" ],
+[ 116, "dj" ],
+[ 117, "dk" ],
+[ 118, "dl" ],
+[ 119, "dm" ],
+[ 120, "dn" ],
+[ 121, "do" ],
+[ 122, "dp" ],
+[ 123, "dq" ],
+[ 124, "dr" ],
+[ 125, "ds" ],
+[ 126, "dt" ],
+[ 127, "du" ],
+[ 128, "dv" ],
+[ 129, "dw" ],
+[ 130, "dx" ],
+[ 131, "dy" ],
+[ 132, "dz" ],
+[ 133, "ea" ],
+[ 134, "eb" ],
+[ 135, "ec" ],
+[ 136, "ed" ],
+[ 137, "ee" ],
+[ 138, "ef" ],
+[ 139, "eg" ],
+[ 140, "eh" ],
+[ 141, "ei" ],
+[ 142, "ej" ],
+[ 143, "ek" ],
+[ 144, "el" ],
+[ 145, "em" ],
+[ 146, "en" ],
+[ 147, "eo" ],
+[ 148, "ep" ],
+[ 149, "eq" ],
+[ 150, "er" ],
+[ 151, "es" ],
+[ 152, "et" ],
+[ 153, "eu" ],
+[ 154, "ev" ],
+[ 155, "ew" ],
+[ 156, "ex" ],
+[ 157, "ey" ],
+[ 158, "ez" ],
+[ 159, "fa" ],
+[ 160, "fb" ],
+[ 161, "fc" ],
+[ 162, "fd" ],
+[ 163, "fe" ],
+[ 164, "ff" ],
+[ 165, "fg" ],
+[ 166, "fh" ],
+[ 167, "fi" ],
+[ 168, "fj" ],
+[ 169, "fk" ],
+[ 170, "fl" ],
+[ 171, "fm" ],
+[ 172, "fn" ],
+[ 173, "fo" ],
+[ 174, "fp" ],
+[ 175, "fq" ],
+[ 176, "fr" ],
+[ 177, "fs" ],
+[ 178, "ft" ],
+[ 179, "fu" ],
+[ 180, "fv" ],
+[ 181, "fw" ],
+[ 182, "fx" ],
+[ 183, "fy" ],
+[ 184, "fz" ],
+[ 185, "ga" ],
+[ 186, "gb" ],
+[ 187, "gc" ],
+[ 188, "gd" ],
+[ 189, "ge" ],
+[ 190, "gf" ],
+[ 191, "gg" ],
+[ 192, "gh" ],
+[ 193, "gi" ],
+[ 194, "gj" ],
+[ 195, "gk" ],
+[ 196, "gl" ],
+[ 197, "gm" ],
+[ 198, "gn" ],
+[ 199, "go" ],
+[ 200, "gp" ],
+[ 201, "gq" ],
+[ 202, "gr" ],
+[ 203, "gs" ],
+[ 204, "gt" ],
+[ 205, "gu" ],
+[ 206, "gv" ],
+[ 207, "gw" ],
+[ 208, "gx" ],
+[ 209, "gy" ],
+[ 210, "gz" ],
+[ 211, "ha" ],
+[ 212, "hb" ],
+[ 213, "hc" ],
+[ 214, "hd" ],
+[ 215, "he" ],
+[ 216, "hf" ],
+[ 217, "hg" ],
+[ 218, "hh" ],
+[ 219, "hi" ],
+[ 220, "hj" ],
+[ 221, "hk" ],
+[ 222, "hl" ],
+[ 223, "hm" ],
+[ 224, "hn" ],
+[ 225, "ho" ],
+[ 226, "hp" ],
+[ 227, "hq" ],
+[ 228, "hr" ],
+[ 229, "hs" ],
+[ 230, "ht" ],
+[ 231, "hu" ],
+[ 232, "hv" ],
+[ 233, "hw" ],
+[ 234, "hx" ],
+[ 235, "hy" ],
+[ 236, "hz" ],
+[ 237, "ia" ],
+[ 238, "ib" ],
+[ 239, "ic" ],
+[ 240, "id" ],
+[ 241, "ie" ],
+[ 242, "if" ],
+[ 243, "ig" ],
+[ 244, "ih" ],
+[ 245, "ii" ],
+[ 246, "ij" ],
+[ 247, "ik" ],
+[ 248, "il" ],
+[ 249, "im" ],
+[ 250, "in" ],
+[ 251, "io" ],
+[ 252, "ip" ],
+[ 253, "iq" ],
+[ 254, "ir" ],
+[ 255, "is" ],
+[ 256, "it" ],
+[ 257, "iu" ],
+[ 258, "iv" ],
+[ 259, "iw" ],
+[ 260, "ix" ],
+[ 261, "iy" ],
+[ 262, "iz" ],
+[ 263, "ja" ],
+[ 264, "jb" ],
+[ 265, "jc" ],
+[ 266, "jd" ],
+[ 267, "je" ],
+[ 268, "jf" ],
+[ 269, "jg" ],
+[ 270, "jh" ],
+[ 271, "ji" ],
+[ 272, "jj" ],
+[ 273, "jk" ],
+[ 274, "jl" ],
+[ 275, "jm" ],
+[ 276, "jn" ],
+[ 277, "jo" ],
+[ 278, "jp" ],
+[ 279, "jq" ],
+[ 280, "jr" ],
+[ 281, "js" ],
+[ 282, "jt" ],
+[ 283, "ju" ],
+[ 284, "jv" ],
+[ 285, "jw" ],
+[ 286, "jx" ],
+[ 287, "jy" ],
+[ 288, "jz" ],
+[ 289, "ka" ],
+[ 290, "kb" ],
+[ 291, "kc" ],
+[ 292, "kd" ],
+[ 293, "ke" ],
+[ 294, "kf" ],
+[ 295, "kg" ],
+[ 296, "kh" ],
+[ 297, "ki" ],
+[ 298, "kj" ],
+[ 299, "kk" ],
+[ 300, "kl" ],
+[ 301, "km" ],
+[ 302, "kn" ],
+[ 303, "ko" ],
+[ 304, "kp" ],
+[ 305, "kq" ],
+[ 306, "kr" ],
+[ 307, "ks" ],
+[ 308, "kt" ],
+[ 309, "ku" ],
+[ 310, "kv" ],
+[ 311, "kw" ],
+[ 312, "kx" ],
+[ 313, "ky" ],
+[ 314, "kz" ],
+[ 315, "la" ],
+[ 316, "lb" ],
+[ 317, "lc" ],
+[ 318, "ld" ],
+[ 319, "le" ],
+[ 320, "lf" ],
+[ 321, "lg" ],
+[ 322, "lh" ],
+[ 323, "li" ],
+[ 324, "lj" ],
+[ 325, "lk" ],
+[ 326, "ll" ],
+[ 327, "lm" ],
+[ 328, "ln" ],
+[ 329, "lo" ],
+[ 330, "lp" ],
+[ 331, "lq" ],
+[ 332, "lr" ],
+[ 333, "ls" ],
+[ 334, "lt" ],
+[ 335, "lu" ],
+[ 336, "lv" ],
+[ 337, "lw" ],
+[ 338, "lx" ],
+[ 339, "ly" ],
+[ 340, "lz" ],
+[ 341, "ma" ],
+[ 342, "mb" ],
+[ 343, "mc" ],
+[ 344, "md" ],
+[ 345, "me" ],
+[ 346, "mf" ],
+[ 347, "mg" ],
+[ 348, "mh" ],
+[ 349, "mi" ],
+[ 350, "mj" ],
+[ 351, "mk" ],
+[ 352, "ml" ],
+[ 353, "mm" ],
+[ 354, "mn" ],
+[ 355, "mo" ],
+[ 356, "mp" ],
+[ 357, "mq" ],
+[ 358, "mr" ],
+[ 359, "ms" ],
+[ 360, "mt" ],
+[ 361, "mu" ],
+[ 362, "mv" ],
+[ 363, "mw" ],
+[ 364, "mx" ],
+[ 365, "my" ],
+[ 366, "mz" ],
+[ 367, "na" ],
+[ 368, "nb" ],
+[ 369, "nc" ],
+[ 370, "nd" ],
+[ 371, "ne" ],
+[ 372, "nf" ],
+[ 373, "ng" ],
+[ 374, "nh" ],
+[ 375, "ni" ],
+[ 376, "nj" ],
+[ 377, "nk" ],
+[ 378, "nl" ],
+[ 379, "nm" ],
+[ 380, "nn" ],
+[ 381, "no" ],
+[ 382, "np" ],
+[ 383, "nq" ],
+[ 384, "nr" ],
+[ 385, "ns" ],
+[ 386, "nt" ],
+[ 387, "nu" ],
+[ 388, "nv" ],
+[ 389, "nw" ],
+[ 390, "nx" ],
+[ 391, "ny" ],
+[ 392, "nz" ],
+[ 393, "oa" ],
+[ 394, "ob" ],
+[ 395, "oc" ],
+[ 396, "od" ],
+[ 397, "oe" ],
+[ 398, "of" ],
+[ 399, "og" ],
+[ 400, "oh" ],
+[ 401, "oi" ],
+[ 402, "oj" ],
+[ 403, "ok" ],
+[ 404, "ol" ],
+[ 405, "om" ],
+[ 406, "on" ],
+[ 407, "oo" ],
+[ 408, "op" ],
+[ 409, "oq" ],
+[ 410, "or" ],
+[ 411, "os" ],
+[ 412, "ot" ],
+[ 413, "ou" ],
+[ 414, "ov" ],
+[ 415, "ow" ],
+[ 416, "ox" ],
+[ 417, "oy" ],
+[ 418, "oz" ],
+[ 419, "pa" ],
+[ 420, "pb" ],
+[ 421, "pc" ],
+[ 422, "pd" ],
+[ 423, "pe" ],
+[ 424, "pf" ],
+[ 425, "pg" ],
+[ 426, "ph" ],
+[ 427, "pi" ],
+[ 428, "pj" ],
+[ 429, "pk" ],
+[ 430, "pl" ],
+[ 431, "pm" ],
+[ 432, "pn" ],
+[ 433, "po" ],
+[ 434, "pp" ],
+[ 435, "pq" ],
+[ 436, "pr" ],
+[ 437, "ps" ],
+[ 438, "pt" ],
+[ 439, "pu" ],
+[ 440, "pv" ],
+[ 441, "pw" ],
+[ 442, "px" ],
+[ 443, "py" ],
+[ 444, "pz" ],
+[ 445, "qa" ],
+[ 446, "qb" ],
+[ 447, "qc" ],
+[ 448, "qd" ],
+[ 449, "qe" ],
+[ 450, "qf" ],
+[ 451, "qg" ],
+[ 452, "qh" ],
+[ 453, "qi" ],
+[ 454, "qj" ],
+[ 455, "qk" ],
+[ 456, "ql" ],
+[ 457, "qm" ],
+[ 458, "qn" ],
+[ 459, "qo" ],
+[ 460, "qp" ],
+[ 461, "qq" ],
+[ 462, "qr" ],
+[ 463, "qs" ],
+[ 464, "qt" ],
+[ 465, "qu" ],
+[ 466, "qv" ],
+[ 467, "qw" ],
+[ 468, "qx" ],
+[ 469, "qy" ],
+[ 470, "qz" ],
+[ 471, "ra" ],
+[ 472, "rb" ],
+[ 473, "rc" ],
+[ 474, "rd" ],
+[ 475, "re" ],
+[ 476, "rf" ],
+[ 477, "rg" ],
+[ 478, "rh" ],
+[ 479, "ri" ],
+[ 480, "rj" ],
+[ 481, "rk" ],
+[ 482, "rl" ],
+[ 483, "rm" ],
+[ 484, "rn" ],
+[ 485, "ro" ],
+[ 486, "rp" ],
+[ 487, "rq" ],
+[ 488, "rr" ],
+[ 489, "rs" ],
+[ 490, "rt" ],
+[ 491, "ru" ],
+[ 492, "rv" ],
+[ 493, "rw" ],
+[ 494, "rx" ],
+[ 495, "ry" ],
+[ 496, "rz" ],
+[ 497, "sa" ],
+[ 498, "sb" ],
+[ 499, "sc" ],
+[ 500, "sd" ],
+[ 501, "se" ],
+[ 502, "sf" ],
+[ 503, "sg" ],
+[ 504, "sh" ],
+[ 505, "si" ],
+[ 506, "sj" ],
+[ 507, "sk" ],
+[ 508, "sl" ],
+[ 509, "sm" ],
+[ 510, "sn" ],
+[ 511, "so" ],
+[ 512, "sp" ],
+[ 513, "sq" ],
+[ 514, "sr" ],
+[ 515, "ss" ],
+[ 516, "st" ],
+[ 517, "su" ],
+[ 518, "sv" ],
+[ 519, "sw" ],
+[ 520, "sx" ],
+[ 521, "sy" ],
+[ 522, "sz" ],
+[ 523, "ta" ],
+[ 524, "tb" ],
+[ 525, "tc" ],
+[ 526, "td" ],
+[ 527, "te" ],
+[ 528, "tf" ],
+[ 529, "tg" ],
+[ 530, "th" ],
+[ 531, "ti" ],
+[ 532, "tj" ],
+[ 533, "tk" ],
+[ 534, "tl" ],
+[ 535, "tm" ],
+[ 536, "tn" ],
+[ 537, "to" ],
+[ 538, "tp" ],
+[ 539, "tq" ],
+[ 540, "tr" ],
+[ 541, "ts" ],
+[ 542, "tt" ],
+[ 543, "tu" ],
+[ 544, "tv" ],
+[ 545, "tw" ],
+[ 546, "tx" ],
+[ 547, "ty" ],
+[ 548, "tz" ],
+[ 549, "ua" ],
+[ 550, "ub" ],
+[ 551, "uc" ],
+[ 552, "ud" ],
+[ 553, "ue" ],
+[ 554, "uf" ],
+[ 555, "ug" ],
+[ 556, "uh" ],
+[ 557, "ui" ],
+[ 558, "uj" ],
+[ 559, "uk" ],
+[ 560, "ul" ],
+[ 561, "um" ],
+[ 562, "un" ],
+[ 563, "uo" ],
+[ 564, "up" ],
+[ 565, "uq" ],
+[ 566, "ur" ],
+[ 567, "us" ],
+[ 568, "ut" ],
+[ 569, "uu" ],
+[ 570, "uv" ],
+[ 571, "uw" ],
+[ 572, "ux" ],
+[ 573, "uy" ],
+[ 574, "uz" ],
+[ 575, "va" ],
+[ 576, "vb" ],
+[ 577, "vc" ],
+[ 578, "vd" ],
+[ 579, "ve" ],
+[ 580, "vf" ],
+[ 581, "vg" ],
+[ 582, "vh" ],
+[ 583, "vi" ],
+[ 584, "vj" ],
+[ 585, "vk" ],
+[ 586, "vl" ],
+[ 587, "vm" ],
+[ 588, "vn" ],
+[ 589, "vo" ],
+[ 590, "vp" ],
+[ 591, "vq" ],
+[ 592, "vr" ],
+[ 593, "vs" ],
+[ 594, "vt" ],
+[ 595, "vu" ],
+[ 596, "vv" ],
+[ 597, "vw" ],
+[ 598, "vx" ],
+[ 599, "vy" ],
+[ 600, "vz" ],
+[ 601, "wa" ],
+[ 602, "wb" ],
+[ 603, "wc" ],
+[ 604, "wd" ],
+[ 605, "we" ],
+[ 606, "wf" ],
+[ 607, "wg" ],
+[ 608, "wh" ],
+[ 609, "wi" ],
+[ 610, "wj" ],
+[ 611, "wk" ],
+[ 612, "wl" ],
+[ 613, "wm" ],
+[ 614, "wn" ],
+[ 615, "wo" ],
+[ 616, "wp" ],
+[ 617, "wq" ],
+[ 618, "wr" ],
+[ 619, "ws" ],
+[ 620, "wt" ],
+[ 621, "wu" ],
+[ 622, "wv" ],
+[ 623, "ww" ],
+[ 624, "wx" ],
+[ 625, "wy" ],
+[ 626, "wz" ],
+[ 627, "xa" ],
+[ 628, "xb" ],
+[ 629, "xc" ],
+[ 630, "xd" ],
+[ 631, "xe" ],
+[ 632, "xf" ],
+[ 633, "xg" ],
+[ 634, "xh" ],
+[ 635, "xi" ],
+[ 636, "xj" ],
+[ 637, "xk" ],
+[ 638, "xl" ],
+[ 639, "xm" ],
+[ 640, "xn" ],
+[ 641, "xo" ],
+[ 642, "xp" ],
+[ 643, "xq" ],
+[ 644, "xr" ],
+[ 645, "xs" ],
+[ 646, "xt" ],
+[ 647, "xu" ],
+[ 648, "xv" ],
+[ 649, "xw" ],
+[ 650, "xx" ],
+[ 651, "xy" ],
+[ 652, "xz" ],
+[ 653, "ya" ],
+[ 654, "yb" ],
+[ 655, "yc" ],
+[ 656, "yd" ],
+[ 657, "ye" ],
+[ 658, "yf" ],
+[ 659, "yg" ],
+[ 660, "yh" ],
+[ 661, "yi" ],
+[ 662, "yj" ],
+[ 663, "yk" ],
+[ 664, "yl" ],
+[ 665, "ym" ],
+[ 666, "yn" ],
+[ 667, "yo" ],
+[ 668, "yp" ],
+[ 669, "yq" ],
+[ 670, "yr" ],
+[ 671, "ys" ],
+[ 672, "yt" ],
+[ 673, "yu" ],
+[ 674, "yv" ],
+[ 675, "yw" ],
+[ 676, "yx" ],
+[ 677, "yy" ],
+[ 678, "yz" ],
+[ 679, "za" ],
+[ 680, "zb" ],
+[ 681, "zc" ],
+[ 682, "zd" ],
+[ 683, "ze" ],
+[ 684, "zf" ],
+[ 685, "zg" ],
+[ 686, "zh" ],
+[ 687, "zi" ],
+[ 688, "zj" ],
+[ 689, "zk" ],
+[ 690, "zl" ],
+[ 691, "zm" ],
+[ 692, "zn" ],
+[ 693, "zo" ],
+[ 694, "zp" ],
+[ 695, "zq" ],
+[ 696, "zr" ],
+[ 697, "zs" ],
+[ 698, "zt" ],
+[ 699, "zu" ],
+[ 700, "zv" ],
+[ 701, "zw" ],
+[ 702, "zx" ],
+[ 703, "zy" ],
+[ 704, "zz" ],
+[ 705, "aaa" ],
+[ 706, "aab" ],
+[ 707, "aac" ],
+[ 708, "aad" ],
+[ 709, "aae" ],
+[ 710, "aaf" ],
+[ 711, "aag" ],
+[ 712, "aah" ],
+[ 713, "aai" ],
+[ 714, "aaj" ],
+[ 715, "aak" ],
+[ 716, "aal" ],
+[ 717, "aam" ],
+[ 718, "aan" ],
+[ 719, "aao" ],
+[ 720, "aap" ],
+[ 721, "aaq" ],
+[ 722, "aar" ],
+[ 723, "aas" ],
+[ 724, "aat" ],
+[ 725, "aau" ],
+[ 726, "aav" ],
+[ 727, "aaw" ],
+[ 728, "aax" ],
+[ 729, "aay" ],
+[ 730, "aaz" ],
+[ 731, "aba" ],
+[ 732, "abb" ],
+[ 733, "abc" ],
+[ 734, "abd" ],
+[ 735, "abe" ],
+[ 736, "abf" ],
+[ 737, "abg" ],
+[ 738, "abh" ],
+[ 739, "abi" ],
+[ 740, "abj" ],
+[ 741, "abk" ],
+[ 742, "abl" ],
+[ 743, "abm" ],
+[ 744, "abn" ],
+[ 745, "abo" ],
+[ 746, "abp" ],
+[ 747, "abq" ],
+[ 748, "abr" ],
+[ 749, "abs" ],
+[ 750, "abt" ],
+[ 751, "abu" ],
+[ 752, "abv" ],
+[ 753, "abw" ],
+[ 754, "abx" ],
+[ 755, "aby" ],
+[ 756, "abz" ],
+[ 757, "aca" ],
+[ 758, "acb" ],
+[ 759, "acc" ],
+[ 760, "acd" ],
+[ 761, "ace" ],
+[ 762, "acf" ],
+[ 763, "acg" ],
+[ 764, "ach" ],
+[ 765, "aci" ],
+[ 766, "acj" ],
+[ 767, "ack" ],
+[ 768, "acl" ],
+[ 769, "acm" ],
+[ 770, "acn" ],
+[ 771, "aco" ],
+[ 772, "acp" ],
+[ 773, "acq" ],
+[ 774, "acr" ],
+[ 775, "acs" ],
+[ 776, "act" ],
+[ 777, "acu" ],
+[ 778, "acv" ],
+[ 779, "acw" ],
+[ 780, "acx" ],
+[ 781, "acy" ],
+[ 782, "acz" ],
+[ 783, "ada" ],
+[ 784, "adb" ],
+[ 785, "adc" ],
+[ 786, "add" ],
+[ 787, "ade" ],
+[ 788, "adf" ],
+[ 789, "adg" ],
+[ 790, "adh" ],
+[ 791, "adi" ],
+[ 792, "adj" ],
+[ 793, "adk" ],
+[ 794, "adl" ],
+[ 795, "adm" ],
+[ 796, "adn" ],
+[ 797, "ado" ],
+[ 798, "adp" ],
+[ 799, "adq" ],
+[ 800, "adr" ],
+[ 801, "ads" ],
+[ 802, "adt" ],
+[ 803, "adu" ],
+[ 804, "adv" ],
+[ 805, "adw" ],
+[ 806, "adx" ],
+[ 807, "ady" ],
+[ 808, "adz" ],
+[ 809, "aea" ],
+[ 810, "aeb" ],
+[ 811, "aec" ],
+[ 812, "aed" ],
+[ 813, "aee" ],
+[ 814, "aef" ],
+[ 815, "aeg" ],
+[ 816, "aeh" ],
+[ 817, "aei" ],
+[ 818, "aej" ],
+[ 819, "aek" ],
+[ 820, "ael" ],
+[ 821, "aem" ],
+[ 822, "aen" ],
+[ 823, "aeo" ],
+[ 824, "aep" ],
+[ 825, "aeq" ],
+[ 826, "aer" ],
+[ 827, "aes" ],
+[ 828, "aet" ],
+[ 829, "aeu" ],
+[ 830, "aev" ],
+[ 831, "aew" ],
+[ 832, "aex" ],
+[ 833, "aey" ],
+[ 834, "aez" ],
+[ 835, "afa" ],
+[ 836, "afb" ],
+[ 837, "afc" ],
+[ 838, "afd" ],
+[ 839, "afe" ],
+[ 840, "aff" ],
+[ 841, "afg" ],
+[ 842, "afh" ],
+[ 843, "afi" ],
+[ 844, "afj" ],
+[ 845, "afk" ],
+[ 846, "afl" ],
+[ 847, "afm" ],
+[ 848, "afn" ],
+[ 849, "afo" ],
+[ 850, "afp" ],
+[ 851, "afq" ],
+[ 852, "afr" ],
+[ 853, "afs" ],
+[ 854, "aft" ],
+[ 855, "afu" ],
+[ 856, "afv" ],
+[ 857, "afw" ],
+[ 858, "afx" ],
+[ 859, "afy" ],
+[ 860, "afz" ],
+[ 861, "aga" ],
+[ 862, "agb" ],
+[ 863, "agc" ],
+[ 864, "agd" ],
+[ 865, "age" ],
+[ 866, "agf" ],
+[ 867, "agg" ],
+[ 868, "agh" ],
+[ 869, "agi" ],
+[ 870, "agj" ],
+[ 871, "agk" ],
+[ 872, "agl" ],
+[ 873, "agm" ],
+[ 874, "agn" ],
+[ 875, "ago" ],
+[ 876, "agp" ],
+[ 877, "agq" ],
+[ 878, "agr" ],
+[ 879, "ags" ],
+[ 880, "agt" ],
+[ 881, "agu" ],
+[ 882, "agv" ],
+[ 883, "agw" ],
+[ 884, "agx" ],
+[ 885, "agy" ],
+[ 886, "agz" ],
+[ 887, "aha" ],
+[ 888, "ahb" ],
+[ 889, "ahc" ],
+[ 890, "ahd" ],
+[ 891, "ahe" ],
+[ 892, "ahf" ],
+[ 893, "ahg" ],
+[ 894, "ahh" ],
+[ 895, "ahi" ],
+[ 896, "ahj" ],
+[ 897, "ahk" ],
+[ 898, "ahl" ],
+[ 899, "ahm" ],
+[ 900, "ahn" ],
+[ 901, "aho" ],
+[ 902, "ahp" ],
+[ 903, "ahq" ],
+[ 904, "ahr" ],
+[ 905, "ahs" ],
+[ 906, "aht" ],
+[ 907, "ahu" ],
+[ 908, "ahv" ],
+[ 909, "ahw" ],
+[ 910, "ahx" ],
+[ 911, "ahy" ],
+[ 912, "ahz" ],
+[ 913, "aia" ],
+[ 914, "aib" ],
+[ 915, "aic" ],
+[ 916, "aid" ],
+[ 917, "aie" ],
+[ 918, "aif" ],
+[ 919, "aig" ],
+[ 920, "aih" ],
+[ 921, "aii" ],
+[ 922, "aij" ],
+[ 923, "aik" ],
+[ 924, "ail" ],
+[ 925, "aim" ],
+[ 926, "ain" ],
+[ 927, "aio" ],
+[ 928, "aip" ],
+[ 929, "aiq" ],
+[ 930, "air" ],
+[ 931, "ais" ],
+[ 932, "ait" ],
+[ 933, "aiu" ],
+[ 934, "aiv" ],
+[ 935, "aiw" ],
+[ 936, "aix" ],
+[ 937, "aiy" ],
+[ 938, "aiz" ],
+[ 939, "aja" ],
+[ 940, "ajb" ],
+[ 941, "ajc" ],
+[ 942, "ajd" ],
+[ 943, "aje" ],
+[ 944, "ajf" ],
+[ 945, "ajg" ],
+[ 946, "ajh" ],
+[ 947, "aji" ],
+[ 948, "ajj" ],
+[ 949, "ajk" ],
+[ 950, "ajl" ],
+[ 951, "ajm" ],
+[ 952, "ajn" ],
+[ 953, "ajo" ],
+[ 954, "ajp" ],
+[ 955, "ajq" ],
+[ 956, "ajr" ],
+[ 957, "ajs" ],
+[ 958, "ajt" ],
+[ 959, "aju" ],
+[ 960, "ajv" ],
+[ 961, "ajw" ],
+[ 962, "ajx" ],
+[ 963, "ajy" ],
+[ 964, "ajz" ],
+[ 965, "aka" ],
+[ 966, "akb" ],
+[ 967, "akc" ],
+[ 968, "akd" ],
+[ 969, "ake" ],
+[ 970, "akf" ],
+[ 971, "akg" ],
+[ 972, "akh" ],
+[ 973, "aki" ],
+[ 974, "akj" ],
+[ 975, "akk" ],
+[ 976, "akl" ],
+[ 977, "akm" ],
+[ 978, "akn" ],
+[ 979, "ako" ],
+[ 980, "akp" ],
+[ 981, "akq" ],
+[ 982, "akr" ],
+[ 983, "aks" ],
+[ 984, "akt" ],
+[ 985, "aku" ],
+[ 986, "akv" ],
+[ 987, "akw" ],
+[ 988, "akx" ],
+[ 989, "aky" ],
+[ 990, "akz" ],
+[ 991, "ala" ],
+[ 992, "alb" ],
+[ 993, "alc" ],
+[ 994, "ald" ],
+[ 995, "ale" ],
+[ 996, "alf" ],
+[ 997, "alg" ],
+[ 998, "alh" ],
+[ 999, "ali" ],
+[ 1000, "alj" ],
+[ 1001, "alk" ],
+[ 1002, "all" ],
+[ 1003, "alm" ],
+[ 1004, "aln" ],
+[ 1005, "alo" ],
+[ 1006, "alp" ],
+[ 1007, "alq" ],
+[ 1008, "alr" ],
+[ 1009, "als" ],
+[ 1010, "alt" ],
+[ 1011, "alu" ],
+[ 1012, "alv" ],
+[ 1013, "alw" ],
+[ 1014, "alx" ],
+[ 1015, "aly" ],
+[ 1016, "alz" ],
+[ 1017, "ama" ],
+[ 1018, "amb" ],
+[ 1019, "amc" ],
+[ 1020, "amd" ],
+[ 1021, "ame" ],
+[ 1022, "amf" ],
+[ 1023, "amg" ],
+[ 1024, "amh" ],
+[ 1025, "ami" ],
+[ 1026, "amj" ],
+[ 1027, "amk" ],
+[ 1028, "aml" ],
+[ 1029, "amm" ],
+[ 1030, "amn" ],
+[ 1031, "amo" ],
+[ 1032, "amp" ],
+[ 1033, "amq" ],
+[ 1034, "amr" ],
+[ 1035, "ams" ],
+[ 1036, "amt" ],
+[ 1037, "amu" ],
+[ 1038, "amv" ],
+[ 1039, "amw" ],
+[ 1040, "amx" ],
+[ 1041, "amy" ],
+[ 1042, "amz" ],
+[ 1043, "ana" ],
+[ 1044, "anb" ],
+[ 1045, "anc" ],
+[ 1046, "and" ],
+[ 1047, "ane" ],
+[ 1048, "anf" ],
+[ 1049, "ang" ],
+[ 1050, "anh" ],
+[ 1051, "ani" ],
+[ 1052, "anj" ],
+[ 1053, "ank" ],
+[ 1054, "anl" ],
+[ 1055, "anm" ],
+[ 1056, "ann" ],
+[ 1057, "ano" ],
+[ 1058, "anp" ],
+[ 1059, "anq" ],
+[ 1060, "anr" ],
+[ 1061, "ans" ],
+[ 1062, "ant" ],
+[ 1063, "anu" ],
+[ 1064, "anv" ],
+[ 1065, "anw" ],
+[ 1066, "anx" ],
+[ 1067, "any" ],
+[ 1068, "anz" ],
+[ 1069, "aoa" ],
+[ 1070, "aob" ],
+[ 1071, "aoc" ],
+[ 1072, "aod" ],
+[ 1073, "aoe" ],
+[ 1074, "aof" ],
+[ 1075, "aog" ],
+[ 1076, "aoh" ],
+[ 1077, "aoi" ],
+[ 1078, "aoj" ],
+[ 1079, "aok" ],
+[ 1080, "aol" ],
+[ 1081, "aom" ],
+[ 1082, "aon" ],
+[ 1083, "aoo" ],
+[ 1084, "aop" ],
+[ 1085, "aoq" ],
+[ 1086, "aor" ],
+[ 1087, "aos" ],
+[ 1088, "aot" ],
+[ 1089, "aou" ],
+[ 1090, "aov" ],
+[ 1091, "aow" ],
+[ 1092, "aox" ],
+[ 1093, "aoy" ],
+[ 1094, "aoz" ],
+[ 1095, "apa" ],
+[ 1096, "apb" ],
+[ 1097, "apc" ],
+[ 1098, "apd" ],
+[ 1099, "ape" ],
+[ 1100, "apf" ],
+[ 1101, "apg" ],
+[ 1102, "aph" ],
+[ 1103, "api" ],
+[ 1104, "apj" ],
+[ 1105, "apk" ],
+[ 1106, "apl" ],
+[ 1107, "apm" ],
+[ 1108, "apn" ],
+[ 1109, "apo" ],
+[ 1110, "app" ],
+[ 1111, "apq" ],
+[ 1112, "apr" ],
+[ 1113, "aps" ],
+[ 1114, "apt" ],
+[ 1115, "apu" ],
+[ 1116, "apv" ],
+[ 1117, "apw" ],
+[ 1118, "apx" ],
+[ 1119, "apy" ],
+[ 1120, "apz" ],
+[ 1121, "aqa" ],
+[ 1122, "aqb" ],
+[ 1123, "aqc" ],
+[ 1124, "aqd" ],
+[ 1125, "aqe" ],
+[ 1126, "aqf" ],
+[ 1127, "aqg" ],
+[ 1128, "aqh" ],
+[ 1129, "aqi" ],
+[ 1130, "aqj" ],
+[ 1131, "aqk" ],
+[ 1132, "aql" ],
+[ 1133, "aqm" ],
+[ 1134, "aqn" ],
+[ 1135, "aqo" ],
+[ 1136, "aqp" ],
+[ 1137, "aqq" ],
+[ 1138, "aqr" ],
+[ 1139, "aqs" ],
+[ 1140, "aqt" ],
+[ 1141, "aqu" ],
+[ 1142, "aqv" ],
+[ 1143, "aqw" ],
+[ 1144, "aqx" ],
+[ 1145, "aqy" ],
+[ 1146, "aqz" ],
+[ 1147, "ara" ],
+[ 1148, "arb" ],
+[ 1149, "arc" ],
+[ 1150, "ard" ],
+[ 1151, "are" ],
+[ 1152, "arf" ],
+[ 1153, "arg" ],
+[ 1154, "arh" ],
+[ 1155, "ari" ],
+[ 1156, "arj" ],
+[ 1157, "ark" ],
+[ 1158, "arl" ],
+[ 1159, "arm" ],
+[ 1160, "arn" ],
+[ 1161, "aro" ],
+[ 1162, "arp" ],
+[ 1163, "arq" ],
+[ 1164, "arr" ],
+[ 1165, "ars" ],
+[ 1166, "art" ],
+[ 1167, "aru" ],
+[ 1168, "arv" ],
+[ 1169, "arw" ],
+[ 1170, "arx" ],
+[ 1171, "ary" ],
+[ 1172, "arz" ],
+[ 1173, "asa" ],
+[ 1174, "asb" ],
+[ 1175, "asc" ],
+[ 1176, "asd" ],
+[ 1177, "ase" ],
+[ 1178, "asf" ],
+[ 1179, "asg" ],
+[ 1180, "ash" ],
+[ 1181, "asi" ],
+[ 1182, "asj" ],
+[ 1183, "ask" ],
+[ 1184, "asl" ],
+[ 1185, "asm" ],
+[ 1186, "asn" ],
+[ 1187, "aso" ],
+[ 1188, "asp" ],
+[ 1189, "asq" ],
+[ 1190, "asr" ],
+[ 1191, "ass" ],
+[ 1192, "ast" ],
+[ 1193, "asu" ],
+[ 1194, "asv" ],
+[ 1195, "asw" ],
+[ 1196, "asx" ],
+[ 1197, "asy" ],
+[ 1198, "asz" ],
+[ 1199, "ata" ],
+[ 1200, "atb" ],
+[ 1201, "atc" ],
+[ 1202, "atd" ],
+[ 1203, "ate" ],
+[ 1204, "atf" ],
+[ 1205, "atg" ],
+[ 1206, "ath" ],
+[ 1207, "ati" ],
+[ 1208, "atj" ],
+[ 1209, "atk" ],
+[ 1210, "atl" ],
+[ 1211, "atm" ],
+[ 1212, "atn" ],
+[ 1213, "ato" ],
+[ 1214, "atp" ],
+[ 1215, "atq" ],
+[ 1216, "atr" ],
+[ 1217, "ats" ],
+[ 1218, "att" ],
+[ 1219, "atu" ],
+[ 1220, "atv" ],
+[ 1221, "atw" ],
+[ 1222, "atx" ],
+[ 1223, "aty" ],
+[ 1224, "atz" ],
+[ 1225, "aua" ],
+[ 1226, "aub" ],
+[ 1227, "auc" ],
+[ 1228, "aud" ],
+[ 1229, "aue" ],
+[ 1230, "auf" ],
+[ 1231, "aug" ],
+[ 1232, "auh" ],
+[ 1233, "aui" ],
+[ 1234, "auj" ],
+[ 1235, "auk" ],
+[ 1236, "aul" ],
+[ 1237, "aum" ],
+[ 1238, "aun" ],
+[ 1239, "auo" ],
+[ 1240, "aup" ],
+[ 1241, "auq" ],
+[ 1242, "aur" ],
+[ 1243, "aus" ],
+[ 1244, "aut" ],
+[ 1245, "auu" ],
+[ 1246, "auv" ],
+[ 1247, "auw" ],
+[ 1248, "aux" ],
+[ 1249, "auy" ],
+[ 1250, "auz" ],
+[ 1251, "ava" ],
+[ 1252, "avb" ],
+[ 1253, "avc" ],
+[ 1254, "avd" ],
+[ 1255, "ave" ],
+[ 1256, "avf" ],
+[ 1257, "avg" ],
+[ 1258, "avh" ],
+[ 1259, "avi" ],
+[ 1260, "avj" ],
+[ 1261, "avk" ],
+[ 1262, "avl" ],
+[ 1263, "avm" ],
+[ 1264, "avn" ],
+[ 1265, "avo" ],
+[ 1266, "avp" ],
+[ 1267, "avq" ],
+[ 1268, "avr" ],
+[ 1269, "avs" ],
+[ 1270, "avt" ],
+[ 1271, "avu" ],
+[ 1272, "avv" ],
+[ 1273, "avw" ],
+[ 1274, "avx" ],
+[ 1275, "avy" ],
+[ 1276, "avz" ],
+[ 1277, "awa" ],
+[ 1278, "awb" ],
+[ 1279, "awc" ],
+[ 1280, "awd" ],
+[ 1281, "awe" ],
+[ 1282, "awf" ],
+[ 1283, "awg" ],
+[ 1284, "awh" ],
+[ 1285, "awi" ],
+[ 1286, "awj" ],
+[ 1287, "awk" ],
+[ 1288, "awl" ],
+[ 1289, "awm" ],
+[ 1290, "awn" ],
+[ 1291, "awo" ],
+[ 1292, "awp" ],
+[ 1293, "awq" ],
+[ 1294, "awr" ],
+[ 1295, "aws" ],
+[ 1296, "awt" ],
+[ 1297, "awu" ],
+[ 1298, "awv" ],
+[ 1299, "aww" ],
+[ 1300, "awx" ],
+[ 1301, "awy" ],
+[ 1302, "awz" ],
+[ 1303, "axa" ],
+[ 1304, "axb" ],
+[ 1305, "axc" ],
+[ 1306, "axd" ],
+[ 1307, "axe" ],
+[ 1308, "axf" ],
+[ 1309, "axg" ],
+[ 1310, "axh" ],
+[ 1311, "axi" ],
+[ 1312, "axj" ],
+[ 1313, "axk" ],
+[ 1314, "axl" ],
+[ 1315, "axm" ],
+[ 1316, "axn" ],
+[ 1317, "axo" ],
+[ 1318, "axp" ],
+[ 1319, "axq" ],
+[ 1320, "axr" ],
+[ 1321, "axs" ],
+[ 1322, "axt" ],
+[ 1323, "axu" ],
+[ 1324, "axv" ],
+[ 1325, "axw" ],
+[ 1326, "axx" ],
+[ 1327, "axy" ],
+[ 1328, "axz" ],
+[ 1329, "aya" ],
+[ 1330, "ayb" ],
+[ 1331, "ayc" ],
+[ 1332, "ayd" ],
+[ 1333, "aye" ],
+[ 1334, "ayf" ],
+[ 1335, "ayg" ],
+[ 1336, "ayh" ],
+[ 1337, "ayi" ],
+[ 1338, "ayj" ],
+[ 1339, "ayk" ],
+[ 1340, "ayl" ],
+[ 1341, "aym" ],
+[ 1342, "ayn" ],
+[ 1343, "ayo" ],
+[ 1344, "ayp" ],
+[ 1345, "ayq" ],
+[ 1346, "ayr" ],
+[ 1347, "ays" ],
+[ 1348, "ayt" ],
+[ 1349, "ayu" ],
+[ 1350, "ayv" ],
+[ 1351, "ayw" ],
+[ 1352, "ayx" ],
+[ 1353, "ayy" ],
+[ 1354, "ayz" ],
+[ 1355, "aza" ],
+[ 1356, "azb" ],
+[ 1357, "azc" ],
+[ 1358, "azd" ],
+[ 1359, "aze" ],
+[ 1360, "azf" ],
+[ 1361, "azg" ],
+[ 1362, "azh" ],
+[ 1363, "azi" ],
+[ 1364, "azj" ],
+[ 1365, "azk" ],
+[ 1366, "azl" ],
+[ 1367, "azm" ],
+[ 1368, "azn" ],
+[ 1369, "azo" ],
+[ 1370, "azp" ],
+[ 1371, "azq" ],
+[ 1372, "azr" ],
+[ 1373, "azs" ],
+[ 1374, "azt" ],
+[ 1375, "azu" ],
+[ 1376, "azv" ],
+[ 1377, "azw" ],
+[ 1378, "azx" ],
+[ 1379, "azy" ],
+[ 1380, "azz" ],
+[ 1381, "baa" ],
+[ 1382, "bab" ],
+[ 1383, "bac" ],
+[ 1384, "bad" ],
+[ 1385, "bae" ],
+[ 1386, "baf" ],
+[ 1387, "bag" ],
+[ 1388, "bah" ],
+[ 1389, "bai" ],
+[ 1390, "baj" ],
+[ 1391, "bak" ],
+[ 1392, "bal" ],
+[ 1393, "bam" ],
+[ 1394, "ban" ],
+[ 1395, "bao" ],
+[ 1396, "bap" ],
+[ 1397, "baq" ],
+[ 1398, "bar" ],
+[ 1399, "bas" ],
+[ 1400, "bat" ],
+[ 1401, "bau" ],
+[ 1402, "bav" ],
+[ 1403, "baw" ],
+[ 1404, "bax" ],
+[ 1405, "bay" ],
+[ 1406, "baz" ],
+[ 1407, "bba" ],
+[ 1408, "bbb" ],
+[ 1409, "bbc" ],
+[ 1410, "bbd" ],
+[ 1411, "bbe" ],
+[ 1412, "bbf" ],
+[ 1413, "bbg" ],
+[ 1414, "bbh" ],
+[ 1415, "bbi" ],
+[ 1416, "bbj" ],
+[ 1417, "bbk" ],
+[ 1418, "bbl" ],
+[ 1419, "bbm" ],
+[ 1420, "bbn" ],
+[ 1421, "bbo" ],
+[ 1422, "bbp" ],
+[ 1423, "bbq" ],
+[ 1424, "bbr" ],
+[ 1425, "bbs" ],
+[ 1426, "bbt" ],
+[ 1427, "bbu" ],
+[ 1428, "bbv" ],
+[ 1429, "bbw" ],
+[ 1430, "bbx" ],
+[ 1431, "bby" ],
+[ 1432, "bbz" ],
+[ 1433, "bca" ],
+[ 1434, "bcb" ],
+[ 1435, "bcc" ],
+[ 1436, "bcd" ],
+[ 1437, "bce" ],
+[ 1438, "bcf" ],
+[ 1439, "bcg" ],
+[ 1440, "bch" ],
+[ 1441, "bci" ],
+[ 1442, "bcj" ],
+[ 1443, "bck" ],
+[ 1444, "bcl" ],
+[ 1445, "bcm" ],
+[ 1446, "bcn" ],
+[ 1447, "bco" ],
+[ 1448, "bcp" ],
+[ 1449, "bcq" ],
+[ 1450, "bcr" ],
+[ 1451, "bcs" ],
+[ 1452, "bct" ],
+[ 1453, "bcu" ],
+[ 1454, "bcv" ],
+[ 1455, "bcw" ],
+[ 1456, "bcx" ],
+[ 1457, "bcy" ],
+[ 1458, "bcz" ],
+[ 1459, "bda" ],
+[ 1460, "bdb" ],
+[ 1461, "bdc" ],
+[ 1462, "bdd" ],
+[ 1463, "bde" ],
+[ 1464, "bdf" ],
+[ 1465, "bdg" ],
+[ 1466, "bdh" ],
+[ 1467, "bdi" ],
+[ 1468, "bdj" ],
+[ 1469, "bdk" ],
+[ 1470, "bdl" ],
+[ 1471, "bdm" ],
+[ 1472, "bdn" ],
+[ 1473, "bdo" ],
+[ 1474, "bdp" ],
+[ 1475, "bdq" ],
+[ 1476, "bdr" ],
+[ 1477, "bds" ],
+[ 1478, "bdt" ],
+[ 1479, "bdu" ],
+[ 1480, "bdv" ],
+[ 1481, "bdw" ],
+[ 1482, "bdx" ],
+[ 1483, "bdy" ],
+[ 1484, "bdz" ],
+[ 1485, "bea" ],
+[ 1486, "beb" ],
+[ 1487, "bec" ],
+[ 1488, "bed" ],
+[ 1489, "bee" ],
+[ 1490, "bef" ],
+[ 1491, "beg" ],
+[ 1492, "beh" ],
+[ 1493, "bei" ],
+[ 1494, "bej" ],
+[ 1495, "bek" ],
+[ 1496, "bel" ],
+[ 1497, "bem" ],
+[ 1498, "ben" ],
+[ 1499, "beo" ],
+[ 1500, "bep" ],
+[ 1501, "beq" ],
+[ 1502, "ber" ],
+[ 1503, "bes" ],
+[ 1504, "bet" ],
+[ 1505, "beu" ],
+[ 1506, "bev" ],
+[ 1507, "bew" ],
+[ 1508, "bex" ],
+[ 1509, "bey" ],
+[ 1510, "bez" ],
+[ 1511, "bfa" ],
+[ 1512, "bfb" ],
+[ 1513, "bfc" ],
+[ 1514, "bfd" ],
+[ 1515, "bfe" ],
+[ 1516, "bff" ],
+[ 1517, "bfg" ],
+[ 1518, "bfh" ],
+[ 1519, "bfi" ],
+[ 1520, "bfj" ],
+[ 1521, "bfk" ],
+[ 1522, "bfl" ],
+[ 1523, "bfm" ],
+[ 1524, "bfn" ],
+[ 1525, "bfo" ],
+[ 1526, "bfp" ],
+[ 1527, "bfq" ],
+[ 1528, "bfr" ],
+[ 1529, "bfs" ],
+[ 1530, "bft" ],
+[ 1531, "bfu" ],
+[ 1532, "bfv" ],
+[ 1533, "bfw" ],
+[ 1534, "bfx" ],
+[ 1535, "bfy" ],
+[ 1536, "bfz" ],
+[ 1537, "bga" ],
+[ 1538, "bgb" ],
+[ 1539, "bgc" ],
+[ 1540, "bgd" ],
+[ 1541, "bge" ],
+[ 1542, "bgf" ],
+[ 1543, "bgg" ],
+[ 1544, "bgh" ],
+[ 1545, "bgi" ],
+[ 1546, "bgj" ],
+[ 1547, "bgk" ],
+[ 1548, "bgl" ],
+[ 1549, "bgm" ],
+[ 1550, "bgn" ],
+[ 1551, "bgo" ],
+[ 1552, "bgp" ],
+[ 1553, "bgq" ],
+[ 1554, "bgr" ],
+[ 1555, "bgs" ],
+[ 1556, "bgt" ],
+[ 1557, "bgu" ],
+[ 1558, "bgv" ],
+[ 1559, "bgw" ],
+[ 1560, "bgx" ],
+[ 1561, "bgy" ],
+[ 1562, "bgz" ],
+[ 1563, "bha" ],
+[ 1564, "bhb" ],
+[ 1565, "bhc" ],
+[ 1566, "bhd" ],
+[ 1567, "bhe" ],
+[ 1568, "bhf" ],
+[ 1569, "bhg" ],
+[ 1570, "bhh" ],
+[ 1571, "bhi" ],
+[ 1572, "bhj" ],
+[ 1573, "bhk" ],
+[ 1574, "bhl" ],
+[ 1575, "bhm" ],
+[ 1576, "bhn" ],
+[ 1577, "bho" ],
+[ 1578, "bhp" ],
+[ 1579, "bhq" ],
+[ 1580, "bhr" ],
+[ 1581, "bhs" ],
+[ 1582, "bht" ],
+[ 1583, "bhu" ],
+[ 1584, "bhv" ],
+[ 1585, "bhw" ],
+[ 1586, "bhx" ],
+[ 1587, "bhy" ],
+[ 1588, "bhz" ],
+[ 1589, "bia" ],
+[ 1590, "bib" ],
+[ 1591, "bic" ],
+[ 1592, "bid" ],
+[ 1593, "bie" ],
+[ 1594, "bif" ],
+[ 1595, "big" ],
+[ 1596, "bih" ],
+[ 1597, "bii" ],
+[ 1598, "bij" ],
+[ 1599, "bik" ],
+[ 1600, "bil" ],
+[ 1601, "bim" ],
+[ 1602, "bin" ],
+[ 1603, "bio" ],
+[ 1604, "bip" ],
+[ 1605, "biq" ],
+[ 1606, "bir" ],
+[ 1607, "bis" ],
+[ 1608, "bit" ],
+[ 1609, "biu" ],
+[ 1610, "biv" ],
+[ 1611, "biw" ],
+[ 1612, "bix" ],
+[ 1613, "biy" ],
+[ 1614, "biz" ],
+[ 1615, "bja" ],
+[ 1616, "bjb" ],
+[ 1617, "bjc" ],
+[ 1618, "bjd" ],
+[ 1619, "bje" ],
+[ 1620, "bjf" ],
+[ 1621, "bjg" ],
+[ 1622, "bjh" ],
+[ 1623, "bji" ],
+[ 1624, "bjj" ],
+[ 1625, "bjk" ],
+[ 1626, "bjl" ],
+[ 1627, "bjm" ],
+[ 1628, "bjn" ],
+[ 1629, "bjo" ],
+[ 1630, "bjp" ],
+[ 1631, "bjq" ],
+[ 1632, "bjr" ],
+[ 1633, "bjs" ],
+[ 1634, "bjt" ],
+[ 1635, "bju" ],
+[ 1636, "bjv" ],
+[ 1637, "bjw" ],
+[ 1638, "bjx" ],
+[ 1639, "bjy" ],
+[ 1640, "bjz" ],
+[ 1641, "bka" ],
+[ 1642, "bkb" ],
+[ 1643, "bkc" ],
+[ 1644, "bkd" ],
+[ 1645, "bke" ],
+[ 1646, "bkf" ],
+[ 1647, "bkg" ],
+[ 1648, "bkh" ],
+[ 1649, "bki" ],
+[ 1650, "bkj" ],
+[ 1651, "bkk" ],
+[ 1652, "bkl" ],
+[ 1653, "bkm" ],
+[ 1654, "bkn" ],
+[ 1655, "bko" ],
+[ 1656, "bkp" ],
+[ 1657, "bkq" ],
+[ 1658, "bkr" ],
+[ 1659, "bks" ],
+[ 1660, "bkt" ],
+[ 1661, "bku" ],
+[ 1662, "bkv" ],
+[ 1663, "bkw" ],
+[ 1664, "bkx" ],
+[ 1665, "bky" ],
+[ 1666, "bkz" ],
+[ 1667, "bla" ],
+[ 1668, "blb" ],
+[ 1669, "blc" ],
+[ 1670, "bld" ],
+[ 1671, "ble" ],
+[ 1672, "blf" ],
+[ 1673, "blg" ],
+[ 1674, "blh" ],
+[ 1675, "bli" ],
+[ 1676, "blj" ],
+[ 1677, "blk" ],
+[ 1678, "bll" ],
+[ 1679, "blm" ],
+[ 1680, "bln" ],
+[ 1681, "blo" ],
+[ 1682, "blp" ],
+[ 1683, "blq" ],
+[ 1684, "blr" ],
+[ 1685, "bls" ],
+[ 1686, "blt" ],
+[ 1687, "blu" ],
+[ 1688, "blv" ],
+[ 1689, "blw" ],
+[ 1690, "blx" ],
+[ 1691, "bly" ],
+[ 1692, "blz" ],
+[ 1693, "bma" ],
+[ 1694, "bmb" ],
+[ 1695, "bmc" ],
+[ 1696, "bmd" ],
+[ 1697, "bme" ],
+[ 1698, "bmf" ],
+[ 1699, "bmg" ],
+[ 1700, "bmh" ],
+[ 1701, "bmi" ],
+[ 1702, "bmj" ],
+[ 1703, "bmk" ],
+[ 1704, "bml" ],
+[ 1705, "bmm" ],
+[ 1706, "bmn" ],
+[ 1707, "bmo" ],
+[ 1708, "bmp" ],
+[ 1709, "bmq" ],
+[ 1710, "bmr" ],
+[ 1711, "bms" ],
+[ 1712, "bmt" ],
+[ 1713, "bmu" ],
+[ 1714, "bmv" ],
+[ 1715, "bmw" ],
+[ 1716, "bmx" ],
+[ 1717, "bmy" ],
+[ 1718, "bmz" ],
+[ 1719, "bna" ],
+[ 1720, "bnb" ],
+[ 1721, "bnc" ],
+[ 1722, "bnd" ],
+[ 1723, "bne" ],
+[ 1724, "bnf" ],
+[ 1725, "bng" ],
+[ 1726, "bnh" ],
+[ 1727, "bni" ],
+[ 1728, "bnj" ],
+[ 1729, "bnk" ],
+[ 1730, "bnl" ],
+[ 1731, "bnm" ],
+[ 1732, "bnn" ],
+[ 1733, "bno" ],
+[ 1734, "bnp" ],
+[ 1735, "bnq" ],
+[ 1736, "bnr" ],
+[ 1737, "bns" ],
+[ 1738, "bnt" ],
+[ 1739, "bnu" ],
+[ 1740, "bnv" ],
+[ 1741, "bnw" ],
+[ 1742, "bnx" ],
+[ 1743, "bny" ],
+[ 1744, "bnz" ],
+[ 1745, "boa" ],
+[ 1746, "bob" ],
+[ 1747, "boc" ],
+[ 1748, "bod" ],
+[ 1749, "boe" ],
+[ 1750, "bof" ],
+[ 1751, "bog" ],
+[ 1752, "boh" ],
+[ 1753, "boi" ],
+[ 1754, "boj" ],
+[ 1755, "bok" ],
+[ 1756, "bol" ],
+[ 1757, "bom" ],
+[ 1758, "bon" ],
+[ 1759, "boo" ],
+[ 1760, "bop" ],
+[ 1761, "boq" ],
+[ 1762, "bor" ],
+[ 1763, "bos" ],
+[ 1764, "bot" ],
+[ 1765, "bou" ],
+[ 1766, "bov" ],
+[ 1767, "bow" ],
+[ 1768, "box" ],
+[ 1769, "boy" ],
+[ 1770, "boz" ],
+[ 1771, "bpa" ],
+[ 1772, "bpb" ],
+[ 1773, "bpc" ],
+[ 1774, "bpd" ],
+[ 1775, "bpe" ],
+[ 1776, "bpf" ],
+[ 1777, "bpg" ],
+[ 1778, "bph" ],
+[ 1779, "bpi" ],
+[ 1780, "bpj" ],
+[ 1781, "bpk" ],
+[ 1782, "bpl" ],
+[ 1783, "bpm" ],
+[ 1784, "bpn" ],
+[ 1785, "bpo" ],
+[ 1786, "bpp" ],
+[ 1787, "bpq" ],
+[ 1788, "bpr" ],
+[ 1789, "bps" ],
+[ 1790, "bpt" ],
+[ 1791, "bpu" ],
+[ 1792, "bpv" ],
+[ 1793, "bpw" ],
+[ 1794, "bpx" ],
+[ 1795, "bpy" ],
+[ 1796, "bpz" ],
+[ 1797, "bqa" ],
+[ 1798, "bqb" ],
+[ 1799, "bqc" ],
+[ 1800, "bqd" ],
+[ 1801, "bqe" ],
+[ 1802, "bqf" ],
+[ 1803, "bqg" ],
+[ 1804, "bqh" ],
+[ 1805, "bqi" ],
+[ 1806, "bqj" ],
+[ 1807, "bqk" ],
+[ 1808, "bql" ],
+[ 1809, "bqm" ],
+[ 1810, "bqn" ],
+[ 1811, "bqo" ],
+[ 1812, "bqp" ],
+[ 1813, "bqq" ],
+[ 1814, "bqr" ],
+[ 1815, "bqs" ],
+[ 1816, "bqt" ],
+[ 1817, "bqu" ],
+[ 1818, "bqv" ],
+[ 1819, "bqw" ],
+[ 1820, "bqx" ],
+[ 1821, "bqy" ],
+[ 1822, "bqz" ],
+[ 1823, "bra" ],
+[ 1824, "brb" ],
+[ 1825, "brc" ],
+[ 1826, "brd" ],
+[ 1827, "bre" ],
+[ 1828, "brf" ],
+[ 1829, "brg" ],
+[ 1830, "brh" ],
+[ 1831, "bri" ],
+[ 1832, "brj" ],
+[ 1833, "brk" ],
+[ 1834, "brl" ],
+[ 1835, "brm" ],
+[ 1836, "brn" ],
+[ 1837, "bro" ],
+[ 1838, "brp" ],
+[ 1839, "brq" ],
+[ 1840, "brr" ],
+[ 1841, "brs" ],
+[ 1842, "brt" ],
+[ 1843, "bru" ],
+[ 1844, "brv" ],
+[ 1845, "brw" ],
+[ 1846, "brx" ],
+[ 1847, "bry" ],
+[ 1848, "brz" ],
+[ 1849, "bsa" ],
+[ 1850, "bsb" ],
+[ 1851, "bsc" ],
+[ 1852, "bsd" ],
+[ 1853, "bse" ],
+[ 1854, "bsf" ],
+[ 1855, "bsg" ],
+[ 1856, "bsh" ],
+[ 1857, "bsi" ],
+[ 1858, "bsj" ],
+[ 1859, "bsk" ],
+[ 1860, "bsl" ],
+[ 1861, "bsm" ],
+[ 1862, "bsn" ],
+[ 1863, "bso" ],
+[ 1864, "bsp" ],
+[ 1865, "bsq" ],
+[ 1866, "bsr" ],
+[ 1867, "bss" ],
+[ 1868, "bst" ],
+[ 1869, "bsu" ],
+[ 1870, "bsv" ],
+[ 1871, "bsw" ],
+[ 1872, "bsx" ],
+[ 1873, "bsy" ],
+[ 1874, "bsz" ],
+[ 1875, "bta" ],
+[ 1876, "btb" ],
+[ 1877, "btc" ],
+[ 1878, "btd" ],
+[ 1879, "bte" ],
+[ 1880, "btf" ],
+[ 1881, "btg" ],
+[ 1882, "bth" ],
+[ 1883, "bti" ],
+[ 1884, "btj" ],
+[ 1885, "btk" ],
+[ 1886, "btl" ],
+[ 1887, "btm" ],
+[ 1888, "btn" ],
+[ 1889, "bto" ],
+[ 1890, "btp" ],
+[ 1891, "btq" ],
+[ 1892, "btr" ],
+[ 1893, "bts" ],
+[ 1894, "btt" ],
+[ 1895, "btu" ],
+[ 1896, "btv" ],
+[ 1897, "btw" ],
+[ 1898, "btx" ],
+[ 1899, "bty" ],
+[ 1900, "btz" ],
+[ 1901, "bua" ],
+[ 1902, "bub" ],
+[ 1903, "buc" ],
+[ 1904, "bud" ],
+[ 1905, "bue" ],
+[ 1906, "buf" ],
+[ 1907, "bug" ],
+[ 1908, "buh" ],
+[ 1909, "bui" ],
+[ 1910, "buj" ],
+[ 1911, "buk" ],
+[ 1912, "bul" ],
+[ 1913, "bum" ],
+[ 1914, "bun" ],
+[ 1915, "buo" ],
+[ 1916, "bup" ],
+[ 1917, "buq" ],
+[ 1918, "bur" ],
+[ 1919, "bus" ],
+[ 1920, "but" ],
+[ 1921, "buu" ],
+[ 1922, "buv" ],
+[ 1923, "buw" ],
+[ 1924, "bux" ],
+[ 1925, "buy" ],
+[ 1926, "buz" ],
+[ 1927, "bva" ],
+[ 1928, "bvb" ],
+[ 1929, "bvc" ],
+[ 1930, "bvd" ],
+[ 1931, "bve" ],
+[ 1932, "bvf" ],
+[ 1933, "bvg" ],
+[ 1934, "bvh" ],
+[ 1935, "bvi" ],
+[ 1936, "bvj" ],
+[ 1937, "bvk" ],
+[ 1938, "bvl" ],
+[ 1939, "bvm" ],
+[ 1940, "bvn" ],
+[ 1941, "bvo" ],
+[ 1942, "bvp" ],
+[ 1943, "bvq" ],
+[ 1944, "bvr" ],
+[ 1945, "bvs" ],
+[ 1946, "bvt" ],
+[ 1947, "bvu" ],
+[ 1948, "bvv" ],
+[ 1949, "bvw" ],
+[ 1950, "bvx" ],
+[ 1951, "bvy" ],
+[ 1952, "bvz" ],
+[ 1953, "bwa" ],
+[ 1954, "bwb" ],
+[ 1955, "bwc" ],
+[ 1956, "bwd" ],
+[ 1957, "bwe" ],
+[ 1958, "bwf" ],
+[ 1959, "bwg" ],
+[ 1960, "bwh" ],
+[ 1961, "bwi" ],
+[ 1962, "bwj" ],
+[ 1963, "bwk" ],
+[ 1964, "bwl" ],
+[ 1965, "bwm" ],
+[ 1966, "bwn" ],
+[ 1967, "bwo" ],
+[ 1968, "bwp" ],
+[ 1969, "bwq" ],
+[ 1970, "bwr" ],
+[ 1971, "bws" ],
+[ 1972, "bwt" ],
+[ 1973, "bwu" ],
+[ 1974, "bwv" ],
+[ 1975, "bww" ],
+[ 1976, "bwx" ],
+[ 1977, "bwy" ],
+[ 1978, "bwz" ],
+[ 1979, "bxa" ],
+[ 1980, "bxb" ],
+[ 1981, "bxc" ],
+[ 1982, "bxd" ],
+[ 1983, "bxe" ],
+[ 1984, "bxf" ],
+[ 1985, "bxg" ],
+[ 1986, "bxh" ],
+[ 1987, "bxi" ],
+[ 1988, "bxj" ],
+[ 1989, "bxk" ],
+[ 1990, "bxl" ],
+[ 1991, "bxm" ],
+[ 1992, "bxn" ],
+[ 1993, "bxo" ],
+[ 1994, "bxp" ],
+[ 1995, "bxq" ],
+[ 1996, "bxr" ],
+[ 1997, "bxs" ],
+[ 1998, "bxt" ],
+[ 1999, "bxu" ],
+[ 2000, "bxv" ],
+[ 2001, "bxw" ],
+[ 2002, "bxx" ],
+[ 2003, "bxy" ],
+[ 2004, "bxz" ],
+[ 2005, "bya" ],
+[ 2006, "byb" ],
+[ 2007, "byc" ],
+[ 2008, "byd" ],
+[ 2009, "bye" ],
+[ 2010, "byf" ],
+[ 2011, "byg" ],
+[ 2012, "byh" ],
+[ 2013, "byi" ],
+[ 2014, "byj" ],
+[ 2015, "byk" ],
+[ 2016, "byl" ],
+[ 2017, "bym" ],
+[ 2018, "byn" ],
+[ 2019, "byo" ],
+[ 2020, "byp" ],
+[ 2021, "byq" ],
+[ 2022, "byr" ],
+[ 2023, "bys" ],
+[ 2024, "byt" ],
+[ 2025, "byu" ],
+[ 2026, "byv" ],
+[ 2027, "byw" ],
+[ 2028, "byx" ],
+[ 2029, "byy" ],
+[ 2030, "byz" ],
+[ 2031, "bza" ],
+[ 2032, "bzb" ],
+[ 2033, "bzc" ],
+[ 2034, "bzd" ],
+[ 2035, "bze" ],
+[ 2036, "bzf" ],
+[ 2037, "bzg" ],
+[ 2038, "bzh" ],
+[ 2039, "bzi" ],
+[ 2040, "bzj" ],
+[ 2041, "bzk" ],
+[ 2042, "bzl" ],
+[ 2043, "bzm" ],
+[ 2044, "bzn" ],
+[ 2045, "bzo" ],
+[ 2046, "bzp" ],
+[ 2047, "bzq" ],
+[ 2048, "bzr" ],
+[ 2049, "bzs" ],
+[ 2050, "bzt" ],
+[ 2051, "bzu" ],
+[ 2052, "bzv" ],
+[ 2053, "bzw" ],
+[ 2054, "bzx" ],
+[ 2055, "bzy" ],
+[ 2056, "bzz" ],
+[ 2057, "caa" ],
+[ 2058, "cab" ],
+[ 2059, "cac" ],
+[ 2060, "cad" ],
+[ 2061, "cae" ],
+[ 2062, "caf" ],
+[ 2063, "cag" ],
+[ 2064, "cah" ],
+[ 2065, "cai" ],
+[ 2066, "caj" ],
+[ 2067, "cak" ],
+[ 2068, "cal" ],
+[ 2069, "cam" ],
+[ 2070, "can" ],
+[ 2071, "cao" ],
+[ 2072, "cap" ],
+[ 2073, "caq" ],
+[ 2074, "car" ],
+[ 2075, "cas" ],
+[ 2076, "cat" ],
+[ 2077, "cau" ],
+[ 2078, "cav" ],
+[ 2079, "caw" ],
+[ 2080, "cax" ],
+[ 2081, "cay" ],
+[ 2082, "caz" ],
+[ 2083, "cba" ],
+[ 2084, "cbb" ],
+[ 2085, "cbc" ],
+[ 2086, "cbd" ],
+[ 2087, "cbe" ],
+[ 2088, "cbf" ],
+[ 2089, "cbg" ],
+[ 2090, "cbh" ],
+[ 2091, "cbi" ],
+[ 2092, "cbj" ],
+[ 2093, "cbk" ],
+[ 2094, "cbl" ],
+[ 2095, "cbm" ],
+[ 2096, "cbn" ],
+[ 2097, "cbo" ],
+[ 2098, "cbp" ],
+[ 2099, "cbq" ],
+[ 2100, "cbr" ],
+[ 2101, "cbs" ],
+[ 2102, "cbt" ],
+[ 2103, "cbu" ],
+[ 2104, "cbv" ],
+[ 2105, "cbw" ],
+[ 2106, "cbx" ],
+[ 2107, "cby" ],
+[ 2108, "cbz" ],
+[ 2109, "cca" ],
+[ 2110, "ccb" ],
+[ 2111, "ccc" ],
+[ 2112, "ccd" ],
+[ 2113, "cce" ],
+[ 2114, "ccf" ],
+[ 2115, "ccg" ],
+[ 2116, "cch" ],
+[ 2117, "cci" ],
+[ 2118, "ccj" ],
+[ 2119, "cck" ],
+[ 2120, "ccl" ],
+[ 2121, "ccm" ],
+[ 2122, "ccn" ],
+[ 2123, "cco" ],
+[ 2124, "ccp" ],
+[ 2125, "ccq" ],
+[ 2126, "ccr" ],
+[ 2127, "ccs" ],
+[ 2128, "cct" ],
+[ 2129, "ccu" ],
+[ 2130, "ccv" ],
+[ 2131, "ccw" ],
+[ 2132, "ccx" ],
+[ 2133, "ccy" ],
+[ 2134, "ccz" ],
+[ 2135, "cda" ],
+[ 2136, "cdb" ],
+[ 2137, "cdc" ],
+[ 2138, "cdd" ],
+[ 2139, "cde" ],
+[ 2140, "cdf" ],
+[ 2141, "cdg" ],
+[ 2142, "cdh" ],
+[ 2143, "cdi" ],
+[ 2144, "cdj" ],
+[ 2145, "cdk" ],
+[ 2146, "cdl" ],
+[ 2147, "cdm" ],
+[ 2148, "cdn" ],
+[ 2149, "cdo" ],
+[ 2150, "cdp" ],
+[ 2151, "cdq" ],
+[ 2152, "cdr" ],
+[ 2153, "cds" ],
+[ 2154, "cdt" ],
+[ 2155, "cdu" ],
+[ 2156, "cdv" ],
+[ 2157, "cdw" ],
+[ 2158, "cdx" ],
+[ 2159, "cdy" ],
+[ 2160, "cdz" ],
+[ 2161, "cea" ],
+[ 2162, "ceb" ],
+[ 2163, "cec" ],
+[ 2164, "ced" ],
+[ 2165, "cee" ],
+[ 2166, "cef" ],
+[ 2167, "ceg" ],
+[ 2168, "ceh" ],
+[ 2169, "cei" ],
+[ 2170, "cej" ],
+[ 2171, "cek" ],
+[ 2172, "cel" ],
+[ 2173, "cem" ],
+[ 2174, "cen" ],
+[ 2175, "ceo" ],
+[ 2176, "cep" ],
+[ 2177, "ceq" ],
+[ 2178, "cer" ],
+[ 2179, "ces" ],
+[ 2180, "cet" ],
+[ 2181, "ceu" ],
+[ 2182, "cev" ],
+[ 2183, "cew" ],
+[ 2184, "cex" ],
+[ 2185, "cey" ],
+[ 2186, "cez" ],
+[ 2187, "cfa" ],
+[ 2188, "cfb" ],
+[ 2189, "cfc" ],
+[ 2190, "cfd" ],
+[ 2191, "cfe" ],
+[ 2192, "cff" ],
+[ 2193, "cfg" ],
+[ 2194, "cfh" ],
+[ 2195, "cfi" ],
+[ 2196, "cfj" ],
+[ 2197, "cfk" ],
+[ 2198, "cfl" ],
+[ 2199, "cfm" ],
+[ 2200, "cfn" ],
+[ 2201, "cfo" ],
+[ 2202, "cfp" ],
+[ 2203, "cfq" ],
+[ 2204, "cfr" ],
+[ 2205, "cfs" ],
+[ 2206, "cft" ],
+[ 2207, "cfu" ],
+[ 2208, "cfv" ],
+[ 2209, "cfw" ],
+[ 2210, "cfx" ],
+[ 2211, "cfy" ],
+[ 2212, "cfz" ],
+[ 2213, "cga" ],
+[ 2214, "cgb" ],
+[ 2215, "cgc" ],
+[ 2216, "cgd" ],
+[ 2217, "cge" ],
+[ 2218, "cgf" ],
+[ 2219, "cgg" ],
+[ 2220, "cgh" ],
+[ 2221, "cgi" ],
+[ 2222, "cgj" ],
+[ 2223, "cgk" ],
+[ 2224, "cgl" ],
+[ 2225, "cgm" ],
+[ 2226, "cgn" ],
+[ 2227, "cgo" ],
+[ 2228, "cgp" ],
+[ 2229, "cgq" ],
+[ 2230, "cgr" ],
+[ 2231, "cgs" ],
+[ 2232, "cgt" ],
+[ 2233, "cgu" ],
+[ 2234, "cgv" ],
+[ 2235, "cgw" ],
+[ 2236, "cgx" ],
+[ 2237, "cgy" ],
+[ 2238, "cgz" ],
+[ 2239, "cha" ],
+[ 2240, "chb" ],
+[ 2241, "chc" ],
+[ 2242, "chd" ],
+[ 2243, "che" ],
+[ 2244, "chf" ],
+[ 2245, "chg" ],
+[ 2246, "chh" ],
+[ 2247, "chi" ],
+[ 2248, "chj" ],
+[ 2249, "chk" ],
+[ 2250, "chl" ],
+[ 2251, "chm" ],
+[ 2252, "chn" ],
+[ 2253, "cho" ],
+[ 2254, "chp" ],
+[ 2255, "chq" ],
+[ 2256, "chr" ],
+[ 2257, "chs" ],
+[ 2258, "cht" ],
+[ 2259, "chu" ],
+[ 2260, "chv" ],
+[ 2261, "chw" ],
+[ 2262, "chx" ],
+[ 2263, "chy" ],
+[ 2264, "chz" ],
+[ 2265, "cia" ],
+[ 2266, "cib" ],
+[ 2267, "cic" ],
+[ 2268, "cid" ],
+[ 2269, "cie" ],
+[ 2270, "cif" ],
+[ 2271, "cig" ],
+[ 2272, "cih" ],
+[ 2273, "cii" ],
+[ 2274, "cij" ],
+[ 2275, "cik" ],
+[ 2276, "cil" ],
+[ 2277, "cim" ],
+[ 2278, "cin" ],
+[ 2279, "cio" ],
+[ 2280, "cip" ],
+[ 2281, "ciq" ],
+[ 2282, "cir" ],
+[ 2283, "cis" ],
+[ 2284, "cit" ],
+[ 2285, "ciu" ],
+[ 2286, "civ" ],
+[ 2287, "ciw" ],
+[ 2288, "cix" ],
+[ 2289, "ciy" ],
+[ 2290, "ciz" ],
+[ 2291, "cja" ],
+[ 2292, "cjb" ],
+[ 2293, "cjc" ],
+[ 2294, "cjd" ],
+[ 2295, "cje" ],
+[ 2296, "cjf" ],
+[ 2297, "cjg" ],
+[ 2298, "cjh" ],
+[ 2299, "cji" ],
+[ 2300, "cjj" ],
+[ 2301, "cjk" ],
+[ 2302, "cjl" ],
+[ 2303, "cjm" ],
+[ 2304, "cjn" ],
+[ 2305, "cjo" ],
+[ 2306, "cjp" ],
+[ 2307, "cjq" ],
+[ 2308, "cjr" ],
+[ 2309, "cjs" ],
+[ 2310, "cjt" ],
+[ 2311, "cju" ],
+[ 2312, "cjv" ],
+[ 2313, "cjw" ],
+[ 2314, "cjx" ],
+[ 2315, "cjy" ],
+[ 2316, "cjz" ],
+[ 2317, "cka" ],
+[ 2318, "ckb" ],
+[ 2319, "ckc" ],
+[ 2320, "ckd" ],
+[ 2321, "cke" ],
+[ 2322, "ckf" ],
+[ 2323, "ckg" ],
+[ 2324, "ckh" ],
+[ 2325, "cki" ],
+[ 2326, "ckj" ],
+[ 2327, "ckk" ],
+[ 2328, "ckl" ],
+[ 2329, "ckm" ],
+[ 2330, "ckn" ],
+[ 2331, "cko" ],
+[ 2332, "ckp" ],
+[ 2333, "ckq" ],
+[ 2334, "ckr" ],
+[ 2335, "cks" ],
+[ 2336, "ckt" ],
+[ 2337, "cku" ],
+[ 2338, "ckv" ],
+[ 2339, "ckw" ],
+[ 2340, "ckx" ],
+[ 2341, "cky" ],
+[ 2342, "ckz" ],
+[ 2343, "cla" ],
+[ 2344, "clb" ],
+[ 2345, "clc" ],
+[ 2346, "cld" ],
+[ 2347, "cle" ],
+[ 2348, "clf" ],
+[ 2349, "clg" ],
+[ 2350, "clh" ],
+[ 2351, "cli" ],
+[ 2352, "clj" ],
+[ 2353, "clk" ],
+[ 2354, "cll" ],
+[ 2355, "clm" ],
+[ 2356, "cln" ],
+[ 2357, "clo" ],
+[ 2358, "clp" ],
+[ 2359, "clq" ],
+[ 2360, "clr" ],
+[ 2361, "cls" ],
+[ 2362, "clt" ],
+[ 2363, "clu" ],
+[ 2364, "clv" ],
+[ 2365, "clw" ],
+[ 2366, "clx" ],
+[ 2367, "cly" ],
+[ 2368, "clz" ],
+[ 2369, "cma" ],
+[ 2370, "cmb" ],
+[ 2371, "cmc" ],
+[ 2372, "cmd" ],
+[ 2373, "cme" ],
+[ 2374, "cmf" ],
+[ 2375, "cmg" ],
+[ 2376, "cmh" ],
+[ 2377, "cmi" ],
+[ 2378, "cmj" ],
+[ 2379, "cmk" ],
+[ 2380, "cml" ],
+[ 2381, "cmm" ],
+[ 2382, "cmn" ],
+[ 2383, "cmo" ],
+[ 2384, "cmp" ],
+[ 2385, "cmq" ],
+[ 2386, "cmr" ],
+[ 2387, "cms" ],
+[ 2388, "cmt" ],
+[ 2389, "cmu" ],
+[ 2390, "cmv" ],
+[ 2391, "cmw" ],
+[ 2392, "cmx" ],
+[ 2393, "cmy" ],
+[ 2394, "cmz" ],
+[ 2395, "cna" ],
+[ 2396, "cnb" ],
+[ 2397, "cnc" ],
+[ 2398, "cnd" ],
+[ 2399, "cne" ],
+[ 2400, "cnf" ],
+[ 2401, "cng" ],
+[ 2402, "cnh" ],
+[ 2403, "cni" ],
+[ 2404, "cnj" ],
+[ 2405, "cnk" ],
+[ 2406, "cnl" ],
+[ 2407, "cnm" ],
+[ 2408, "cnn" ],
+[ 2409, "cno" ],
+[ 2410, "cnp" ],
+[ 2411, "cnq" ],
+[ 2412, "cnr" ],
+[ 2413, "cns" ],
+[ 2414, "cnt" ],
+[ 2415, "cnu" ],
+[ 2416, "cnv" ],
+[ 2417, "cnw" ],
+[ 2418, "cnx" ],
+[ 2419, "cny" ],
+[ 2420, "cnz" ],
+[ 2421, "coa" ],
+[ 2422, "cob" ],
+[ 2423, "coc" ],
+[ 2424, "cod" ],
+[ 2425, "coe" ],
+[ 2426, "cof" ],
+[ 2427, "cog" ],
+[ 2428, "coh" ],
+[ 2429, "coi" ],
+[ 2430, "coj" ],
+[ 2431, "cok" ],
+[ 2432, "col" ],
+[ 2433, "com" ],
+[ 2434, "con" ],
+[ 2435, "coo" ],
+[ 2436, "cop" ],
+[ 2437, "coq" ],
+[ 2438, "cor" ],
+[ 2439, "cos" ],
+[ 2440, "cot" ],
+[ 2441, "cou" ],
+[ 2442, "cov" ],
+[ 2443, "cow" ],
+[ 2444, "cox" ],
+[ 2445, "coy" ],
+[ 2446, "coz" ],
+[ 2447, "cpa" ],
+[ 2448, "cpb" ],
+[ 2449, "cpc" ],
+[ 2450, "cpd" ],
+[ 2451, "cpe" ],
+[ 2452, "cpf" ],
+[ 2453, "cpg" ],
+[ 2454, "cph" ],
+[ 2455, "cpi" ],
+[ 2456, "cpj" ],
+[ 2457, "cpk" ],
+[ 2458, "cpl" ],
+[ 2459, "cpm" ],
+[ 2460, "cpn" ],
+[ 2461, "cpo" ],
+[ 2462, "cpp" ],
+[ 2463, "cpq" ],
+[ 2464, "cpr" ],
+[ 2465, "cps" ],
+[ 2466, "cpt" ],
+[ 2467, "cpu" ],
+[ 2468, "cpv" ],
+[ 2469, "cpw" ],
+[ 2470, "cpx" ],
+[ 2471, "cpy" ],
+[ 2472, "cpz" ],
+[ 2473, "cqa" ],
+[ 2474, "cqb" ],
+[ 2475, "cqc" ],
+[ 2476, "cqd" ],
+[ 2477, "cqe" ],
+[ 2478, "cqf" ],
+[ 2479, "cqg" ],
+[ 2480, "cqh" ],
+[ 2481, "cqi" ],
+[ 2482, "cqj" ],
+[ 2483, "cqk" ],
+[ 2484, "cql" ],
+[ 2485, "cqm" ],
+[ 2486, "cqn" ],
+[ 2487, "cqo" ],
+[ 2488, "cqp" ],
+[ 2489, "cqq" ],
+[ 2490, "cqr" ],
+[ 2491, "cqs" ],
+[ 2492, "cqt" ],
+[ 2493, "cqu" ],
+[ 2494, "cqv" ],
+[ 2495, "cqw" ],
+[ 2496, "cqx" ],
+[ 2497, "cqy" ],
+[ 2498, "cqz" ],
+[ 2499, "cra" ],
+[ 2500, "crb" ],
+[ 2501, "crc" ],
+[ 2502, "crd" ],
+[ 2503, "cre" ],
+[ 2504, "crf" ],
+[ 2505, "crg" ],
+[ 2506, "crh" ],
+[ 2507, "cri" ],
+[ 2508, "crj" ],
+[ 2509, "crk" ],
+[ 2510, "crl" ],
+[ 2511, "crm" ],
+[ 2512, "crn" ],
+[ 2513, "cro" ],
+[ 2514, "crp" ],
+[ 2515, "crq" ],
+[ 2516, "crr" ],
+[ 2517, "crs" ],
+[ 2518, "crt" ],
+[ 2519, "cru" ],
+[ 2520, "crv" ],
+[ 2521, "crw" ],
+[ 2522, "crx" ],
+[ 2523, "cry" ],
+[ 2524, "crz" ],
+[ 2525, "csa" ],
+[ 2526, "csb" ],
+[ 2527, "csc" ],
+[ 2528, "csd" ],
+[ 2529, "cse" ],
+[ 2530, "csf" ],
+[ 2531, "csg" ],
+[ 2532, "csh" ],
+[ 2533, "csi" ],
+[ 2534, "csj" ],
+[ 2535, "csk" ],
+[ 2536, "csl" ],
+[ 2537, "csm" ],
+[ 2538, "csn" ],
+[ 2539, "cso" ],
+[ 2540, "csp" ],
+[ 2541, "csq" ],
+[ 2542, "csr" ],
+[ 2543, "css" ],
+[ 2544, "cst" ],
+[ 2545, "csu" ],
+[ 2546, "csv" ],
+[ 2547, "csw" ],
+[ 2548, "csx" ],
+[ 2549, "csy" ],
+[ 2550, "csz" ],
+[ 2551, "cta" ],
+[ 2552, "ctb" ],
+[ 2553, "ctc" ],
+[ 2554, "ctd" ],
+[ 2555, "cte" ],
+[ 2556, "ctf" ],
+[ 2557, "ctg" ],
+[ 2558, "cth" ],
+[ 2559, "cti" ],
+[ 2560, "ctj" ],
+[ 2561, "ctk" ],
+[ 2562, "ctl" ],
+[ 2563, "ctm" ],
+[ 2564, "ctn" ],
+[ 2565, "cto" ],
+[ 2566, "ctp" ],
+[ 2567, "ctq" ],
+[ 2568, "ctr" ],
+[ 2569, "cts" ],
+[ 2570, "ctt" ],
+[ 2571, "ctu" ],
+[ 2572, "ctv" ],
+[ 2573, "ctw" ],
+[ 2574, "ctx" ],
+[ 2575, "cty" ],
+[ 2576, "ctz" ],
+[ 2577, "cua" ],
+[ 2578, "cub" ],
+[ 2579, "cuc" ],
+[ 2580, "cud" ],
+[ 2581, "cue" ],
+[ 2582, "cuf" ],
+[ 2583, "cug" ],
+[ 2584, "cuh" ],
+[ 2585, "cui" ],
+[ 2586, "cuj" ],
+[ 2587, "cuk" ],
+[ 2588, "cul" ],
+[ 2589, "cum" ],
+[ 2590, "cun" ],
+[ 2591, "cuo" ],
+[ 2592, "cup" ],
+[ 2593, "cuq" ],
+[ 2594, "cur" ],
+[ 2595, "cus" ],
+[ 2596, "cut" ],
+[ 2597, "cuu" ],
+[ 2598, "cuv" ],
+[ 2599, "cuw" ],
+[ 2600, "cux" ],
+[ 2601, "cuy" ],
+[ 2602, "cuz" ],
+[ 2603, "cva" ],
+[ 2604, "cvb" ],
+[ 2605, "cvc" ],
+[ 2606, "cvd" ],
+[ 2607, "cve" ],
+[ 2608, "cvf" ],
+[ 2609, "cvg" ],
+[ 2610, "cvh" ],
+[ 2611, "cvi" ],
+[ 2612, "cvj" ],
+[ 2613, "cvk" ],
+[ 2614, "cvl" ],
+[ 2615, "cvm" ],
+[ 2616, "cvn" ],
+[ 2617, "cvo" ],
+[ 2618, "cvp" ],
+[ 2619, "cvq" ],
+[ 2620, "cvr" ],
+[ 2621, "cvs" ],
+[ 2622, "cvt" ],
+[ 2623, "cvu" ],
+[ 2624, "cvv" ],
+[ 2625, "cvw" ],
+[ 2626, "cvx" ],
+[ 2627, "cvy" ],
+[ 2628, "cvz" ],
+[ 2629, "cwa" ],
+[ 2630, "cwb" ],
+[ 2631, "cwc" ],
+[ 2632, "cwd" ],
+[ 2633, "cwe" ],
+[ 2634, "cwf" ],
+[ 2635, "cwg" ],
+[ 2636, "cwh" ],
+[ 2637, "cwi" ],
+[ 2638, "cwj" ],
+[ 2639, "cwk" ],
+[ 2640, "cwl" ],
+[ 2641, "cwm" ],
+[ 2642, "cwn" ],
+[ 2643, "cwo" ],
+[ 2644, "cwp" ],
+[ 2645, "cwq" ],
+[ 2646, "cwr" ],
+[ 2647, "cws" ],
+[ 2648, "cwt" ],
+[ 2649, "cwu" ],
+[ 2650, "cwv" ],
+[ 2651, "cww" ],
+[ 2652, "cwx" ],
+[ 2653, "cwy" ],
+[ 2654, "cwz" ],
+[ 2655, "cxa" ],
+[ 2656, "cxb" ],
+[ 2657, "cxc" ],
+[ 2658, "cxd" ],
+[ 2659, "cxe" ],
+[ 2660, "cxf" ],
+[ 2661, "cxg" ],
+[ 2662, "cxh" ],
+[ 2663, "cxi" ],
+[ 2664, "cxj" ],
+[ 2665, "cxk" ],
+[ 2666, "cxl" ],
+[ 2667, "cxm" ],
+[ 2668, "cxn" ],
+[ 2669, "cxo" ],
+[ 2670, "cxp" ],
+[ 2671, "cxq" ],
+[ 2672, "cxr" ],
+[ 2673, "cxs" ],
+[ 2674, "cxt" ],
+[ 2675, "cxu" ],
+[ 2676, "cxv" ],
+[ 2677, "cxw" ],
+[ 2678, "cxx" ],
+[ 2679, "cxy" ],
+[ 2680, "cxz" ],
+[ 2681, "cya" ],
+[ 2682, "cyb" ],
+[ 2683, "cyc" ],
+[ 2684, "cyd" ],
+[ 2685, "cye" ],
+[ 2686, "cyf" ],
+[ 2687, "cyg" ],
+[ 2688, "cyh" ],
+[ 2689, "cyi" ],
+[ 2690, "cyj" ],
+[ 2691, "cyk" ],
+[ 2692, "cyl" ],
+[ 2693, "cym" ],
+[ 2694, "cyn" ],
+[ 2695, "cyo" ],
+[ 2696, "cyp" ],
+[ 2697, "cyq" ],
+[ 2698, "cyr" ],
+[ 2699, "cys" ],
+[ 2700, "cyt" ],
+[ 2701, "cyu" ],
+[ 2702, "cyv" ],
+[ 2703, "cyw" ],
+[ 2704, "cyx" ],
+[ 2705, "cyy" ],
+[ 2706, "cyz" ],
+[ 2707, "cza" ],
+[ 2708, "czb" ],
+[ 2709, "czc" ],
+[ 2710, "czd" ],
+[ 2711, "cze" ],
+[ 2712, "czf" ],
+[ 2713, "czg" ],
+[ 2714, "czh" ],
+[ 2715, "czi" ],
+[ 2716, "czj" ],
+[ 2717, "czk" ],
+[ 2718, "czl" ],
+[ 2719, "czm" ],
+[ 2720, "czn" ],
+[ 2721, "czo" ],
+[ 2722, "czp" ],
+[ 2723, "czq" ],
+[ 2724, "czr" ],
+[ 2725, "czs" ],
+[ 2726, "czt" ],
+[ 2727, "czu" ],
+[ 2728, "czv" ],
+[ 2729, "czw" ],
+[ 2730, "czx" ],
+[ 2731, "czy" ],
+[ 2732, "czz" ],
+[ 2733, "daa" ],
+[ 2734, "dab" ],
+[ 2735, "dac" ],
+[ 2736, "dad" ],
+[ 2737, "dae" ],
+[ 2738, "daf" ],
+[ 2739, "dag" ],
+[ 2740, "dah" ],
+[ 2741, "dai" ],
+[ 2742, "daj" ],
+[ 2743, "dak" ],
+[ 2744, "dal" ],
+[ 2745, "dam" ],
+[ 2746, "dan" ],
+[ 2747, "dao" ],
+[ 2748, "dap" ],
+[ 2749, "daq" ],
+[ 2750, "dar" ],
+[ 2751, "das" ],
+[ 2752, "dat" ],
+[ 2753, "dau" ],
+[ 2754, "dav" ],
+[ 2755, "daw" ],
+[ 2756, "dax" ],
+[ 2757, "day" ],
+[ 2758, "daz" ],
+[ 2759, "dba" ],
+[ 2760, "dbb" ],
+[ 2761, "dbc" ],
+[ 2762, "dbd" ],
+[ 2763, "dbe" ],
+[ 2764, "dbf" ],
+[ 2765, "dbg" ],
+[ 2766, "dbh" ],
+[ 2767, "dbi" ],
+[ 2768, "dbj" ],
+[ 2769, "dbk" ],
+[ 2770, "dbl" ],
+[ 2771, "dbm" ],
+[ 2772, "dbn" ],
+[ 2773, "dbo" ],
+[ 2774, "dbp" ],
+[ 2775, "dbq" ],
+[ 2776, "dbr" ],
+[ 2777, "dbs" ],
+[ 2778, "dbt" ],
+[ 2779, "dbu" ],
+[ 2780, "dbv" ],
+[ 2781, "dbw" ],
+[ 2782, "dbx" ],
+[ 2783, "dby" ],
+[ 2784, "dbz" ],
+[ 2785, "dca" ],
+[ 2786, "dcb" ],
+[ 2787, "dcc" ],
+[ 2788, "dcd" ],
+[ 2789, "dce" ],
+[ 2790, "dcf" ],
+[ 2791, "dcg" ],
+[ 2792, "dch" ],
+[ 2793, "dci" ],
+[ 2794, "dcj" ],
+[ 2795, "dck" ],
+[ 2796, "dcl" ],
+[ 2797, "dcm" ],
+[ 2798, "dcn" ],
+[ 2799, "dco" ],
+[ 2800, "dcp" ],
+[ 2801, "dcq" ],
+[ 2802, "dcr" ],
+[ 2803, "dcs" ],
+[ 2804, "dct" ],
+[ 2805, "dcu" ],
+[ 2806, "dcv" ],
+[ 2807, "dcw" ],
+[ 2808, "dcx" ],
+[ 2809, "dcy" ],
+[ 2810, "dcz" ],
+[ 2811, "dda" ],
+[ 2812, "ddb" ],
+[ 2813, "ddc" ],
+[ 2814, "ddd" ],
+[ 2815, "dde" ],
+[ 2816, "ddf" ],
+[ 2817, "ddg" ],
+[ 2818, "ddh" ],
+[ 2819, "ddi" ],
+[ 2820, "ddj" ],
+[ 2821, "ddk" ],
+[ 2822, "ddl" ],
+[ 2823, "ddm" ],
+[ 2824, "ddn" ],
+[ 2825, "ddo" ],
+[ 2826, "ddp" ],
+[ 2827, "ddq" ],
+[ 2828, "ddr" ],
+[ 2829, "dds" ],
+[ 2830, "ddt" ],
+[ 2831, "ddu" ],
+[ 2832, "ddv" ],
+[ 2833, "ddw" ],
+[ 2834, "ddx" ],
+[ 2835, "ddy" ],
+[ 2836, "ddz" ],
+[ 2837, "dea" ],
+[ 2838, "deb" ],
+[ 2839, "dec" ],
+[ 2840, "ded" ],
+[ 2841, "dee" ],
+[ 2842, "def" ],
+[ 2843, "deg" ],
+[ 2844, "deh" ],
+[ 2845, "dei" ],
+[ 2846, "dej" ],
+[ 2847, "dek" ],
+[ 2848, "del" ],
+[ 2849, "dem" ],
+[ 2850, "den" ],
+[ 2851, "deo" ],
+[ 2852, "dep" ],
+[ 2853, "deq" ],
+[ 2854, "der" ],
+[ 2855, "des" ],
+[ 2856, "det" ],
+[ 2857, "deu" ],
+[ 2858, "dev" ],
+[ 2859, "dew" ],
+[ 2860, "dex" ],
+[ 2861, "dey" ],
+[ 2862, "dez" ],
+[ 2863, "dfa" ],
+[ 2864, "dfb" ],
+[ 2865, "dfc" ],
+[ 2866, "dfd" ],
+[ 2867, "dfe" ],
+[ 2868, "dff" ],
+[ 2869, "dfg" ],
+[ 2870, "dfh" ],
+[ 2871, "dfi" ],
+[ 2872, "dfj" ],
+[ 2873, "dfk" ],
+[ 2874, "dfl" ],
+[ 2875, "dfm" ],
+[ 2876, "dfn" ],
+[ 2877, "dfo" ],
+[ 2878, "dfp" ],
+[ 2879, "dfq" ],
+[ 2880, "dfr" ],
+[ 2881, "dfs" ],
+[ 2882, "dft" ],
+[ 2883, "dfu" ],
+[ 2884, "dfv" ],
+[ 2885, "dfw" ],
+[ 2886, "dfx" ],
+[ 2887, "dfy" ],
+[ 2888, "dfz" ],
+[ 2889, "dga" ],
+[ 2890, "dgb" ],
+[ 2891, "dgc" ],
+[ 2892, "dgd" ],
+[ 2893, "dge" ],
+[ 2894, "dgf" ],
+[ 2895, "dgg" ],
+[ 2896, "dgh" ],
+[ 2897, "dgi" ],
+[ 2898, "dgj" ],
+[ 2899, "dgk" ],
+[ 2900, "dgl" ],
+[ 2901, "dgm" ],
+[ 2902, "dgn" ],
+[ 2903, "dgo" ],
+[ 2904, "dgp" ],
+[ 2905, "dgq" ],
+[ 2906, "dgr" ],
+[ 2907, "dgs" ],
+[ 2908, "dgt" ],
+[ 2909, "dgu" ],
+[ 2910, "dgv" ],
+[ 2911, "dgw" ],
+[ 2912, "dgx" ],
+[ 2913, "dgy" ],
+[ 2914, "dgz" ],
+[ 2915, "dha" ],
+[ 2916, "dhb" ],
+[ 2917, "dhc" ],
+[ 2918, "dhd" ],
+[ 2919, "dhe" ],
+[ 2920, "dhf" ],
+[ 2921, "dhg" ],
+[ 2922, "dhh" ],
+[ 2923, "dhi" ],
+[ 2924, "dhj" ],
+[ 2925, "dhk" ],
+[ 2926, "dhl" ],
+[ 2927, "dhm" ],
+[ 2928, "dhn" ],
+[ 2929, "dho" ],
+[ 2930, "dhp" ],
+[ 2931, "dhq" ],
+[ 2932, "dhr" ],
+[ 2933, "dhs" ],
+[ 2934, "dht" ],
+[ 2935, "dhu" ],
+[ 2936, "dhv" ],
+[ 2937, "dhw" ],
+[ 2938, "dhx" ],
+[ 2939, "dhy" ],
+[ 2940, "dhz" ],
+[ 2941, "dia" ],
+[ 2942, "dib" ],
+[ 2943, "dic" ],
+[ 2944, "did" ],
+[ 2945, "die" ],
+[ 2946, "dif" ],
+[ 2947, "dig" ],
+[ 2948, "dih" ],
+[ 2949, "dii" ],
+[ 2950, "dij" ],
+[ 2951, "dik" ],
+[ 2952, "dil" ],
+[ 2953, "dim" ],
+[ 2954, "din" ],
+[ 2955, "dio" ],
+[ 2956, "dip" ],
+[ 2957, "diq" ],
+[ 2958, "dir" ],
+[ 2959, "dis" ],
+[ 2960, "dit" ],
+[ 2961, "diu" ],
+[ 2962, "div" ],
+[ 2963, "diw" ],
+[ 2964, "dix" ],
+[ 2965, "diy" ],
+[ 2966, "diz" ],
+[ 2967, "dja" ],
+[ 2968, "djb" ],
+[ 2969, "djc" ],
+[ 2970, "djd" ],
+[ 2971, "dje" ],
+[ 2972, "djf" ],
+[ 2973, "djg" ],
+[ 2974, "djh" ],
+[ 2975, "dji" ],
+[ 2976, "djj" ],
+[ 2977, "djk" ],
+[ 2978, "djl" ],
+[ 2979, "djm" ],
+[ 2980, "djn" ],
+[ 2981, "djo" ],
+[ 2982, "djp" ],
+[ 2983, "djq" ],
+[ 2984, "djr" ],
+[ 2985, "djs" ],
+[ 2986, "djt" ],
+[ 2987, "dju" ],
+[ 2988, "djv" ],
+[ 2989, "djw" ],
+[ 2990, "djx" ],
+[ 2991, "djy" ],
+[ 2992, "djz" ],
+[ 2993, "dka" ],
+[ 2994, "dkb" ],
+[ 2995, "dkc" ],
+[ 2996, "dkd" ],
+[ 2997, "dke" ],
+[ 2998, "dkf" ],
+[ 2999, "dkg" ],
+[ 3000, "dkh" ],
+[ 3001, "dki" ],
+[ 3002, "dkj" ],
+[ 3003, "dkk" ],
+[ 3004, "dkl" ],
+[ 3005, "dkm" ],
+[ 3006, "dkn" ],
+[ 3007, "dko" ],
+[ 3008, "dkp" ],
+[ 3009, "dkq" ],
+[ 3010, "dkr" ],
+[ 3011, "dks" ],
+[ 3012, "dkt" ],
+[ 3013, "dku" ],
+[ 3014, "dkv" ],
+[ 3015, "dkw" ],
+[ 3016, "dkx" ],
+[ 3017, "dky" ],
+[ 3018, "dkz" ],
+[ 3019, "dla" ],
+[ 3020, "dlb" ],
+[ 3021, "dlc" ],
+[ 3022, "dld" ],
+[ 3023, "dle" ],
+[ 3024, "dlf" ],
+[ 3025, "dlg" ],
+[ 3026, "dlh" ],
+[ 3027, "dli" ],
+[ 3028, "dlj" ],
+[ 3029, "dlk" ],
+[ 3030, "dll" ],
+[ 3031, "dlm" ],
+[ 3032, "dln" ],
+[ 3033, "dlo" ],
+[ 3034, "dlp" ],
+[ 3035, "dlq" ],
+[ 3036, "dlr" ],
+[ 3037, "dls" ],
+[ 3038, "dlt" ],
+[ 3039, "dlu" ],
+[ 3040, "dlv" ],
+[ 3041, "dlw" ],
+[ 3042, "dlx" ],
+[ 3043, "dly" ],
+[ 3044, "dlz" ],
+[ 3045, "dma" ],
+[ 3046, "dmb" ],
+[ 3047, "dmc" ],
+[ 3048, "dmd" ],
+[ 3049, "dme" ],
+[ 3050, "dmf" ],
+[ 3051, "dmg" ],
+[ 3052, "dmh" ],
+[ 3053, "dmi" ],
+[ 3054, "dmj" ],
+[ 3055, "dmk" ],
+[ 3056, "dml" ],
+[ 3057, "dmm" ],
+[ 3058, "dmn" ],
+[ 3059, "dmo" ],
+[ 3060, "dmp" ],
+[ 3061, "dmq" ],
+[ 3062, "dmr" ],
+[ 3063, "dms" ],
+[ 3064, "dmt" ],
+[ 3065, "dmu" ],
+[ 3066, "dmv" ],
+[ 3067, "dmw" ],
+[ 3068, "dmx" ],
+[ 3069, "dmy" ],
+[ 3070, "dmz" ],
+[ 3071, "dna" ],
+[ 3072, "dnb" ],
+[ 3073, "dnc" ],
+[ 3074, "dnd" ],
+[ 3075, "dne" ],
+[ 3076, "dnf" ],
+[ 3077, "dng" ],
+[ 3078, "dnh" ],
+[ 3079, "dni" ],
+[ 3080, "dnj" ],
+[ 3081, "dnk" ],
+[ 3082, "dnl" ],
+[ 3083, "dnm" ],
+[ 3084, "dnn" ],
+[ 3085, "dno" ],
+[ 3086, "dnp" ],
+[ 3087, "dnq" ],
+[ 3088, "dnr" ],
+[ 3089, "dns" ],
+[ 3090, "dnt" ],
+[ 3091, "dnu" ],
+[ 3092, "dnv" ],
+[ 3093, "dnw" ],
+[ 3094, "dnx" ],
+[ 3095, "dny" ],
+[ 3096, "dnz" ],
+[ 3097, "doa" ],
+[ 3098, "dob" ],
+[ 3099, "doc" ],
+[ 3100, "dod" ],
+[ 3101, "doe" ],
+[ 3102, "dof" ],
+[ 3103, "dog" ],
+[ 3104, "doh" ],
+[ 3105, "doi" ],
+[ 3106, "doj" ],
+[ 3107, "dok" ],
+[ 3108, "dol" ],
+[ 3109, "dom" ],
+[ 3110, "don" ],
+[ 3111, "doo" ],
+[ 3112, "dop" ],
+[ 3113, "doq" ],
+[ 3114, "dor" ],
+[ 3115, "dos" ],
+[ 3116, "dot" ],
+[ 3117, "dou" ],
+[ 3118, "dov" ],
+[ 3119, "dow" ],
+[ 3120, "dox" ],
+[ 3121, "doy" ],
+[ 3122, "doz" ],
+[ 3123, "dpa" ],
+[ 3124, "dpb" ],
+[ 3125, "dpc" ],
+[ 3126, "dpd" ],
+[ 3127, "dpe" ],
+[ 3128, "dpf" ],
+[ 3129, "dpg" ],
+[ 3130, "dph" ],
+[ 3131, "dpi" ],
+[ 3132, "dpj" ],
+[ 3133, "dpk" ],
+[ 3134, "dpl" ],
+[ 3135, "dpm" ],
+[ 3136, "dpn" ],
+[ 3137, "dpo" ],
+[ 3138, "dpp" ],
+[ 3139, "dpq" ],
+[ 3140, "dpr" ],
+[ 3141, "dps" ],
+[ 3142, "dpt" ],
+[ 3143, "dpu" ],
+[ 3144, "dpv" ],
+[ 3145, "dpw" ],
+[ 3146, "dpx" ],
+[ 3147, "dpy" ],
+[ 3148, "dpz" ],
+[ 3149, "dqa" ],
+[ 3150, "dqb" ],
+[ 3151, "dqc" ],
+[ 3152, "dqd" ],
+[ 3153, "dqe" ],
+[ 3154, "dqf" ],
+[ 3155, "dqg" ],
+[ 3156, "dqh" ],
+[ 3157, "dqi" ],
+[ 3158, "dqj" ],
+[ 3159, "dqk" ],
+[ 3160, "dql" ],
+[ 3161, "dqm" ],
+[ 3162, "dqn" ],
+[ 3163, "dqo" ],
+[ 3164, "dqp" ],
+[ 3165, "dqq" ],
+[ 3166, "dqr" ],
+[ 3167, "dqs" ],
+[ 3168, "dqt" ],
+[ 3169, "dqu" ],
+[ 3170, "dqv" ],
+[ 3171, "dqw" ],
+[ 3172, "dqx" ],
+[ 3173, "dqy" ],
+[ 3174, "dqz" ],
+[ 3175, "dra" ],
+[ 3176, "drb" ],
+[ 3177, "drc" ],
+[ 3178, "drd" ],
+[ 3179, "dre" ],
+[ 3180, "drf" ],
+[ 3181, "drg" ],
+[ 3182, "drh" ],
+[ 3183, "dri" ],
+[ 3184, "drj" ],
+[ 3185, "drk" ],
+[ 3186, "drl" ],
+[ 3187, "drm" ],
+[ 3188, "drn" ],
+[ 3189, "dro" ],
+[ 3190, "drp" ],
+[ 3191, "drq" ],
+[ 3192, "drr" ],
+[ 3193, "drs" ],
+[ 3194, "drt" ],
+[ 3195, "dru" ],
+[ 3196, "drv" ],
+[ 3197, "drw" ],
+[ 3198, "drx" ],
+[ 3199, "dry" ],
+[ 3200, "drz" ],
+[ 3201, "dsa" ],
+[ 3202, "dsb" ],
+[ 3203, "dsc" ],
+[ 3204, "dsd" ],
+[ 3205, "dse" ],
+[ 3206, "dsf" ],
+[ 3207, "dsg" ],
+[ 3208, "dsh" ],
+[ 3209, "dsi" ],
+[ 3210, "dsj" ],
+[ 3211, "dsk" ],
+[ 3212, "dsl" ],
+[ 3213, "dsm" ],
+[ 3214, "dsn" ],
+[ 3215, "dso" ],
+[ 3216, "dsp" ],
+[ 3217, "dsq" ],
+[ 3218, "dsr" ],
+[ 3219, "dss" ],
+[ 3220, "dst" ],
+[ 3221, "dsu" ],
+[ 3222, "dsv" ],
+[ 3223, "dsw" ],
+[ 3224, "dsx" ],
+[ 3225, "dsy" ],
+[ 3226, "dsz" ],
+[ 3227, "dta" ],
+[ 3228, "dtb" ],
+[ 3229, "dtc" ],
+[ 3230, "dtd" ],
+[ 3231, "dte" ],
+[ 3232, "dtf" ],
+[ 3233, "dtg" ],
+[ 3234, "dth" ],
+[ 3235, "dti" ],
+[ 3236, "dtj" ],
+[ 3237, "dtk" ],
+[ 3238, "dtl" ],
+[ 3239, "dtm" ],
+[ 3240, "dtn" ],
+[ 3241, "dto" ],
+[ 3242, "dtp" ],
+[ 3243, "dtq" ],
+[ 3244, "dtr" ],
+[ 3245, "dts" ],
+[ 3246, "dtt" ],
+[ 3247, "dtu" ],
+[ 3248, "dtv" ],
+[ 3249, "dtw" ],
+[ 3250, "dtx" ],
+[ 3251, "dty" ],
+[ 3252, "dtz" ],
+[ 3253, "dua" ],
+[ 3254, "dub" ],
+[ 3255, "duc" ],
+[ 3256, "dud" ],
+[ 3257, "due" ],
+[ 3258, "duf" ],
+[ 3259, "dug" ],
+[ 3260, "duh" ],
+[ 3261, "dui" ],
+[ 3262, "duj" ],
+[ 3263, "duk" ],
+[ 3264, "dul" ],
+[ 3265, "dum" ],
+[ 3266, "dun" ],
+[ 3267, "duo" ],
+[ 3268, "dup" ],
+[ 3269, "duq" ],
+[ 3270, "dur" ],
+[ 3271, "dus" ],
+[ 3272, "dut" ],
+[ 3273, "duu" ],
+[ 3274, "duv" ],
+[ 3275, "duw" ],
+[ 3276, "dux" ],
+[ 3277, "duy" ],
+[ 3278, "duz" ],
+[ 3279, "dva" ],
+[ 3280, "dvb" ],
+[ 3281, "dvc" ],
+[ 3282, "dvd" ],
+[ 3283, "dve" ],
+[ 3284, "dvf" ],
+[ 3285, "dvg" ],
+[ 3286, "dvh" ],
+[ 3287, "dvi" ],
+[ 3288, "dvj" ],
+[ 3289, "dvk" ],
+[ 3290, "dvl" ],
+[ 3291, "dvm" ],
+[ 3292, "dvn" ],
+[ 3293, "dvo" ],
+[ 3294, "dvp" ],
+[ 3295, "dvq" ],
+[ 3296, "dvr" ],
+[ 3297, "dvs" ],
+[ 3298, "dvt" ],
+[ 3299, "dvu" ],
+[ 3300, "dvv" ],
+[ 3301, "dvw" ],
+[ 3302, "dvx" ],
+[ 3303, "dvy" ],
+[ 3304, "dvz" ],
+[ 3305, "dwa" ],
+[ 3306, "dwb" ],
+[ 3307, "dwc" ],
+[ 3308, "dwd" ],
+[ 3309, "dwe" ],
+[ 3310, "dwf" ],
+[ 3311, "dwg" ],
+[ 3312, "dwh" ],
+[ 3313, "dwi" ],
+[ 3314, "dwj" ],
+[ 3315, "dwk" ],
+[ 3316, "dwl" ],
+[ 3317, "dwm" ],
+[ 3318, "dwn" ],
+[ 3319, "dwo" ],
+[ 3320, "dwp" ],
+[ 3321, "dwq" ],
+[ 3322, "dwr" ],
+[ 3323, "dws" ],
+[ 3324, "dwt" ],
+[ 3325, "dwu" ],
+[ 3326, "dwv" ],
+[ 3327, "dww" ],
+[ 3328, "dwx" ],
+[ 3329, "dwy" ],
+[ 3330, "dwz" ],
+[ 3331, "dxa" ],
+[ 3332, "dxb" ],
+[ 3333, "dxc" ],
+[ 3334, "dxd" ],
+[ 3335, "dxe" ],
+[ 3336, "dxf" ],
+[ 3337, "dxg" ],
+[ 3338, "dxh" ],
+[ 3339, "dxi" ],
+[ 3340, "dxj" ],
+[ 3341, "dxk" ],
+[ 3342, "dxl" ],
+[ 3343, "dxm" ],
+[ 3344, "dxn" ],
+[ 3345, "dxo" ],
+[ 3346, "dxp" ],
+[ 3347, "dxq" ],
+[ 3348, "dxr" ],
+[ 3349, "dxs" ],
+[ 3350, "dxt" ],
+[ 3351, "dxu" ],
+[ 3352, "dxv" ],
+[ 3353, "dxw" ],
+[ 3354, "dxx" ],
+[ 3355, "dxy" ],
+[ 3356, "dxz" ],
+[ 3357, "dya" ],
+[ 3358, "dyb" ],
+[ 3359, "dyc" ],
+[ 3360, "dyd" ],
+[ 3361, "dye" ],
+[ 3362, "dyf" ],
+[ 3363, "dyg" ],
+[ 3364, "dyh" ],
+[ 3365, "dyi" ],
+[ 3366, "dyj" ],
+[ 3367, "dyk" ],
+[ 3368, "dyl" ],
+[ 3369, "dym" ],
+[ 3370, "dyn" ],
+[ 3371, "dyo" ],
+[ 3372, "dyp" ],
+[ 3373, "dyq" ],
+[ 3374, "dyr" ],
+[ 3375, "dys" ],
+[ 3376, "dyt" ],
+[ 3377, "dyu" ],
+[ 3378, "dyv" ],
+[ 3379, "dyw" ],
+[ 3380, "dyx" ],
+[ 3381, "dyy" ],
+[ 3382, "dyz" ],
+[ 3383, "dza" ],
+[ 3384, "dzb" ],
+[ 3385, "dzc" ],
+[ 3386, "dzd" ],
+[ 3387, "dze" ],
+[ 3388, "dzf" ],
+[ 3389, "dzg" ],
+[ 3390, "dzh" ],
+[ 3391, "dzi" ],
+[ 3392, "dzj" ],
+[ 3393, "dzk" ],
+[ 3394, "dzl" ],
+[ 3395, "dzm" ],
+[ 3396, "dzn" ],
+[ 3397, "dzo" ],
+[ 3398, "dzp" ],
+[ 3399, "dzq" ],
+[ 3400, "dzr" ],
+[ 3401, "dzs" ],
+[ 3402, "dzt" ],
+[ 3403, "dzu" ],
+[ 3404, "dzv" ],
+[ 3405, "dzw" ],
+[ 3406, "dzx" ],
+[ 3407, "dzy" ],
+[ 3408, "dzz" ],
+[ 3409, "eaa" ],
+[ 3410, "eab" ],
+[ 3411, "eac" ],
+[ 3412, "ead" ],
+[ 3413, "eae" ],
+[ 3414, "eaf" ],
+[ 3415, "eag" ],
+[ 3416, "eah" ],
+[ 3417, "eai" ],
+[ 3418, "eaj" ],
+[ 3419, "eak" ],
+[ 3420, "eal" ],
+[ 3421, "eam" ],
+[ 3422, "ean" ],
+[ 3423, "eao" ],
+[ 3424, "eap" ],
+[ 3425, "eaq" ],
+[ 3426, "ear" ],
+[ 3427, "eas" ],
+[ 3428, "eat" ],
+[ 3429, "eau" ],
+[ 3430, "eav" ],
+[ 3431, "eaw" ],
+[ 3432, "eax" ],
+[ 3433, "eay" ],
+[ 3434, "eaz" ],
+[ 3435, "eba" ],
+[ 3436, "ebb" ],
+[ 3437, "ebc" ],
+[ 3438, "ebd" ],
+[ 3439, "ebe" ],
+[ 3440, "ebf" ],
+[ 3441, "ebg" ],
+[ 3442, "ebh" ],
+[ 3443, "ebi" ],
+[ 3444, "ebj" ],
+[ 3445, "ebk" ],
+[ 3446, "ebl" ],
+[ 3447, "ebm" ],
+[ 3448, "ebn" ],
+[ 3449, "ebo" ],
+[ 3450, "ebp" ],
+[ 3451, "ebq" ],
+[ 3452, "ebr" ],
+[ 3453, "ebs" ],
+[ 3454, "ebt" ],
+[ 3455, "ebu" ],
+[ 3456, "ebv" ],
+[ 3457, "ebw" ],
+[ 3458, "ebx" ],
+[ 3459, "eby" ],
+[ 3460, "ebz" ],
+[ 3461, "eca" ],
+[ 3462, "ecb" ],
+[ 3463, "ecc" ],
+[ 3464, "ecd" ],
+[ 3465, "ece" ],
+[ 3466, "ecf" ],
+[ 3467, "ecg" ],
+[ 3468, "ech" ],
+[ 3469, "eci" ],
+[ 3470, "ecj" ],
+[ 3471, "eck" ],
+[ 3472, "ecl" ],
+[ 3473, "ecm" ],
+[ 3474, "ecn" ],
+[ 3475, "eco" ],
+[ 3476, "ecp" ],
+[ 3477, "ecq" ],
+[ 3478, "ecr" ],
+[ 3479, "ecs" ],
+[ 3480, "ect" ],
+[ 3481, "ecu" ],
+[ 3482, "ecv" ],
+[ 3483, "ecw" ],
+[ 3484, "ecx" ],
+[ 3485, "ecy" ],
+[ 3486, "ecz" ],
+[ 3487, "eda" ],
+[ 3488, "edb" ],
+[ 3489, "edc" ],
+[ 3490, "edd" ],
+[ 3491, "ede" ],
+[ 3492, "edf" ],
+[ 3493, "edg" ],
+[ 3494, "edh" ],
+[ 3495, "edi" ],
+[ 3496, "edj" ],
+[ 3497, "edk" ],
+[ 3498, "edl" ],
+[ 3499, "edm" ],
+[ 3500, "edn" ],
+[ 3501, "edo" ],
+[ 3502, "edp" ],
+[ 3503, "edq" ],
+[ 3504, "edr" ],
+[ 3505, "eds" ],
+[ 3506, "edt" ],
+[ 3507, "edu" ],
+[ 3508, "edv" ],
+[ 3509, "edw" ],
+[ 3510, "edx" ],
+[ 3511, "edy" ],
+[ 3512, "edz" ],
+[ 3513, "eea" ],
+[ 3514, "eeb" ],
+[ 3515, "eec" ],
+[ 3516, "eed" ],
+[ 3517, "eee" ],
+[ 3518, "eef" ],
+[ 3519, "eeg" ],
+[ 3520, "eeh" ],
+[ 3521, "eei" ],
+[ 3522, "eej" ],
+[ 3523, "eek" ],
+[ 3524, "eel" ],
+[ 3525, "eem" ],
+[ 3526, "een" ],
+[ 3527, "eeo" ],
+[ 3528, "eep" ],
+[ 3529, "eeq" ],
+[ 3530, "eer" ],
+[ 3531, "ees" ],
+[ 3532, "eet" ],
+[ 3533, "eeu" ],
+[ 3534, "eev" ],
+[ 3535, "eew" ],
+[ 3536, "eex" ],
+[ 3537, "eey" ],
+[ 3538, "eez" ],
+[ 3539, "efa" ],
+[ 3540, "efb" ],
+[ 3541, "efc" ],
+[ 3542, "efd" ],
+[ 3543, "efe" ],
+[ 3544, "eff" ],
+[ 3545, "efg" ],
+[ 3546, "efh" ],
+[ 3547, "efi" ],
+[ 3548, "efj" ],
+[ 3549, "efk" ],
+[ 3550, "efl" ],
+[ 3551, "efm" ],
+[ 3552, "efn" ],
+[ 3553, "efo" ],
+[ 3554, "efp" ],
+[ 3555, "efq" ],
+[ 3556, "efr" ],
+[ 3557, "efs" ],
+[ 3558, "eft" ],
+[ 3559, "efu" ],
+[ 3560, "efv" ],
+[ 3561, "efw" ],
+[ 3562, "efx" ],
+[ 3563, "efy" ],
+[ 3564, "efz" ],
+[ 3565, "ega" ],
+[ 3566, "egb" ],
+[ 3567, "egc" ],
+[ 3568, "egd" ],
+[ 3569, "ege" ],
+[ 3570, "egf" ],
+[ 3571, "egg" ],
+[ 3572, "egh" ],
+[ 3573, "egi" ],
+[ 3574, "egj" ],
+[ 3575, "egk" ],
+[ 3576, "egl" ],
+[ 3577, "egm" ],
+[ 3578, "egn" ],
+[ 3579, "ego" ],
+[ 3580, "egp" ],
+[ 3581, "egq" ],
+[ 3582, "egr" ],
+[ 3583, "egs" ],
+[ 3584, "egt" ],
+[ 3585, "egu" ],
+[ 3586, "egv" ],
+[ 3587, "egw" ],
+[ 3588, "egx" ],
+[ 3589, "egy" ],
+[ 3590, "egz" ],
+[ 3591, "eha" ],
+[ 3592, "ehb" ],
+[ 3593, "ehc" ],
+[ 3594, "ehd" ],
+[ 3595, "ehe" ],
+[ 3596, "ehf" ],
+[ 3597, "ehg" ],
+[ 3598, "ehh" ],
+[ 3599, "ehi" ],
+[ 3600, "ehj" ],
+[ 3601, "ehk" ],
+[ 3602, "ehl" ],
+[ 3603, "ehm" ],
+[ 3604, "ehn" ],
+[ 3605, "eho" ],
+[ 3606, "ehp" ],
+[ 3607, "ehq" ],
+[ 3608, "ehr" ],
+[ 3609, "ehs" ],
+[ 3610, "eht" ],
+[ 3611, "ehu" ],
+[ 3612, "ehv" ],
+[ 3613, "ehw" ],
+[ 3614, "ehx" ],
+[ 3615, "ehy" ],
+[ 3616, "ehz" ],
+[ 3617, "eia" ],
+[ 3618, "eib" ],
+[ 3619, "eic" ],
+[ 3620, "eid" ],
+[ 3621, "eie" ],
+[ 3622, "eif" ],
+[ 3623, "eig" ],
+[ 3624, "eih" ],
+[ 3625, "eii" ],
+[ 3626, "eij" ],
+[ 3627, "eik" ],
+[ 3628, "eil" ],
+[ 3629, "eim" ],
+[ 3630, "ein" ],
+[ 3631, "eio" ],
+[ 3632, "eip" ],
+[ 3633, "eiq" ],
+[ 3634, "eir" ],
+[ 3635, "eis" ],
+[ 3636, "eit" ],
+[ 3637, "eiu" ],
+[ 3638, "eiv" ],
+[ 3639, "eiw" ],
+[ 3640, "eix" ],
+[ 3641, "eiy" ],
+[ 3642, "eiz" ],
+[ 3643, "eja" ],
+[ 3644, "ejb" ],
+[ 3645, "ejc" ],
+[ 3646, "ejd" ],
+[ 3647, "eje" ],
+[ 3648, "ejf" ],
+[ 3649, "ejg" ],
+[ 3650, "ejh" ],
+[ 3651, "eji" ],
+[ 3652, "ejj" ],
+[ 3653, "ejk" ],
+[ 3654, "ejl" ],
+[ 3655, "ejm" ],
+[ 3656, "ejn" ],
+[ 3657, "ejo" ],
+[ 3658, "ejp" ],
+[ 3659, "ejq" ],
+[ 3660, "ejr" ],
+[ 3661, "ejs" ],
+[ 3662, "ejt" ],
+[ 3663, "eju" ],
+[ 3664, "ejv" ],
+[ 3665, "ejw" ],
+[ 3666, "ejx" ],
+[ 3667, "ejy" ],
+[ 3668, "ejz" ],
+[ 3669, "eka" ],
+[ 3670, "ekb" ],
+[ 3671, "ekc" ],
+[ 3672, "ekd" ],
+[ 3673, "eke" ],
+[ 3674, "ekf" ],
+[ 3675, "ekg" ],
+[ 3676, "ekh" ],
+[ 3677, "eki" ],
+[ 3678, "ekj" ],
+[ 3679, "ekk" ],
+[ 3680, "ekl" ],
+[ 3681, "ekm" ],
+[ 3682, "ekn" ],
+[ 3683, "eko" ],
+[ 3684, "ekp" ],
+[ 3685, "ekq" ],
+[ 3686, "ekr" ],
+[ 3687, "eks" ],
+[ 3688, "ekt" ],
+[ 3689, "eku" ],
+[ 3690, "ekv" ],
+[ 3691, "ekw" ],
+[ 3692, "ekx" ],
+[ 3693, "eky" ],
+[ 3694, "ekz" ],
+[ 3695, "ela" ],
+[ 3696, "elb" ],
+[ 3697, "elc" ],
+[ 3698, "eld" ],
+[ 3699, "ele" ],
+[ 3700, "elf" ],
+[ 3701, "elg" ],
+[ 3702, "elh" ],
+[ 3703, "eli" ],
+[ 3704, "elj" ],
+[ 3705, "elk" ],
+[ 3706, "ell" ],
+[ 3707, "elm" ],
+[ 3708, "eln" ],
+[ 3709, "elo" ],
+[ 3710, "elp" ],
+[ 3711, "elq" ],
+[ 3712, "elr" ],
+[ 3713, "els" ],
+[ 3714, "elt" ],
+[ 3715, "elu" ],
+[ 3716, "elv" ],
+[ 3717, "elw" ],
+[ 3718, "elx" ],
+[ 3719, "ely" ],
+[ 3720, "elz" ],
+[ 3721, "ema" ],
+[ 3722, "emb" ],
+[ 3723, "emc" ],
+[ 3724, "emd" ],
+[ 3725, "eme" ],
+[ 3726, "emf" ],
+[ 3727, "emg" ],
+[ 3728, "emh" ],
+[ 3729, "emi" ],
+[ 3730, "emj" ],
+[ 3731, "emk" ],
+[ 3732, "eml" ],
+[ 3733, "emm" ],
+[ 3734, "emn" ],
+[ 3735, "emo" ],
+[ 3736, "emp" ],
+[ 3737, "emq" ],
+[ 3738, "emr" ],
+[ 3739, "ems" ],
+[ 3740, "emt" ],
+[ 3741, "emu" ],
+[ 3742, "emv" ],
+[ 3743, "emw" ],
+[ 3744, "emx" ],
+[ 3745, "emy" ],
+[ 3746, "emz" ],
+[ 3747, "ena" ],
+[ 3748, "enb" ],
+[ 3749, "enc" ],
+[ 3750, "end" ],
+[ 3751, "ene" ],
+[ 3752, "enf" ],
+[ 3753, "eng" ],
+[ 3754, "enh" ],
+[ 3755, "eni" ],
+[ 3756, "enj" ],
+[ 3757, "enk" ],
+[ 3758, "enl" ],
+[ 3759, "enm" ],
+[ 3760, "enn" ],
+[ 3761, "eno" ],
+[ 3762, "enp" ],
+[ 3763, "enq" ],
+[ 3764, "enr" ],
+[ 3765, "ens" ],
+[ 3766, "ent" ],
+[ 3767, "enu" ],
+[ 3768, "env" ],
+[ 3769, "enw" ],
+[ 3770, "enx" ],
+[ 3771, "eny" ],
+[ 3772, "enz" ],
+[ 3773, "eoa" ],
+[ 3774, "eob" ],
+[ 3775, "eoc" ],
+[ 3776, "eod" ],
+[ 3777, "eoe" ],
+[ 3778, "eof" ],
+[ 3779, "eog" ],
+[ 3780, "eoh" ],
+[ 3781, "eoi" ],
+[ 3782, "eoj" ],
+[ 3783, "eok" ],
+[ 3784, "eol" ],
+[ 3785, "eom" ],
+[ 3786, "eon" ],
+[ 3787, "eoo" ],
+[ 3788, "eop" ],
+[ 3789, "eoq" ],
+[ 3790, "eor" ],
+[ 3791, "eos" ],
+[ 3792, "eot" ],
+[ 3793, "eou" ],
+[ 3794, "eov" ],
+[ 3795, "eow" ],
+[ 3796, "eox" ],
+[ 3797, "eoy" ],
+[ 3798, "eoz" ],
+[ 3799, "epa" ],
+[ 3800, "epb" ],
+[ 3801, "epc" ],
+[ 3802, "epd" ],
+[ 3803, "epe" ],
+[ 3804, "epf" ],
+[ 3805, "epg" ],
+[ 3806, "eph" ],
+[ 3807, "epi" ],
+[ 3808, "epj" ],
+[ 3809, "epk" ],
+[ 3810, "epl" ],
+[ 3811, "epm" ],
+[ 3812, "epn" ],
+[ 3813, "epo" ],
+[ 3814, "epp" ],
+[ 3815, "epq" ],
+[ 3816, "epr" ],
+[ 3817, "eps" ],
+[ 3818, "ept" ],
+[ 3819, "epu" ],
+[ 3820, "epv" ],
+[ 3821, "epw" ],
+[ 3822, "epx" ],
+[ 3823, "epy" ],
+[ 3824, "epz" ],
+[ 3825, "eqa" ],
+[ 3826, "eqb" ],
+[ 3827, "eqc" ],
+[ 3828, "eqd" ],
+[ 3829, "eqe" ],
+[ 3830, "eqf" ],
+[ 3831, "eqg" ],
+[ 3832, "eqh" ],
+[ 3833, "eqi" ],
+[ 3834, "eqj" ],
+[ 3835, "eqk" ],
+[ 3836, "eql" ],
+[ 3837, "eqm" ],
+[ 3838, "eqn" ],
+[ 3839, "eqo" ],
+[ 3840, "eqp" ],
+[ 3841, "eqq" ],
+[ 3842, "eqr" ],
+[ 3843, "eqs" ],
+[ 3844, "eqt" ],
+[ 3845, "equ" ],
+[ 3846, "eqv" ],
+[ 3847, "eqw" ],
+[ 3848, "eqx" ],
+[ 3849, "eqy" ],
+[ 3850, "eqz" ],
+[ 3851, "era" ],
+[ 3852, "erb" ],
+[ 3853, "erc" ],
+[ 3854, "erd" ],
+[ 3855, "ere" ],
+[ 3856, "erf" ],
+[ 3857, "erg" ],
+[ 3858, "erh" ],
+[ 3859, "eri" ],
+[ 3860, "erj" ],
+[ 3861, "erk" ],
+[ 3862, "erl" ],
+[ 3863, "erm" ],
+[ 3864, "ern" ],
+[ 3865, "ero" ],
+[ 3866, "erp" ],
+[ 3867, "erq" ],
+[ 3868, "err" ],
+[ 3869, "ers" ],
+[ 3870, "ert" ],
+[ 3871, "eru" ],
+[ 3872, "erv" ],
+[ 3873, "erw" ],
+[ 3874, "erx" ],
+[ 3875, "ery" ],
+[ 3876, "erz" ],
+[ 3877, "esa" ],
+[ 3878, "esb" ],
+[ 3879, "esc" ],
+[ 3880, "esd" ],
+[ 3881, "ese" ],
+[ 3882, "esf" ],
+[ 3883, "esg" ],
+[ 3884, "esh" ],
+[ 3885, "esi" ],
+[ 3886, "esj" ],
+[ 3887, "esk" ],
+[ 3888, "esl" ],
+[ 3889, "esm" ],
+[ 3890, "esn" ],
+[ 3891, "eso" ],
+[ 3892, "esp" ],
+[ 3893, "esq" ],
+[ 3894, "esr" ],
+[ 3895, "ess" ],
+[ 3896, "est" ],
+[ 3897, "esu" ],
+[ 3898, "esv" ],
+[ 3899, "esw" ],
+[ 3900, "esx" ],
+[ 3901, "esy" ],
+[ 3902, "esz" ],
+[ 3903, "eta" ],
+[ 3904, "etb" ],
+[ 3905, "etc" ],
+[ 3906, "etd" ],
+[ 3907, "ete" ],
+[ 3908, "etf" ],
+[ 3909, "etg" ],
+[ 3910, "eth" ],
+[ 3911, "eti" ],
+[ 3912, "etj" ],
+[ 3913, "etk" ],
+[ 3914, "etl" ],
+[ 3915, "etm" ],
+[ 3916, "etn" ],
+[ 3917, "eto" ],
+[ 3918, "etp" ],
+[ 3919, "etq" ],
+[ 3920, "etr" ],
+[ 3921, "ets" ],
+[ 3922, "ett" ],
+[ 3923, "etu" ],
+[ 3924, "etv" ],
+[ 3925, "etw" ],
+[ 3926, "etx" ],
+[ 3927, "ety" ],
+[ 3928, "etz" ],
+[ 3929, "eua" ],
+[ 3930, "eub" ],
+[ 3931, "euc" ],
+[ 3932, "eud" ],
+[ 3933, "eue" ],
+[ 3934, "euf" ],
+[ 3935, "eug" ],
+[ 3936, "euh" ],
+[ 3937, "eui" ],
+[ 3938, "euj" ],
+[ 3939, "euk" ],
+[ 3940, "eul" ],
+[ 3941, "eum" ],
+[ 3942, "eun" ],
+[ 3943, "euo" ],
+[ 3944, "eup" ],
+[ 3945, "euq" ],
+[ 3946, "eur" ],
+[ 3947, "eus" ],
+[ 3948, "eut" ],
+[ 3949, "euu" ],
+[ 3950, "euv" ],
+[ 3951, "euw" ],
+[ 3952, "eux" ],
+[ 3953, "euy" ],
+[ 3954, "euz" ],
+[ 3955, "eva" ],
+[ 3956, "evb" ],
+[ 3957, "evc" ],
+[ 3958, "evd" ],
+[ 3959, "eve" ],
+[ 3960, "evf" ],
+[ 3961, "evg" ],
+[ 3962, "evh" ],
+[ 3963, "evi" ],
+[ 3964, "evj" ],
+[ 3965, "evk" ],
+[ 3966, "evl" ],
+[ 3967, "evm" ],
+[ 3968, "evn" ],
+[ 3969, "evo" ],
+[ 3970, "evp" ],
+[ 3971, "evq" ],
+[ 3972, "evr" ],
+[ 3973, "evs" ],
+[ 3974, "evt" ],
+[ 3975, "evu" ],
+[ 3976, "evv" ],
+[ 3977, "evw" ],
+[ 3978, "evx" ],
+[ 3979, "evy" ],
+[ 3980, "evz" ],
+[ 3981, "ewa" ],
+[ 3982, "ewb" ],
+[ 3983, "ewc" ],
+[ 3984, "ewd" ],
+[ 3985, "ewe" ],
+[ 3986, "ewf" ],
+[ 3987, "ewg" ],
+[ 3988, "ewh" ],
+[ 3989, "ewi" ],
+[ 3990, "ewj" ],
+[ 3991, "ewk" ],
+[ 3992, "ewl" ],
+[ 3993, "ewm" ],
+[ 3994, "ewn" ],
+[ 3995, "ewo" ],
+[ 3996, "ewp" ],
+[ 3997, "ewq" ],
+[ 3998, "ewr" ],
+[ 3999, "ews" ],
+[ 4000, "ewt" ],
+[ 4001, "ewu" ],
+[ 4002, "ewv" ],
+[ 4003, "eww" ],
+[ 4004, "ewx" ],
+[ 4005, "ewy" ],
+[ 4006, "ewz" ],
+[ 4007, "exa" ],
+[ 4008, "exb" ],
+[ 4009, "exc" ],
+[ 4010, "exd" ],
+[ 4011, "exe" ],
+[ 4012, "exf" ],
+[ 4013, "exg" ],
+[ 4014, "exh" ],
+[ 4015, "exi" ],
+[ 4016, "exj" ],
+[ 4017, "exk" ],
+[ 4018, "exl" ],
+[ 4019, "exm" ],
+[ 4020, "exn" ],
+[ 4021, "exo" ],
+[ 4022, "exp" ],
+[ 4023, "exq" ],
+[ 4024, "exr" ],
+[ 4025, "exs" ],
+[ 4026, "ext" ],
+[ 4027, "exu" ],
+[ 4028, "exv" ],
+[ 4029, "exw" ],
+[ 4030, "exx" ],
+[ 4031, "exy" ],
+[ 4032, "exz" ],
+[ 4033, "eya" ],
+[ 4034, "eyb" ],
+[ 4035, "eyc" ],
+[ 4036, "eyd" ],
+[ 4037, "eye" ],
+[ 4038, "eyf" ],
+[ 4039, "eyg" ],
+[ 4040, "eyh" ],
+[ 4041, "eyi" ],
+[ 4042, "eyj" ],
+[ 4043, "eyk" ],
+[ 4044, "eyl" ],
+[ 4045, "eym" ],
+[ 4046, "eyn" ],
+[ 4047, "eyo" ],
+[ 4048, "eyp" ],
+[ 4049, "eyq" ],
+[ 4050, "eyr" ],
+[ 4051, "eys" ],
+[ 4052, "eyt" ],
+[ 4053, "eyu" ],
+[ 4054, "eyv" ],
+[ 4055, "eyw" ],
+[ 4056, "eyx" ],
+[ 4057, "eyy" ],
+[ 4058, "eyz" ],
+[ 4059, "eza" ],
+[ 4060, "ezb" ],
+[ 4061, "ezc" ],
+[ 4062, "ezd" ],
+[ 4063, "eze" ],
+[ 4064, "ezf" ],
+[ 4065, "ezg" ],
+[ 4066, "ezh" ],
+[ 4067, "ezi" ],
+[ 4068, "ezj" ],
+[ 4069, "ezk" ],
+[ 4070, "ezl" ],
+[ 4071, "ezm" ],
+[ 4072, "ezn" ],
+[ 4073, "ezo" ],
+[ 4074, "ezp" ],
+[ 4075, "ezq" ],
+[ 4076, "ezr" ],
+[ 4077, "ezs" ],
+[ 4078, "ezt" ],
+[ 4079, "ezu" ],
+[ 4080, "ezv" ],
+[ 4081, "ezw" ],
+[ 4082, "ezx" ],
+[ 4083, "ezy" ],
+[ 4084, "ezz" ],
+[ 4085, "faa" ],
+[ 4086, "fab" ],
+[ 4087, "fac" ],
+[ 4088, "fad" ],
+[ 4089, "fae" ],
+[ 4090, "faf" ],
+[ 4091, "fag" ],
+[ 4092, "fah" ],
+[ 4093, "fai" ],
+[ 4094, "faj" ],
+[ 4095, "fak" ],
+[ 4096, "fal" ],
+[ 4097, "fam" ],
+[ 4098, "fan" ],
+[ 4099, "fao" ],
+[ 4100, "fap" ],
+[ 4101, "faq" ],
+[ 4102, "far" ],
+[ 4103, "fas" ],
+[ 4104, "fat" ],
+[ 4105, "fau" ],
+[ 4106, "fav" ],
+[ 4107, "faw" ],
+[ 4108, "fax" ],
+[ 4109, "fay" ],
+[ 4110, "faz" ],
+[ 4111, "fba" ],
+[ 4112, "fbb" ],
+[ 4113, "fbc" ],
+[ 4114, "fbd" ],
+[ 4115, "fbe" ],
+[ 4116, "fbf" ],
+[ 4117, "fbg" ],
+[ 4118, "fbh" ],
+[ 4119, "fbi" ],
+[ 4120, "fbj" ],
+[ 4121, "fbk" ],
+[ 4122, "fbl" ],
+[ 4123, "fbm" ],
+[ 4124, "fbn" ],
+[ 4125, "fbo" ],
+[ 4126, "fbp" ],
+[ 4127, "fbq" ],
+[ 4128, "fbr" ],
+[ 4129, "fbs" ],
+[ 4130, "fbt" ],
+[ 4131, "fbu" ],
+[ 4132, "fbv" ],
+[ 4133, "fbw" ],
+[ 4134, "fbx" ],
+[ 4135, "fby" ],
+[ 4136, "fbz" ],
+[ 4137, "fca" ],
+[ 4138, "fcb" ],
+[ 4139, "fcc" ],
+[ 4140, "fcd" ],
+[ 4141, "fce" ],
+[ 4142, "fcf" ],
+[ 4143, "fcg" ],
+[ 4144, "fch" ],
+[ 4145, "fci" ],
+[ 4146, "fcj" ],
+[ 4147, "fck" ],
+[ 4148, "fcl" ],
+[ 4149, "fcm" ],
+[ 4150, "fcn" ],
+[ 4151, "fco" ],
+[ 4152, "fcp" ],
+[ 4153, "fcq" ],
+[ 4154, "fcr" ],
+[ 4155, "fcs" ],
+[ 4156, "fct" ],
+[ 4157, "fcu" ],
+[ 4158, "fcv" ],
+[ 4159, "fcw" ],
+[ 4160, "fcx" ],
+[ 4161, "fcy" ],
+[ 4162, "fcz" ],
+[ 4163, "fda" ],
+[ 4164, "fdb" ],
+[ 4165, "fdc" ],
+[ 4166, "fdd" ],
+[ 4167, "fde" ],
+[ 4168, "fdf" ],
+[ 4169, "fdg" ],
+[ 4170, "fdh" ],
+[ 4171, "fdi" ],
+[ 4172, "fdj" ],
+[ 4173, "fdk" ],
+[ 4174, "fdl" ],
+[ 4175, "fdm" ],
+[ 4176, "fdn" ],
+[ 4177, "fdo" ],
+[ 4178, "fdp" ],
+[ 4179, "fdq" ],
+[ 4180, "fdr" ],
+[ 4181, "fds" ],
+[ 4182, "fdt" ],
+[ 4183, "fdu" ],
+[ 4184, "fdv" ],
+[ 4185, "fdw" ],
+[ 4186, "fdx" ],
+[ 4187, "fdy" ],
+[ 4188, "fdz" ],
+[ 4189, "fea" ],
+[ 4190, "feb" ],
+[ 4191, "fec" ],
+[ 4192, "fed" ],
+[ 4193, "fee" ],
+[ 4194, "fef" ],
+[ 4195, "feg" ],
+[ 4196, "feh" ],
+[ 4197, "fei" ],
+[ 4198, "fej" ],
+[ 4199, "fek" ],
+[ 4200, "fel" ],
+[ 4201, "fem" ],
+[ 4202, "fen" ],
+[ 4203, "feo" ],
+[ 4204, "fep" ],
+[ 4205, "feq" ],
+[ 4206, "fer" ],
+[ 4207, "fes" ],
+[ 4208, "fet" ],
+[ 4209, "feu" ],
+[ 4210, "fev" ],
+[ 4211, "few" ],
+[ 4212, "fex" ],
+[ 4213, "fey" ],
+[ 4214, "fez" ],
+[ 4215, "ffa" ],
+[ 4216, "ffb" ],
+[ 4217, "ffc" ],
+[ 4218, "ffd" ],
+[ 4219, "ffe" ],
+[ 4220, "fff" ],
+[ 4221, "ffg" ],
+[ 4222, "ffh" ],
+[ 4223, "ffi" ],
+[ 4224, "ffj" ],
+[ 4225, "ffk" ],
+[ 4226, "ffl" ],
+[ 4227, "ffm" ],
+[ 4228, "ffn" ],
+[ 4229, "ffo" ],
+[ 4230, "ffp" ],
+[ 4231, "ffq" ],
+[ 4232, "ffr" ],
+[ 4233, "ffs" ],
+[ 4234, "fft" ],
+[ 4235, "ffu" ],
+[ 4236, "ffv" ],
+[ 4237, "ffw" ],
+[ 4238, "ffx" ],
+[ 4239, "ffy" ],
+[ 4240, "ffz" ],
+[ 4241, "fga" ],
+[ 4242, "fgb" ],
+[ 4243, "fgc" ],
+[ 4244, "fgd" ],
+[ 4245, "fge" ],
+[ 4246, "fgf" ],
+[ 4247, "fgg" ],
+[ 4248, "fgh" ],
+[ 4249, "fgi" ],
+[ 4250, "fgj" ],
+[ 4251, "fgk" ],
+[ 4252, "fgl" ],
+[ 4253, "fgm" ],
+[ 4254, "fgn" ],
+[ 4255, "fgo" ],
+[ 4256, "fgp" ],
+[ 4257, "fgq" ],
+[ 4258, "fgr" ],
+[ 4259, "fgs" ],
+[ 4260, "fgt" ],
+[ 4261, "fgu" ],
+[ 4262, "fgv" ],
+[ 4263, "fgw" ],
+[ 4264, "fgx" ],
+[ 4265, "fgy" ],
+[ 4266, "fgz" ],
+[ 4267, "fha" ],
+[ 4268, "fhb" ],
+[ 4269, "fhc" ],
+[ 4270, "fhd" ],
+[ 4271, "fhe" ],
+[ 4272, "fhf" ],
+[ 4273, "fhg" ],
+[ 4274, "fhh" ],
+[ 4275, "fhi" ],
+[ 4276, "fhj" ],
+[ 4277, "fhk" ],
+[ 4278, "fhl" ],
+[ 4279, "fhm" ],
+[ 4280, "fhn" ],
+[ 4281, "fho" ],
+[ 4282, "fhp" ],
+[ 4283, "fhq" ],
+[ 4284, "fhr" ],
+[ 4285, "fhs" ],
+[ 4286, "fht" ],
+[ 4287, "fhu" ],
+[ 4288, "fhv" ],
+[ 4289, "fhw" ],
+[ 4290, "fhx" ],
+[ 4291, "fhy" ],
+[ 4292, "fhz" ],
+[ 4293, "fia" ],
+[ 4294, "fib" ],
+[ 4295, "fic" ],
+[ 4296, "fid" ],
+[ 4297, "fie" ],
+[ 4298, "fif" ],
+[ 4299, "fig" ],
+[ 4300, "fih" ],
+[ 4301, "fii" ],
+[ 4302, "fij" ],
+[ 4303, "fik" ],
+[ 4304, "fil" ],
+[ 4305, "fim" ],
+[ 4306, "fin" ],
+[ 4307, "fio" ],
+[ 4308, "fip" ],
+[ 4309, "fiq" ],
+[ 4310, "fir" ],
+[ 4311, "fis" ],
+[ 4312, "fit" ],
+[ 4313, "fiu" ],
+[ 4314, "fiv" ],
+[ 4315, "fiw" ],
+[ 4316, "fix" ],
+[ 4317, "fiy" ],
+[ 4318, "fiz" ],
+[ 4319, "fja" ],
+[ 4320, "fjb" ],
+[ 4321, "fjc" ],
+[ 4322, "fjd" ],
+[ 4323, "fje" ],
+[ 4324, "fjf" ],
+[ 4325, "fjg" ],
+[ 4326, "fjh" ],
+[ 4327, "fji" ],
+[ 4328, "fjj" ],
+[ 4329, "fjk" ],
+[ 4330, "fjl" ],
+[ 4331, "fjm" ],
+[ 4332, "fjn" ],
+[ 4333, "fjo" ],
+[ 4334, "fjp" ],
+[ 4335, "fjq" ],
+[ 4336, "fjr" ],
+[ 4337, "fjs" ],
+[ 4338, "fjt" ],
+[ 4339, "fju" ],
+[ 4340, "fjv" ],
+[ 4341, "fjw" ],
+[ 4342, "fjx" ],
+[ 4343, "fjy" ],
+[ 4344, "fjz" ],
+[ 4345, "fka" ],
+[ 4346, "fkb" ],
+[ 4347, "fkc" ],
+[ 4348, "fkd" ],
+[ 4349, "fke" ],
+[ 4350, "fkf" ],
+[ 4351, "fkg" ],
+[ 4352, "fkh" ],
+[ 4353, "fki" ],
+[ 4354, "fkj" ],
+[ 4355, "fkk" ],
+[ 4356, "fkl" ],
+[ 4357, "fkm" ],
+[ 4358, "fkn" ],
+[ 4359, "fko" ],
+[ 4360, "fkp" ],
+[ 4361, "fkq" ],
+[ 4362, "fkr" ],
+[ 4363, "fks" ],
+[ 4364, "fkt" ],
+[ 4365, "fku" ],
+[ 4366, "fkv" ],
+[ 4367, "fkw" ],
+[ 4368, "fkx" ],
+[ 4369, "fky" ],
+[ 4370, "fkz" ],
+[ 4371, "fla" ],
+[ 4372, "flb" ],
+[ 4373, "flc" ],
+[ 4374, "fld" ],
+[ 4375, "fle" ],
+[ 4376, "flf" ],
+[ 4377, "flg" ],
+[ 4378, "flh" ],
+[ 4379, "fli" ],
+[ 4380, "flj" ],
+[ 4381, "flk" ],
+[ 4382, "fll" ],
+[ 4383, "flm" ],
+[ 4384, "fln" ],
+[ 4385, "flo" ],
+[ 4386, "flp" ],
+[ 4387, "flq" ],
+[ 4388, "flr" ],
+[ 4389, "fls" ],
+[ 4390, "flt" ],
+[ 4391, "flu" ],
+[ 4392, "flv" ],
+[ 4393, "flw" ],
+[ 4394, "flx" ],
+[ 4395, "fly" ],
+[ 4396, "flz" ],
+[ 4397, "fma" ],
+[ 4398, "fmb" ],
+[ 4399, "fmc" ],
+[ 4400, "fmd" ],
+[ 4401, "fme" ],
+[ 4402, "fmf" ],
+[ 4403, "fmg" ],
+[ 4404, "fmh" ],
+[ 4405, "fmi" ],
+[ 4406, "fmj" ],
+[ 4407, "fmk" ],
+[ 4408, "fml" ],
+[ 4409, "fmm" ],
+[ 4410, "fmn" ],
+[ 4411, "fmo" ],
+[ 4412, "fmp" ],
+[ 4413, "fmq" ],
+[ 4414, "fmr" ],
+[ 4415, "fms" ],
+[ 4416, "fmt" ],
+[ 4417, "fmu" ],
+[ 4418, "fmv" ],
+[ 4419, "fmw" ],
+[ 4420, "fmx" ],
+[ 4421, "fmy" ],
+[ 4422, "fmz" ],
+[ 4423, "fna" ],
+[ 4424, "fnb" ],
+[ 4425, "fnc" ],
+[ 4426, "fnd" ],
+[ 4427, "fne" ],
+[ 4428, "fnf" ],
+[ 4429, "fng" ],
+[ 4430, "fnh" ],
+[ 4431, "fni" ],
+[ 4432, "fnj" ],
+[ 4433, "fnk" ],
+[ 4434, "fnl" ],
+[ 4435, "fnm" ],
+[ 4436, "fnn" ],
+[ 4437, "fno" ],
+[ 4438, "fnp" ],
+[ 4439, "fnq" ],
+[ 4440, "fnr" ],
+[ 4441, "fns" ],
+[ 4442, "fnt" ],
+[ 4443, "fnu" ],
+[ 4444, "fnv" ],
+[ 4445, "fnw" ],
+[ 4446, "fnx" ],
+[ 4447, "fny" ],
+[ 4448, "fnz" ],
+[ 4449, "foa" ],
+[ 4450, "fob" ],
+[ 4451, "foc" ],
+[ 4452, "fod" ],
+[ 4453, "foe" ],
+[ 4454, "fof" ],
+[ 4455, "fog" ],
+[ 4456, "foh" ],
+[ 4457, "foi" ],
+[ 4458, "foj" ],
+[ 4459, "fok" ],
+[ 4460, "fol" ],
+[ 4461, "fom" ],
+[ 4462, "fon" ],
+[ 4463, "foo" ],
+[ 4464, "fop" ],
+[ 4465, "foq" ],
+[ 4466, "for" ],
+[ 4467, "fos" ],
+[ 4468, "fot" ],
+[ 4469, "fou" ],
+[ 4470, "fov" ],
+[ 4471, "fow" ],
+[ 4472, "fox" ],
+[ 4473, "foy" ],
+[ 4474, "foz" ],
+[ 4475, "fpa" ],
+[ 4476, "fpb" ],
+[ 4477, "fpc" ],
+[ 4478, "fpd" ],
+[ 4479, "fpe" ],
+[ 4480, "fpf" ],
+[ 4481, "fpg" ],
+[ 4482, "fph" ],
+[ 4483, "fpi" ],
+[ 4484, "fpj" ],
+[ 4485, "fpk" ],
+[ 4486, "fpl" ],
+[ 4487, "fpm" ],
+[ 4488, "fpn" ],
+[ 4489, "fpo" ],
+[ 4490, "fpp" ],
+[ 4491, "fpq" ],
+[ 4492, "fpr" ],
+[ 4493, "fps" ],
+[ 4494, "fpt" ],
+[ 4495, "fpu" ],
+[ 4496, "fpv" ],
+[ 4497, "fpw" ],
+[ 4498, "fpx" ],
+[ 4499, "fpy" ],
+[ 4500, "fpz" ],
+[ 4501, "fqa" ],
+[ 4502, "fqb" ],
+[ 4503, "fqc" ],
+[ 4504, "fqd" ],
+[ 4505, "fqe" ],
+[ 4506, "fqf" ],
+[ 4507, "fqg" ],
+[ 4508, "fqh" ],
+[ 4509, "fqi" ],
+[ 4510, "fqj" ],
+[ 4511, "fqk" ],
+[ 4512, "fql" ],
+[ 4513, "fqm" ],
+[ 4514, "fqn" ],
+[ 4515, "fqo" ],
+[ 4516, "fqp" ],
+[ 4517, "fqq" ],
+[ 4518, "fqr" ],
+[ 4519, "fqs" ],
+[ 4520, "fqt" ],
+[ 4521, "fqu" ],
+[ 4522, "fqv" ],
+[ 4523, "fqw" ],
+[ 4524, "fqx" ],
+[ 4525, "fqy" ],
+[ 4526, "fqz" ],
+[ 4527, "fra" ],
+[ 4528, "frb" ],
+[ 4529, "frc" ],
+[ 4530, "frd" ],
+[ 4531, "fre" ],
+[ 4532, "frf" ],
+[ 4533, "frg" ],
+[ 4534, "frh" ],
+[ 4535, "fri" ],
+[ 4536, "frj" ],
+[ 4537, "frk" ],
+[ 4538, "frl" ],
+[ 4539, "frm" ],
+[ 4540, "frn" ],
+[ 4541, "fro" ],
+[ 4542, "frp" ],
+[ 4543, "frq" ],
+[ 4544, "frr" ],
+[ 4545, "frs" ],
+[ 4546, "frt" ],
+[ 4547, "fru" ],
+[ 4548, "frv" ],
+[ 4549, "frw" ],
+[ 4550, "frx" ],
+[ 4551, "fry" ],
+[ 4552, "frz" ],
+[ 4553, "fsa" ],
+[ 4554, "fsb" ],
+[ 4555, "fsc" ],
+[ 4556, "fsd" ],
+[ 4557, "fse" ],
+[ 4558, "fsf" ],
+[ 4559, "fsg" ],
+[ 4560, "fsh" ],
+[ 4561, "fsi" ],
+[ 4562, "fsj" ],
+[ 4563, "fsk" ],
+[ 4564, "fsl" ],
+[ 4565, "fsm" ],
+[ 4566, "fsn" ],
+[ 4567, "fso" ],
+[ 4568, "fsp" ],
+[ 4569, "fsq" ],
+[ 4570, "fsr" ],
+[ 4571, "fss" ],
+[ 4572, "fst" ],
+[ 4573, "fsu" ],
+[ 4574, "fsv" ],
+[ 4575, "fsw" ],
+[ 4576, "fsx" ],
+[ 4577, "fsy" ],
+[ 4578, "fsz" ],
+[ 4579, "fta" ],
+[ 4580, "ftb" ],
+[ 4581, "ftc" ],
+[ 4582, "ftd" ],
+[ 4583, "fte" ],
+[ 4584, "ftf" ],
+[ 4585, "ftg" ],
+[ 4586, "fth" ],
+[ 4587, "fti" ],
+[ 4588, "ftj" ],
+[ 4589, "ftk" ],
+[ 4590, "ftl" ],
+[ 4591, "ftm" ],
+[ 4592, "ftn" ],
+[ 4593, "fto" ],
+[ 4594, "ftp" ],
+[ 4595, "ftq" ],
+[ 4596, "ftr" ],
+[ 4597, "fts" ],
+[ 4598, "ftt" ],
+[ 4599, "ftu" ],
+[ 4600, "ftv" ],
+[ 4601, "ftw" ],
+[ 4602, "ftx" ],
+[ 4603, "fty" ],
+[ 4604, "ftz" ],
+[ 4605, "fua" ],
+[ 4606, "fub" ],
+[ 4607, "fuc" ],
+[ 4608, "fud" ],
+[ 4609, "fue" ],
+[ 4610, "fuf" ],
+[ 4611, "fug" ],
+[ 4612, "fuh" ],
+[ 4613, "fui" ],
+[ 4614, "fuj" ],
+[ 4615, "fuk" ],
+[ 4616, "ful" ],
+[ 4617, "fum" ],
+[ 4618, "fun" ],
+[ 4619, "fuo" ],
+[ 4620, "fup" ],
+[ 4621, "fuq" ],
+[ 4622, "fur" ],
+[ 4623, "fus" ],
+[ 4624, "fut" ],
+[ 4625, "fuu" ],
+[ 4626, "fuv" ],
+[ 4627, "fuw" ],
+[ 4628, "fux" ],
+[ 4629, "fuy" ],
+[ 4630, "fuz" ],
+[ 4631, "fva" ],
+[ 4632, "fvb" ],
+[ 4633, "fvc" ],
+[ 4634, "fvd" ],
+[ 4635, "fve" ],
+[ 4636, "fvf" ],
+[ 4637, "fvg" ],
+[ 4638, "fvh" ],
+[ 4639, "fvi" ],
+[ 4640, "fvj" ],
+[ 4641, "fvk" ],
+[ 4642, "fvl" ],
+[ 4643, "fvm" ],
+[ 4644, "fvn" ],
+[ 4645, "fvo" ],
+[ 4646, "fvp" ],
+[ 4647, "fvq" ],
+[ 4648, "fvr" ],
+[ 4649, "fvs" ],
+[ 4650, "fvt" ],
+[ 4651, "fvu" ],
+[ 4652, "fvv" ],
+[ 4653, "fvw" ],
+[ 4654, "fvx" ],
+[ 4655, "fvy" ],
+[ 4656, "fvz" ],
+[ 4657, "fwa" ],
+[ 4658, "fwb" ],
+[ 4659, "fwc" ],
+[ 4660, "fwd" ],
+[ 4661, "fwe" ],
+[ 4662, "fwf" ],
+[ 4663, "fwg" ],
+[ 4664, "fwh" ],
+[ 4665, "fwi" ],
+[ 4666, "fwj" ],
+[ 4667, "fwk" ],
+[ 4668, "fwl" ],
+[ 4669, "fwm" ],
+[ 4670, "fwn" ],
+[ 4671, "fwo" ],
+[ 4672, "fwp" ],
+[ 4673, "fwq" ],
+[ 4674, "fwr" ],
+[ 4675, "fws" ],
+[ 4676, "fwt" ],
+[ 4677, "fwu" ],
+[ 4678, "fwv" ],
+[ 4679, "fww" ],
+[ 4680, "fwx" ],
+[ 4681, "fwy" ],
+[ 4682, "fwz" ],
+[ 4683, "fxa" ],
+[ 4684, "fxb" ],
+[ 4685, "fxc" ],
+[ 4686, "fxd" ],
+[ 4687, "fxe" ],
+[ 4688, "fxf" ],
+[ 4689, "fxg" ],
+[ 4690, "fxh" ],
+[ 4691, "fxi" ],
+[ 4692, "fxj" ],
+[ 4693, "fxk" ],
+[ 4694, "fxl" ],
+[ 4695, "fxm" ],
+[ 4696, "fxn" ],
+[ 4697, "fxo" ],
+[ 4698, "fxp" ],
+[ 4699, "fxq" ],
+[ 4700, "fxr" ],
+[ 4701, "fxs" ],
+[ 4702, "fxt" ],
+[ 4703, "fxu" ],
+[ 4704, "fxv" ],
+[ 4705, "fxw" ],
+[ 4706, "fxx" ],
+[ 4707, "fxy" ],
+[ 4708, "fxz" ],
+[ 4709, "fya" ],
+[ 4710, "fyb" ],
+[ 4711, "fyc" ],
+[ 4712, "fyd" ],
+[ 4713, "fye" ],
+[ 4714, "fyf" ],
+[ 4715, "fyg" ],
+[ 4716, "fyh" ],
+[ 4717, "fyi" ],
+[ 4718, "fyj" ],
+[ 4719, "fyk" ],
+[ 4720, "fyl" ],
+[ 4721, "fym" ],
+[ 4722, "fyn" ],
+[ 4723, "fyo" ],
+[ 4724, "fyp" ],
+[ 4725, "fyq" ],
+[ 4726, "fyr" ],
+[ 4727, "fys" ],
+[ 4728, "fyt" ],
+[ 4729, "fyu" ],
+[ 4730, "fyv" ],
+[ 4731, "fyw" ],
+[ 4732, "fyx" ],
+[ 4733, "fyy" ],
+[ 4734, "fyz" ],
+[ 4735, "fza" ],
+[ 4736, "fzb" ],
+[ 4737, "fzc" ],
+[ 4738, "fzd" ],
+[ 4739, "fze" ],
+[ 4740, "fzf" ],
+[ 4741, "fzg" ],
+[ 4742, "fzh" ],
+[ 4743, "fzi" ],
+[ 4744, "fzj" ],
+[ 4745, "fzk" ],
+[ 4746, "fzl" ],
+[ 4747, "fzm" ],
+[ 4748, "fzn" ],
+[ 4749, "fzo" ],
+[ 4750, "fzp" ],
+[ 4751, "fzq" ],
+[ 4752, "fzr" ],
+[ 4753, "fzs" ],
+[ 4754, "fzt" ],
+[ 4755, "fzu" ],
+[ 4756, "fzv" ],
+[ 4757, "fzw" ],
+[ 4758, "fzx" ],
+[ 4759, "fzy" ],
+[ 4760, "fzz" ],
+[ 4761, "gaa" ],
+[ 4762, "gab" ],
+[ 4763, "gac" ],
+[ 4764, "gad" ],
+[ 4765, "gae" ],
+[ 4766, "gaf" ],
+[ 4767, "gag" ],
+[ 4768, "gah" ],
+[ 4769, "gai" ],
+[ 4770, "gaj" ],
+[ 4771, "gak" ],
+[ 4772, "gal" ],
+[ 4773, "gam" ],
+[ 4774, "gan" ],
+[ 4775, "gao" ],
+[ 4776, "gap" ],
+[ 4777, "gaq" ],
+[ 4778, "gar" ],
+[ 4779, "gas" ],
+[ 4780, "gat" ],
+[ 4781, "gau" ],
+[ 4782, "gav" ],
+[ 4783, "gaw" ],
+[ 4784, "gax" ],
+[ 4785, "gay" ],
+[ 4786, "gaz" ],
+[ 4787, "gba" ],
+[ 4788, "gbb" ],
+[ 4789, "gbc" ],
+[ 4790, "gbd" ],
+[ 4791, "gbe" ],
+[ 4792, "gbf" ],
+[ 4793, "gbg" ],
+[ 4794, "gbh" ],
+[ 4795, "gbi" ],
+[ 4796, "gbj" ],
+[ 4797, "gbk" ],
+[ 4798, "gbl" ],
+[ 4799, "gbm" ],
+[ 4800, "gbn" ],
+[ 4801, "gbo" ],
+[ 4802, "gbp" ],
+[ 4803, "gbq" ],
+[ 4804, "gbr" ],
+[ 4805, "gbs" ],
+[ 4806, "gbt" ],
+[ 4807, "gbu" ],
+[ 4808, "gbv" ],
+[ 4809, "gbw" ],
+[ 4810, "gbx" ],
+[ 4811, "gby" ],
+[ 4812, "gbz" ],
+[ 4813, "gca" ],
+[ 4814, "gcb" ],
+[ 4815, "gcc" ],
+[ 4816, "gcd" ],
+[ 4817, "gce" ],
+[ 4818, "gcf" ],
+[ 4819, "gcg" ],
+[ 4820, "gch" ],
+[ 4821, "gci" ],
+[ 4822, "gcj" ],
+[ 4823, "gck" ],
+[ 4824, "gcl" ],
+[ 4825, "gcm" ],
+[ 4826, "gcn" ],
+[ 4827, "gco" ],
+[ 4828, "gcp" ],
+[ 4829, "gcq" ],
+[ 4830, "gcr" ],
+[ 4831, "gcs" ],
+[ 4832, "gct" ],
+[ 4833, "gcu" ],
+[ 4834, "gcv" ],
+[ 4835, "gcw" ],
+[ 4836, "gcx" ],
+[ 4837, "gcy" ],
+[ 4838, "gcz" ],
+[ 4839, "gda" ],
+[ 4840, "gdb" ],
+[ 4841, "gdc" ],
+[ 4842, "gdd" ],
+[ 4843, "gde" ],
+[ 4844, "gdf" ],
+[ 4845, "gdg" ],
+[ 4846, "gdh" ],
+[ 4847, "gdi" ],
+[ 4848, "gdj" ],
+[ 4849, "gdk" ],
+[ 4850, "gdl" ],
+[ 4851, "gdm" ],
+[ 4852, "gdn" ],
+[ 4853, "gdo" ],
+[ 4854, "gdp" ],
+[ 4855, "gdq" ],
+[ 4856, "gdr" ],
+[ 4857, "gds" ],
+[ 4858, "gdt" ],
+[ 4859, "gdu" ],
+[ 4860, "gdv" ],
+[ 4861, "gdw" ],
+[ 4862, "gdx" ],
+[ 4863, "gdy" ],
+[ 4864, "gdz" ],
+[ 4865, "gea" ],
+[ 4866, "geb" ],
+[ 4867, "gec" ],
+[ 4868, "ged" ],
+[ 4869, "gee" ],
+[ 4870, "gef" ],
+[ 4871, "geg" ],
+[ 4872, "geh" ],
+[ 4873, "gei" ],
+[ 4874, "gej" ],
+[ 4875, "gek" ],
+[ 4876, "gel" ],
+[ 4877, "gem" ],
+[ 4878, "gen" ],
+[ 4879, "geo" ],
+[ 4880, "gep" ],
+[ 4881, "geq" ],
+[ 4882, "ger" ],
+[ 4883, "ges" ],
+[ 4884, "get" ],
+[ 4885, "geu" ],
+[ 4886, "gev" ],
+[ 4887, "gew" ],
+[ 4888, "gex" ],
+[ 4889, "gey" ],
+[ 4890, "gez" ],
+[ 4891, "gfa" ],
+[ 4892, "gfb" ],
+[ 4893, "gfc" ],
+[ 4894, "gfd" ],
+[ 4895, "gfe" ],
+[ 4896, "gff" ],
+[ 4897, "gfg" ],
+[ 4898, "gfh" ],
+[ 4899, "gfi" ],
+[ 4900, "gfj" ],
+[ 4901, "gfk" ],
+[ 4902, "gfl" ],
+[ 4903, "gfm" ],
+[ 4904, "gfn" ],
+[ 4905, "gfo" ],
+[ 4906, "gfp" ],
+[ 4907, "gfq" ],
+[ 4908, "gfr" ],
+[ 4909, "gfs" ],
+[ 4910, "gft" ],
+[ 4911, "gfu" ],
+[ 4912, "gfv" ],
+[ 4913, "gfw" ],
+[ 4914, "gfx" ],
+[ 4915, "gfy" ],
+[ 4916, "gfz" ],
+[ 4917, "gga" ],
+[ 4918, "ggb" ],
+[ 4919, "ggc" ],
+[ 4920, "ggd" ],
+[ 4921, "gge" ],
+[ 4922, "ggf" ],
+[ 4923, "ggg" ],
+[ 4924, "ggh" ],
+[ 4925, "ggi" ],
+[ 4926, "ggj" ],
+[ 4927, "ggk" ],
+[ 4928, "ggl" ],
+[ 4929, "ggm" ],
+[ 4930, "ggn" ],
+[ 4931, "ggo" ],
+[ 4932, "ggp" ],
+[ 4933, "ggq" ],
+[ 4934, "ggr" ],
+[ 4935, "ggs" ],
+[ 4936, "ggt" ],
+[ 4937, "ggu" ],
+[ 4938, "ggv" ],
+[ 4939, "ggw" ],
+[ 4940, "ggx" ],
+[ 4941, "ggy" ],
+[ 4942, "ggz" ],
+[ 4943, "gha" ],
+[ 4944, "ghb" ],
+[ 4945, "ghc" ],
+[ 4946, "ghd" ],
+[ 4947, "ghe" ],
+[ 4948, "ghf" ],
+[ 4949, "ghg" ],
+[ 4950, "ghh" ],
+[ 4951, "ghi" ],
+[ 4952, "ghj" ],
+[ 4953, "ghk" ],
+[ 4954, "ghl" ],
+[ 4955, "ghm" ],
+[ 4956, "ghn" ],
+[ 4957, "gho" ],
+[ 4958, "ghp" ],
+[ 4959, "ghq" ],
+[ 4960, "ghr" ],
+[ 4961, "ghs" ],
+[ 4962, "ght" ],
+[ 4963, "ghu" ],
+[ 4964, "ghv" ],
+[ 4965, "ghw" ],
+[ 4966, "ghx" ],
+[ 4967, "ghy" ],
+[ 4968, "ghz" ],
+[ 4969, "gia" ],
+[ 4970, "gib" ],
+[ 4971, "gic" ],
+[ 4972, "gid" ],
+[ 4973, "gie" ],
+[ 4974, "gif" ],
+[ 4975, "gig" ],
+[ 4976, "gih" ],
+[ 4977, "gii" ],
+[ 4978, "gij" ],
+[ 4979, "gik" ],
+[ 4980, "gil" ],
+[ 4981, "gim" ],
+[ 4982, "gin" ],
+[ 4983, "gio" ],
+[ 4984, "gip" ],
+[ 4985, "giq" ],
+[ 4986, "gir" ],
+[ 4987, "gis" ],
+[ 4988, "git" ],
+[ 4989, "giu" ],
+[ 4990, "giv" ],
+[ 4991, "giw" ],
+[ 4992, "gix" ],
+[ 4993, "giy" ],
+[ 4994, "giz" ],
+[ 4995, "gja" ],
+[ 4996, "gjb" ],
+[ 4997, "gjc" ],
+[ 4998, "gjd" ],
+[ 4999, "gje" ],
+[ 5000, "gjf" ],
+[ 5001, "gjg" ],
+[ 5002, "gjh" ],
+[ 5003, "gji" ],
+[ 5004, "gjj" ],
+[ 5005, "gjk" ],
+[ 5006, "gjl" ],
+[ 5007, "gjm" ],
+[ 5008, "gjn" ],
+[ 5009, "gjo" ],
+[ 5010, "gjp" ],
+[ 5011, "gjq" ],
+[ 5012, "gjr" ],
+[ 5013, "gjs" ],
+[ 5014, "gjt" ],
+[ 5015, "gju" ],
+[ 5016, "gjv" ],
+[ 5017, "gjw" ],
+[ 5018, "gjx" ],
+[ 5019, "gjy" ],
+[ 5020, "gjz" ],
+[ 5021, "gka" ],
+[ 5022, "gkb" ],
+[ 5023, "gkc" ],
+[ 5024, "gkd" ],
+[ 5025, "gke" ],
+[ 5026, "gkf" ],
+[ 5027, "gkg" ],
+[ 5028, "gkh" ],
+[ 5029, "gki" ],
+[ 5030, "gkj" ],
+[ 5031, "gkk" ],
+[ 5032, "gkl" ],
+[ 5033, "gkm" ],
+[ 5034, "gkn" ],
+[ 5035, "gko" ],
+[ 5036, "gkp" ],
+[ 5037, "gkq" ],
+[ 5038, "gkr" ],
+[ 5039, "gks" ],
+[ 5040, "gkt" ],
+[ 5041, "gku" ],
+[ 5042, "gkv" ],
+[ 5043, "gkw" ],
+[ 5044, "gkx" ],
+[ 5045, "gky" ],
+[ 5046, "gkz" ],
+[ 5047, "gla" ],
+[ 5048, "glb" ],
+[ 5049, "glc" ],
+[ 5050, "gld" ],
+[ 5051, "gle" ],
+[ 5052, "glf" ],
+[ 5053, "glg" ],
+[ 5054, "glh" ],
+[ 5055, "gli" ],
+[ 5056, "glj" ],
+[ 5057, "glk" ],
+[ 5058, "gll" ],
+[ 5059, "glm" ],
+[ 5060, "gln" ],
+[ 5061, "glo" ],
+[ 5062, "glp" ],
+[ 5063, "glq" ],
+[ 5064, "glr" ],
+[ 5065, "gls" ],
+[ 5066, "glt" ],
+[ 5067, "glu" ],
+[ 5068, "glv" ],
+[ 5069, "glw" ],
+[ 5070, "glx" ],
+[ 5071, "gly" ],
+[ 5072, "glz" ],
+[ 5073, "gma" ],
+[ 5074, "gmb" ],
+[ 5075, "gmc" ],
+[ 5076, "gmd" ],
+[ 5077, "gme" ],
+[ 5078, "gmf" ],
+[ 5079, "gmg" ],
+[ 5080, "gmh" ],
+[ 5081, "gmi" ],
+[ 5082, "gmj" ],
+[ 5083, "gmk" ],
+[ 5084, "gml" ],
+[ 5085, "gmm" ],
+[ 5086, "gmn" ],
+[ 5087, "gmo" ],
+[ 5088, "gmp" ],
+[ 5089, "gmq" ],
+[ 5090, "gmr" ],
+[ 5091, "gms" ],
+[ 5092, "gmt" ],
+[ 5093, "gmu" ],
+[ 5094, "gmv" ],
+[ 5095, "gmw" ],
+[ 5096, "gmx" ],
+[ 5097, "gmy" ],
+[ 5098, "gmz" ],
+[ 5099, "gna" ],
+[ 5100, "gnb" ],
+[ 5101, "gnc" ],
+[ 5102, "gnd" ],
+[ 5103, "gne" ],
+[ 5104, "gnf" ],
+[ 5105, "gng" ],
+[ 5106, "gnh" ],
+[ 5107, "gni" ],
+[ 5108, "gnj" ],
+[ 5109, "gnk" ],
+[ 5110, "gnl" ],
+[ 5111, "gnm" ],
+[ 5112, "gnn" ],
+[ 5113, "gno" ],
+[ 5114, "gnp" ],
+[ 5115, "gnq" ],
+[ 5116, "gnr" ],
+[ 5117, "gns" ],
+[ 5118, "gnt" ],
+[ 5119, "gnu" ],
+[ 5120, "gnv" ],
+[ 5121, "gnw" ],
+[ 5122, "gnx" ],
+[ 5123, "gny" ],
+[ 5124, "gnz" ],
+[ 5125, "goa" ],
+[ 5126, "gob" ],
+[ 5127, "goc" ],
+[ 5128, "god" ],
+[ 5129, "goe" ],
+[ 5130, "gof" ],
+[ 5131, "gog" ],
+[ 5132, "goh" ],
+[ 5133, "goi" ],
+[ 5134, "goj" ],
+[ 5135, "gok" ],
+[ 5136, "gol" ],
+[ 5137, "gom" ],
+[ 5138, "gon" ],
+[ 5139, "goo" ],
+[ 5140, "gop" ],
+[ 5141, "goq" ],
+[ 5142, "gor" ],
+[ 5143, "gos" ],
+[ 5144, "got" ],
+[ 5145, "gou" ],
+[ 5146, "gov" ],
+[ 5147, "gow" ],
+[ 5148, "gox" ],
+[ 5149, "goy" ],
+[ 5150, "goz" ],
+[ 5151, "gpa" ],
+[ 5152, "gpb" ],
+[ 5153, "gpc" ],
+[ 5154, "gpd" ],
+[ 5155, "gpe" ],
+[ 5156, "gpf" ],
+[ 5157, "gpg" ],
+[ 5158, "gph" ],
+[ 5159, "gpi" ],
+[ 5160, "gpj" ],
+[ 5161, "gpk" ],
+[ 5162, "gpl" ],
+[ 5163, "gpm" ],
+[ 5164, "gpn" ],
+[ 5165, "gpo" ],
+[ 5166, "gpp" ],
+[ 5167, "gpq" ],
+[ 5168, "gpr" ],
+[ 5169, "gps" ],
+[ 5170, "gpt" ],
+[ 5171, "gpu" ],
+[ 5172, "gpv" ],
+[ 5173, "gpw" ],
+[ 5174, "gpx" ],
+[ 5175, "gpy" ],
+[ 5176, "gpz" ],
+[ 5177, "gqa" ],
+[ 5178, "gqb" ],
+[ 5179, "gqc" ],
+[ 5180, "gqd" ],
+[ 5181, "gqe" ],
+[ 5182, "gqf" ],
+[ 5183, "gqg" ],
+[ 5184, "gqh" ],
+[ 5185, "gqi" ],
+[ 5186, "gqj" ],
+[ 5187, "gqk" ],
+[ 5188, "gql" ],
+[ 5189, "gqm" ],
+[ 5190, "gqn" ],
+[ 5191, "gqo" ],
+[ 5192, "gqp" ],
+[ 5193, "gqq" ],
+[ 5194, "gqr" ],
+[ 5195, "gqs" ],
+[ 5196, "gqt" ],
+[ 5197, "gqu" ],
+[ 5198, "gqv" ],
+[ 5199, "gqw" ],
+[ 5200, "gqx" ],
+[ 5201, "gqy" ],
+[ 5202, "gqz" ],
+[ 5203, "gra" ],
+[ 5204, "grb" ],
+[ 5205, "grc" ],
+[ 5206, "grd" ],
+[ 5207, "gre" ],
+[ 5208, "grf" ],
+[ 5209, "grg" ],
+[ 5210, "grh" ],
+[ 5211, "gri" ],
+[ 5212, "grj" ],
+[ 5213, "grk" ],
+[ 5214, "grl" ],
+[ 5215, "grm" ],
+[ 5216, "grn" ],
+[ 5217, "gro" ],
+[ 5218, "grp" ],
+[ 5219, "grq" ],
+[ 5220, "grr" ],
+[ 5221, "grs" ],
+[ 5222, "grt" ],
+[ 5223, "gru" ],
+[ 5224, "grv" ],
+[ 5225, "grw" ],
+[ 5226, "grx" ],
+[ 5227, "gry" ],
+[ 5228, "grz" ],
+[ 5229, "gsa" ],
+[ 5230, "gsb" ],
+[ 5231, "gsc" ],
+[ 5232, "gsd" ],
+[ 5233, "gse" ],
+[ 5234, "gsf" ],
+[ 5235, "gsg" ],
+[ 5236, "gsh" ],
+[ 5237, "gsi" ],
+[ 5238, "gsj" ],
+[ 5239, "gsk" ],
+[ 5240, "gsl" ],
+[ 5241, "gsm" ],
+[ 5242, "gsn" ],
+[ 5243, "gso" ],
+[ 5244, "gsp" ],
+[ 5245, "gsq" ],
+[ 5246, "gsr" ],
+[ 5247, "gss" ],
+[ 5248, "gst" ],
+[ 5249, "gsu" ],
+[ 5250, "gsv" ],
+[ 5251, "gsw" ],
+[ 5252, "gsx" ],
+[ 5253, "gsy" ],
+[ 5254, "gsz" ],
+[ 5255, "gta" ],
+[ 5256, "gtb" ],
+[ 5257, "gtc" ],
+[ 5258, "gtd" ],
+[ 5259, "gte" ],
+[ 5260, "gtf" ],
+[ 5261, "gtg" ],
+[ 5262, "gth" ],
+[ 5263, "gti" ],
+[ 5264, "gtj" ],
+[ 5265, "gtk" ],
+[ 5266, "gtl" ],
+[ 5267, "gtm" ],
+[ 5268, "gtn" ],
+[ 5269, "gto" ],
+[ 5270, "gtp" ],
+[ 5271, "gtq" ],
+[ 5272, "gtr" ],
+[ 5273, "gts" ],
+[ 5274, "gtt" ],
+[ 5275, "gtu" ],
+[ 5276, "gtv" ],
+[ 5277, "gtw" ],
+[ 5278, "gtx" ],
+[ 5279, "gty" ],
+[ 5280, "gtz" ],
+[ 5281, "gua" ],
+[ 5282, "gub" ],
+[ 5283, "guc" ],
+[ 5284, "gud" ],
+[ 5285, "gue" ],
+[ 5286, "guf" ],
+[ 5287, "gug" ],
+[ 5288, "guh" ],
+[ 5289, "gui" ],
+[ 5290, "guj" ],
+[ 5291, "guk" ],
+[ 5292, "gul" ],
+[ 5293, "gum" ],
+[ 5294, "gun" ],
+[ 5295, "guo" ],
+[ 5296, "gup" ],
+[ 5297, "guq" ],
+[ 5298, "gur" ],
+[ 5299, "gus" ],
+[ 5300, "gut" ],
+[ 5301, "guu" ],
+[ 5302, "guv" ],
+[ 5303, "guw" ],
+[ 5304, "gux" ],
+[ 5305, "guy" ],
+[ 5306, "guz" ],
+[ 5307, "gva" ],
+[ 5308, "gvb" ],
+[ 5309, "gvc" ],
+[ 5310, "gvd" ],
+[ 5311, "gve" ],
+[ 5312, "gvf" ],
+[ 5313, "gvg" ],
+[ 5314, "gvh" ],
+[ 5315, "gvi" ],
+[ 5316, "gvj" ],
+[ 5317, "gvk" ],
+[ 5318, "gvl" ],
+[ 5319, "gvm" ],
+[ 5320, "gvn" ],
+[ 5321, "gvo" ],
+[ 5322, "gvp" ],
+[ 5323, "gvq" ],
+[ 5324, "gvr" ],
+[ 5325, "gvs" ],
+[ 5326, "gvt" ],
+[ 5327, "gvu" ],
+[ 5328, "gvv" ],
+[ 5329, "gvw" ],
+[ 5330, "gvx" ],
+[ 5331, "gvy" ],
+[ 5332, "gvz" ],
+[ 5333, "gwa" ],
+[ 5334, "gwb" ],
+[ 5335, "gwc" ],
+[ 5336, "gwd" ],
+[ 5337, "gwe" ],
+[ 5338, "gwf" ],
+[ 5339, "gwg" ],
+[ 5340, "gwh" ],
+[ 5341, "gwi" ],
+[ 5342, "gwj" ],
+[ 5343, "gwk" ],
+[ 5344, "gwl" ],
+[ 5345, "gwm" ],
+[ 5346, "gwn" ],
+[ 5347, "gwo" ],
+[ 5348, "gwp" ],
+[ 5349, "gwq" ],
+[ 5350, "gwr" ],
+[ 5351, "gws" ],
+[ 5352, "gwt" ],
+[ 5353, "gwu" ],
+[ 5354, "gwv" ],
+[ 5355, "gww" ],
+[ 5356, "gwx" ],
+[ 5357, "gwy" ],
+[ 5358, "gwz" ],
+[ 5359, "gxa" ],
+[ 5360, "gxb" ],
+[ 5361, "gxc" ],
+[ 5362, "gxd" ],
+[ 5363, "gxe" ],
+[ 5364, "gxf" ],
+[ 5365, "gxg" ],
+[ 5366, "gxh" ],
+[ 5367, "gxi" ],
+[ 5368, "gxj" ],
+[ 5369, "gxk" ],
+[ 5370, "gxl" ],
+[ 5371, "gxm" ],
+[ 5372, "gxn" ],
+[ 5373, "gxo" ],
+[ 5374, "gxp" ],
+[ 5375, "gxq" ],
+[ 5376, "gxr" ],
+[ 5377, "gxs" ],
+[ 5378, "gxt" ],
+[ 5379, "gxu" ],
+[ 5380, "gxv" ],
+[ 5381, "gxw" ],
+[ 5382, "gxx" ],
+[ 5383, "gxy" ],
+[ 5384, "gxz" ],
+[ 5385, "gya" ],
+[ 5386, "gyb" ],
+[ 5387, "gyc" ],
+[ 5388, "gyd" ],
+[ 5389, "gye" ],
+[ 5390, "gyf" ],
+[ 5391, "gyg" ],
+[ 5392, "gyh" ],
+[ 5393, "gyi" ],
+[ 5394, "gyj" ],
+[ 5395, "gyk" ],
+[ 5396, "gyl" ],
+[ 5397, "gym" ],
+[ 5398, "gyn" ],
+[ 5399, "gyo" ],
+[ 5400, "gyp" ],
+[ 5401, "gyq" ],
+[ 5402, "gyr" ],
+[ 5403, "gys" ],
+[ 5404, "gyt" ],
+[ 5405, "gyu" ],
+[ 5406, "gyv" ],
+[ 5407, "gyw" ],
+[ 5408, "gyx" ],
+[ 5409, "gyy" ],
+[ 5410, "gyz" ],
+[ 5411, "gza" ],
+[ 5412, "gzb" ],
+[ 5413, "gzc" ],
+[ 5414, "gzd" ],
+[ 5415, "gze" ],
+[ 5416, "gzf" ],
+[ 5417, "gzg" ],
+[ 5418, "gzh" ],
+[ 5419, "gzi" ],
+[ 5420, "gzj" ],
+[ 5421, "gzk" ],
+[ 5422, "gzl" ],
+[ 5423, "gzm" ],
+[ 5424, "gzn" ],
+[ 5425, "gzo" ],
+[ 5426, "gzp" ],
+[ 5427, "gzq" ],
+[ 5428, "gzr" ],
+[ 5429, "gzs" ],
+[ 5430, "gzt" ],
+[ 5431, "gzu" ],
+[ 5432, "gzv" ],
+[ 5433, "gzw" ],
+[ 5434, "gzx" ],
+[ 5435, "gzy" ],
+[ 5436, "gzz" ],
+[ 5437, "haa" ],
+[ 5438, "hab" ],
+[ 5439, "hac" ],
+[ 5440, "had" ],
+[ 5441, "hae" ],
+[ 5442, "haf" ],
+[ 5443, "hag" ],
+[ 5444, "hah" ],
+[ 5445, "hai" ],
+[ 5446, "haj" ],
+[ 5447, "hak" ],
+[ 5448, "hal" ],
+[ 5449, "ham" ],
+[ 5450, "han" ],
+[ 5451, "hao" ],
+[ 5452, "hap" ],
+[ 5453, "haq" ],
+[ 5454, "har" ],
+[ 5455, "has" ],
+[ 5456, "hat" ],
+[ 5457, "hau" ],
+[ 5458, "hav" ],
+[ 5459, "haw" ],
+[ 5460, "hax" ],
+[ 5461, "hay" ],
+[ 5462, "haz" ],
+[ 5463, "hba" ],
+[ 5464, "hbb" ],
+[ 5465, "hbc" ],
+[ 5466, "hbd" ],
+[ 5467, "hbe" ],
+[ 5468, "hbf" ],
+[ 5469, "hbg" ],
+[ 5470, "hbh" ],
+[ 5471, "hbi" ],
+[ 5472, "hbj" ],
+[ 5473, "hbk" ],
+[ 5474, "hbl" ],
+[ 5475, "hbm" ],
+[ 5476, "hbn" ],
+[ 5477, "hbo" ],
+[ 5478, "hbp" ],
+[ 5479, "hbq" ],
+[ 5480, "hbr" ],
+[ 5481, "hbs" ],
+[ 5482, "hbt" ],
+[ 5483, "hbu" ],
+[ 5484, "hbv" ],
+[ 5485, "hbw" ],
+[ 5486, "hbx" ],
+[ 5487, "hby" ],
+[ 5488, "hbz" ],
+[ 5489, "hca" ],
+[ 5490, "hcb" ],
+[ 5491, "hcc" ],
+[ 5492, "hcd" ],
+[ 5493, "hce" ],
+[ 5494, "hcf" ],
+[ 5495, "hcg" ],
+[ 5496, "hch" ],
+[ 5497, "hci" ],
+[ 5498, "hcj" ],
+[ 5499, "hck" ],
+[ 5500, "hcl" ],
+[ 5501, "hcm" ],
+[ 5502, "hcn" ],
+[ 5503, "hco" ],
+[ 5504, "hcp" ],
+[ 5505, "hcq" ],
+[ 5506, "hcr" ],
+[ 5507, "hcs" ],
+[ 5508, "hct" ],
+[ 5509, "hcu" ],
+[ 5510, "hcv" ],
+[ 5511, "hcw" ],
+[ 5512, "hcx" ],
+[ 5513, "hcy" ],
+[ 5514, "hcz" ],
+[ 5515, "hda" ],
+[ 5516, "hdb" ],
+[ 5517, "hdc" ],
+[ 5518, "hdd" ],
+[ 5519, "hde" ],
+[ 5520, "hdf" ],
+[ 5521, "hdg" ],
+[ 5522, "hdh" ],
+[ 5523, "hdi" ],
+[ 5524, "hdj" ],
+[ 5525, "hdk" ],
+[ 5526, "hdl" ],
+[ 5527, "hdm" ],
+[ 5528, "hdn" ],
+[ 5529, "hdo" ],
+[ 5530, "hdp" ],
+[ 5531, "hdq" ],
+[ 5532, "hdr" ],
+[ 5533, "hds" ],
+[ 5534, "hdt" ],
+[ 5535, "hdu" ],
+[ 5536, "hdv" ],
+[ 5537, "hdw" ],
+[ 5538, "hdx" ],
+[ 5539, "hdy" ],
+[ 5540, "hdz" ],
+[ 5541, "hea" ],
+[ 5542, "heb" ],
+[ 5543, "hec" ],
+[ 5544, "hed" ],
+[ 5545, "hee" ],
+[ 5546, "hef" ],
+[ 5547, "heg" ],
+[ 5548, "heh" ],
+[ 5549, "hei" ],
+[ 5550, "hej" ],
+[ 5551, "hek" ],
+[ 5552, "hel" ],
+[ 5553, "hem" ],
+[ 5554, "hen" ],
+[ 5555, "heo" ],
+[ 5556, "hep" ],
+[ 5557, "heq" ],
+[ 5558, "her" ],
+[ 5559, "hes" ],
+[ 5560, "het" ],
+[ 5561, "heu" ],
+[ 5562, "hev" ],
+[ 5563, "hew" ],
+[ 5564, "hex" ],
+[ 5565, "hey" ],
+[ 5566, "hez" ],
+[ 5567, "hfa" ],
+[ 5568, "hfb" ],
+[ 5569, "hfc" ],
+[ 5570, "hfd" ],
+[ 5571, "hfe" ],
+[ 5572, "hff" ],
+[ 5573, "hfg" ],
+[ 5574, "hfh" ],
+[ 5575, "hfi" ],
+[ 5576, "hfj" ],
+[ 5577, "hfk" ],
+[ 5578, "hfl" ],
+[ 5579, "hfm" ],
+[ 5580, "hfn" ],
+[ 5581, "hfo" ],
+[ 5582, "hfp" ],
+[ 5583, "hfq" ],
+[ 5584, "hfr" ],
+[ 5585, "hfs" ],
+[ 5586, "hft" ],
+[ 5587, "hfu" ],
+[ 5588, "hfv" ],
+[ 5589, "hfw" ],
+[ 5590, "hfx" ],
+[ 5591, "hfy" ],
+[ 5592, "hfz" ],
+[ 5593, "hga" ],
+[ 5594, "hgb" ],
+[ 5595, "hgc" ],
+[ 5596, "hgd" ],
+[ 5597, "hge" ],
+[ 5598, "hgf" ],
+[ 5599, "hgg" ],
+[ 5600, "hgh" ],
+[ 5601, "hgi" ],
+[ 5602, "hgj" ],
+[ 5603, "hgk" ],
+[ 5604, "hgl" ],
+[ 5605, "hgm" ],
+[ 5606, "hgn" ],
+[ 5607, "hgo" ],
+[ 5608, "hgp" ],
+[ 5609, "hgq" ],
+[ 5610, "hgr" ],
+[ 5611, "hgs" ],
+[ 5612, "hgt" ],
+[ 5613, "hgu" ],
+[ 5614, "hgv" ],
+[ 5615, "hgw" ],
+[ 5616, "hgx" ],
+[ 5617, "hgy" ],
+[ 5618, "hgz" ],
+[ 5619, "hha" ],
+[ 5620, "hhb" ],
+[ 5621, "hhc" ],
+[ 5622, "hhd" ],
+[ 5623, "hhe" ],
+[ 5624, "hhf" ],
+[ 5625, "hhg" ],
+[ 5626, "hhh" ],
+[ 5627, "hhi" ],
+[ 5628, "hhj" ],
+[ 5629, "hhk" ],
+[ 5630, "hhl" ],
+[ 5631, "hhm" ],
+[ 5632, "hhn" ],
+[ 5633, "hho" ],
+[ 5634, "hhp" ],
+[ 5635, "hhq" ],
+[ 5636, "hhr" ],
+[ 5637, "hhs" ],
+[ 5638, "hht" ],
+[ 5639, "hhu" ],
+[ 5640, "hhv" ],
+[ 5641, "hhw" ],
+[ 5642, "hhx" ],
+[ 5643, "hhy" ],
+[ 5644, "hhz" ],
+[ 5645, "hia" ],
+[ 5646, "hib" ],
+[ 5647, "hic" ],
+[ 5648, "hid" ],
+[ 5649, "hie" ],
+[ 5650, "hif" ],
+[ 5651, "hig" ],
+[ 5652, "hih" ],
+[ 5653, "hii" ],
+[ 5654, "hij" ],
+[ 5655, "hik" ],
+[ 5656, "hil" ],
+[ 5657, "him" ],
+[ 5658, "hin" ],
+[ 5659, "hio" ],
+[ 5660, "hip" ],
+[ 5661, "hiq" ],
+[ 5662, "hir" ],
+[ 5663, "his" ],
+[ 5664, "hit" ],
+[ 5665, "hiu" ],
+[ 5666, "hiv" ],
+[ 5667, "hiw" ],
+[ 5668, "hix" ],
+[ 5669, "hiy" ],
+[ 5670, "hiz" ],
+[ 5671, "hja" ],
+[ 5672, "hjb" ],
+[ 5673, "hjc" ],
+[ 5674, "hjd" ],
+[ 5675, "hje" ],
+[ 5676, "hjf" ],
+[ 5677, "hjg" ],
+[ 5678, "hjh" ],
+[ 5679, "hji" ],
+[ 5680, "hjj" ],
+[ 5681, "hjk" ],
+[ 5682, "hjl" ],
+[ 5683, "hjm" ],
+[ 5684, "hjn" ],
+[ 5685, "hjo" ],
+[ 5686, "hjp" ],
+[ 5687, "hjq" ],
+[ 5688, "hjr" ],
+[ 5689, "hjs" ],
+[ 5690, "hjt" ],
+[ 5691, "hju" ],
+[ 5692, "hjv" ],
+[ 5693, "hjw" ],
+[ 5694, "hjx" ],
+[ 5695, "hjy" ],
+[ 5696, "hjz" ],
+[ 5697, "hka" ],
+[ 5698, "hkb" ],
+[ 5699, "hkc" ],
+[ 5700, "hkd" ],
+[ 5701, "hke" ],
+[ 5702, "hkf" ],
+[ 5703, "hkg" ],
+[ 5704, "hkh" ],
+[ 5705, "hki" ],
+[ 5706, "hkj" ],
+[ 5707, "hkk" ],
+[ 5708, "hkl" ],
+[ 5709, "hkm" ],
+[ 5710, "hkn" ],
+[ 5711, "hko" ],
+[ 5712, "hkp" ],
+[ 5713, "hkq" ],
+[ 5714, "hkr" ],
+[ 5715, "hks" ],
+[ 5716, "hkt" ],
+[ 5717, "hku" ],
+[ 5718, "hkv" ],
+[ 5719, "hkw" ],
+[ 5720, "hkx" ],
+[ 5721, "hky" ],
+[ 5722, "hkz" ],
+[ 5723, "hla" ],
+[ 5724, "hlb" ],
+[ 5725, "hlc" ],
+[ 5726, "hld" ],
+[ 5727, "hle" ],
+[ 5728, "hlf" ],
+[ 5729, "hlg" ],
+[ 5730, "hlh" ],
+[ 5731, "hli" ],
+[ 5732, "hlj" ],
+[ 5733, "hlk" ],
+[ 5734, "hll" ],
+[ 5735, "hlm" ],
+[ 5736, "hln" ],
+[ 5737, "hlo" ],
+[ 5738, "hlp" ],
+[ 5739, "hlq" ],
+[ 5740, "hlr" ],
+[ 5741, "hls" ],
+[ 5742, "hlt" ],
+[ 5743, "hlu" ],
+[ 5744, "hlv" ],
+[ 5745, "hlw" ],
+[ 5746, "hlx" ],
+[ 5747, "hly" ],
+[ 5748, "hlz" ],
+[ 5749, "hma" ],
+[ 5750, "hmb" ],
+[ 5751, "hmc" ],
+[ 5752, "hmd" ],
+[ 5753, "hme" ],
+[ 5754, "hmf" ],
+[ 5755, "hmg" ],
+[ 5756, "hmh" ],
+[ 5757, "hmi" ],
+[ 5758, "hmj" ],
+[ 5759, "hmk" ],
+[ 5760, "hml" ],
+[ 5761, "hmm" ],
+[ 5762, "hmn" ],
+[ 5763, "hmo" ],
+[ 5764, "hmp" ],
+[ 5765, "hmq" ],
+[ 5766, "hmr" ],
+[ 5767, "hms" ],
+[ 5768, "hmt" ],
+[ 5769, "hmu" ],
+[ 5770, "hmv" ],
+[ 5771, "hmw" ],
+[ 5772, "hmx" ],
+[ 5773, "hmy" ],
+[ 5774, "hmz" ],
+[ 5775, "hna" ],
+[ 5776, "hnb" ],
+[ 5777, "hnc" ],
+[ 5778, "hnd" ],
+[ 5779, "hne" ],
+[ 5780, "hnf" ],
+[ 5781, "hng" ],
+[ 5782, "hnh" ],
+[ 5783, "hni" ],
+[ 5784, "hnj" ],
+[ 5785, "hnk" ],
+[ 5786, "hnl" ],
+[ 5787, "hnm" ],
+[ 5788, "hnn" ],
+[ 5789, "hno" ],
+[ 5790, "hnp" ],
+[ 5791, "hnq" ],
+[ 5792, "hnr" ],
+[ 5793, "hns" ],
+[ 5794, "hnt" ],
+[ 5795, "hnu" ],
+[ 5796, "hnv" ],
+[ 5797, "hnw" ],
+[ 5798, "hnx" ],
+[ 5799, "hny" ],
+[ 5800, "hnz" ],
+[ 5801, "hoa" ],
+[ 5802, "hob" ],
+[ 5803, "hoc" ],
+[ 5804, "hod" ],
+[ 5805, "hoe" ],
+[ 5806, "hof" ],
+[ 5807, "hog" ],
+[ 5808, "hoh" ],
+[ 5809, "hoi" ],
+[ 5810, "hoj" ],
+[ 5811, "hok" ],
+[ 5812, "hol" ],
+[ 5813, "hom" ],
+[ 5814, "hon" ],
+[ 5815, "hoo" ],
+[ 5816, "hop" ],
+[ 5817, "hoq" ],
+[ 5818, "hor" ],
+[ 5819, "hos" ],
+[ 5820, "hot" ],
+[ 5821, "hou" ],
+[ 5822, "hov" ],
+[ 5823, "how" ],
+[ 5824, "hox" ],
+[ 5825, "hoy" ],
+[ 5826, "hoz" ],
+[ 5827, "hpa" ],
+[ 5828, "hpb" ],
+[ 5829, "hpc" ],
+[ 5830, "hpd" ],
+[ 5831, "hpe" ],
+[ 5832, "hpf" ],
+[ 5833, "hpg" ],
+[ 5834, "hph" ],
+[ 5835, "hpi" ],
+[ 5836, "hpj" ],
+[ 5837, "hpk" ],
+[ 5838, "hpl" ],
+[ 5839, "hpm" ],
+[ 5840, "hpn" ],
+[ 5841, "hpo" ],
+[ 5842, "hpp" ],
+[ 5843, "hpq" ],
+[ 5844, "hpr" ],
+[ 5845, "hps" ],
+[ 5846, "hpt" ],
+[ 5847, "hpu" ],
+[ 5848, "hpv" ],
+[ 5849, "hpw" ],
+[ 5850, "hpx" ],
+[ 5851, "hpy" ],
+[ 5852, "hpz" ],
+[ 5853, "hqa" ],
+[ 5854, "hqb" ],
+[ 5855, "hqc" ],
+[ 5856, "hqd" ],
+[ 5857, "hqe" ],
+[ 5858, "hqf" ],
+[ 5859, "hqg" ],
+[ 5860, "hqh" ],
+[ 5861, "hqi" ],
+[ 5862, "hqj" ],
+[ 5863, "hqk" ],
+[ 5864, "hql" ],
+[ 5865, "hqm" ],
+[ 5866, "hqn" ],
+[ 5867, "hqo" ],
+[ 5868, "hqp" ],
+[ 5869, "hqq" ],
+[ 5870, "hqr" ],
+[ 5871, "hqs" ],
+[ 5872, "hqt" ],
+[ 5873, "hqu" ],
+[ 5874, "hqv" ],
+[ 5875, "hqw" ],
+[ 5876, "hqx" ],
+[ 5877, "hqy" ],
+[ 5878, "hqz" ],
+[ 5879, "hra" ],
+[ 5880, "hrb" ],
+[ 5881, "hrc" ],
+[ 5882, "hrd" ],
+[ 5883, "hre" ],
+[ 5884, "hrf" ],
+[ 5885, "hrg" ],
+[ 5886, "hrh" ],
+[ 5887, "hri" ],
+[ 5888, "hrj" ],
+[ 5889, "hrk" ],
+[ 5890, "hrl" ],
+[ 5891, "hrm" ],
+[ 5892, "hrn" ],
+[ 5893, "hro" ],
+[ 5894, "hrp" ],
+[ 5895, "hrq" ],
+[ 5896, "hrr" ],
+[ 5897, "hrs" ],
+[ 5898, "hrt" ],
+[ 5899, "hru" ],
+[ 5900, "hrv" ],
+[ 5901, "hrw" ],
+[ 5902, "hrx" ],
+[ 5903, "hry" ],
+[ 5904, "hrz" ],
+[ 5905, "hsa" ],
+[ 5906, "hsb" ],
+[ 5907, "hsc" ],
+[ 5908, "hsd" ],
+[ 5909, "hse" ],
+[ 5910, "hsf" ],
+[ 5911, "hsg" ],
+[ 5912, "hsh" ],
+[ 5913, "hsi" ],
+[ 5914, "hsj" ],
+[ 5915, "hsk" ],
+[ 5916, "hsl" ],
+[ 5917, "hsm" ],
+[ 5918, "hsn" ],
+[ 5919, "hso" ],
+[ 5920, "hsp" ],
+[ 5921, "hsq" ],
+[ 5922, "hsr" ],
+[ 5923, "hss" ],
+[ 5924, "hst" ],
+[ 5925, "hsu" ],
+[ 5926, "hsv" ],
+[ 5927, "hsw" ],
+[ 5928, "hsx" ],
+[ 5929, "hsy" ],
+[ 5930, "hsz" ],
+[ 5931, "hta" ],
+[ 5932, "htb" ],
+[ 5933, "htc" ],
+[ 5934, "htd" ],
+[ 5935, "hte" ],
+[ 5936, "htf" ],
+[ 5937, "htg" ],
+[ 5938, "hth" ],
+[ 5939, "hti" ],
+[ 5940, "htj" ],
+[ 5941, "htk" ],
+[ 5942, "htl" ],
+[ 5943, "htm" ],
+[ 5944, "htn" ],
+[ 5945, "hto" ],
+[ 5946, "htp" ],
+[ 5947, "htq" ],
+[ 5948, "htr" ],
+[ 5949, "hts" ],
+[ 5950, "htt" ],
+[ 5951, "htu" ],
+[ 5952, "htv" ],
+[ 5953, "htw" ],
+[ 5954, "htx" ],
+[ 5955, "hty" ],
+[ 5956, "htz" ],
+[ 5957, "hua" ],
+[ 5958, "hub" ],
+[ 5959, "huc" ],
+[ 5960, "hud" ],
+[ 5961, "hue" ],
+[ 5962, "huf" ],
+[ 5963, "hug" ],
+[ 5964, "huh" ],
+[ 5965, "hui" ],
+[ 5966, "huj" ],
+[ 5967, "huk" ],
+[ 5968, "hul" ],
+[ 5969, "hum" ],
+[ 5970, "hun" ],
+[ 5971, "huo" ],
+[ 5972, "hup" ],
+[ 5973, "huq" ],
+[ 5974, "hur" ],
+[ 5975, "hus" ],
+[ 5976, "hut" ],
+[ 5977, "huu" ],
+[ 5978, "huv" ],
+[ 5979, "huw" ],
+[ 5980, "hux" ],
+[ 5981, "huy" ],
+[ 5982, "huz" ],
+[ 5983, "hva" ],
+[ 5984, "hvb" ],
+[ 5985, "hvc" ],
+[ 5986, "hvd" ],
+[ 5987, "hve" ],
+[ 5988, "hvf" ],
+[ 5989, "hvg" ],
+[ 5990, "hvh" ],
+[ 5991, "hvi" ],
+[ 5992, "hvj" ],
+[ 5993, "hvk" ],
+[ 5994, "hvl" ],
+[ 5995, "hvm" ],
+[ 5996, "hvn" ],
+[ 5997, "hvo" ],
+[ 5998, "hvp" ],
+[ 5999, "hvq" ],
+[ 6000, "hvr" ],
+[ 6001, "hvs" ],
+[ 6002, "hvt" ],
+[ 6003, "hvu" ],
+[ 6004, "hvv" ],
+[ 6005, "hvw" ],
+[ 6006, "hvx" ],
+[ 6007, "hvy" ],
+[ 6008, "hvz" ],
+[ 6009, "hwa" ],
+[ 6010, "hwb" ],
+[ 6011, "hwc" ],
+[ 6012, "hwd" ],
+[ 6013, "hwe" ],
+[ 6014, "hwf" ],
+[ 6015, "hwg" ],
+[ 6016, "hwh" ],
+[ 6017, "hwi" ],
+[ 6018, "hwj" ],
+[ 6019, "hwk" ],
+[ 6020, "hwl" ],
+[ 6021, "hwm" ],
+[ 6022, "hwn" ],
+[ 6023, "hwo" ],
+[ 6024, "hwp" ],
+[ 6025, "hwq" ],
+[ 6026, "hwr" ],
+[ 6027, "hws" ],
+[ 6028, "hwt" ],
+[ 6029, "hwu" ],
+[ 6030, "hwv" ],
+[ 6031, "hww" ],
+[ 6032, "hwx" ],
+[ 6033, "hwy" ],
+[ 6034, "hwz" ],
+[ 6035, "hxa" ],
+[ 6036, "hxb" ],
+[ 6037, "hxc" ],
+[ 6038, "hxd" ],
+[ 6039, "hxe" ],
+[ 6040, "hxf" ],
+[ 6041, "hxg" ],
+[ 6042, "hxh" ],
+[ 6043, "hxi" ],
+[ 6044, "hxj" ],
+[ 6045, "hxk" ],
+[ 6046, "hxl" ],
+[ 6047, "hxm" ],
+[ 6048, "hxn" ],
+[ 6049, "hxo" ],
+[ 6050, "hxp" ],
+[ 6051, "hxq" ],
+[ 6052, "hxr" ],
+[ 6053, "hxs" ],
+[ 6054, "hxt" ],
+[ 6055, "hxu" ],
+[ 6056, "hxv" ],
+[ 6057, "hxw" ],
+[ 6058, "hxx" ],
+[ 6059, "hxy" ],
+[ 6060, "hxz" ],
+[ 6061, "hya" ],
+[ 6062, "hyb" ],
+[ 6063, "hyc" ],
+[ 6064, "hyd" ],
+[ 6065, "hye" ],
+[ 6066, "hyf" ],
+[ 6067, "hyg" ],
+[ 6068, "hyh" ],
+[ 6069, "hyi" ],
+[ 6070, "hyj" ],
+[ 6071, "hyk" ],
+[ 6072, "hyl" ],
+[ 6073, "hym" ],
+[ 6074, "hyn" ],
+[ 6075, "hyo" ],
+[ 6076, "hyp" ],
+[ 6077, "hyq" ],
+[ 6078, "hyr" ],
+[ 6079, "hys" ],
+[ 6080, "hyt" ],
+[ 6081, "hyu" ],
+[ 6082, "hyv" ],
+[ 6083, "hyw" ],
+[ 6084, "hyx" ],
+[ 6085, "hyy" ],
+[ 6086, "hyz" ],
+[ 6087, "hza" ],
+[ 6088, "hzb" ],
+[ 6089, "hzc" ],
+[ 6090, "hzd" ],
+[ 6091, "hze" ],
+[ 6092, "hzf" ],
+[ 6093, "hzg" ],
+[ 6094, "hzh" ],
+[ 6095, "hzi" ],
+[ 6096, "hzj" ],
+[ 6097, "hzk" ],
+[ 6098, "hzl" ],
+[ 6099, "hzm" ],
+[ 6100, "hzn" ],
+[ 6101, "hzo" ],
+[ 6102, "hzp" ],
+[ 6103, "hzq" ],
+[ 6104, "hzr" ],
+[ 6105, "hzs" ],
+[ 6106, "hzt" ],
+[ 6107, "hzu" ],
+[ 6108, "hzv" ],
+[ 6109, "hzw" ],
+[ 6110, "hzx" ],
+[ 6111, "hzy" ],
+[ 6112, "hzz" ],
+[ 6113, "iaa" ],
+[ 6114, "iab" ],
+[ 6115, "iac" ],
+[ 6116, "iad" ],
+[ 6117, "iae" ],
+[ 6118, "iaf" ],
+[ 6119, "iag" ],
+[ 6120, "iah" ],
+[ 6121, "iai" ],
+[ 6122, "iaj" ],
+[ 6123, "iak" ],
+[ 6124, "ial" ],
+[ 6125, "iam" ],
+[ 6126, "ian" ],
+[ 6127, "iao" ],
+[ 6128, "iap" ],
+[ 6129, "iaq" ],
+[ 6130, "iar" ],
+[ 6131, "ias" ],
+[ 6132, "iat" ],
+[ 6133, "iau" ],
+[ 6134, "iav" ],
+[ 6135, "iaw" ],
+[ 6136, "iax" ],
+[ 6137, "iay" ],
+[ 6138, "iaz" ],
+[ 6139, "iba" ],
+[ 6140, "ibb" ],
+[ 6141, "ibc" ],
+[ 6142, "ibd" ],
+[ 6143, "ibe" ],
+[ 6144, "ibf" ],
+[ 6145, "ibg" ],
+[ 6146, "ibh" ],
+[ 6147, "ibi" ],
+[ 6148, "ibj" ],
+[ 6149, "ibk" ],
+[ 6150, "ibl" ],
+[ 6151, "ibm" ],
+[ 6152, "ibn" ],
+[ 6153, "ibo" ],
+[ 6154, "ibp" ],
+[ 6155, "ibq" ],
+[ 6156, "ibr" ],
+[ 6157, "ibs" ],
+[ 6158, "ibt" ],
+[ 6159, "ibu" ],
+[ 6160, "ibv" ],
+[ 6161, "ibw" ],
+[ 6162, "ibx" ],
+[ 6163, "iby" ],
+[ 6164, "ibz" ],
+[ 6165, "ica" ],
+[ 6166, "icb" ],
+[ 6167, "icc" ],
+[ 6168, "icd" ],
+[ 6169, "ice" ],
+[ 6170, "icf" ],
+[ 6171, "icg" ],
+[ 6172, "ich" ],
+[ 6173, "ici" ],
+[ 6174, "icj" ],
+[ 6175, "ick" ],
+[ 6176, "icl" ],
+[ 6177, "icm" ],
+[ 6178, "icn" ],
+[ 6179, "ico" ],
+[ 6180, "icp" ],
+[ 6181, "icq" ],
+[ 6182, "icr" ],
+[ 6183, "ics" ],
+[ 6184, "ict" ],
+[ 6185, "icu" ],
+[ 6186, "icv" ],
+[ 6187, "icw" ],
+[ 6188, "icx" ],
+[ 6189, "icy" ],
+[ 6190, "icz" ],
+[ 6191, "ida" ],
+[ 6192, "idb" ],
+[ 6193, "idc" ],
+[ 6194, "idd" ],
+[ 6195, "ide" ],
+[ 6196, "idf" ],
+[ 6197, "idg" ],
+[ 6198, "idh" ],
+[ 6199, "idi" ],
+[ 6200, "idj" ],
+[ 6201, "idk" ],
+[ 6202, "idl" ],
+[ 6203, "idm" ],
+[ 6204, "idn" ],
+[ 6205, "ido" ],
+[ 6206, "idp" ],
+[ 6207, "idq" ],
+[ 6208, "idr" ],
+[ 6209, "ids" ],
+[ 6210, "idt" ],
+[ 6211, "idu" ],
+[ 6212, "idv" ],
+[ 6213, "idw" ],
+[ 6214, "idx" ],
+[ 6215, "idy" ],
+[ 6216, "idz" ],
+[ 6217, "iea" ],
+[ 6218, "ieb" ],
+[ 6219, "iec" ],
+[ 6220, "ied" ],
+[ 6221, "iee" ],
+[ 6222, "ief" ],
+[ 6223, "ieg" ],
+[ 6224, "ieh" ],
+[ 6225, "iei" ],
+[ 6226, "iej" ],
+[ 6227, "iek" ],
+[ 6228, "iel" ],
+[ 6229, "iem" ],
+[ 6230, "ien" ],
+[ 6231, "ieo" ],
+[ 6232, "iep" ],
+[ 6233, "ieq" ],
+[ 6234, "ier" ],
+[ 6235, "ies" ],
+[ 6236, "iet" ],
+[ 6237, "ieu" ],
+[ 6238, "iev" ],
+[ 6239, "iew" ],
+[ 6240, "iex" ],
+[ 6241, "iey" ],
+[ 6242, "iez" ],
+[ 6243, "ifa" ],
+[ 6244, "ifb" ],
+[ 6245, "ifc" ],
+[ 6246, "ifd" ],
+[ 6247, "ife" ],
+[ 6248, "iff" ],
+[ 6249, "ifg" ],
+[ 6250, "ifh" ],
+[ 6251, "ifi" ],
+[ 6252, "ifj" ],
+[ 6253, "ifk" ],
+[ 6254, "ifl" ],
+[ 6255, "ifm" ],
+[ 6256, "ifn" ],
+[ 6257, "ifo" ],
+[ 6258, "ifp" ],
+[ 6259, "ifq" ],
+[ 6260, "ifr" ],
+[ 6261, "ifs" ],
+[ 6262, "ift" ],
+[ 6263, "ifu" ],
+[ 6264, "ifv" ],
+[ 6265, "ifw" ],
+[ 6266, "ifx" ],
+[ 6267, "ify" ],
+[ 6268, "ifz" ],
+[ 6269, "iga" ],
+[ 6270, "igb" ],
+[ 6271, "igc" ],
+[ 6272, "igd" ],
+[ 6273, "ige" ],
+[ 6274, "igf" ],
+[ 6275, "igg" ],
+[ 6276, "igh" ],
+[ 6277, "igi" ],
+[ 6278, "igj" ],
+[ 6279, "igk" ],
+[ 6280, "igl" ],
+[ 6281, "igm" ],
+[ 6282, "ign" ],
+[ 6283, "igo" ],
+[ 6284, "igp" ],
+[ 6285, "igq" ],
+[ 6286, "igr" ],
+[ 6287, "igs" ],
+[ 6288, "igt" ],
+[ 6289, "igu" ],
+[ 6290, "igv" ],
+[ 6291, "igw" ],
+[ 6292, "igx" ],
+[ 6293, "igy" ],
+[ 6294, "igz" ],
+[ 6295, "iha" ],
+[ 6296, "ihb" ],
+[ 6297, "ihc" ],
+[ 6298, "ihd" ],
+[ 6299, "ihe" ],
+[ 6300, "ihf" ],
+[ 6301, "ihg" ],
+[ 6302, "ihh" ],
+[ 6303, "ihi" ],
+[ 6304, "ihj" ],
+[ 6305, "ihk" ],
+[ 6306, "ihl" ],
+[ 6307, "ihm" ],
+[ 6308, "ihn" ],
+[ 6309, "iho" ],
+[ 6310, "ihp" ],
+[ 6311, "ihq" ],
+[ 6312, "ihr" ],
+[ 6313, "ihs" ],
+[ 6314, "iht" ],
+[ 6315, "ihu" ],
+[ 6316, "ihv" ],
+[ 6317, "ihw" ],
+[ 6318, "ihx" ],
+[ 6319, "ihy" ],
+[ 6320, "ihz" ],
+[ 6321, "iia" ],
+[ 6322, "iib" ],
+[ 6323, "iic" ],
+[ 6324, "iid" ],
+[ 6325, "iie" ],
+[ 6326, "iif" ],
+[ 6327, "iig" ],
+[ 6328, "iih" ],
+[ 6329, "iii" ],
+[ 6330, "iij" ],
+[ 6331, "iik" ],
+[ 6332, "iil" ],
+[ 6333, "iim" ],
+[ 6334, "iin" ],
+[ 6335, "iio" ],
+[ 6336, "iip" ],
+[ 6337, "iiq" ],
+[ 6338, "iir" ],
+[ 6339, "iis" ],
+[ 6340, "iit" ],
+[ 6341, "iiu" ],
+[ 6342, "iiv" ],
+[ 6343, "iiw" ],
+[ 6344, "iix" ],
+[ 6345, "iiy" ],
+[ 6346, "iiz" ],
+[ 6347, "ija" ],
+[ 6348, "ijb" ],
+[ 6349, "ijc" ],
+[ 6350, "ijd" ],
+[ 6351, "ije" ],
+[ 6352, "ijf" ],
+[ 6353, "ijg" ],
+[ 6354, "ijh" ],
+[ 6355, "iji" ],
+[ 6356, "ijj" ],
+[ 6357, "ijk" ],
+[ 6358, "ijl" ],
+[ 6359, "ijm" ],
+[ 6360, "ijn" ],
+[ 6361, "ijo" ],
+[ 6362, "ijp" ],
+[ 6363, "ijq" ],
+[ 6364, "ijr" ],
+[ 6365, "ijs" ],
+[ 6366, "ijt" ],
+[ 6367, "iju" ],
+[ 6368, "ijv" ],
+[ 6369, "ijw" ],
+[ 6370, "ijx" ],
+[ 6371, "ijy" ],
+[ 6372, "ijz" ],
+[ 6373, "ika" ],
+[ 6374, "ikb" ],
+[ 6375, "ikc" ],
+[ 6376, "ikd" ],
+[ 6377, "ike" ],
+[ 6378, "ikf" ],
+[ 6379, "ikg" ],
+[ 6380, "ikh" ],
+[ 6381, "iki" ],
+[ 6382, "ikj" ],
+[ 6383, "ikk" ],
+[ 6384, "ikl" ],
+[ 6385, "ikm" ],
+[ 6386, "ikn" ],
+[ 6387, "iko" ],
+[ 6388, "ikp" ],
+[ 6389, "ikq" ],
+[ 6390, "ikr" ],
+[ 6391, "iks" ],
+[ 6392, "ikt" ],
+[ 6393, "iku" ],
+[ 6394, "ikv" ],
+[ 6395, "ikw" ],
+[ 6396, "ikx" ],
+[ 6397, "iky" ],
+[ 6398, "ikz" ],
+[ 6399, "ila" ],
+[ 6400, "ilb" ],
+[ 6401, "ilc" ],
+[ 6402, "ild" ],
+[ 6403, "ile" ],
+[ 6404, "ilf" ],
+[ 6405, "ilg" ],
+[ 6406, "ilh" ],
+[ 6407, "ili" ],
+[ 6408, "ilj" ],
+[ 6409, "ilk" ],
+[ 6410, "ill" ],
+[ 6411, "ilm" ],
+[ 6412, "iln" ],
+[ 6413, "ilo" ],
+[ 6414, "ilp" ],
+[ 6415, "ilq" ],
+[ 6416, "ilr" ],
+[ 6417, "ils" ],
+[ 6418, "ilt" ],
+[ 6419, "ilu" ],
+[ 6420, "ilv" ],
+[ 6421, "ilw" ],
+[ 6422, "ilx" ],
+[ 6423, "ily" ],
+[ 6424, "ilz" ],
+[ 6425, "ima" ],
+[ 6426, "imb" ],
+[ 6427, "imc" ],
+[ 6428, "imd" ],
+[ 6429, "ime" ],
+[ 6430, "imf" ],
+[ 6431, "img" ],
+[ 6432, "imh" ],
+[ 6433, "imi" ],
+[ 6434, "imj" ],
+[ 6435, "imk" ],
+[ 6436, "iml" ],
+[ 6437, "imm" ],
+[ 6438, "imn" ],
+[ 6439, "imo" ],
+[ 6440, "imp" ],
+[ 6441, "imq" ],
+[ 6442, "imr" ],
+[ 6443, "ims" ],
+[ 6444, "imt" ],
+[ 6445, "imu" ],
+[ 6446, "imv" ],
+[ 6447, "imw" ],
+[ 6448, "imx" ],
+[ 6449, "imy" ],
+[ 6450, "imz" ],
+[ 6451, "ina" ],
+[ 6452, "inb" ],
+[ 6453, "inc" ],
+[ 6454, "ind" ],
+[ 6455, "ine" ],
+[ 6456, "inf" ],
+[ 6457, "ing" ],
+[ 6458, "inh" ],
+[ 6459, "ini" ],
+[ 6460, "inj" ],
+[ 6461, "ink" ],
+[ 6462, "inl" ],
+[ 6463, "inm" ],
+[ 6464, "inn" ],
+[ 6465, "ino" ],
+[ 6466, "inp" ],
+[ 6467, "inq" ],
+[ 6468, "inr" ],
+[ 6469, "ins" ],
+[ 6470, "int" ],
+[ 6471, "inu" ],
+[ 6472, "inv" ],
+[ 6473, "inw" ],
+[ 6474, "inx" ],
+[ 6475, "iny" ],
+[ 6476, "inz" ],
+[ 6477, "ioa" ],
+[ 6478, "iob" ],
+[ 6479, "ioc" ],
+[ 6480, "iod" ],
+[ 6481, "ioe" ],
+[ 6482, "iof" ],
+[ 6483, "iog" ],
+[ 6484, "ioh" ],
+[ 6485, "ioi" ],
+[ 6486, "ioj" ],
+[ 6487, "iok" ],
+[ 6488, "iol" ],
+[ 6489, "iom" ],
+[ 6490, "ion" ],
+[ 6491, "ioo" ],
+[ 6492, "iop" ],
+[ 6493, "ioq" ],
+[ 6494, "ior" ],
+[ 6495, "ios" ],
+[ 6496, "iot" ],
+[ 6497, "iou" ],
+[ 6498, "iov" ],
+[ 6499, "iow" ],
+[ 6500, "iox" ],
+[ 6501, "ioy" ],
+[ 6502, "ioz" ],
+[ 6503, "ipa" ],
+[ 6504, "ipb" ],
+[ 6505, "ipc" ],
+[ 6506, "ipd" ],
+[ 6507, "ipe" ],
+[ 6508, "ipf" ],
+[ 6509, "ipg" ],
+[ 6510, "iph" ],
+[ 6511, "ipi" ],
+[ 6512, "ipj" ],
+[ 6513, "ipk" ],
+[ 6514, "ipl" ],
+[ 6515, "ipm" ],
+[ 6516, "ipn" ],
+[ 6517, "ipo" ],
+[ 6518, "ipp" ],
+[ 6519, "ipq" ],
+[ 6520, "ipr" ],
+[ 6521, "ips" ],
+[ 6522, "ipt" ],
+[ 6523, "ipu" ],
+[ 6524, "ipv" ],
+[ 6525, "ipw" ],
+[ 6526, "ipx" ],
+[ 6527, "ipy" ],
+[ 6528, "ipz" ],
+[ 6529, "iqa" ],
+[ 6530, "iqb" ],
+[ 6531, "iqc" ],
+[ 6532, "iqd" ],
+[ 6533, "iqe" ],
+[ 6534, "iqf" ],
+[ 6535, "iqg" ],
+[ 6536, "iqh" ],
+[ 6537, "iqi" ],
+[ 6538, "iqj" ],
+[ 6539, "iqk" ],
+[ 6540, "iql" ],
+[ 6541, "iqm" ],
+[ 6542, "iqn" ],
+[ 6543, "iqo" ],
+[ 6544, "iqp" ],
+[ 6545, "iqq" ],
+[ 6546, "iqr" ],
+[ 6547, "iqs" ],
+[ 6548, "iqt" ],
+[ 6549, "iqu" ],
+[ 6550, "iqv" ],
+[ 6551, "iqw" ],
+[ 6552, "iqx" ],
+[ 6553, "iqy" ],
+[ 6554, "iqz" ],
+[ 6555, "ira" ],
+[ 6556, "irb" ],
+[ 6557, "irc" ],
+[ 6558, "ird" ],
+[ 6559, "ire" ],
+[ 6560, "irf" ],
+[ 6561, "irg" ],
+[ 6562, "irh" ],
+[ 6563, "iri" ],
+[ 6564, "irj" ],
+[ 6565, "irk" ],
+[ 6566, "irl" ],
+[ 6567, "irm" ],
+[ 6568, "irn" ],
+[ 6569, "iro" ],
+[ 6570, "irp" ],
+[ 6571, "irq" ],
+[ 6572, "irr" ],
+[ 6573, "irs" ],
+[ 6574, "irt" ],
+[ 6575, "iru" ],
+[ 6576, "irv" ],
+[ 6577, "irw" ],
+[ 6578, "irx" ],
+[ 6579, "iry" ],
+[ 6580, "irz" ],
+[ 6581, "isa" ],
+[ 6582, "isb" ],
+[ 6583, "isc" ],
+[ 6584, "isd" ],
+[ 6585, "ise" ],
+[ 6586, "isf" ],
+[ 6587, "isg" ],
+[ 6588, "ish" ],
+[ 6589, "isi" ],
+[ 6590, "isj" ],
+[ 6591, "isk" ],
+[ 6592, "isl" ],
+[ 6593, "ism" ],
+[ 6594, "isn" ],
+[ 6595, "iso" ],
+[ 6596, "isp" ],
+[ 6597, "isq" ],
+[ 6598, "isr" ],
+[ 6599, "iss" ],
+[ 6600, "ist" ],
+[ 6601, "isu" ],
+[ 6602, "isv" ],
+[ 6603, "isw" ],
+[ 6604, "isx" ],
+[ 6605, "isy" ],
+[ 6606, "isz" ],
+[ 6607, "ita" ],
+[ 6608, "itb" ],
+[ 6609, "itc" ],
+[ 6610, "itd" ],
+[ 6611, "ite" ],
+[ 6612, "itf" ],
+[ 6613, "itg" ],
+[ 6614, "ith" ],
+[ 6615, "iti" ],
+[ 6616, "itj" ],
+[ 6617, "itk" ],
+[ 6618, "itl" ],
+[ 6619, "itm" ],
+[ 6620, "itn" ],
+[ 6621, "ito" ],
+[ 6622, "itp" ],
+[ 6623, "itq" ],
+[ 6624, "itr" ],
+[ 6625, "its" ],
+[ 6626, "itt" ],
+[ 6627, "itu" ],
+[ 6628, "itv" ],
+[ 6629, "itw" ],
+[ 6630, "itx" ],
+[ 6631, "ity" ],
+[ 6632, "itz" ],
+[ 6633, "iua" ],
+[ 6634, "iub" ],
+[ 6635, "iuc" ],
+[ 6636, "iud" ],
+[ 6637, "iue" ],
+[ 6638, "iuf" ],
+[ 6639, "iug" ],
+[ 6640, "iuh" ],
+[ 6641, "iui" ],
+[ 6642, "iuj" ],
+[ 6643, "iuk" ],
+[ 6644, "iul" ],
+[ 6645, "ium" ],
+[ 6646, "iun" ],
+[ 6647, "iuo" ],
+[ 6648, "iup" ],
+[ 6649, "iuq" ],
+[ 6650, "iur" ],
+[ 6651, "ius" ],
+[ 6652, "iut" ],
+[ 6653, "iuu" ],
+[ 6654, "iuv" ],
+[ 6655, "iuw" ],
+[ 6656, "iux" ],
+[ 6657, "iuy" ],
+[ 6658, "iuz" ],
+[ 6659, "iva" ],
+[ 6660, "ivb" ],
+[ 6661, "ivc" ],
+[ 6662, "ivd" ],
+[ 6663, "ive" ],
+[ 6664, "ivf" ],
+[ 6665, "ivg" ],
+[ 6666, "ivh" ],
+[ 6667, "ivi" ],
+[ 6668, "ivj" ],
+[ 6669, "ivk" ],
+[ 6670, "ivl" ],
+[ 6671, "ivm" ],
+[ 6672, "ivn" ],
+[ 6673, "ivo" ],
+[ 6674, "ivp" ],
+[ 6675, "ivq" ],
+[ 6676, "ivr" ],
+[ 6677, "ivs" ],
+[ 6678, "ivt" ],
+[ 6679, "ivu" ],
+[ 6680, "ivv" ],
+[ 6681, "ivw" ],
+[ 6682, "ivx" ],
+[ 6683, "ivy" ],
+[ 6684, "ivz" ],
+[ 6685, "iwa" ],
+[ 6686, "iwb" ],
+[ 6687, "iwc" ],
+[ 6688, "iwd" ],
+[ 6689, "iwe" ],
+[ 6690, "iwf" ],
+[ 6691, "iwg" ],
+[ 6692, "iwh" ],
+[ 6693, "iwi" ],
+[ 6694, "iwj" ],
+[ 6695, "iwk" ],
+[ 6696, "iwl" ],
+[ 6697, "iwm" ],
+[ 6698, "iwn" ],
+[ 6699, "iwo" ],
+[ 6700, "iwp" ],
+[ 6701, "iwq" ],
+[ 6702, "iwr" ],
+[ 6703, "iws" ],
+[ 6704, "iwt" ],
+[ 6705, "iwu" ],
+[ 6706, "iwv" ],
+[ 6707, "iww" ],
+[ 6708, "iwx" ],
+[ 6709, "iwy" ],
+[ 6710, "iwz" ],
+[ 6711, "ixa" ],
+[ 6712, "ixb" ],
+[ 6713, "ixc" ],
+[ 6714, "ixd" ],
+[ 6715, "ixe" ],
+[ 6716, "ixf" ],
+[ 6717, "ixg" ],
+[ 6718, "ixh" ],
+[ 6719, "ixi" ],
+[ 6720, "ixj" ],
+[ 6721, "ixk" ],
+[ 6722, "ixl" ],
+[ 6723, "ixm" ],
+[ 6724, "ixn" ],
+[ 6725, "ixo" ],
+[ 6726, "ixp" ],
+[ 6727, "ixq" ],
+[ 6728, "ixr" ],
+[ 6729, "ixs" ],
+[ 6730, "ixt" ],
+[ 6731, "ixu" ],
+[ 6732, "ixv" ],
+[ 6733, "ixw" ],
+[ 6734, "ixx" ],
+[ 6735, "ixy" ],
+[ 6736, "ixz" ],
+[ 6737, "iya" ],
+[ 6738, "iyb" ],
+[ 6739, "iyc" ],
+[ 6740, "iyd" ],
+[ 6741, "iye" ],
+[ 6742, "iyf" ],
+[ 6743, "iyg" ],
+[ 6744, "iyh" ],
+[ 6745, "iyi" ],
+[ 6746, "iyj" ],
+[ 6747, "iyk" ],
+[ 6748, "iyl" ],
+[ 6749, "iym" ],
+[ 6750, "iyn" ],
+[ 6751, "iyo" ],
+[ 6752, "iyp" ],
+[ 6753, "iyq" ],
+[ 6754, "iyr" ],
+[ 6755, "iys" ],
+[ 6756, "iyt" ],
+[ 6757, "iyu" ],
+[ 6758, "iyv" ],
+[ 6759, "iyw" ],
+[ 6760, "iyx" ],
+[ 6761, "iyy" ],
+[ 6762, "iyz" ],
+[ 6763, "iza" ],
+[ 6764, "izb" ],
+[ 6765, "izc" ],
+[ 6766, "izd" ],
+[ 6767, "ize" ],
+[ 6768, "izf" ],
+[ 6769, "izg" ],
+[ 6770, "izh" ],
+[ 6771, "izi" ],
+[ 6772, "izj" ],
+[ 6773, "izk" ],
+[ 6774, "izl" ],
+[ 6775, "izm" ],
+[ 6776, "izn" ],
+[ 6777, "izo" ],
+[ 6778, "izp" ],
+[ 6779, "izq" ],
+[ 6780, "izr" ],
+[ 6781, "izs" ],
+[ 6782, "izt" ],
+[ 6783, "izu" ],
+[ 6784, "izv" ],
+[ 6785, "izw" ],
+[ 6786, "izx" ],
+[ 6787, "izy" ],
+[ 6788, "izz" ],
+[ 6789, "jaa" ],
+[ 6790, "jab" ],
+[ 6791, "jac" ],
+[ 6792, "jad" ],
+[ 6793, "jae" ],
+[ 6794, "jaf" ],
+[ 6795, "jag" ],
+[ 6796, "jah" ],
+[ 6797, "jai" ],
+[ 6798, "jaj" ],
+[ 6799, "jak" ],
+[ 6800, "jal" ],
+[ 6801, "jam" ],
+[ 6802, "jan" ],
+[ 6803, "jao" ],
+[ 6804, "jap" ],
+[ 6805, "jaq" ],
+[ 6806, "jar" ],
+[ 6807, "jas" ],
+[ 6808, "jat" ],
+[ 6809, "jau" ],
+[ 6810, "jav" ],
+[ 6811, "jaw" ],
+[ 6812, "jax" ],
+[ 6813, "jay" ],
+[ 6814, "jaz" ],
+[ 6815, "jba" ],
+[ 6816, "jbb" ],
+[ 6817, "jbc" ],
+[ 6818, "jbd" ],
+[ 6819, "jbe" ],
+[ 6820, "jbf" ],
+[ 6821, "jbg" ],
+[ 6822, "jbh" ],
+[ 6823, "jbi" ],
+[ 6824, "jbj" ],
+[ 6825, "jbk" ],
+[ 6826, "jbl" ],
+[ 6827, "jbm" ],
+[ 6828, "jbn" ],
+[ 6829, "jbo" ],
+[ 6830, "jbp" ],
+[ 6831, "jbq" ],
+[ 6832, "jbr" ],
+[ 6833, "jbs" ],
+[ 6834, "jbt" ],
+[ 6835, "jbu" ],
+[ 6836, "jbv" ],
+[ 6837, "jbw" ],
+[ 6838, "jbx" ],
+[ 6839, "jby" ],
+[ 6840, "jbz" ],
+[ 6841, "jca" ],
+[ 6842, "jcb" ],
+[ 6843, "jcc" ],
+[ 6844, "jcd" ],
+[ 6845, "jce" ],
+[ 6846, "jcf" ],
+[ 6847, "jcg" ],
+[ 6848, "jch" ],
+[ 6849, "jci" ],
+[ 6850, "jcj" ],
+[ 6851, "jck" ],
+[ 6852, "jcl" ],
+[ 6853, "jcm" ],
+[ 6854, "jcn" ],
+[ 6855, "jco" ],
+[ 6856, "jcp" ],
+[ 6857, "jcq" ],
+[ 6858, "jcr" ],
+[ 6859, "jcs" ],
+[ 6860, "jct" ],
+[ 6861, "jcu" ],
+[ 6862, "jcv" ],
+[ 6863, "jcw" ],
+[ 6864, "jcx" ],
+[ 6865, "jcy" ],
+[ 6866, "jcz" ],
+[ 6867, "jda" ],
+[ 6868, "jdb" ],
+[ 6869, "jdc" ],
+[ 6870, "jdd" ],
+[ 6871, "jde" ],
+[ 6872, "jdf" ],
+[ 6873, "jdg" ],
+[ 6874, "jdh" ],
+[ 6875, "jdi" ],
+[ 6876, "jdj" ],
+[ 6877, "jdk" ],
+[ 6878, "jdl" ],
+[ 6879, "jdm" ],
+[ 6880, "jdn" ],
+[ 6881, "jdo" ],
+[ 6882, "jdp" ],
+[ 6883, "jdq" ],
+[ 6884, "jdr" ],
+[ 6885, "jds" ],
+[ 6886, "jdt" ],
+[ 6887, "jdu" ],
+[ 6888, "jdv" ],
+[ 6889, "jdw" ],
+[ 6890, "jdx" ],
+[ 6891, "jdy" ],
+[ 6892, "jdz" ],
+[ 6893, "jea" ],
+[ 6894, "jeb" ],
+[ 6895, "jec" ],
+[ 6896, "jed" ],
+[ 6897, "jee" ],
+[ 6898, "jef" ],
+[ 6899, "jeg" ],
+[ 6900, "jeh" ],
+[ 6901, "jei" ],
+[ 6902, "jej" ],
+[ 6903, "jek" ],
+[ 6904, "jel" ],
+[ 6905, "jem" ],
+[ 6906, "jen" ],
+[ 6907, "jeo" ],
+[ 6908, "jep" ],
+[ 6909, "jeq" ],
+[ 6910, "jer" ],
+[ 6911, "jes" ],
+[ 6912, "jet" ],
+[ 6913, "jeu" ],
+[ 6914, "jev" ],
+[ 6915, "jew" ],
+[ 6916, "jex" ],
+[ 6917, "jey" ],
+[ 6918, "jez" ],
+[ 6919, "jfa" ],
+[ 6920, "jfb" ],
+[ 6921, "jfc" ],
+[ 6922, "jfd" ],
+[ 6923, "jfe" ],
+[ 6924, "jff" ],
+[ 6925, "jfg" ],
+[ 6926, "jfh" ],
+[ 6927, "jfi" ],
+[ 6928, "jfj" ],
+[ 6929, "jfk" ],
+[ 6930, "jfl" ],
+[ 6931, "jfm" ],
+[ 6932, "jfn" ],
+[ 6933, "jfo" ],
+[ 6934, "jfp" ],
+[ 6935, "jfq" ],
+[ 6936, "jfr" ],
+[ 6937, "jfs" ],
+[ 6938, "jft" ],
+[ 6939, "jfu" ],
+[ 6940, "jfv" ],
+[ 6941, "jfw" ],
+[ 6942, "jfx" ],
+[ 6943, "jfy" ],
+[ 6944, "jfz" ],
+[ 6945, "jga" ],
+[ 6946, "jgb" ],
+[ 6947, "jgc" ],
+[ 6948, "jgd" ],
+[ 6949, "jge" ],
+[ 6950, "jgf" ],
+[ 6951, "jgg" ],
+[ 6952, "jgh" ],
+[ 6953, "jgi" ],
+[ 6954, "jgj" ],
+[ 6955, "jgk" ],
+[ 6956, "jgl" ],
+[ 6957, "jgm" ],
+[ 6958, "jgn" ],
+[ 6959, "jgo" ],
+[ 6960, "jgp" ],
+[ 6961, "jgq" ],
+[ 6962, "jgr" ],
+[ 6963, "jgs" ],
+[ 6964, "jgt" ],
+[ 6965, "jgu" ],
+[ 6966, "jgv" ],
+[ 6967, "jgw" ],
+[ 6968, "jgx" ],
+[ 6969, "jgy" ],
+[ 6970, "jgz" ],
+[ 6971, "jha" ],
+[ 6972, "jhb" ],
+[ 6973, "jhc" ],
+[ 6974, "jhd" ],
+[ 6975, "jhe" ],
+[ 6976, "jhf" ],
+[ 6977, "jhg" ],
+[ 6978, "jhh" ],
+[ 6979, "jhi" ],
+[ 6980, "jhj" ],
+[ 6981, "jhk" ],
+[ 6982, "jhl" ],
+[ 6983, "jhm" ],
+[ 6984, "jhn" ],
+[ 6985, "jho" ],
+[ 6986, "jhp" ],
+[ 6987, "jhq" ],
+[ 6988, "jhr" ],
+[ 6989, "jhs" ],
+[ 6990, "jht" ],
+[ 6991, "jhu" ],
+[ 6992, "jhv" ],
+[ 6993, "jhw" ],
+[ 6994, "jhx" ],
+[ 6995, "jhy" ],
+[ 6996, "jhz" ],
+[ 6997, "jia" ],
+[ 6998, "jib" ],
+[ 6999, "jic" ],
+[ 7000, "jid" ],
+[ 7001, "jie" ],
+[ 7002, "jif" ],
+[ 7003, "jig" ],
+[ 7004, "jih" ],
+[ 7005, "jii" ],
+[ 7006, "jij" ],
+[ 7007, "jik" ],
+[ 7008, "jil" ],
+[ 7009, "jim" ],
+[ 7010, "jin" ],
+[ 7011, "jio" ],
+[ 7012, "jip" ],
+[ 7013, "jiq" ],
+[ 7014, "jir" ],
+[ 7015, "jis" ],
+[ 7016, "jit" ],
+[ 7017, "jiu" ],
+[ 7018, "jiv" ],
+[ 7019, "jiw" ],
+[ 7020, "jix" ],
+[ 7021, "jiy" ],
+[ 7022, "jiz" ],
+[ 7023, "jja" ],
+[ 7024, "jjb" ],
+[ 7025, "jjc" ],
+[ 7026, "jjd" ],
+[ 7027, "jje" ],
+[ 7028, "jjf" ],
+[ 7029, "jjg" ],
+[ 7030, "jjh" ],
+[ 7031, "jji" ],
+[ 7032, "jjj" ],
+[ 7033, "jjk" ],
+[ 7034, "jjl" ],
+[ 7035, "jjm" ],
+[ 7036, "jjn" ],
+[ 7037, "jjo" ],
+[ 7038, "jjp" ],
+[ 7039, "jjq" ],
+[ 7040, "jjr" ],
+[ 7041, "jjs" ],
+[ 7042, "jjt" ],
+[ 7043, "jju" ],
+[ 7044, "jjv" ],
+[ 7045, "jjw" ],
+[ 7046, "jjx" ],
+[ 7047, "jjy" ],
+[ 7048, "jjz" ],
+[ 7049, "jka" ],
+[ 7050, "jkb" ],
+[ 7051, "jkc" ],
+[ 7052, "jkd" ],
+[ 7053, "jke" ],
+[ 7054, "jkf" ],
+[ 7055, "jkg" ],
+[ 7056, "jkh" ],
+[ 7057, "jki" ],
+[ 7058, "jkj" ],
+[ 7059, "jkk" ],
+[ 7060, "jkl" ],
+[ 7061, "jkm" ],
+[ 7062, "jkn" ],
+[ 7063, "jko" ],
+[ 7064, "jkp" ],
+[ 7065, "jkq" ],
+[ 7066, "jkr" ],
+[ 7067, "jks" ],
+[ 7068, "jkt" ],
+[ 7069, "jku" ],
+[ 7070, "jkv" ],
+[ 7071, "jkw" ],
+[ 7072, "jkx" ],
+[ 7073, "jky" ],
+[ 7074, "jkz" ],
+[ 7075, "jla" ],
+[ 7076, "jlb" ],
+[ 7077, "jlc" ],
+[ 7078, "jld" ],
+[ 7079, "jle" ],
+[ 7080, "jlf" ],
+[ 7081, "jlg" ],
+[ 7082, "jlh" ],
+[ 7083, "jli" ],
+[ 7084, "jlj" ],
+[ 7085, "jlk" ],
+[ 7086, "jll" ],
+[ 7087, "jlm" ],
+[ 7088, "jln" ],
+[ 7089, "jlo" ],
+[ 7090, "jlp" ],
+[ 7091, "jlq" ],
+[ 7092, "jlr" ],
+[ 7093, "jls" ],
+[ 7094, "jlt" ],
+[ 7095, "jlu" ],
+[ 7096, "jlv" ],
+[ 7097, "jlw" ],
+[ 7098, "jlx" ],
+[ 7099, "jly" ],
+[ 7100, "jlz" ],
+[ 7101, "jma" ],
+[ 7102, "jmb" ],
+[ 7103, "jmc" ],
+[ 7104, "jmd" ],
+[ 7105, "jme" ],
+[ 7106, "jmf" ],
+[ 7107, "jmg" ],
+[ 7108, "jmh" ],
+[ 7109, "jmi" ],
+[ 7110, "jmj" ],
+[ 7111, "jmk" ],
+[ 7112, "jml" ],
+[ 7113, "jmm" ],
+[ 7114, "jmn" ],
+[ 7115, "jmo" ],
+[ 7116, "jmp" ],
+[ 7117, "jmq" ],
+[ 7118, "jmr" ],
+[ 7119, "jms" ],
+[ 7120, "jmt" ],
+[ 7121, "jmu" ],
+[ 7122, "jmv" ],
+[ 7123, "jmw" ],
+[ 7124, "jmx" ],
+[ 7125, "jmy" ],
+[ 7126, "jmz" ],
+[ 7127, "jna" ],
+[ 7128, "jnb" ],
+[ 7129, "jnc" ],
+[ 7130, "jnd" ],
+[ 7131, "jne" ],
+[ 7132, "jnf" ],
+[ 7133, "jng" ],
+[ 7134, "jnh" ],
+[ 7135, "jni" ],
+[ 7136, "jnj" ],
+[ 7137, "jnk" ],
+[ 7138, "jnl" ],
+[ 7139, "jnm" ],
+[ 7140, "jnn" ],
+[ 7141, "jno" ],
+[ 7142, "jnp" ],
+[ 7143, "jnq" ],
+[ 7144, "jnr" ],
+[ 7145, "jns" ],
+[ 7146, "jnt" ],
+[ 7147, "jnu" ],
+[ 7148, "jnv" ],
+[ 7149, "jnw" ],
+[ 7150, "jnx" ],
+[ 7151, "jny" ],
+[ 7152, "jnz" ],
+[ 7153, "joa" ],
+[ 7154, "job" ],
+[ 7155, "joc" ],
+[ 7156, "jod" ],
+[ 7157, "joe" ],
+[ 7158, "jof" ],
+[ 7159, "jog" ],
+[ 7160, "joh" ],
+[ 7161, "joi" ],
+[ 7162, "joj" ],
+[ 7163, "jok" ],
+[ 7164, "jol" ],
+[ 7165, "jom" ],
+[ 7166, "jon" ],
+[ 7167, "joo" ],
+[ 7168, "jop" ],
+[ 7169, "joq" ],
+[ 7170, "jor" ],
+[ 7171, "jos" ],
+[ 7172, "jot" ],
+[ 7173, "jou" ],
+[ 7174, "jov" ],
+[ 7175, "jow" ],
+[ 7176, "jox" ],
+[ 7177, "joy" ],
+[ 7178, "joz" ],
+[ 7179, "jpa" ],
+[ 7180, "jpb" ],
+[ 7181, "jpc" ],
+[ 7182, "jpd" ],
+[ 7183, "jpe" ],
+[ 7184, "jpf" ],
+[ 7185, "jpg" ],
+[ 7186, "jph" ],
+[ 7187, "jpi" ],
+[ 7188, "jpj" ],
+[ 7189, "jpk" ],
+[ 7190, "jpl" ],
+[ 7191, "jpm" ],
+[ 7192, "jpn" ],
+[ 7193, "jpo" ],
+[ 7194, "jpp" ],
+[ 7195, "jpq" ],
+[ 7196, "jpr" ],
+[ 7197, "jps" ],
+[ 7198, "jpt" ],
+[ 7199, "jpu" ],
+[ 7200, "jpv" ],
+[ 7201, "jpw" ],
+[ 7202, "jpx" ],
+[ 7203, "jpy" ],
+[ 7204, "jpz" ],
+[ 7205, "jqa" ],
+[ 7206, "jqb" ],
+[ 7207, "jqc" ],
+[ 7208, "jqd" ],
+[ 7209, "jqe" ],
+[ 7210, "jqf" ],
+[ 7211, "jqg" ],
+[ 7212, "jqh" ],
+[ 7213, "jqi" ],
+[ 7214, "jqj" ],
+[ 7215, "jqk" ],
+[ 7216, "jql" ],
+[ 7217, "jqm" ],
+[ 7218, "jqn" ],
+[ 7219, "jqo" ],
+[ 7220, "jqp" ],
+[ 7221, "jqq" ],
+[ 7222, "jqr" ],
+[ 7223, "jqs" ],
+[ 7224, "jqt" ],
+[ 7225, "jqu" ],
+[ 7226, "jqv" ],
+[ 7227, "jqw" ],
+[ 7228, "jqx" ],
+[ 7229, "jqy" ],
+[ 7230, "jqz" ],
+[ 7231, "jra" ],
+[ 7232, "jrb" ],
+[ 7233, "jrc" ],
+[ 7234, "jrd" ],
+[ 7235, "jre" ],
+[ 7236, "jrf" ],
+[ 7237, "jrg" ],
+[ 7238, "jrh" ],
+[ 7239, "jri" ],
+[ 7240, "jrj" ],
+[ 7241, "jrk" ],
+[ 7242, "jrl" ],
+[ 7243, "jrm" ],
+[ 7244, "jrn" ],
+[ 7245, "jro" ],
+[ 7246, "jrp" ],
+[ 7247, "jrq" ],
+[ 7248, "jrr" ],
+[ 7249, "jrs" ],
+[ 7250, "jrt" ],
+[ 7251, "jru" ],
+[ 7252, "jrv" ],
+[ 7253, "jrw" ],
+[ 7254, "jrx" ],
+[ 7255, "jry" ],
+[ 7256, "jrz" ],
+[ 7257, "jsa" ],
+[ 7258, "jsb" ],
+[ 7259, "jsc" ],
+[ 7260, "jsd" ],
+[ 7261, "jse" ],
+[ 7262, "jsf" ],
+[ 7263, "jsg" ],
+[ 7264, "jsh" ],
+[ 7265, "jsi" ],
+[ 7266, "jsj" ],
+[ 7267, "jsk" ],
+[ 7268, "jsl" ],
+[ 7269, "jsm" ],
+[ 7270, "jsn" ],
+[ 7271, "jso" ],
+[ 7272, "jsp" ],
+[ 7273, "jsq" ],
+[ 7274, "jsr" ],
+[ 7275, "jss" ],
+[ 7276, "jst" ],
+[ 7277, "jsu" ],
+[ 7278, "jsv" ],
+[ 7279, "jsw" ],
+[ 7280, "jsx" ],
+[ 7281, "jsy" ],
+[ 7282, "jsz" ],
+[ 7283, "jta" ],
+[ 7284, "jtb" ],
+[ 7285, "jtc" ],
+[ 7286, "jtd" ],
+[ 7287, "jte" ],
+[ 7288, "jtf" ],
+[ 7289, "jtg" ],
+[ 7290, "jth" ],
+[ 7291, "jti" ],
+[ 7292, "jtj" ],
+[ 7293, "jtk" ],
+[ 7294, "jtl" ],
+[ 7295, "jtm" ],
+[ 7296, "jtn" ],
+[ 7297, "jto" ],
+[ 7298, "jtp" ],
+[ 7299, "jtq" ],
+[ 7300, "jtr" ],
+[ 7301, "jts" ],
+[ 7302, "jtt" ],
+[ 7303, "jtu" ],
+[ 7304, "jtv" ],
+[ 7305, "jtw" ],
+[ 7306, "jtx" ],
+[ 7307, "jty" ],
+[ 7308, "jtz" ],
+[ 7309, "jua" ],
+[ 7310, "jub" ],
+[ 7311, "juc" ],
+[ 7312, "jud" ],
+[ 7313, "jue" ],
+[ 7314, "juf" ],
+[ 7315, "jug" ],
+[ 7316, "juh" ],
+[ 7317, "jui" ],
+[ 7318, "juj" ],
+[ 7319, "juk" ],
+[ 7320, "jul" ],
+[ 7321, "jum" ],
+[ 7322, "jun" ],
+[ 7323, "juo" ],
+[ 7324, "jup" ],
+[ 7325, "juq" ],
+[ 7326, "jur" ],
+[ 7327, "jus" ],
+[ 7328, "jut" ],
+[ 7329, "juu" ],
+[ 7330, "juv" ],
+[ 7331, "juw" ],
+[ 7332, "jux" ],
+[ 7333, "juy" ],
+[ 7334, "juz" ],
+[ 7335, "jva" ],
+[ 7336, "jvb" ],
+[ 7337, "jvc" ],
+[ 7338, "jvd" ],
+[ 7339, "jve" ],
+[ 7340, "jvf" ],
+[ 7341, "jvg" ],
+[ 7342, "jvh" ],
+[ 7343, "jvi" ],
+[ 7344, "jvj" ],
+[ 7345, "jvk" ],
+[ 7346, "jvl" ],
+[ 7347, "jvm" ],
+[ 7348, "jvn" ],
+[ 7349, "jvo" ],
+[ 7350, "jvp" ],
+[ 7351, "jvq" ],
+[ 7352, "jvr" ],
+[ 7353, "jvs" ],
+[ 7354, "jvt" ],
+[ 7355, "jvu" ],
+[ 7356, "jvv" ],
+[ 7357, "jvw" ],
+[ 7358, "jvx" ],
+[ 7359, "jvy" ],
+[ 7360, "jvz" ],
+[ 7361, "jwa" ],
+[ 7362, "jwb" ],
+[ 7363, "jwc" ],
+[ 7364, "jwd" ],
+[ 7365, "jwe" ],
+[ 7366, "jwf" ],
+[ 7367, "jwg" ],
+[ 7368, "jwh" ],
+[ 7369, "jwi" ],
+[ 7370, "jwj" ],
+[ 7371, "jwk" ],
+[ 7372, "jwl" ],
+[ 7373, "jwm" ],
+[ 7374, "jwn" ],
+[ 7375, "jwo" ],
+[ 7376, "jwp" ],
+[ 7377, "jwq" ],
+[ 7378, "jwr" ],
+[ 7379, "jws" ],
+[ 7380, "jwt" ],
+[ 7381, "jwu" ],
+[ 7382, "jwv" ],
+[ 7383, "jww" ],
+[ 7384, "jwx" ],
+[ 7385, "jwy" ],
+[ 7386, "jwz" ],
+[ 7387, "jxa" ],
+[ 7388, "jxb" ],
+[ 7389, "jxc" ],
+[ 7390, "jxd" ],
+[ 7391, "jxe" ],
+[ 7392, "jxf" ],
+[ 7393, "jxg" ],
+[ 7394, "jxh" ],
+[ 7395, "jxi" ],
+[ 7396, "jxj" ],
+[ 7397, "jxk" ],
+[ 7398, "jxl" ],
+[ 7399, "jxm" ],
+[ 7400, "jxn" ],
+[ 7401, "jxo" ],
+[ 7402, "jxp" ],
+[ 7403, "jxq" ],
+[ 7404, "jxr" ],
+[ 7405, "jxs" ],
+[ 7406, "jxt" ],
+[ 7407, "jxu" ],
+[ 7408, "jxv" ],
+[ 7409, "jxw" ],
+[ 7410, "jxx" ],
+[ 7411, "jxy" ],
+[ 7412, "jxz" ],
+[ 7413, "jya" ],
+[ 7414, "jyb" ],
+[ 7415, "jyc" ],
+[ 7416, "jyd" ],
+[ 7417, "jye" ],
+[ 7418, "jyf" ],
+[ 7419, "jyg" ],
+[ 7420, "jyh" ],
+[ 7421, "jyi" ],
+[ 7422, "jyj" ],
+[ 7423, "jyk" ],
+[ 7424, "jyl" ],
+[ 7425, "jym" ],
+[ 7426, "jyn" ],
+[ 7427, "jyo" ],
+[ 7428, "jyp" ],
+[ 7429, "jyq" ],
+[ 7430, "jyr" ],
+[ 7431, "jys" ],
+[ 7432, "jyt" ],
+[ 7433, "jyu" ],
+[ 7434, "jyv" ],
+[ 7435, "jyw" ],
+[ 7436, "jyx" ],
+[ 7437, "jyy" ],
+[ 7438, "jyz" ],
+[ 7439, "jza" ],
+[ 7440, "jzb" ],
+[ 7441, "jzc" ],
+[ 7442, "jzd" ],
+[ 7443, "jze" ],
+[ 7444, "jzf" ],
+[ 7445, "jzg" ],
+[ 7446, "jzh" ],
+[ 7447, "jzi" ],
+[ 7448, "jzj" ],
+[ 7449, "jzk" ],
+[ 7450, "jzl" ],
+[ 7451, "jzm" ],
+[ 7452, "jzn" ],
+[ 7453, "jzo" ],
+[ 7454, "jzp" ],
+[ 7455, "jzq" ],
+[ 7456, "jzr" ],
+[ 7457, "jzs" ],
+[ 7458, "jzt" ],
+[ 7459, "jzu" ],
+[ 7460, "jzv" ],
+[ 7461, "jzw" ],
+[ 7462, "jzx" ],
+[ 7463, "jzy" ],
+[ 7464, "jzz" ],
+[ 7465, "kaa" ],
+[ 7466, "kab" ],
+[ 7467, "kac" ],
+[ 7468, "kad" ],
+[ 7469, "kae" ],
+[ 7470, "kaf" ],
+[ 7471, "kag" ],
+[ 7472, "kah" ],
+[ 7473, "kai" ],
+[ 7474, "kaj" ],
+[ 7475, "kak" ],
+[ 7476, "kal" ],
+[ 7477, "kam" ],
+[ 7478, "kan" ],
+[ 7479, "kao" ],
+[ 7480, "kap" ],
+[ 7481, "kaq" ],
+[ 7482, "kar" ],
+[ 7483, "kas" ],
+[ 7484, "kat" ],
+[ 7485, "kau" ],
+[ 7486, "kav" ],
+[ 7487, "kaw" ],
+[ 7488, "kax" ],
+[ 7489, "kay" ],
+[ 7490, "kaz" ],
+[ 7491, "kba" ],
+[ 7492, "kbb" ],
+[ 7493, "kbc" ],
+[ 7494, "kbd" ],
+[ 7495, "kbe" ],
+[ 7496, "kbf" ],
+[ 7497, "kbg" ],
+[ 7498, "kbh" ],
+[ 7499, "kbi" ],
+[ 7500, "kbj" ],
+[ 7501, "kbk" ],
+[ 7502, "kbl" ],
+[ 7503, "kbm" ],
+[ 7504, "kbn" ],
+[ 7505, "kbo" ],
+[ 7506, "kbp" ],
+[ 7507, "kbq" ],
+[ 7508, "kbr" ],
+[ 7509, "kbs" ],
+[ 7510, "kbt" ],
+[ 7511, "kbu" ],
+[ 7512, "kbv" ],
+[ 7513, "kbw" ],
+[ 7514, "kbx" ],
+[ 7515, "kby" ],
+[ 7516, "kbz" ],
+[ 7517, "kca" ],
+[ 7518, "kcb" ],
+[ 7519, "kcc" ],
+[ 7520, "kcd" ],
+[ 7521, "kce" ],
+[ 7522, "kcf" ],
+[ 7523, "kcg" ],
+[ 7524, "kch" ],
+[ 7525, "kci" ],
+[ 7526, "kcj" ],
+[ 7527, "kck" ],
+[ 7528, "kcl" ],
+[ 7529, "kcm" ],
+[ 7530, "kcn" ],
+[ 7531, "kco" ],
+[ 7532, "kcp" ],
+[ 7533, "kcq" ],
+[ 7534, "kcr" ],
+[ 7535, "kcs" ],
+[ 7536, "kct" ],
+[ 7537, "kcu" ],
+[ 7538, "kcv" ],
+[ 7539, "kcw" ],
+[ 7540, "kcx" ],
+[ 7541, "kcy" ],
+[ 7542, "kcz" ],
+[ 7543, "kda" ],
+[ 7544, "kdb" ],
+[ 7545, "kdc" ],
+[ 7546, "kdd" ],
+[ 7547, "kde" ],
+[ 7548, "kdf" ],
+[ 7549, "kdg" ],
+[ 7550, "kdh" ],
+[ 7551, "kdi" ],
+[ 7552, "kdj" ],
+[ 7553, "kdk" ],
+[ 7554, "kdl" ],
+[ 7555, "kdm" ],
+[ 7556, "kdn" ],
+[ 7557, "kdo" ],
+[ 7558, "kdp" ],
+[ 7559, "kdq" ],
+[ 7560, "kdr" ],
+[ 7561, "kds" ],
+[ 7562, "kdt" ],
+[ 7563, "kdu" ],
+[ 7564, "kdv" ],
+[ 7565, "kdw" ],
+[ 7566, "kdx" ],
+[ 7567, "kdy" ],
+[ 7568, "kdz" ],
+[ 7569, "kea" ],
+[ 7570, "keb" ],
+[ 7571, "kec" ],
+[ 7572, "ked" ],
+[ 7573, "kee" ],
+[ 7574, "kef" ],
+[ 7575, "keg" ],
+[ 7576, "keh" ],
+[ 7577, "kei" ],
+[ 7578, "kej" ],
+[ 7579, "kek" ],
+[ 7580, "kel" ],
+[ 7581, "kem" ],
+[ 7582, "ken" ],
+[ 7583, "keo" ],
+[ 7584, "kep" ],
+[ 7585, "keq" ],
+[ 7586, "ker" ],
+[ 7587, "kes" ],
+[ 7588, "ket" ],
+[ 7589, "keu" ],
+[ 7590, "kev" ],
+[ 7591, "kew" ],
+[ 7592, "kex" ],
+[ 7593, "key" ],
+[ 7594, "kez" ],
+[ 7595, "kfa" ],
+[ 7596, "kfb" ],
+[ 7597, "kfc" ],
+[ 7598, "kfd" ],
+[ 7599, "kfe" ],
+[ 7600, "kff" ],
+[ 7601, "kfg" ],
+[ 7602, "kfh" ],
+[ 7603, "kfi" ],
+[ 7604, "kfj" ],
+[ 7605, "kfk" ],
+[ 7606, "kfl" ],
+[ 7607, "kfm" ],
+[ 7608, "kfn" ],
+[ 7609, "kfo" ],
+[ 7610, "kfp" ],
+[ 7611, "kfq" ],
+[ 7612, "kfr" ],
+[ 7613, "kfs" ],
+[ 7614, "kft" ],
+[ 7615, "kfu" ],
+[ 7616, "kfv" ],
+[ 7617, "kfw" ],
+[ 7618, "kfx" ],
+[ 7619, "kfy" ],
+[ 7620, "kfz" ],
+[ 7621, "kga" ],
+[ 7622, "kgb" ],
+[ 7623, "kgc" ],
+[ 7624, "kgd" ],
+[ 7625, "kge" ],
+[ 7626, "kgf" ],
+[ 7627, "kgg" ],
+[ 7628, "kgh" ],
+[ 7629, "kgi" ],
+[ 7630, "kgj" ],
+[ 7631, "kgk" ],
+[ 7632, "kgl" ],
+[ 7633, "kgm" ],
+[ 7634, "kgn" ],
+[ 7635, "kgo" ],
+[ 7636, "kgp" ],
+[ 7637, "kgq" ],
+[ 7638, "kgr" ],
+[ 7639, "kgs" ],
+[ 7640, "kgt" ],
+[ 7641, "kgu" ],
+[ 7642, "kgv" ],
+[ 7643, "kgw" ],
+[ 7644, "kgx" ],
+[ 7645, "kgy" ],
+[ 7646, "kgz" ],
+[ 7647, "kha" ],
+[ 7648, "khb" ],
+[ 7649, "khc" ],
+[ 7650, "khd" ],
+[ 7651, "khe" ],
+[ 7652, "khf" ],
+[ 7653, "khg" ],
+[ 7654, "khh" ],
+[ 7655, "khi" ],
+[ 7656, "khj" ],
+[ 7657, "khk" ],
+[ 7658, "khl" ],
+[ 7659, "khm" ],
+[ 7660, "khn" ],
+[ 7661, "kho" ],
+[ 7662, "khp" ],
+[ 7663, "khq" ],
+[ 7664, "khr" ],
+[ 7665, "khs" ],
+[ 7666, "kht" ],
+[ 7667, "khu" ],
+[ 7668, "khv" ],
+[ 7669, "khw" ],
+[ 7670, "khx" ],
+[ 7671, "khy" ],
+[ 7672, "khz" ],
+[ 7673, "kia" ],
+[ 7674, "kib" ],
+[ 7675, "kic" ],
+[ 7676, "kid" ],
+[ 7677, "kie" ],
+[ 7678, "kif" ],
+[ 7679, "kig" ],
+[ 7680, "kih" ],
+[ 7681, "kii" ],
+[ 7682, "kij" ],
+[ 7683, "kik" ],
+[ 7684, "kil" ],
+[ 7685, "kim" ],
+[ 7686, "kin" ],
+[ 7687, "kio" ],
+[ 7688, "kip" ],
+[ 7689, "kiq" ],
+[ 7690, "kir" ],
+[ 7691, "kis" ],
+[ 7692, "kit" ],
+[ 7693, "kiu" ],
+[ 7694, "kiv" ],
+[ 7695, "kiw" ],
+[ 7696, "kix" ],
+[ 7697, "kiy" ],
+[ 7698, "kiz" ],
+[ 7699, "kja" ],
+[ 7700, "kjb" ],
+[ 7701, "kjc" ],
+[ 7702, "kjd" ],
+[ 7703, "kje" ],
+[ 7704, "kjf" ],
+[ 7705, "kjg" ],
+[ 7706, "kjh" ],
+[ 7707, "kji" ],
+[ 7708, "kjj" ],
+[ 7709, "kjk" ],
+[ 7710, "kjl" ],
+[ 7711, "kjm" ],
+[ 7712, "kjn" ],
+[ 7713, "kjo" ],
+[ 7714, "kjp" ],
+[ 7715, "kjq" ],
+[ 7716, "kjr" ],
+[ 7717, "kjs" ],
+[ 7718, "kjt" ],
+[ 7719, "kju" ],
+[ 7720, "kjv" ],
+[ 7721, "kjw" ],
+[ 7722, "kjx" ],
+[ 7723, "kjy" ],
+[ 7724, "kjz" ],
+[ 7725, "kka" ],
+[ 7726, "kkb" ],
+[ 7727, "kkc" ],
+[ 7728, "kkd" ],
+[ 7729, "kke" ],
+[ 7730, "kkf" ],
+[ 7731, "kkg" ],
+[ 7732, "kkh" ],
+[ 7733, "kki" ],
+[ 7734, "kkj" ],
+[ 7735, "kkk" ],
+[ 7736, "kkl" ],
+[ 7737, "kkm" ],
+[ 7738, "kkn" ],
+[ 7739, "kko" ],
+[ 7740, "kkp" ],
+[ 7741, "kkq" ],
+[ 7742, "kkr" ],
+[ 7743, "kks" ],
+[ 7744, "kkt" ],
+[ 7745, "kku" ],
+[ 7746, "kkv" ],
+[ 7747, "kkw" ],
+[ 7748, "kkx" ],
+[ 7749, "kky" ],
+[ 7750, "kkz" ],
+[ 7751, "kla" ],
+[ 7752, "klb" ],
+[ 7753, "klc" ],
+[ 7754, "kld" ],
+[ 7755, "kle" ],
+[ 7756, "klf" ],
+[ 7757, "klg" ],
+[ 7758, "klh" ],
+[ 7759, "kli" ],
+[ 7760, "klj" ],
+[ 7761, "klk" ],
+[ 7762, "kll" ],
+[ 7763, "klm" ],
+[ 7764, "kln" ],
+[ 7765, "klo" ],
+[ 7766, "klp" ],
+[ 7767, "klq" ],
+[ 7768, "klr" ],
+[ 7769, "kls" ],
+[ 7770, "klt" ],
+[ 7771, "klu" ],
+[ 7772, "klv" ],
+[ 7773, "klw" ],
+[ 7774, "klx" ],
+[ 7775, "kly" ],
+[ 7776, "klz" ],
+[ 7777, "kma" ],
+[ 7778, "kmb" ],
+[ 7779, "kmc" ],
+[ 7780, "kmd" ],
+[ 7781, "kme" ],
+[ 7782, "kmf" ],
+[ 7783, "kmg" ],
+[ 7784, "kmh" ],
+[ 7785, "kmi" ],
+[ 7786, "kmj" ],
+[ 7787, "kmk" ],
+[ 7788, "kml" ],
+[ 7789, "kmm" ],
+[ 7790, "kmn" ],
+[ 7791, "kmo" ],
+[ 7792, "kmp" ],
+[ 7793, "kmq" ],
+[ 7794, "kmr" ],
+[ 7795, "kms" ],
+[ 7796, "kmt" ],
+[ 7797, "kmu" ],
+[ 7798, "kmv" ],
+[ 7799, "kmw" ],
+[ 7800, "kmx" ],
+[ 7801, "kmy" ],
+[ 7802, "kmz" ],
+[ 7803, "kna" ],
+[ 7804, "knb" ],
+[ 7805, "knc" ],
+[ 7806, "knd" ],
+[ 7807, "kne" ],
+[ 7808, "knf" ],
+[ 7809, "kng" ],
+[ 7810, "knh" ],
+[ 7811, "kni" ],
+[ 7812, "knj" ],
+[ 7813, "knk" ],
+[ 7814, "knl" ],
+[ 7815, "knm" ],
+[ 7816, "knn" ],
+[ 7817, "kno" ],
+[ 7818, "knp" ],
+[ 7819, "knq" ],
+[ 7820, "knr" ],
+[ 7821, "kns" ],
+[ 7822, "knt" ],
+[ 7823, "knu" ],
+[ 7824, "knv" ],
+[ 7825, "knw" ],
+[ 7826, "knx" ],
+[ 7827, "kny" ],
+[ 7828, "knz" ],
+[ 7829, "koa" ],
+[ 7830, "kob" ],
+[ 7831, "koc" ],
+[ 7832, "kod" ],
+[ 7833, "koe" ],
+[ 7834, "kof" ],
+[ 7835, "kog" ],
+[ 7836, "koh" ],
+[ 7837, "koi" ],
+[ 7838, "koj" ],
+[ 7839, "kok" ],
+[ 7840, "kol" ],
+[ 7841, "kom" ],
+[ 7842, "kon" ],
+[ 7843, "koo" ],
+[ 7844, "kop" ],
+[ 7845, "koq" ],
+[ 7846, "kor" ],
+[ 7847, "kos" ],
+[ 7848, "kot" ],
+[ 7849, "kou" ],
+[ 7850, "kov" ],
+[ 7851, "kow" ],
+[ 7852, "kox" ],
+[ 7853, "koy" ],
+[ 7854, "koz" ],
+[ 7855, "kpa" ],
+[ 7856, "kpb" ],
+[ 7857, "kpc" ],
+[ 7858, "kpd" ],
+[ 7859, "kpe" ],
+[ 7860, "kpf" ],
+[ 7861, "kpg" ],
+[ 7862, "kph" ],
+[ 7863, "kpi" ],
+[ 7864, "kpj" ],
+[ 7865, "kpk" ],
+[ 7866, "kpl" ],
+[ 7867, "kpm" ],
+[ 7868, "kpn" ],
+[ 7869, "kpo" ],
+[ 7870, "kpp" ],
+[ 7871, "kpq" ],
+[ 7872, "kpr" ],
+[ 7873, "kps" ],
+[ 7874, "kpt" ],
+[ 7875, "kpu" ],
+[ 7876, "kpv" ],
+[ 7877, "kpw" ],
+[ 7878, "kpx" ],
+[ 7879, "kpy" ],
+[ 7880, "kpz" ],
+[ 7881, "kqa" ],
+[ 7882, "kqb" ],
+[ 7883, "kqc" ],
+[ 7884, "kqd" ],
+[ 7885, "kqe" ],
+[ 7886, "kqf" ],
+[ 7887, "kqg" ],
+[ 7888, "kqh" ],
+[ 7889, "kqi" ],
+[ 7890, "kqj" ],
+[ 7891, "kqk" ],
+[ 7892, "kql" ],
+[ 7893, "kqm" ],
+[ 7894, "kqn" ],
+[ 7895, "kqo" ],
+[ 7896, "kqp" ],
+[ 7897, "kqq" ],
+[ 7898, "kqr" ],
+[ 7899, "kqs" ],
+[ 7900, "kqt" ],
+[ 7901, "kqu" ],
+[ 7902, "kqv" ],
+[ 7903, "kqw" ],
+[ 7904, "kqx" ],
+[ 7905, "kqy" ],
+[ 7906, "kqz" ],
+[ 7907, "kra" ],
+[ 7908, "krb" ],
+[ 7909, "krc" ],
+[ 7910, "krd" ],
+[ 7911, "kre" ],
+[ 7912, "krf" ],
+[ 7913, "krg" ],
+[ 7914, "krh" ],
+[ 7915, "kri" ],
+[ 7916, "krj" ],
+[ 7917, "krk" ],
+[ 7918, "krl" ],
+[ 7919, "krm" ],
+[ 7920, "krn" ],
+[ 7921, "kro" ],
+[ 7922, "krp" ],
+[ 7923, "krq" ],
+[ 7924, "krr" ],
+[ 7925, "krs" ],
+[ 7926, "krt" ],
+[ 7927, "kru" ],
+[ 7928, "krv" ],
+[ 7929, "krw" ],
+[ 7930, "krx" ],
+[ 7931, "kry" ],
+[ 7932, "krz" ],
+[ 7933, "ksa" ],
+[ 7934, "ksb" ],
+[ 7935, "ksc" ],
+[ 7936, "ksd" ],
+[ 7937, "kse" ],
+[ 7938, "ksf" ],
+[ 7939, "ksg" ],
+[ 7940, "ksh" ],
+[ 7941, "ksi" ],
+[ 7942, "ksj" ],
+[ 7943, "ksk" ],
+[ 7944, "ksl" ],
+[ 7945, "ksm" ],
+[ 7946, "ksn" ],
+[ 7947, "kso" ],
+[ 7948, "ksp" ],
+[ 7949, "ksq" ],
+[ 7950, "ksr" ],
+[ 7951, "kss" ],
+[ 7952, "kst" ],
+[ 7953, "ksu" ],
+[ 7954, "ksv" ],
+[ 7955, "ksw" ],
+[ 7956, "ksx" ],
+[ 7957, "ksy" ],
+[ 7958, "ksz" ],
+[ 7959, "kta" ],
+[ 7960, "ktb" ],
+[ 7961, "ktc" ],
+[ 7962, "ktd" ],
+[ 7963, "kte" ],
+[ 7964, "ktf" ],
+[ 7965, "ktg" ],
+[ 7966, "kth" ],
+[ 7967, "kti" ],
+[ 7968, "ktj" ],
+[ 7969, "ktk" ],
+[ 7970, "ktl" ],
+[ 7971, "ktm" ],
+[ 7972, "ktn" ],
+[ 7973, "kto" ],
+[ 7974, "ktp" ],
+[ 7975, "ktq" ],
+[ 7976, "ktr" ],
+[ 7977, "kts" ],
+[ 7978, "ktt" ],
+[ 7979, "ktu" ],
+[ 7980, "ktv" ],
+[ 7981, "ktw" ],
+[ 7982, "ktx" ],
+[ 7983, "kty" ],
+[ 7984, "ktz" ],
+[ 7985, "kua" ],
+[ 7986, "kub" ],
+[ 7987, "kuc" ],
+[ 7988, "kud" ],
+[ 7989, "kue" ],
+[ 7990, "kuf" ],
+[ 7991, "kug" ],
+[ 7992, "kuh" ],
+[ 7993, "kui" ],
+[ 7994, "kuj" ],
+[ 7995, "kuk" ],
+[ 7996, "kul" ],
+[ 7997, "kum" ],
+[ 7998, "kun" ],
+[ 7999, "kuo" ],
+[ 8000, "kup" ],
+[ 8001, "kuq" ],
+[ 8002, "kur" ],
+[ 8003, "kus" ],
+[ 8004, "kut" ],
+[ 8005, "kuu" ],
+[ 8006, "kuv" ],
+[ 8007, "kuw" ],
+[ 8008, "kux" ],
+[ 8009, "kuy" ],
+[ 8010, "kuz" ],
+[ 8011, "kva" ],
+[ 8012, "kvb" ],
+[ 8013, "kvc" ],
+[ 8014, "kvd" ],
+[ 8015, "kve" ],
+[ 8016, "kvf" ],
+[ 8017, "kvg" ],
+[ 8018, "kvh" ],
+[ 8019, "kvi" ],
+[ 8020, "kvj" ],
+[ 8021, "kvk" ],
+[ 8022, "kvl" ],
+[ 8023, "kvm" ],
+[ 8024, "kvn" ],
+[ 8025, "kvo" ],
+[ 8026, "kvp" ],
+[ 8027, "kvq" ],
+[ 8028, "kvr" ],
+[ 8029, "kvs" ],
+[ 8030, "kvt" ],
+[ 8031, "kvu" ],
+[ 8032, "kvv" ],
+[ 8033, "kvw" ],
+[ 8034, "kvx" ],
+[ 8035, "kvy" ],
+[ 8036, "kvz" ],
+[ 8037, "kwa" ],
+[ 8038, "kwb" ],
+[ 8039, "kwc" ],
+[ 8040, "kwd" ],
+[ 8041, "kwe" ],
+[ 8042, "kwf" ],
+[ 8043, "kwg" ],
+[ 8044, "kwh" ],
+[ 8045, "kwi" ],
+[ 8046, "kwj" ],
+[ 8047, "kwk" ],
+[ 8048, "kwl" ],
+[ 8049, "kwm" ],
+[ 8050, "kwn" ],
+[ 8051, "kwo" ],
+[ 8052, "kwp" ],
+[ 8053, "kwq" ],
+[ 8054, "kwr" ],
+[ 8055, "kws" ],
+[ 8056, "kwt" ],
+[ 8057, "kwu" ],
+[ 8058, "kwv" ],
+[ 8059, "kww" ],
+[ 8060, "kwx" ],
+[ 8061, "kwy" ],
+[ 8062, "kwz" ],
+[ 8063, "kxa" ],
+[ 8064, "kxb" ],
+[ 8065, "kxc" ],
+[ 8066, "kxd" ],
+[ 8067, "kxe" ],
+[ 8068, "kxf" ],
+[ 8069, "kxg" ],
+[ 8070, "kxh" ],
+[ 8071, "kxi" ],
+[ 8072, "kxj" ],
+[ 8073, "kxk" ],
+[ 8074, "kxl" ],
+[ 8075, "kxm" ],
+[ 8076, "kxn" ],
+[ 8077, "kxo" ],
+[ 8078, "kxp" ],
+[ 8079, "kxq" ],
+[ 8080, "kxr" ],
+[ 8081, "kxs" ],
+[ 8082, "kxt" ],
+[ 8083, "kxu" ],
+[ 8084, "kxv" ],
+[ 8085, "kxw" ],
+[ 8086, "kxx" ],
+[ 8087, "kxy" ],
+[ 8088, "kxz" ],
+[ 8089, "kya" ],
+[ 8090, "kyb" ],
+[ 8091, "kyc" ],
+[ 8092, "kyd" ],
+[ 8093, "kye" ],
+[ 8094, "kyf" ],
+[ 8095, "kyg" ],
+[ 8096, "kyh" ],
+[ 8097, "kyi" ],
+[ 8098, "kyj" ],
+[ 8099, "kyk" ],
+[ 8100, "kyl" ],
+[ 8101, "kym" ],
+[ 8102, "kyn" ],
+[ 8103, "kyo" ],
+[ 8104, "kyp" ],
+[ 8105, "kyq" ],
+[ 8106, "kyr" ],
+[ 8107, "kys" ],
+[ 8108, "kyt" ],
+[ 8109, "kyu" ],
+[ 8110, "kyv" ],
+[ 8111, "kyw" ],
+[ 8112, "kyx" ],
+[ 8113, "kyy" ],
+[ 8114, "kyz" ],
+[ 8115, "kza" ],
+[ 8116, "kzb" ],
+[ 8117, "kzc" ],
+[ 8118, "kzd" ],
+[ 8119, "kze" ],
+[ 8120, "kzf" ],
+[ 8121, "kzg" ],
+[ 8122, "kzh" ],
+[ 8123, "kzi" ],
+[ 8124, "kzj" ],
+[ 8125, "kzk" ],
+[ 8126, "kzl" ],
+[ 8127, "kzm" ],
+[ 8128, "kzn" ],
+[ 8129, "kzo" ],
+[ 8130, "kzp" ],
+[ 8131, "kzq" ],
+[ 8132, "kzr" ],
+[ 8133, "kzs" ],
+[ 8134, "kzt" ],
+[ 8135, "kzu" ],
+[ 8136, "kzv" ],
+[ 8137, "kzw" ],
+[ 8138, "kzx" ],
+[ 8139, "kzy" ],
+[ 8140, "kzz" ],
+[ 8141, "laa" ],
+[ 8142, "lab" ],
+[ 8143, "lac" ],
+[ 8144, "lad" ],
+[ 8145, "lae" ],
+[ 8146, "laf" ],
+[ 8147, "lag" ],
+[ 8148, "lah" ],
+[ 8149, "lai" ],
+[ 8150, "laj" ],
+[ 8151, "lak" ],
+[ 8152, "lal" ],
+[ 8153, "lam" ],
+[ 8154, "lan" ],
+[ 8155, "lao" ],
+[ 8156, "lap" ],
+[ 8157, "laq" ],
+[ 8158, "lar" ],
+[ 8159, "las" ],
+[ 8160, "lat" ],
+[ 8161, "lau" ],
+[ 8162, "lav" ],
+[ 8163, "law" ],
+[ 8164, "lax" ],
+[ 8165, "lay" ],
+[ 8166, "laz" ],
+[ 8167, "lba" ],
+[ 8168, "lbb" ],
+[ 8169, "lbc" ],
+[ 8170, "lbd" ],
+[ 8171, "lbe" ],
+[ 8172, "lbf" ],
+[ 8173, "lbg" ],
+[ 8174, "lbh" ],
+[ 8175, "lbi" ],
+[ 8176, "lbj" ],
+[ 8177, "lbk" ],
+[ 8178, "lbl" ],
+[ 8179, "lbm" ],
+[ 8180, "lbn" ],
+[ 8181, "lbo" ],
+[ 8182, "lbp" ],
+[ 8183, "lbq" ],
+[ 8184, "lbr" ],
+[ 8185, "lbs" ],
+[ 8186, "lbt" ],
+[ 8187, "lbu" ],
+[ 8188, "lbv" ],
+[ 8189, "lbw" ],
+[ 8190, "lbx" ],
+[ 8191, "lby" ],
+[ 8192, "lbz" ],
+[ 8193, "lca" ],
+[ 8194, "lcb" ],
+[ 8195, "lcc" ],
+[ 8196, "lcd" ],
+[ 8197, "lce" ],
+[ 8198, "lcf" ],
+[ 8199, "lcg" ],
+[ 8200, "lch" ],
+[ 8201, "lci" ],
+[ 8202, "lcj" ],
+[ 8203, "lck" ],
+[ 8204, "lcl" ],
+[ 8205, "lcm" ],
+[ 8206, "lcn" ],
+[ 8207, "lco" ],
+[ 8208, "lcp" ],
+[ 8209, "lcq" ],
+[ 8210, "lcr" ],
+[ 8211, "lcs" ],
+[ 8212, "lct" ],
+[ 8213, "lcu" ],
+[ 8214, "lcv" ],
+[ 8215, "lcw" ],
+[ 8216, "lcx" ],
+[ 8217, "lcy" ],
+[ 8218, "lcz" ],
+[ 8219, "lda" ],
+[ 8220, "ldb" ],
+[ 8221, "ldc" ],
+[ 8222, "ldd" ],
+[ 8223, "lde" ],
+[ 8224, "ldf" ],
+[ 8225, "ldg" ],
+[ 8226, "ldh" ],
+[ 8227, "ldi" ],
+[ 8228, "ldj" ],
+[ 8229, "ldk" ],
+[ 8230, "ldl" ],
+[ 8231, "ldm" ],
+[ 8232, "ldn" ],
+[ 8233, "ldo" ],
+[ 8234, "ldp" ],
+[ 8235, "ldq" ],
+[ 8236, "ldr" ],
+[ 8237, "lds" ],
+[ 8238, "ldt" ],
+[ 8239, "ldu" ],
+[ 8240, "ldv" ],
+[ 8241, "ldw" ],
+[ 8242, "ldx" ],
+[ 8243, "ldy" ],
+[ 8244, "ldz" ],
+[ 8245, "lea" ],
+[ 8246, "leb" ],
+[ 8247, "lec" ],
+[ 8248, "led" ],
+[ 8249, "lee" ],
+[ 8250, "lef" ],
+[ 8251, "leg" ],
+[ 8252, "leh" ],
+[ 8253, "lei" ],
+[ 8254, "lej" ],
+[ 8255, "lek" ],
+[ 8256, "lel" ],
+[ 8257, "lem" ],
+[ 8258, "len" ],
+[ 8259, "leo" ],
+[ 8260, "lep" ],
+[ 8261, "leq" ],
+[ 8262, "ler" ],
+[ 8263, "les" ],
+[ 8264, "let" ],
+[ 8265, "leu" ],
+[ 8266, "lev" ],
+[ 8267, "lew" ],
+[ 8268, "lex" ],
+[ 8269, "ley" ],
+[ 8270, "lez" ],
+[ 8271, "lfa" ],
+[ 8272, "lfb" ],
+[ 8273, "lfc" ],
+[ 8274, "lfd" ],
+[ 8275, "lfe" ],
+[ 8276, "lff" ],
+[ 8277, "lfg" ],
+[ 8278, "lfh" ],
+[ 8279, "lfi" ],
+[ 8280, "lfj" ],
+[ 8281, "lfk" ],
+[ 8282, "lfl" ],
+[ 8283, "lfm" ],
+[ 8284, "lfn" ],
+[ 8285, "lfo" ],
+[ 8286, "lfp" ],
+[ 8287, "lfq" ],
+[ 8288, "lfr" ],
+[ 8289, "lfs" ],
+[ 8290, "lft" ],
+[ 8291, "lfu" ],
+[ 8292, "lfv" ],
+[ 8293, "lfw" ],
+[ 8294, "lfx" ],
+[ 8295, "lfy" ],
+[ 8296, "lfz" ],
+[ 8297, "lga" ],
+[ 8298, "lgb" ],
+[ 8299, "lgc" ],
+[ 8300, "lgd" ],
+[ 8301, "lge" ],
+[ 8302, "lgf" ],
+[ 8303, "lgg" ],
+[ 8304, "lgh" ],
+[ 8305, "lgi" ],
+[ 8306, "lgj" ],
+[ 8307, "lgk" ],
+[ 8308, "lgl" ],
+[ 8309, "lgm" ],
+[ 8310, "lgn" ],
+[ 8311, "lgo" ],
+[ 8312, "lgp" ],
+[ 8313, "lgq" ],
+[ 8314, "lgr" ],
+[ 8315, "lgs" ],
+[ 8316, "lgt" ],
+[ 8317, "lgu" ],
+[ 8318, "lgv" ],
+[ 8319, "lgw" ],
+[ 8320, "lgx" ],
+[ 8321, "lgy" ],
+[ 8322, "lgz" ],
+[ 8323, "lha" ],
+[ 8324, "lhb" ],
+[ 8325, "lhc" ],
+[ 8326, "lhd" ],
+[ 8327, "lhe" ],
+[ 8328, "lhf" ],
+[ 8329, "lhg" ],
+[ 8330, "lhh" ],
+[ 8331, "lhi" ],
+[ 8332, "lhj" ],
+[ 8333, "lhk" ],
+[ 8334, "lhl" ],
+[ 8335, "lhm" ],
+[ 8336, "lhn" ],
+[ 8337, "lho" ],
+[ 8338, "lhp" ],
+[ 8339, "lhq" ],
+[ 8340, "lhr" ],
+[ 8341, "lhs" ],
+[ 8342, "lht" ],
+[ 8343, "lhu" ],
+[ 8344, "lhv" ],
+[ 8345, "lhw" ],
+[ 8346, "lhx" ],
+[ 8347, "lhy" ],
+[ 8348, "lhz" ],
+[ 8349, "lia" ],
+[ 8350, "lib" ],
+[ 8351, "lic" ],
+[ 8352, "lid" ],
+[ 8353, "lie" ],
+[ 8354, "lif" ],
+[ 8355, "lig" ],
+[ 8356, "lih" ],
+[ 8357, "lii" ],
+[ 8358, "lij" ],
+[ 8359, "lik" ],
+[ 8360, "lil" ],
+[ 8361, "lim" ],
+[ 8362, "lin" ],
+[ 8363, "lio" ],
+[ 8364, "lip" ],
+[ 8365, "liq" ],
+[ 8366, "lir" ],
+[ 8367, "lis" ],
+[ 8368, "lit" ],
+[ 8369, "liu" ],
+[ 8370, "liv" ],
+[ 8371, "liw" ],
+[ 8372, "lix" ],
+[ 8373, "liy" ],
+[ 8374, "liz" ],
+[ 8375, "lja" ],
+[ 8376, "ljb" ],
+[ 8377, "ljc" ],
+[ 8378, "ljd" ],
+[ 8379, "lje" ],
+[ 8380, "ljf" ],
+[ 8381, "ljg" ],
+[ 8382, "ljh" ],
+[ 8383, "lji" ],
+[ 8384, "ljj" ],
+[ 8385, "ljk" ],
+[ 8386, "ljl" ],
+[ 8387, "ljm" ],
+[ 8388, "ljn" ],
+[ 8389, "ljo" ],
+[ 8390, "ljp" ],
+[ 8391, "ljq" ],
+[ 8392, "ljr" ],
+[ 8393, "ljs" ],
+[ 8394, "ljt" ],
+[ 8395, "lju" ],
+[ 8396, "ljv" ],
+[ 8397, "ljw" ],
+[ 8398, "ljx" ],
+[ 8399, "ljy" ],
+[ 8400, "ljz" ],
+[ 8401, "lka" ],
+[ 8402, "lkb" ],
+[ 8403, "lkc" ],
+[ 8404, "lkd" ],
+[ 8405, "lke" ],
+[ 8406, "lkf" ],
+[ 8407, "lkg" ],
+[ 8408, "lkh" ],
+[ 8409, "lki" ],
+[ 8410, "lkj" ],
+[ 8411, "lkk" ],
+[ 8412, "lkl" ],
+[ 8413, "lkm" ],
+[ 8414, "lkn" ],
+[ 8415, "lko" ],
+[ 8416, "lkp" ],
+[ 8417, "lkq" ],
+[ 8418, "lkr" ],
+[ 8419, "lks" ],
+[ 8420, "lkt" ],
+[ 8421, "lku" ],
+[ 8422, "lkv" ],
+[ 8423, "lkw" ],
+[ 8424, "lkx" ],
+[ 8425, "lky" ],
+[ 8426, "lkz" ],
+[ 8427, "lla" ],
+[ 8428, "llb" ],
+[ 8429, "llc" ],
+[ 8430, "lld" ],
+[ 8431, "lle" ],
+[ 8432, "llf" ],
+[ 8433, "llg" ],
+[ 8434, "llh" ],
+[ 8435, "lli" ],
+[ 8436, "llj" ],
+[ 8437, "llk" ],
+[ 8438, "lll" ],
+[ 8439, "llm" ],
+[ 8440, "lln" ],
+[ 8441, "llo" ],
+[ 8442, "llp" ],
+[ 8443, "llq" ],
+[ 8444, "llr" ],
+[ 8445, "lls" ],
+[ 8446, "llt" ],
+[ 8447, "llu" ],
+[ 8448, "llv" ],
+[ 8449, "llw" ],
+[ 8450, "llx" ],
+[ 8451, "lly" ],
+[ 8452, "llz" ],
+[ 8453, "lma" ],
+[ 8454, "lmb" ],
+[ 8455, "lmc" ],
+[ 8456, "lmd" ],
+[ 8457, "lme" ],
+[ 8458, "lmf" ],
+[ 8459, "lmg" ],
+[ 8460, "lmh" ],
+[ 8461, "lmi" ],
+[ 8462, "lmj" ],
+[ 8463, "lmk" ],
+[ 8464, "lml" ],
+[ 8465, "lmm" ],
+[ 8466, "lmn" ],
+[ 8467, "lmo" ],
+[ 8468, "lmp" ],
+[ 8469, "lmq" ],
+[ 8470, "lmr" ],
+[ 8471, "lms" ],
+[ 8472, "lmt" ],
+[ 8473, "lmu" ],
+[ 8474, "lmv" ],
+[ 8475, "lmw" ],
+[ 8476, "lmx" ],
+[ 8477, "lmy" ],
+[ 8478, "lmz" ],
+[ 8479, "lna" ],
+[ 8480, "lnb" ],
+[ 8481, "lnc" ],
+[ 8482, "lnd" ],
+[ 8483, "lne" ],
+[ 8484, "lnf" ],
+[ 8485, "lng" ],
+[ 8486, "lnh" ],
+[ 8487, "lni" ],
+[ 8488, "lnj" ],
+[ 8489, "lnk" ],
+[ 8490, "lnl" ],
+[ 8491, "lnm" ],
+[ 8492, "lnn" ],
+[ 8493, "lno" ],
+[ 8494, "lnp" ],
+[ 8495, "lnq" ],
+[ 8496, "lnr" ],
+[ 8497, "lns" ],
+[ 8498, "lnt" ],
+[ 8499, "lnu" ],
+[ 8500, "lnv" ],
+[ 8501, "lnw" ],
+[ 8502, "lnx" ],
+[ 8503, "lny" ],
+[ 8504, "lnz" ],
+[ 8505, "loa" ],
+[ 8506, "lob" ],
+[ 8507, "loc" ],
+[ 8508, "lod" ],
+[ 8509, "loe" ],
+[ 8510, "lof" ],
+[ 8511, "log" ],
+[ 8512, "loh" ],
+[ 8513, "loi" ],
+[ 8514, "loj" ],
+[ 8515, "lok" ],
+[ 8516, "lol" ],
+[ 8517, "lom" ],
+[ 8518, "lon" ],
+[ 8519, "loo" ],
+[ 8520, "lop" ],
+[ 8521, "loq" ],
+[ 8522, "lor" ],
+[ 8523, "los" ],
+[ 8524, "lot" ],
+[ 8525, "lou" ],
+[ 8526, "lov" ],
+[ 8527, "low" ],
+[ 8528, "lox" ],
+[ 8529, "loy" ],
+[ 8530, "loz" ],
+[ 8531, "lpa" ],
+[ 8532, "lpb" ],
+[ 8533, "lpc" ],
+[ 8534, "lpd" ],
+[ 8535, "lpe" ],
+[ 8536, "lpf" ],
+[ 8537, "lpg" ],
+[ 8538, "lph" ],
+[ 8539, "lpi" ],
+[ 8540, "lpj" ],
+[ 8541, "lpk" ],
+[ 8542, "lpl" ],
+[ 8543, "lpm" ],
+[ 8544, "lpn" ],
+[ 8545, "lpo" ],
+[ 8546, "lpp" ],
+[ 8547, "lpq" ],
+[ 8548, "lpr" ],
+[ 8549, "lps" ],
+[ 8550, "lpt" ],
+[ 8551, "lpu" ],
+[ 8552, "lpv" ],
+[ 8553, "lpw" ],
+[ 8554, "lpx" ],
+[ 8555, "lpy" ],
+[ 8556, "lpz" ],
+[ 8557, "lqa" ],
+[ 8558, "lqb" ],
+[ 8559, "lqc" ],
+[ 8560, "lqd" ],
+[ 8561, "lqe" ],
+[ 8562, "lqf" ],
+[ 8563, "lqg" ],
+[ 8564, "lqh" ],
+[ 8565, "lqi" ],
+[ 8566, "lqj" ],
+[ 8567, "lqk" ],
+[ 8568, "lql" ],
+[ 8569, "lqm" ],
+[ 8570, "lqn" ],
+[ 8571, "lqo" ],
+[ 8572, "lqp" ],
+[ 8573, "lqq" ],
+[ 8574, "lqr" ],
+[ 8575, "lqs" ],
+[ 8576, "lqt" ],
+[ 8577, "lqu" ],
+[ 8578, "lqv" ],
+[ 8579, "lqw" ],
+[ 8580, "lqx" ],
+[ 8581, "lqy" ],
+[ 8582, "lqz" ],
+[ 8583, "lra" ],
+[ 8584, "lrb" ],
+[ 8585, "lrc" ],
+[ 8586, "lrd" ],
+[ 8587, "lre" ],
+[ 8588, "lrf" ],
+[ 8589, "lrg" ],
+[ 8590, "lrh" ],
+[ 8591, "lri" ],
+[ 8592, "lrj" ],
+[ 8593, "lrk" ],
+[ 8594, "lrl" ],
+[ 8595, "lrm" ],
+[ 8596, "lrn" ],
+[ 8597, "lro" ],
+[ 8598, "lrp" ],
+[ 8599, "lrq" ],
+[ 8600, "lrr" ],
+[ 8601, "lrs" ],
+[ 8602, "lrt" ],
+[ 8603, "lru" ],
+[ 8604, "lrv" ],
+[ 8605, "lrw" ],
+[ 8606, "lrx" ],
+[ 8607, "lry" ],
+[ 8608, "lrz" ],
+[ 8609, "lsa" ],
+[ 8610, "lsb" ],
+[ 8611, "lsc" ],
+[ 8612, "lsd" ],
+[ 8613, "lse" ],
+[ 8614, "lsf" ],
+[ 8615, "lsg" ],
+[ 8616, "lsh" ],
+[ 8617, "lsi" ],
+[ 8618, "lsj" ],
+[ 8619, "lsk" ],
+[ 8620, "lsl" ],
+[ 8621, "lsm" ],
+[ 8622, "lsn" ],
+[ 8623, "lso" ],
+[ 8624, "lsp" ],
+[ 8625, "lsq" ],
+[ 8626, "lsr" ],
+[ 8627, "lss" ],
+[ 8628, "lst" ],
+[ 8629, "lsu" ],
+[ 8630, "lsv" ],
+[ 8631, "lsw" ],
+[ 8632, "lsx" ],
+[ 8633, "lsy" ],
+[ 8634, "lsz" ],
+[ 8635, "lta" ],
+[ 8636, "ltb" ],
+[ 8637, "ltc" ],
+[ 8638, "ltd" ],
+[ 8639, "lte" ],
+[ 8640, "ltf" ],
+[ 8641, "ltg" ],
+[ 8642, "lth" ],
+[ 8643, "lti" ],
+[ 8644, "ltj" ],
+[ 8645, "ltk" ],
+[ 8646, "ltl" ],
+[ 8647, "ltm" ],
+[ 8648, "ltn" ],
+[ 8649, "lto" ],
+[ 8650, "ltp" ],
+[ 8651, "ltq" ],
+[ 8652, "ltr" ],
+[ 8653, "lts" ],
+[ 8654, "ltt" ],
+[ 8655, "ltu" ],
+[ 8656, "ltv" ],
+[ 8657, "ltw" ],
+[ 8658, "ltx" ],
+[ 8659, "lty" ],
+[ 8660, "ltz" ],
+[ 8661, "lua" ],
+[ 8662, "lub" ],
+[ 8663, "luc" ],
+[ 8664, "lud" ],
+[ 8665, "lue" ],
+[ 8666, "luf" ],
+[ 8667, "lug" ],
+[ 8668, "luh" ],
+[ 8669, "lui" ],
+[ 8670, "luj" ],
+[ 8671, "luk" ],
+[ 8672, "lul" ],
+[ 8673, "lum" ],
+[ 8674, "lun" ],
+[ 8675, "luo" ],
+[ 8676, "lup" ],
+[ 8677, "luq" ],
+[ 8678, "lur" ],
+[ 8679, "lus" ],
+[ 8680, "lut" ],
+[ 8681, "luu" ],
+[ 8682, "luv" ],
+[ 8683, "luw" ],
+[ 8684, "lux" ],
+[ 8685, "luy" ],
+[ 8686, "luz" ],
+[ 8687, "lva" ],
+[ 8688, "lvb" ],
+[ 8689, "lvc" ],
+[ 8690, "lvd" ],
+[ 8691, "lve" ],
+[ 8692, "lvf" ],
+[ 8693, "lvg" ],
+[ 8694, "lvh" ],
+[ 8695, "lvi" ],
+[ 8696, "lvj" ],
+[ 8697, "lvk" ],
+[ 8698, "lvl" ],
+[ 8699, "lvm" ],
+[ 8700, "lvn" ],
+[ 8701, "lvo" ],
+[ 8702, "lvp" ],
+[ 8703, "lvq" ],
+[ 8704, "lvr" ],
+[ 8705, "lvs" ],
+[ 8706, "lvt" ],
+[ 8707, "lvu" ],
+[ 8708, "lvv" ],
+[ 8709, "lvw" ],
+[ 8710, "lvx" ],
+[ 8711, "lvy" ],
+[ 8712, "lvz" ],
+[ 8713, "lwa" ],
+[ 8714, "lwb" ],
+[ 8715, "lwc" ],
+[ 8716, "lwd" ],
+[ 8717, "lwe" ],
+[ 8718, "lwf" ],
+[ 8719, "lwg" ],
+[ 8720, "lwh" ],
+[ 8721, "lwi" ],
+[ 8722, "lwj" ],
+[ 8723, "lwk" ],
+[ 8724, "lwl" ],
+[ 8725, "lwm" ],
+[ 8726, "lwn" ],
+[ 8727, "lwo" ],
+[ 8728, "lwp" ],
+[ 8729, "lwq" ],
+[ 8730, "lwr" ],
+[ 8731, "lws" ],
+[ 8732, "lwt" ],
+[ 8733, "lwu" ],
+[ 8734, "lwv" ],
+[ 8735, "lww" ],
+[ 8736, "lwx" ],
+[ 8737, "lwy" ],
+[ 8738, "lwz" ],
+[ 8739, "lxa" ],
+[ 8740, "lxb" ],
+[ 8741, "lxc" ],
+[ 8742, "lxd" ],
+[ 8743, "lxe" ],
+[ 8744, "lxf" ],
+[ 8745, "lxg" ],
+[ 8746, "lxh" ],
+[ 8747, "lxi" ],
+[ 8748, "lxj" ],
+[ 8749, "lxk" ],
+[ 8750, "lxl" ],
+[ 8751, "lxm" ],
+[ 8752, "lxn" ],
+[ 8753, "lxo" ],
+[ 8754, "lxp" ],
+[ 8755, "lxq" ],
+[ 8756, "lxr" ],
+[ 8757, "lxs" ],
+[ 8758, "lxt" ],
+[ 8759, "lxu" ],
+[ 8760, "lxv" ],
+[ 8761, "lxw" ],
+[ 8762, "lxx" ],
+[ 8763, "lxy" ],
+[ 8764, "lxz" ],
+[ 8765, "lya" ],
+[ 8766, "lyb" ],
+[ 8767, "lyc" ],
+[ 8768, "lyd" ],
+[ 8769, "lye" ],
+[ 8770, "lyf" ],
+[ 8771, "lyg" ],
+[ 8772, "lyh" ],
+[ 8773, "lyi" ],
+[ 8774, "lyj" ],
+[ 8775, "lyk" ],
+[ 8776, "lyl" ],
+[ 8777, "lym" ],
+[ 8778, "lyn" ],
+[ 8779, "lyo" ],
+[ 8780, "lyp" ],
+[ 8781, "lyq" ],
+[ 8782, "lyr" ],
+[ 8783, "lys" ],
+[ 8784, "lyt" ],
+[ 8785, "lyu" ],
+[ 8786, "lyv" ],
+[ 8787, "lyw" ],
+[ 8788, "lyx" ],
+[ 8789, "lyy" ],
+[ 8790, "lyz" ],
+[ 8791, "lza" ],
+[ 8792, "lzb" ],
+[ 8793, "lzc" ],
+[ 8794, "lzd" ],
+[ 8795, "lze" ],
+[ 8796, "lzf" ],
+[ 8797, "lzg" ],
+[ 8798, "lzh" ],
+[ 8799, "lzi" ],
+[ 8800, "lzj" ],
+[ 8801, "lzk" ],
+[ 8802, "lzl" ],
+[ 8803, "lzm" ],
+[ 8804, "lzn" ],
+[ 8805, "lzo" ],
+[ 8806, "lzp" ],
+[ 8807, "lzq" ],
+[ 8808, "lzr" ],
+[ 8809, "lzs" ],
+[ 8810, "lzt" ],
+[ 8811, "lzu" ],
+[ 8812, "lzv" ],
+[ 8813, "lzw" ],
+[ 8814, "lzx" ],
+[ 8815, "lzy" ],
+[ 8816, "lzz" ],
+[ 8817, "maa" ],
+[ 8818, "mab" ],
+[ 8819, "mac" ],
+[ 8820, "mad" ],
+[ 8821, "mae" ],
+[ 8822, "maf" ],
+[ 8823, "mag" ],
+[ 8824, "mah" ],
+[ 8825, "mai" ],
+[ 8826, "maj" ],
+[ 8827, "mak" ],
+[ 8828, "mal" ],
+[ 8829, "mam" ],
+[ 8830, "man" ],
+[ 8831, "mao" ],
+[ 8832, "map" ],
+[ 8833, "maq" ],
+[ 8834, "mar" ],
+[ 8835, "mas" ],
+[ 8836, "mat" ],
+[ 8837, "mau" ],
+[ 8838, "mav" ],
+[ 8839, "maw" ],
+[ 8840, "max" ],
+[ 8841, "may" ],
+[ 8842, "maz" ],
+[ 8843, "mba" ],
+[ 8844, "mbb" ],
+[ 8845, "mbc" ],
+[ 8846, "mbd" ],
+[ 8847, "mbe" ],
+[ 8848, "mbf" ],
+[ 8849, "mbg" ],
+[ 8850, "mbh" ],
+[ 8851, "mbi" ],
+[ 8852, "mbj" ],
+[ 8853, "mbk" ],
+[ 8854, "mbl" ],
+[ 8855, "mbm" ],
+[ 8856, "mbn" ],
+[ 8857, "mbo" ],
+[ 8858, "mbp" ],
+[ 8859, "mbq" ],
+[ 8860, "mbr" ],
+[ 8861, "mbs" ],
+[ 8862, "mbt" ],
+[ 8863, "mbu" ],
+[ 8864, "mbv" ],
+[ 8865, "mbw" ],
+[ 8866, "mbx" ],
+[ 8867, "mby" ],
+[ 8868, "mbz" ],
+[ 8869, "mca" ],
+[ 8870, "mcb" ],
+[ 8871, "mcc" ],
+[ 8872, "mcd" ],
+[ 8873, "mce" ],
+[ 8874, "mcf" ],
+[ 8875, "mcg" ],
+[ 8876, "mch" ],
+[ 8877, "mci" ],
+[ 8878, "mcj" ],
+[ 8879, "mck" ],
+[ 8880, "mcl" ],
+[ 8881, "mcm" ],
+[ 8882, "mcn" ],
+[ 8883, "mco" ],
+[ 8884, "mcp" ],
+[ 8885, "mcq" ],
+[ 8886, "mcr" ],
+[ 8887, "mcs" ],
+[ 8888, "mct" ],
+[ 8889, "mcu" ],
+[ 8890, "mcv" ],
+[ 8891, "mcw" ],
+[ 8892, "mcx" ],
+[ 8893, "mcy" ],
+[ 8894, "mcz" ],
+[ 8895, "mda" ],
+[ 8896, "mdb" ],
+[ 8897, "mdc" ],
+[ 8898, "mdd" ],
+[ 8899, "mde" ],
+[ 8900, "mdf" ],
+[ 8901, "mdg" ],
+[ 8902, "mdh" ],
+[ 8903, "mdi" ],
+[ 8904, "mdj" ],
+[ 8905, "mdk" ],
+[ 8906, "mdl" ],
+[ 8907, "mdm" ],
+[ 8908, "mdn" ],
+[ 8909, "mdo" ],
+[ 8910, "mdp" ],
+[ 8911, "mdq" ],
+[ 8912, "mdr" ],
+[ 8913, "mds" ],
+[ 8914, "mdt" ],
+[ 8915, "mdu" ],
+[ 8916, "mdv" ],
+[ 8917, "mdw" ],
+[ 8918, "mdx" ],
+[ 8919, "mdy" ],
+[ 8920, "mdz" ],
+[ 8921, "mea" ],
+[ 8922, "meb" ],
+[ 8923, "mec" ],
+[ 8924, "med" ],
+[ 8925, "mee" ],
+[ 8926, "mef" ],
+[ 8927, "meg" ],
+[ 8928, "meh" ],
+[ 8929, "mei" ],
+[ 8930, "mej" ],
+[ 8931, "mek" ],
+[ 8932, "mel" ],
+[ 8933, "mem" ],
+[ 8934, "men" ],
+[ 8935, "meo" ],
+[ 8936, "mep" ],
+[ 8937, "meq" ],
+[ 8938, "mer" ],
+[ 8939, "mes" ],
+[ 8940, "met" ],
+[ 8941, "meu" ],
+[ 8942, "mev" ],
+[ 8943, "mew" ],
+[ 8944, "mex" ],
+[ 8945, "mey" ],
+[ 8946, "mez" ],
+[ 8947, "mfa" ],
+[ 8948, "mfb" ],
+[ 8949, "mfc" ],
+[ 8950, "mfd" ],
+[ 8951, "mfe" ],
+[ 8952, "mff" ],
+[ 8953, "mfg" ],
+[ 8954, "mfh" ],
+[ 8955, "mfi" ],
+[ 8956, "mfj" ],
+[ 8957, "mfk" ],
+[ 8958, "mfl" ],
+[ 8959, "mfm" ],
+[ 8960, "mfn" ],
+[ 8961, "mfo" ],
+[ 8962, "mfp" ],
+[ 8963, "mfq" ],
+[ 8964, "mfr" ],
+[ 8965, "mfs" ],
+[ 8966, "mft" ],
+[ 8967, "mfu" ],
+[ 8968, "mfv" ],
+[ 8969, "mfw" ],
+[ 8970, "mfx" ],
+[ 8971, "mfy" ],
+[ 8972, "mfz" ],
+[ 8973, "mga" ],
+[ 8974, "mgb" ],
+[ 8975, "mgc" ],
+[ 8976, "mgd" ],
+[ 8977, "mge" ],
+[ 8978, "mgf" ],
+[ 8979, "mgg" ],
+[ 8980, "mgh" ],
+[ 8981, "mgi" ],
+[ 8982, "mgj" ],
+[ 8983, "mgk" ],
+[ 8984, "mgl" ],
+[ 8985, "mgm" ],
+[ 8986, "mgn" ],
+[ 8987, "mgo" ],
+[ 8988, "mgp" ],
+[ 8989, "mgq" ],
+[ 8990, "mgr" ],
+[ 8991, "mgs" ],
+[ 8992, "mgt" ],
+[ 8993, "mgu" ],
+[ 8994, "mgv" ],
+[ 8995, "mgw" ],
+[ 8996, "mgx" ],
+[ 8997, "mgy" ],
+[ 8998, "mgz" ],
+[ 8999, "mha" ],
+[ 9000, "mhb" ],
+[ 9001, "mhc" ],
+[ 9002, "mhd" ],
+[ 9003, "mhe" ],
+[ 9004, "mhf" ],
+[ 9005, "mhg" ],
+[ 9006, "mhh" ],
+[ 9007, "mhi" ],
+[ 9008, "mhj" ],
+[ 9009, "mhk" ],
+[ 9010, "mhl" ],
+[ 9011, "mhm" ],
+[ 9012, "mhn" ],
+[ 9013, "mho" ],
+[ 9014, "mhp" ],
+[ 9015, "mhq" ],
+[ 9016, "mhr" ],
+[ 9017, "mhs" ],
+[ 9018, "mht" ],
+[ 9019, "mhu" ],
+[ 9020, "mhv" ],
+[ 9021, "mhw" ],
+[ 9022, "mhx" ],
+[ 9023, "mhy" ],
+[ 9024, "mhz" ],
+[ 9025, "mia" ],
+[ 9026, "mib" ],
+[ 9027, "mic" ],
+[ 9028, "mid" ],
+[ 9029, "mie" ],
+[ 9030, "mif" ],
+[ 9031, "mig" ],
+[ 9032, "mih" ],
+[ 9033, "mii" ],
+[ 9034, "mij" ],
+[ 9035, "mik" ],
+[ 9036, "mil" ],
+[ 9037, "mim" ],
+[ 9038, "min" ],
+[ 9039, "mio" ],
+[ 9040, "mip" ],
+[ 9041, "miq" ],
+[ 9042, "mir" ],
+[ 9043, "mis" ],
+[ 9044, "mit" ],
+[ 9045, "miu" ],
+[ 9046, "miv" ],
+[ 9047, "miw" ],
+[ 9048, "mix" ],
+[ 9049, "miy" ],
+[ 9050, "miz" ],
+[ 9051, "mja" ],
+[ 9052, "mjb" ],
+[ 9053, "mjc" ],
+[ 9054, "mjd" ],
+[ 9055, "mje" ],
+[ 9056, "mjf" ],
+[ 9057, "mjg" ],
+[ 9058, "mjh" ],
+[ 9059, "mji" ],
+[ 9060, "mjj" ],
+[ 9061, "mjk" ],
+[ 9062, "mjl" ],
+[ 9063, "mjm" ],
+[ 9064, "mjn" ],
+[ 9065, "mjo" ],
+[ 9066, "mjp" ],
+[ 9067, "mjq" ],
+[ 9068, "mjr" ],
+[ 9069, "mjs" ],
+[ 9070, "mjt" ],
+[ 9071, "mju" ],
+[ 9072, "mjv" ],
+[ 9073, "mjw" ],
+[ 9074, "mjx" ],
+[ 9075, "mjy" ],
+[ 9076, "mjz" ],
+[ 9077, "mka" ],
+[ 9078, "mkb" ],
+[ 9079, "mkc" ],
+[ 9080, "mkd" ],
+[ 9081, "mke" ],
+[ 9082, "mkf" ],
+[ 9083, "mkg" ],
+[ 9084, "mkh" ],
+[ 9085, "mki" ],
+[ 9086, "mkj" ],
+[ 9087, "mkk" ],
+[ 9088, "mkl" ],
+[ 9089, "mkm" ],
+[ 9090, "mkn" ],
+[ 9091, "mko" ],
+[ 9092, "mkp" ],
+[ 9093, "mkq" ],
+[ 9094, "mkr" ],
+[ 9095, "mks" ],
+[ 9096, "mkt" ],
+[ 9097, "mku" ],
+[ 9098, "mkv" ],
+[ 9099, "mkw" ],
+[ 9100, "mkx" ],
+[ 9101, "mky" ],
+[ 9102, "mkz" ],
+[ 9103, "mla" ],
+[ 9104, "mlb" ],
+[ 9105, "mlc" ],
+[ 9106, "mld" ],
+[ 9107, "mle" ],
+[ 9108, "mlf" ],
+[ 9109, "mlg" ],
+[ 9110, "mlh" ],
+[ 9111, "mli" ],
+[ 9112, "mlj" ],
+[ 9113, "mlk" ],
+[ 9114, "mll" ],
+[ 9115, "mlm" ],
+[ 9116, "mln" ],
+[ 9117, "mlo" ],
+[ 9118, "mlp" ],
+[ 9119, "mlq" ],
+[ 9120, "mlr" ],
+[ 9121, "mls" ],
+[ 9122, "mlt" ],
+[ 9123, "mlu" ],
+[ 9124, "mlv" ],
+[ 9125, "mlw" ],
+[ 9126, "mlx" ],
+[ 9127, "mly" ],
+[ 9128, "mlz" ],
+[ 9129, "mma" ],
+[ 9130, "mmb" ],
+[ 9131, "mmc" ],
+[ 9132, "mmd" ],
+[ 9133, "mme" ],
+[ 9134, "mmf" ],
+[ 9135, "mmg" ],
+[ 9136, "mmh" ],
+[ 9137, "mmi" ],
+[ 9138, "mmj" ],
+[ 9139, "mmk" ],
+[ 9140, "mml" ],
+[ 9141, "mmm" ],
+[ 9142, "mmn" ],
+[ 9143, "mmo" ],
+[ 9144, "mmp" ],
+[ 9145, "mmq" ],
+[ 9146, "mmr" ],
+[ 9147, "mms" ],
+[ 9148, "mmt" ],
+[ 9149, "mmu" ],
+[ 9150, "mmv" ],
+[ 9151, "mmw" ],
+[ 9152, "mmx" ],
+[ 9153, "mmy" ],
+[ 9154, "mmz" ],
+[ 9155, "mna" ],
+[ 9156, "mnb" ],
+[ 9157, "mnc" ],
+[ 9158, "mnd" ],
+[ 9159, "mne" ],
+[ 9160, "mnf" ],
+[ 9161, "mng" ],
+[ 9162, "mnh" ],
+[ 9163, "mni" ],
+[ 9164, "mnj" ],
+[ 9165, "mnk" ],
+[ 9166, "mnl" ],
+[ 9167, "mnm" ],
+[ 9168, "mnn" ],
+[ 9169, "mno" ],
+[ 9170, "mnp" ],
+[ 9171, "mnq" ],
+[ 9172, "mnr" ],
+[ 9173, "mns" ],
+[ 9174, "mnt" ],
+[ 9175, "mnu" ],
+[ 9176, "mnv" ],
+[ 9177, "mnw" ],
+[ 9178, "mnx" ],
+[ 9179, "mny" ],
+[ 9180, "mnz" ],
+[ 9181, "moa" ],
+[ 9182, "mob" ],
+[ 9183, "moc" ],
+[ 9184, "mod" ],
+[ 9185, "moe" ],
+[ 9186, "mof" ],
+[ 9187, "mog" ],
+[ 9188, "moh" ],
+[ 9189, "moi" ],
+[ 9190, "moj" ],
+[ 9191, "mok" ],
+[ 9192, "mol" ],
+[ 9193, "mom" ],
+[ 9194, "mon" ],
+[ 9195, "moo" ],
+[ 9196, "mop" ],
+[ 9197, "moq" ],
+[ 9198, "mor" ],
+[ 9199, "mos" ],
+[ 9200, "mot" ],
+[ 9201, "mou" ],
+[ 9202, "mov" ],
+[ 9203, "mow" ],
+[ 9204, "mox" ],
+[ 9205, "moy" ],
+[ 9206, "moz" ],
+[ 9207, "mpa" ],
+[ 9208, "mpb" ],
+[ 9209, "mpc" ],
+[ 9210, "mpd" ],
+[ 9211, "mpe" ],
+[ 9212, "mpf" ],
+[ 9213, "mpg" ],
+[ 9214, "mph" ],
+[ 9215, "mpi" ],
+[ 9216, "mpj" ],
+[ 9217, "mpk" ],
+[ 9218, "mpl" ],
+[ 9219, "mpm" ],
+[ 9220, "mpn" ],
+[ 9221, "mpo" ],
+[ 9222, "mpp" ],
+[ 9223, "mpq" ],
+[ 9224, "mpr" ],
+[ 9225, "mps" ],
+[ 9226, "mpt" ],
+[ 9227, "mpu" ],
+[ 9228, "mpv" ],
+[ 9229, "mpw" ],
+[ 9230, "mpx" ],
+[ 9231, "mpy" ],
+[ 9232, "mpz" ],
+[ 9233, "mqa" ],
+[ 9234, "mqb" ],
+[ 9235, "mqc" ],
+[ 9236, "mqd" ],
+[ 9237, "mqe" ],
+[ 9238, "mqf" ],
+[ 9239, "mqg" ],
+[ 9240, "mqh" ],
+[ 9241, "mqi" ],
+[ 9242, "mqj" ],
+[ 9243, "mqk" ],
+[ 9244, "mql" ],
+[ 9245, "mqm" ],
+[ 9246, "mqn" ],
+[ 9247, "mqo" ],
+[ 9248, "mqp" ],
+[ 9249, "mqq" ],
+[ 9250, "mqr" ],
+[ 9251, "mqs" ],
+[ 9252, "mqt" ],
+[ 9253, "mqu" ],
+[ 9254, "mqv" ],
+[ 9255, "mqw" ],
+[ 9256, "mqx" ],
+[ 9257, "mqy" ],
+[ 9258, "mqz" ],
+[ 9259, "mra" ],
+[ 9260, "mrb" ],
+[ 9261, "mrc" ],
+[ 9262, "mrd" ],
+[ 9263, "mre" ],
+[ 9264, "mrf" ],
+[ 9265, "mrg" ],
+[ 9266, "mrh" ],
+[ 9267, "mri" ],
+[ 9268, "mrj" ],
+[ 9269, "mrk" ],
+[ 9270, "mrl" ],
+[ 9271, "mrm" ],
+[ 9272, "mrn" ],
+[ 9273, "mro" ],
+[ 9274, "mrp" ],
+[ 9275, "mrq" ],
+[ 9276, "mrr" ],
+[ 9277, "mrs" ],
+[ 9278, "mrt" ],
+[ 9279, "mru" ],
+[ 9280, "mrv" ],
+[ 9281, "mrw" ],
+[ 9282, "mrx" ],
+[ 9283, "mry" ],
+[ 9284, "mrz" ],
+[ 9285, "msa" ],
+[ 9286, "msb" ],
+[ 9287, "msc" ],
+[ 9288, "msd" ],
+[ 9289, "mse" ],
+[ 9290, "msf" ],
+[ 9291, "msg" ],
+[ 9292, "msh" ],
+[ 9293, "msi" ],
+[ 9294, "msj" ],
+[ 9295, "msk" ],
+[ 9296, "msl" ],
+[ 9297, "msm" ],
+[ 9298, "msn" ],
+[ 9299, "mso" ],
+[ 9300, "msp" ],
+[ 9301, "msq" ],
+[ 9302, "msr" ],
+[ 9303, "mss" ],
+[ 9304, "mst" ],
+[ 9305, "msu" ],
+[ 9306, "msv" ],
+[ 9307, "msw" ],
+[ 9308, "msx" ],
+[ 9309, "msy" ],
+[ 9310, "msz" ],
+[ 9311, "mta" ],
+[ 9312, "mtb" ],
+[ 9313, "mtc" ],
+[ 9314, "mtd" ],
+[ 9315, "mte" ],
+[ 9316, "mtf" ],
+[ 9317, "mtg" ],
+[ 9318, "mth" ],
+[ 9319, "mti" ],
+[ 9320, "mtj" ],
+[ 9321, "mtk" ],
+[ 9322, "mtl" ],
+[ 9323, "mtm" ],
+[ 9324, "mtn" ],
+[ 9325, "mto" ],
+[ 9326, "mtp" ],
+[ 9327, "mtq" ],
+[ 9328, "mtr" ],
+[ 9329, "mts" ],
+[ 9330, "mtt" ],
+[ 9331, "mtu" ],
+[ 9332, "mtv" ],
+[ 9333, "mtw" ],
+[ 9334, "mtx" ],
+[ 9335, "mty" ],
+[ 9336, "mtz" ],
+[ 9337, "mua" ],
+[ 9338, "mub" ],
+[ 9339, "muc" ],
+[ 9340, "mud" ],
+[ 9341, "mue" ],
+[ 9342, "muf" ],
+[ 9343, "mug" ],
+[ 9344, "muh" ],
+[ 9345, "mui" ],
+[ 9346, "muj" ],
+[ 9347, "muk" ],
+[ 9348, "mul" ],
+[ 9349, "mum" ],
+[ 9350, "mun" ],
+[ 9351, "muo" ],
+[ 9352, "mup" ],
+[ 9353, "muq" ],
+[ 9354, "mur" ],
+[ 9355, "mus" ],
+[ 9356, "mut" ],
+[ 9357, "muu" ],
+[ 9358, "muv" ],
+[ 9359, "muw" ],
+[ 9360, "mux" ],
+[ 9361, "muy" ],
+[ 9362, "muz" ],
+[ 9363, "mva" ],
+[ 9364, "mvb" ],
+[ 9365, "mvc" ],
+[ 9366, "mvd" ],
+[ 9367, "mve" ],
+[ 9368, "mvf" ],
+[ 9369, "mvg" ],
+[ 9370, "mvh" ],
+[ 9371, "mvi" ],
+[ 9372, "mvj" ],
+[ 9373, "mvk" ],
+[ 9374, "mvl" ],
+[ 9375, "mvm" ],
+[ 9376, "mvn" ],
+[ 9377, "mvo" ],
+[ 9378, "mvp" ],
+[ 9379, "mvq" ],
+[ 9380, "mvr" ],
+[ 9381, "mvs" ],
+[ 9382, "mvt" ],
+[ 9383, "mvu" ],
+[ 9384, "mvv" ],
+[ 9385, "mvw" ],
+[ 9386, "mvx" ],
+[ 9387, "mvy" ],
+[ 9388, "mvz" ],
+[ 9389, "mwa" ],
+[ 9390, "mwb" ],
+[ 9391, "mwc" ],
+[ 9392, "mwd" ],
+[ 9393, "mwe" ],
+[ 9394, "mwf" ],
+[ 9395, "mwg" ],
+[ 9396, "mwh" ],
+[ 9397, "mwi" ],
+[ 9398, "mwj" ],
+[ 9399, "mwk" ],
+[ 9400, "mwl" ],
+[ 9401, "mwm" ],
+[ 9402, "mwn" ],
+[ 9403, "mwo" ],
+[ 9404, "mwp" ],
+[ 9405, "mwq" ],
+[ 9406, "mwr" ],
+[ 9407, "mws" ],
+[ 9408, "mwt" ],
+[ 9409, "mwu" ],
+[ 9410, "mwv" ],
+[ 9411, "mww" ],
+[ 9412, "mwx" ],
+[ 9413, "mwy" ],
+[ 9414, "mwz" ],
+[ 9415, "mxa" ],
+[ 9416, "mxb" ],
+[ 9417, "mxc" ],
+[ 9418, "mxd" ],
+[ 9419, "mxe" ],
+[ 9420, "mxf" ],
+[ 9421, "mxg" ],
+[ 9422, "mxh" ],
+[ 9423, "mxi" ],
+[ 9424, "mxj" ],
+[ 9425, "mxk" ],
+[ 9426, "mxl" ],
+[ 9427, "mxm" ],
+[ 9428, "mxn" ],
+[ 9429, "mxo" ],
+[ 9430, "mxp" ],
+[ 9431, "mxq" ],
+[ 9432, "mxr" ],
+[ 9433, "mxs" ],
+[ 9434, "mxt" ],
+[ 9435, "mxu" ],
+[ 9436, "mxv" ],
+[ 9437, "mxw" ],
+[ 9438, "mxx" ],
+[ 9439, "mxy" ],
+[ 9440, "mxz" ],
+[ 9441, "mya" ],
+[ 9442, "myb" ],
+[ 9443, "myc" ],
+[ 9444, "myd" ],
+[ 9445, "mye" ],
+[ 9446, "myf" ],
+[ 9447, "myg" ],
+[ 9448, "myh" ],
+[ 9449, "myi" ],
+[ 9450, "myj" ],
+[ 9451, "myk" ],
+[ 9452, "myl" ],
+[ 9453, "mym" ],
+[ 9454, "myn" ],
+[ 9455, "myo" ],
+[ 9456, "myp" ],
+[ 9457, "myq" ],
+[ 9458, "myr" ],
+[ 9459, "mys" ],
+[ 9460, "myt" ],
+[ 9461, "myu" ],
+[ 9462, "myv" ],
+[ 9463, "myw" ],
+[ 9464, "myx" ],
+[ 9465, "myy" ],
+[ 9466, "myz" ],
+[ 9467, "mza" ],
+[ 9468, "mzb" ],
+[ 9469, "mzc" ],
+[ 9470, "mzd" ],
+[ 9471, "mze" ],
+[ 9472, "mzf" ],
+[ 9473, "mzg" ],
+[ 9474, "mzh" ],
+[ 9475, "mzi" ],
+[ 9476, "mzj" ],
+[ 9477, "mzk" ],
+[ 9478, "mzl" ],
+[ 9479, "mzm" ],
+[ 9480, "mzn" ],
+[ 9481, "mzo" ],
+[ 9482, "mzp" ],
+[ 9483, "mzq" ],
+[ 9484, "mzr" ],
+[ 9485, "mzs" ],
+[ 9486, "mzt" ],
+[ 9487, "mzu" ],
+[ 9488, "mzv" ],
+[ 9489, "mzw" ],
+[ 9490, "mzx" ],
+[ 9491, "mzy" ],
+[ 9492, "mzz" ],
+[ 9493, "naa" ],
+[ 9494, "nab" ],
+[ 9495, "nac" ],
+[ 9496, "nad" ],
+[ 9497, "nae" ],
+[ 9498, "naf" ],
+[ 9499, "nag" ],
+[ 9500, "nah" ],
+[ 9501, "nai" ],
+[ 9502, "naj" ],
+[ 9503, "nak" ],
+[ 9504, "nal" ],
+[ 9505, "nam" ],
+[ 9506, "nan" ],
+[ 9507, "nao" ],
+[ 9508, "nap" ],
+[ 9509, "naq" ],
+[ 9510, "nar" ],
+[ 9511, "nas" ],
+[ 9512, "nat" ],
+[ 9513, "nau" ],
+[ 9514, "nav" ],
+[ 9515, "naw" ],
+[ 9516, "nax" ],
+[ 9517, "nay" ],
+[ 9518, "naz" ],
+[ 9519, "nba" ],
+[ 9520, "nbb" ],
+[ 9521, "nbc" ],
+[ 9522, "nbd" ],
+[ 9523, "nbe" ],
+[ 9524, "nbf" ],
+[ 9525, "nbg" ],
+[ 9526, "nbh" ],
+[ 9527, "nbi" ],
+[ 9528, "nbj" ],
+[ 9529, "nbk" ],
+[ 9530, "nbl" ],
+[ 9531, "nbm" ],
+[ 9532, "nbn" ],
+[ 9533, "nbo" ],
+[ 9534, "nbp" ],
+[ 9535, "nbq" ],
+[ 9536, "nbr" ],
+[ 9537, "nbs" ],
+[ 9538, "nbt" ],
+[ 9539, "nbu" ],
+[ 9540, "nbv" ],
+[ 9541, "nbw" ],
+[ 9542, "nbx" ],
+[ 9543, "nby" ],
+[ 9544, "nbz" ],
+[ 9545, "nca" ],
+[ 9546, "ncb" ],
+[ 9547, "ncc" ],
+[ 9548, "ncd" ],
+[ 9549, "nce" ],
+[ 9550, "ncf" ],
+[ 9551, "ncg" ],
+[ 9552, "nch" ],
+[ 9553, "nci" ],
+[ 9554, "ncj" ],
+[ 9555, "nck" ],
+[ 9556, "ncl" ],
+[ 9557, "ncm" ],
+[ 9558, "ncn" ],
+[ 9559, "nco" ],
+[ 9560, "ncp" ],
+[ 9561, "ncq" ],
+[ 9562, "ncr" ],
+[ 9563, "ncs" ],
+[ 9564, "nct" ],
+[ 9565, "ncu" ],
+[ 9566, "ncv" ],
+[ 9567, "ncw" ],
+[ 9568, "ncx" ],
+[ 9569, "ncy" ],
+[ 9570, "ncz" ],
+[ 9571, "nda" ],
+[ 9572, "ndb" ],
+[ 9573, "ndc" ],
+[ 9574, "ndd" ],
+[ 9575, "nde" ],
+[ 9576, "ndf" ],
+[ 9577, "ndg" ],
+[ 9578, "ndh" ],
+[ 9579, "ndi" ],
+[ 9580, "ndj" ],
+[ 9581, "ndk" ],
+[ 9582, "ndl" ],
+[ 9583, "ndm" ],
+[ 9584, "ndn" ],
+[ 9585, "ndo" ],
+[ 9586, "ndp" ],
+[ 9587, "ndq" ],
+[ 9588, "ndr" ],
+[ 9589, "nds" ],
+[ 9590, "ndt" ],
+[ 9591, "ndu" ],
+[ 9592, "ndv" ],
+[ 9593, "ndw" ],
+[ 9594, "ndx" ],
+[ 9595, "ndy" ],
+[ 9596, "ndz" ],
+[ 9597, "nea" ],
+[ 9598, "neb" ],
+[ 9599, "nec" ],
+[ 9600, "ned" ],
+[ 9601, "nee" ],
+[ 9602, "nef" ],
+[ 9603, "neg" ],
+[ 9604, "neh" ],
+[ 9605, "nei" ],
+[ 9606, "nej" ],
+[ 9607, "nek" ],
+[ 9608, "nel" ],
+[ 9609, "nem" ],
+[ 9610, "nen" ],
+[ 9611, "neo" ],
+[ 9612, "nep" ],
+[ 9613, "neq" ],
+[ 9614, "ner" ],
+[ 9615, "nes" ],
+[ 9616, "net" ],
+[ 9617, "neu" ],
+[ 9618, "nev" ],
+[ 9619, "new" ],
+[ 9620, "nex" ],
+[ 9621, "ney" ],
+[ 9622, "nez" ],
+[ 9623, "nfa" ],
+[ 9624, "nfb" ],
+[ 9625, "nfc" ],
+[ 9626, "nfd" ],
+[ 9627, "nfe" ],
+[ 9628, "nff" ],
+[ 9629, "nfg" ],
+[ 9630, "nfh" ],
+[ 9631, "nfi" ],
+[ 9632, "nfj" ],
+[ 9633, "nfk" ],
+[ 9634, "nfl" ],
+[ 9635, "nfm" ],
+[ 9636, "nfn" ],
+[ 9637, "nfo" ],
+[ 9638, "nfp" ],
+[ 9639, "nfq" ],
+[ 9640, "nfr" ],
+[ 9641, "nfs" ],
+[ 9642, "nft" ],
+[ 9643, "nfu" ],
+[ 9644, "nfv" ],
+[ 9645, "nfw" ],
+[ 9646, "nfx" ],
+[ 9647, "nfy" ],
+[ 9648, "nfz" ],
+[ 9649, "nga" ],
+[ 9650, "ngb" ],
+[ 9651, "ngc" ],
+[ 9652, "ngd" ],
+[ 9653, "nge" ],
+[ 9654, "ngf" ],
+[ 9655, "ngg" ],
+[ 9656, "ngh" ],
+[ 9657, "ngi" ],
+[ 9658, "ngj" ],
+[ 9659, "ngk" ],
+[ 9660, "ngl" ],
+[ 9661, "ngm" ],
+[ 9662, "ngn" ],
+[ 9663, "ngo" ],
+[ 9664, "ngp" ],
+[ 9665, "ngq" ],
+[ 9666, "ngr" ],
+[ 9667, "ngs" ],
+[ 9668, "ngt" ],
+[ 9669, "ngu" ],
+[ 9670, "ngv" ],
+[ 9671, "ngw" ],
+[ 9672, "ngx" ],
+[ 9673, "ngy" ],
+[ 9674, "ngz" ],
+[ 9675, "nha" ],
+[ 9676, "nhb" ],
+[ 9677, "nhc" ],
+[ 9678, "nhd" ],
+[ 9679, "nhe" ],
+[ 9680, "nhf" ],
+[ 9681, "nhg" ],
+[ 9682, "nhh" ],
+[ 9683, "nhi" ],
+[ 9684, "nhj" ],
+[ 9685, "nhk" ],
+[ 9686, "nhl" ],
+[ 9687, "nhm" ],
+[ 9688, "nhn" ],
+[ 9689, "nho" ],
+[ 9690, "nhp" ],
+[ 9691, "nhq" ],
+[ 9692, "nhr" ],
+[ 9693, "nhs" ],
+[ 9694, "nht" ],
+[ 9695, "nhu" ],
+[ 9696, "nhv" ],
+[ 9697, "nhw" ],
+[ 9698, "nhx" ],
+[ 9699, "nhy" ],
+[ 9700, "nhz" ],
+[ 9701, "nia" ],
+[ 9702, "nib" ],
+[ 9703, "nic" ],
+[ 9704, "nid" ],
+[ 9705, "nie" ],
+[ 9706, "nif" ],
+[ 9707, "nig" ],
+[ 9708, "nih" ],
+[ 9709, "nii" ],
+[ 9710, "nij" ],
+[ 9711, "nik" ],
+[ 9712, "nil" ],
+[ 9713, "nim" ],
+[ 9714, "nin" ],
+[ 9715, "nio" ],
+[ 9716, "nip" ],
+[ 9717, "niq" ],
+[ 9718, "nir" ],
+[ 9719, "nis" ],
+[ 9720, "nit" ],
+[ 9721, "niu" ],
+[ 9722, "niv" ],
+[ 9723, "niw" ],
+[ 9724, "nix" ],
+[ 9725, "niy" ],
+[ 9726, "niz" ],
+[ 9727, "nja" ],
+[ 9728, "njb" ],
+[ 9729, "njc" ],
+[ 9730, "njd" ],
+[ 9731, "nje" ],
+[ 9732, "njf" ],
+[ 9733, "njg" ],
+[ 9734, "njh" ],
+[ 9735, "nji" ],
+[ 9736, "njj" ],
+[ 9737, "njk" ],
+[ 9738, "njl" ],
+[ 9739, "njm" ],
+[ 9740, "njn" ],
+[ 9741, "njo" ],
+[ 9742, "njp" ],
+[ 9743, "njq" ],
+[ 9744, "njr" ],
+[ 9745, "njs" ],
+[ 9746, "njt" ],
+[ 9747, "nju" ],
+[ 9748, "njv" ],
+[ 9749, "njw" ],
+[ 9750, "njx" ],
+[ 9751, "njy" ],
+[ 9752, "njz" ],
+[ 9753, "nka" ],
+[ 9754, "nkb" ],
+[ 9755, "nkc" ],
+[ 9756, "nkd" ],
+[ 9757, "nke" ],
+[ 9758, "nkf" ],
+[ 9759, "nkg" ],
+[ 9760, "nkh" ],
+[ 9761, "nki" ],
+[ 9762, "nkj" ],
+[ 9763, "nkk" ],
+[ 9764, "nkl" ],
+[ 9765, "nkm" ],
+[ 9766, "nkn" ],
+[ 9767, "nko" ],
+[ 9768, "nkp" ],
+[ 9769, "nkq" ],
+[ 9770, "nkr" ],
+[ 9771, "nks" ],
+[ 9772, "nkt" ],
+[ 9773, "nku" ],
+[ 9774, "nkv" ],
+[ 9775, "nkw" ],
+[ 9776, "nkx" ],
+[ 9777, "nky" ],
+[ 9778, "nkz" ],
+[ 9779, "nla" ],
+[ 9780, "nlb" ],
+[ 9781, "nlc" ],
+[ 9782, "nld" ],
+[ 9783, "nle" ],
+[ 9784, "nlf" ],
+[ 9785, "nlg" ],
+[ 9786, "nlh" ],
+[ 9787, "nli" ],
+[ 9788, "nlj" ],
+[ 9789, "nlk" ],
+[ 9790, "nll" ],
+[ 9791, "nlm" ],
+[ 9792, "nln" ],
+[ 9793, "nlo" ],
+[ 9794, "nlp" ],
+[ 9795, "nlq" ],
+[ 9796, "nlr" ],
+[ 9797, "nls" ],
+[ 9798, "nlt" ],
+[ 9799, "nlu" ],
+[ 9800, "nlv" ],
+[ 9801, "nlw" ],
+[ 9802, "nlx" ],
+[ 9803, "nly" ],
+[ 9804, "nlz" ],
+[ 9805, "nma" ],
+[ 9806, "nmb" ],
+[ 9807, "nmc" ],
+[ 9808, "nmd" ],
+[ 9809, "nme" ],
+[ 9810, "nmf" ],
+[ 9811, "nmg" ],
+[ 9812, "nmh" ],
+[ 9813, "nmi" ],
+[ 9814, "nmj" ],
+[ 9815, "nmk" ],
+[ 9816, "nml" ],
+[ 9817, "nmm" ],
+[ 9818, "nmn" ],
+[ 9819, "nmo" ],
+[ 9820, "nmp" ],
+[ 9821, "nmq" ],
+[ 9822, "nmr" ],
+[ 9823, "nms" ],
+[ 9824, "nmt" ],
+[ 9825, "nmu" ],
+[ 9826, "nmv" ],
+[ 9827, "nmw" ],
+[ 9828, "nmx" ],
+[ 9829, "nmy" ],
+[ 9830, "nmz" ],
+[ 9831, "nna" ],
+[ 9832, "nnb" ],
+[ 9833, "nnc" ],
+[ 9834, "nnd" ],
+[ 9835, "nne" ],
+[ 9836, "nnf" ],
+[ 9837, "nng" ],
+[ 9838, "nnh" ],
+[ 9839, "nni" ],
+[ 9840, "nnj" ],
+[ 9841, "nnk" ],
+[ 9842, "nnl" ],
+[ 9843, "nnm" ],
+[ 9844, "nnn" ],
+[ 9845, "nno" ],
+[ 9846, "nnp" ],
+[ 9847, "nnq" ],
+[ 9848, "nnr" ],
+[ 9849, "nns" ],
+[ 9850, "nnt" ],
+[ 9851, "nnu" ],
+[ 9852, "nnv" ],
+[ 9853, "nnw" ],
+[ 9854, "nnx" ],
+[ 9855, "nny" ],
+[ 9856, "nnz" ],
+[ 9857, "noa" ],
+[ 9858, "nob" ],
+[ 9859, "noc" ],
+[ 9860, "nod" ],
+[ 9861, "noe" ],
+[ 9862, "nof" ],
+[ 9863, "nog" ],
+[ 9864, "noh" ],
+[ 9865, "noi" ],
+[ 9866, "noj" ],
+[ 9867, "nok" ],
+[ 9868, "nol" ],
+[ 9869, "nom" ],
+[ 9870, "non" ],
+[ 9871, "noo" ],
+[ 9872, "nop" ],
+[ 9873, "noq" ],
+[ 9874, "nor" ],
+[ 9875, "nos" ],
+[ 9876, "not" ],
+[ 9877, "nou" ],
+[ 9878, "nov" ],
+[ 9879, "now" ],
+[ 9880, "nox" ],
+[ 9881, "noy" ],
+[ 9882, "noz" ],
+[ 9883, "npa" ],
+[ 9884, "npb" ],
+[ 9885, "npc" ],
+[ 9886, "npd" ],
+[ 9887, "npe" ],
+[ 9888, "npf" ],
+[ 9889, "npg" ],
+[ 9890, "nph" ],
+[ 9891, "npi" ],
+[ 9892, "npj" ],
+[ 9893, "npk" ],
+[ 9894, "npl" ],
+[ 9895, "npm" ],
+[ 9896, "npn" ],
+[ 9897, "npo" ],
+[ 9898, "npp" ],
+[ 9899, "npq" ],
+[ 9900, "npr" ],
+[ 9901, "nps" ],
+[ 9902, "npt" ],
+[ 9903, "npu" ],
+[ 9904, "npv" ],
+[ 9905, "npw" ],
+[ 9906, "npx" ],
+[ 9907, "npy" ],
+[ 9908, "npz" ],
+[ 9909, "nqa" ],
+[ 9910, "nqb" ],
+[ 9911, "nqc" ],
+[ 9912, "nqd" ],
+[ 9913, "nqe" ],
+[ 9914, "nqf" ],
+[ 9915, "nqg" ],
+[ 9916, "nqh" ],
+[ 9917, "nqi" ],
+[ 9918, "nqj" ],
+[ 9919, "nqk" ],
+[ 9920, "nql" ],
+[ 9921, "nqm" ],
+[ 9922, "nqn" ],
+[ 9923, "nqo" ],
+[ 9924, "nqp" ],
+[ 9925, "nqq" ],
+[ 9926, "nqr" ],
+[ 9927, "nqs" ],
+[ 9928, "nqt" ],
+[ 9929, "nqu" ],
+[ 9930, "nqv" ],
+[ 9931, "nqw" ],
+[ 9932, "nqx" ],
+[ 9933, "nqy" ],
+[ 9934, "nqz" ],
+[ 9935, "nra" ],
+[ 9936, "nrb" ],
+[ 9937, "nrc" ],
+[ 9938, "nrd" ],
+[ 9939, "nre" ],
+[ 9940, "nrf" ],
+[ 9941, "nrg" ],
+[ 9942, "nrh" ],
+[ 9943, "nri" ],
+[ 9944, "nrj" ],
+[ 9945, "nrk" ],
+[ 9946, "nrl" ],
+[ 9947, "nrm" ],
+[ 9948, "nrn" ],
+[ 9949, "nro" ],
+[ 9950, "nrp" ],
+[ 9951, "nrq" ],
+[ 9952, "nrr" ],
+[ 9953, "nrs" ],
+[ 9954, "nrt" ],
+[ 9955, "nru" ],
+[ 9956, "nrv" ],
+[ 9957, "nrw" ],
+[ 9958, "nrx" ],
+[ 9959, "nry" ],
+[ 9960, "nrz" ],
+[ 9961, "nsa" ],
+[ 9962, "nsb" ],
+[ 9963, "nsc" ],
+[ 9964, "nsd" ],
+[ 9965, "nse" ],
+[ 9966, "nsf" ],
+[ 9967, "nsg" ],
+[ 9968, "nsh" ],
+[ 9969, "nsi" ],
+[ 9970, "nsj" ],
+[ 9971, "nsk" ],
+[ 9972, "nsl" ],
+[ 9973, "nsm" ],
+[ 9974, "nsn" ],
+[ 9975, "nso" ],
+[ 9976, "nsp" ],
+[ 9977, "nsq" ],
+[ 9978, "nsr" ],
+[ 9979, "nss" ],
+[ 9980, "nst" ],
+[ 9981, "nsu" ],
+[ 9982, "nsv" ],
+[ 9983, "nsw" ],
+[ 9984, "nsx" ],
+[ 9985, "nsy" ],
+[ 9986, "nsz" ],
+[ 9987, "nta" ],
+[ 9988, "ntb" ],
+[ 9989, "ntc" ],
+[ 9990, "ntd" ],
+[ 9991, "nte" ],
+[ 9992, "ntf" ],
+[ 9993, "ntg" ],
+[ 9994, "nth" ],
+[ 9995, "nti" ],
+[ 9996, "ntj" ],
+[ 9997, "ntk" ],
+[ 9998, "ntl" ],
+[ 9999, "ntm" ],
+[ 10000, "ntn" ],
+    ]);
+
+
+## make sure populate honors fields/orders in list context
+## schema order
+my @links = $schema->populate('Link', [
+[ qw/id url title/ ],
+[ qw/2 burl btitle/ ]
+]);
+is(scalar @links, 1);
+
+my $link2 = shift @links;
+is($link2->id, 2, 'Link 2 id');
+is($link2->url, 'burl', 'Link 2 url');
+is($link2->title, 'btitle', 'Link 2 title');
+
+## non-schema order
+@links = $schema->populate('Link', [
+[ qw/id title url/ ],
+[ qw/3 ctitle curl/ ]
+]);
+is(scalar @links, 1);
+
+my $link3 = shift @links;
+is($link3->id, 3, 'Link 3 id');
+is($link3->url, 'curl', 'Link 3 url');
+is($link3->title, 'ctitle', 'Link 3 title');
+
+## not all physical columns
+@links = $schema->populate('Link', [
+[ qw/id title/ ],
+[ qw/4 dtitle/ ]
+]);
+is(scalar @links, 1);
+
+my $link4 = shift @links;
+is($link4->id, 4, 'Link 4 id');
+is($link4->url, undef, 'Link 4 url');
+is($link4->title, 'dtitle', 'Link 4 title');
+
+
+## make sure populate -> insert_bulk honors fields/orders in void context
+## schema order
+$schema->populate('Link', [
+[ qw/id url title/ ],
+[ qw/5 eurl etitle/ ]
+]);
+my $link5 = $schema->resultset('Link')->find(5);
+is($link5->id, 5, 'Link 5 id');
+is($link5->url, 'eurl', 'Link 5 url');
+is($link5->title, 'etitle', 'Link 5 title');
+
+## non-schema order
+$schema->populate('Link', [
+[ qw/id title url/ ],
+[ qw/6 ftitle furl/ ]
+]);
+my $link6 = $schema->resultset('Link')->find(6);
+is($link6->id, 6, 'Link 6 id');
+is($link6->url, 'furl', 'Link 6 url');
+is($link6->title, 'ftitle', 'Link 6 title');
+
+## not all physical columns
+$schema->populate('Link', [
+[ qw/id title/ ],
+[ qw/7 gtitle/ ]
+]);
+my $link7 = $schema->resultset('Link')->find(7);
+is($link7->id, 7, 'Link 7 id');
+is($link7->url, undef, 'Link 7 url');
+is($link7->title, 'gtitle', 'Link 7 title');
+
+
+ok(-f "t/var/DBIxClass.db", 'Database created');
index 303f297..646131b 100644 (file)
@@ -14,44 +14,44 @@ BEGIN {
 use lib qw(t/lib);
 
 use_ok('DBICTest');
-DBICTest->init_schema();
+my $schema = DBICTest->init_schema();
 
-my $orig_debugcb = DBICTest->schema->storage->debugcb;
-my $orig_debug = DBICTest->schema->storage->debug;
+my $orig_debugcb = $schema->storage->debugcb;
+my $orig_debug = $schema->storage->debug;
 
-diag('Testing against ' . join(' ', map { DBICTest->schema->storage->dbh->get_info($_) } qw/17 18/));
+diag('Testing against ' . join(' ', map { $schema->storage->dbh->get_info($_) } qw/17 18/));
 
-DBICTest->schema->storage->sql_maker->quote_char('`');
-DBICTest->schema->storage->sql_maker->name_sep('.');
+$schema->storage->sql_maker->quote_char('`');
+$schema->storage->sql_maker->name_sep('.');
 
 my $sql = '';
 
-DBICTest->schema->storage->debugcb(sub { $sql = $_[1] });
-DBICTest->schema->storage->debug(1);
+$schema->storage->debugcb(sub { $sql = $_[1] });
+$schema->storage->debug(1);
 
 my $rs;
 
-$rs = DBICTest::CD->search(
+$rs = $schema->resultset('CD')->search(
            { 'me.year' => 2001, 'artist.name' => 'Caterwauler McCrae' },
            { join => 'artist' });
 eval { $rs->count };
 like($sql, qr/\QSELECT COUNT( * ) FROM `cd` `me`  JOIN `artist` `artist` ON ( `artist`.`artistid` = `me`.`artist` ) WHERE ( `artist`.`name` = ? AND `me`.`year` = ? )\E/, 'got correct SQL for count query with quoting');
 
 my $order = 'year DESC';
-$rs = DBICTest::CD->search({},
+$rs = $schema->resultset('CD')->search({},
             { 'order_by' => $order });
 eval { $rs->first };
 like($sql, qr/ORDER BY `\Q${order}\E`/, 'quoted ORDER BY with DESC (should use a scalarref anyway)');
 
-$rs = DBICTest::CD->search({},
+$rs = $schema->resultset('CD')->search({},
             { 'order_by' => \$order });
 eval { $rs->first };
 like($sql, qr/ORDER BY \Q${order}\E/, 'did not quote ORDER BY with scalarref');
 
-DBICTest->schema->storage->sql_maker->quote_char([qw/[ ]/]);
-DBICTest->schema->storage->sql_maker->name_sep('.');
+$schema->storage->sql_maker->quote_char([qw/[ ]/]);
+$schema->storage->sql_maker->name_sep('.');
 
-$rs = DBICTest::CD->search(
+$rs = $schema->resultset('CD')->search(
            { 'me.year' => 2001, 'artist.name' => 'Caterwauler McCrae' },
            { join => 'artist' });
 eval { $rs->count };
@@ -62,10 +62,10 @@ my %data = (
        order => '12'
 );
 
-DBICTest->schema->storage->sql_maker->quote_char('`');
-DBICTest->schema->storage->sql_maker->name_sep('.');
+$schema->storage->sql_maker->quote_char('`');
+$schema->storage->sql_maker->name_sep('.');
 
-is(DBICTest->schema->storage->sql_maker->update('group', \%data), 'UPDATE `group` SET `name` = ?, `order` = ?', 'quoted table names for UPDATE');
+is($schema->storage->sql_maker->update('group', \%data), 'UPDATE `group` SET `name` = ?, `order` = ?', 'quoted table names for UPDATE');
 
-DBICTest->schema->storage->debugcb($orig_debugcb);
-DBICTest->schema->storage->debug($orig_debug);
+$schema->storage->debugcb($orig_debugcb);
+$schema->storage->debug($orig_debug);
index 31feaa3..b9d7411 100644 (file)
@@ -14,44 +14,44 @@ BEGIN {
 use lib qw(t/lib);
 
 use_ok('DBICTest');
-DBICTest->init_schema();
+my $schema = DBICTest->init_schema();
 
-my $orig_debugcb = DBICTest->schema->storage->debugcb;
-my $orig_debug = DBICTest->schema->storage->debug;
+my $orig_debugcb = $schema->storage->debugcb;
+my $orig_debug = $schema->storage->debug;
 
-diag('Testing against ' . join(' ', map { DBICTest->schema->storage->dbh->get_info($_) } qw/17 18/));
+diag('Testing against ' . join(' ', map { $schema->storage->dbh->get_info($_) } qw/17 18/));
 
-my $dsn = DBICTest->schema->storage->connect_info->[0];
-DBICTest->schema->connection($dsn, { quote_char => '`', name_sep => '.' });
+my $dsn = $schema->storage->connect_info->[0];
+$schema->connection($dsn, { quote_char => '`', name_sep => '.' });
 
 my $sql = '';
-DBICTest->schema->storage->debugcb(sub { $sql = $_[1] });
-DBICTest->schema->storage->debug(1);
+$schema->storage->debugcb(sub { $sql = $_[1] });
+$schema->storage->debug(1);
 
 my $rs;
 
-$rs = DBICTest::CD->search(
+$rs = $schema->resultset('CD')->search(
            { 'me.year' => 2001, 'artist.name' => 'Caterwauler McCrae' },
            { join => 'artist' });
 eval { $rs->count };
 like($sql, qr/\QSELECT COUNT( * ) FROM `cd` `me`  JOIN `artist` `artist` ON ( `artist`.`artistid` = `me`.`artist` ) WHERE ( `artist`.`name` = ? AND `me`.`year` = ? )\E/, 'got correct SQL for count query with quoting');
 
 my $order = 'year DESC';
-$rs = DBICTest::CD->search({},
+$rs = $schema->resultset('CD')->search({},
             { 'order_by' => $order });
 eval { $rs->first };
 like($sql, qr/ORDER BY `\Q${order}\E`/, 'quoted ORDER BY with DESC (should use a scalarref anyway)');
 
-$rs = DBICTest::CD->search({},
+$rs = $schema->resultset('CD')->search({},
             { 'order_by' => \$order });
 eval { $rs->first };
 like($sql, qr/ORDER BY \Q${order}\E/, 'did not quote ORDER BY with scalarref');
 
-DBICTest->schema->connection($dsn, { quote_char => [qw/[ ]/], name_sep => '.' });
-DBICTest->schema->storage->debugcb(sub { $sql = $_[1] });
-DBICTest->schema->storage->debug(1);
+$schema->connection($dsn, { quote_char => [qw/[ ]/], name_sep => '.' });
+$schema->storage->debugcb(sub { $sql = $_[1] });
+$schema->storage->debug(1);
 
-$rs = DBICTest::CD->search(
+$rs = $schema->resultset('CD')->search(
            { 'me.year' => 2001, 'artist.name' => 'Caterwauler McCrae' },
            { join => 'artist' });
 eval { $rs->count };
@@ -62,9 +62,9 @@ my %data = (
        order => '12'
 );
 
-DBICTest->schema->connection($dsn, { quote_char => '`', name_sep => '.' });
+$schema->connection($dsn, { quote_char => '`', name_sep => '.' });
 
-is(DBICTest->schema->storage->sql_maker->update('group', \%data), 'UPDATE `group` SET `name` = ?, `order` = ?', 'quoted table names for UPDATE');
+is($schema->storage->sql_maker->update('group', \%data), 'UPDATE `group` SET `name` = ?, `order` = ?', 'quoted table names for UPDATE');
 
-DBICTest->schema->storage->debugcb($orig_debugcb);
-DBICTest->schema->storage->debug($orig_debug);
+$schema->storage->debugcb($orig_debugcb);
+$schema->storage->debug($orig_debug);
index 59aeb9e..9f0da40 100644 (file)
@@ -14,23 +14,23 @@ BEGIN {
 use lib qw(t/lib);
 
 use_ok('DBICTest');
-DBICTest->init_schema();
+my $schema = DBICTest->init_schema();
 
 my $cbworks = 0;
 
-DBICTest->schema->storage->debugcb(sub { $cbworks = 1; });
-DBICTest->schema->storage->debug(0);
-my $rs = DBICTest::CD->search({});
+$schema->storage->debugcb(sub { $cbworks = 1; });
+$schema->storage->debug(0);
+my $rs = $schema->resultset('CD')->search({});
 $rs->count();
 ok(!$cbworks, 'Callback not called with debug disabled');
 
-DBICTest->schema->storage->debug(1);
+$schema->storage->debug(1);
 
 $rs->count();
 ok($cbworks, 'Debug callback worked.');
 
 my $prof = new DBIx::Test::Profiler();
-DBICTest->schema->storage->debugobj($prof);
+$schema->storage->debugobj($prof);
 
 # Test non-transaction calls.
 $rs->count();
@@ -42,27 +42,27 @@ ok(!$prof->{'txn_commit'}, 'txn_commit not called');
 $prof->reset();
 
 # Test transaction calls
-DBICTest->schema->txn_begin();
+$schema->txn_begin();
 ok($prof->{'txn_begin'}, 'txn_begin called');
 
-$rs = DBICTest::CD->search({});
+$rs = $schema->resultset('CD')->search({});
 $rs->count();
 ok($prof->{'query_start'}, 'query_start called');
 ok($prof->{'query_end'}, 'query_end called');
 
-DBICTest->schema->txn_commit();
+$schema->txn_commit();
 ok($prof->{'txn_commit'}, 'txn_commit called');
 
 $prof->reset();
 
 # Test a rollback
-DBICTest->schema->txn_begin();
-$rs = DBICTest::CD->search({});
+$schema->txn_begin();
+$rs = $schema->resultset('CD')->search({});
 $rs->count();
-DBICTest->schema->txn_rollback();
+$schema->txn_rollback();
 ok($prof->{'txn_rollback'}, 'txn_rollback called');
 
-DBICTest->schema->storage->debug(0);
+$schema->storage->debug(0);
 
 package DBIx::Test::Profiler;
 use strict;
diff --git a/t/33storage_reconnect.t b/t/33storage_reconnect.t
new file mode 100644 (file)
index 0000000..6e82b13
--- /dev/null
@@ -0,0 +1,26 @@
+use strict;
+use warnings;  
+
+use Test::More;
+use lib qw(t/lib);
+use DBICTest;
+
+plan tests => 2;
+
+# Set up the "usual" sqlite for DBICTest
+my $schema = DBICTest->init_schema;
+
+# Make sure we're connected by doing something
+my @art = $schema->resultset("Artist")->search({ }, { order_by => 'name DESC'});
+cmp_ok(@art, '==', 3, "Three artists returned");
+
+# Disconnect the dbh, and be sneaky about it
+$schema->storage->_dbh->disconnect;
+
+# Try the operation again - What should happen here is:
+#   1. S::DBI blindly attempts the SELECT, which throws an exception
+#   2. It catches the exception, checks ->{Active}/->ping, sees the disconnected state...
+#   3. Reconnects, and retries the operation
+#   4. Success!
+my @art_two = $schema->resultset("Artist")->search({ }, { order_by => 'name DESC'});
+cmp_ok(@art_two, '==', 3, "Three artists returned");
diff --git a/t/34exception_action.t b/t/34exception_action.t
new file mode 100644 (file)
index 0000000..7fef551
--- /dev/null
@@ -0,0 +1,64 @@
+use strict;
+use warnings;  
+
+use Test::More;
+use lib qw(t/lib);
+use DBICTest;
+
+plan tests => 6;
+
+# Set up the "usual" sqlite for DBICTest
+my $schema = DBICTest->init_schema;
+
+# This is how we're generating exceptions in the rest of these tests,
+#  which might need updating at some future time to be some other
+#  exception-generating statement:
+
+sub throwex { $schema->resultset("Artist")->search(1,1,1); }
+my $ex_regex = qr/Odd number of arguments to search/;
+
+# Basic check, normal exception
+eval { throwex };
+like($@, $ex_regex);
+
+# Now lets rethrow via exception_action
+$schema->exception_action(sub { die @_ });
+eval { throwex };
+like($@, $ex_regex);
+
+# Now lets suppress the error
+$schema->exception_action(sub { 1 });
+eval { throwex };
+ok(!$@, "Suppress exception");
+
+# Now lets fall through and let croak take back over
+$schema->exception_action(sub { return });
+eval { throwex };
+like($@, $ex_regex);
+
+# Whacky useless exception class
+{
+    package DBICTest::Exception;
+    use overload '""' => \&stringify, fallback => 1;
+    sub new {
+        my $class = shift;
+        bless { msg => shift }, $class;
+    }
+    sub throw {
+        my $self = shift;
+        die $self if ref $self eq __PACKAGE__;
+        die $self->new(shift);
+    }
+    sub stringify {
+        "DBICTest::Exception is handling this: " . shift->{msg};
+    }
+}
+
+# Try the exception class
+$schema->exception_action(sub { DBICTest::Exception->throw(@_) });
+eval { throwex };
+like($@, qr/DBICTest::Exception is handling this: $ex_regex/);
+
+# While we're at it, lets throw a custom exception through Storage::DBI
+eval { $schema->storage->throw_exception('floob') };
+like($@, qr/DBICTest::Exception is handling this: floob/);
diff --git a/t/35disable_sth_caching.t b/t/35disable_sth_caching.t
new file mode 100644 (file)
index 0000000..5ad4cca
--- /dev/null
@@ -0,0 +1,19 @@
+use strict;
+use warnings;  
+
+use Test::More;
+use lib qw(t/lib);
+use DBICTest;
+
+plan tests => 2;
+
+# Set up the "usual" sqlite for DBICTest
+my $schema = DBICTest->init_schema;
+
+my $sth_one = $schema->storage->sth('SELECT 42');
+my $sth_two = $schema->storage->sth('SELECT 42');
+$schema->storage->disable_sth_caching(1);
+my $sth_three = $schema->storage->sth('SELECT 42');
+
+ok($sth_one == $sth_two, "statement caching works");
+ok($sth_two != $sth_three, "disabling statement caching works");
diff --git a/t/39load_namespaces_1.t b/t/39load_namespaces_1.t
new file mode 100644 (file)
index 0000000..7911d8d
--- /dev/null
@@ -0,0 +1,29 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+use Test::More;
+
+unshift(@INC, './t/lib');
+
+plan tests => 6;
+
+my $warnings;
+eval {
+    local $SIG{__WARN__} = sub { $warnings .= shift };
+    package DBICNSTest;
+    use base qw/DBIx::Class::Schema/;
+    __PACKAGE__->load_namespaces;
+};
+ok(!$@) or diag $@;
+like($warnings, qr/load_namespaces found ResultSet class C with no corresponding Result class/);
+
+my $source_a = DBICNSTest->source('A');
+isa_ok($source_a, 'DBIx::Class::ResultSource::Table');
+my $rset_a   = DBICNSTest->resultset('A');
+isa_ok($rset_a, 'DBICNSTest::ResultSet::A');
+
+my $source_b = DBICNSTest->source('B');
+isa_ok($source_b, 'DBIx::Class::ResultSource::Table');
+my $rset_b   = DBICNSTest->resultset('B');
+isa_ok($rset_b, 'DBIx::Class::ResultSet');
diff --git a/t/39load_namespaces_2.t b/t/39load_namespaces_2.t
new file mode 100644 (file)
index 0000000..6daf05f
--- /dev/null
@@ -0,0 +1,32 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+use Test::More;
+
+unshift(@INC, './t/lib');
+
+plan tests => 6;
+
+my $warnings;
+eval {
+    local $SIG{__WARN__} = sub { $warnings .= shift };
+    package DBICNSTest;
+    use base qw/DBIx::Class::Schema/;
+    __PACKAGE__->load_namespaces(
+        result_namespace => 'Rslt',
+        resultset_namespace => 'RSet',
+    );
+};
+ok(!$@) or diag $@;
+like($warnings, qr/load_namespaces found ResultSet class C with no corresponding Result class/);
+
+my $source_a = DBICNSTest->source('A');
+isa_ok($source_a, 'DBIx::Class::ResultSource::Table');
+my $rset_a   = DBICNSTest->resultset('A');
+isa_ok($rset_a, 'DBICNSTest::RSet::A');
+
+my $source_b = DBICNSTest->source('B');
+isa_ok($source_b, 'DBIx::Class::ResultSource::Table');
+my $rset_b   = DBICNSTest->resultset('B');
+isa_ok($rset_b, 'DBIx::Class::ResultSet');
diff --git a/t/39load_namespaces_3.t b/t/39load_namespaces_3.t
new file mode 100644 (file)
index 0000000..f48c838
--- /dev/null
@@ -0,0 +1,35 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+use Test::More;
+
+unshift(@INC, './t/lib');
+
+plan tests => 7;
+
+my $warnings;
+eval {
+    local $SIG{__WARN__} = sub { $warnings .= shift };
+    package DBICNSTestOther;
+    use base qw/DBIx::Class::Schema/;
+    __PACKAGE__->load_namespaces(
+        result_namespace => [ '+DBICNSTest::Rslt', '+DBICNSTest::OtherRslt' ],
+        resultset_namespace => '+DBICNSTest::RSet',
+    );
+};
+ok(!$@) or diag $@;
+like($warnings, qr/load_namespaces found ResultSet class C with no corresponding Result class/);
+
+my $source_a = DBICNSTestOther->source('A');
+isa_ok($source_a, 'DBIx::Class::ResultSource::Table');
+my $rset_a   = DBICNSTestOther->resultset('A');
+isa_ok($rset_a, 'DBICNSTest::RSet::A');
+
+my $source_b = DBICNSTestOther->source('B');
+isa_ok($source_b, 'DBIx::Class::ResultSource::Table');
+my $rset_b   = DBICNSTestOther->resultset('B');
+isa_ok($rset_b, 'DBIx::Class::ResultSet');
+
+my $source_d = DBICNSTestOther->source('D');
+isa_ok($source_d, 'DBIx::Class::ResultSource::Table');
diff --git a/t/39load_namespaces_4.t b/t/39load_namespaces_4.t
new file mode 100644 (file)
index 0000000..b674f30
--- /dev/null
@@ -0,0 +1,29 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+use Test::More;
+
+unshift(@INC, './t/lib');
+
+plan tests => 6;
+
+my $warnings;
+eval {
+    local $SIG{__WARN__} = sub { $warnings .= shift };
+    package DBICNSTest;
+    use base qw/DBIx::Class::Schema/;
+    __PACKAGE__->load_namespaces( default_resultset_class => 'RSBase' );
+};
+ok(!$@) or diag $@;
+like($warnings, qr/load_namespaces found ResultSet class C with no corresponding Result class/);
+
+my $source_a = DBICNSTest->source('A');
+isa_ok($source_a, 'DBIx::Class::ResultSource::Table');
+my $rset_a   = DBICNSTest->resultset('A');
+isa_ok($rset_a, 'DBICNSTest::ResultSet::A');
+
+my $source_b = DBICNSTest->source('B');
+isa_ok($source_b, 'DBIx::Class::ResultSource::Table');
+my $rset_b   = DBICNSTest->resultset('B');
+isa_ok($rset_b, 'DBICNSTest::RSBase');
index bdec159..8389291 100644 (file)
@@ -17,7 +17,7 @@ BEGIN {
 
 use DBICTest::ResultSetManager; # uses Class::Inspector
 
-my $schema = DBICTest::ResultSetManager->compose_connection('DB', 'foo');
+my $schema = DBICTest::ResultSetManager->compose_namespace('DB');
 my $rs = $schema->resultset('Foo');
 
 ok( !DB::Foo->can('bar'), 'Foo class does not have bar method' );
diff --git a/t/55storage_stress.t b/t/55storage_stress.t
new file mode 100644 (file)
index 0000000..f338302
--- /dev/null
@@ -0,0 +1,55 @@
+use strict;
+use warnings;
+use Test::More;
+
+# XXX obviously, the guts of this test haven't been written yet --blblack
+
+use lib qw(t/lib);
+
+plan skip_all => 'Set $ENV{DBICTEST_STORAGE_STRESS} to run this test'
+    . ' (it is very resource intensive!)'
+        unless $ENV{DBICTEST_STORAGE_STRESS};
+
+my $NKIDS = 20;
+my $CYCLES = 5;
+my @KILL_RATES = qw/0 0.001 0.01 0.1 0.2 0.5 0.75 1.0/;
+
+# Stress the storage with these parameters...
+sub stress_storage {
+    my ($connect_info, $num_kids, $cycles, $kill_rate) = @_;
+
+    foreach my $cycle (1..$cycles) {
+        my $schema = DBICTest::Schema->connection(@$connect_info, { AutoCommit => 1 });
+        foreach my $kidno (1..$num_kids) {
+            ok(1);
+        }
+    }
+}
+
+# Get a set of connection information -
+#  whatever the user has supplied for the vendor-specific tests
+sub get_connect_infos {
+    my @connect_infos;
+    foreach my $db_prefix (qw/PG MYSQL DB2 MSSQL ORA/) {
+        my @conn_info = @ENV{
+            map { "DBICTEST_${db_prefix}_${_}" } qw/DSN USER PASS/
+        };
+        push(@connect_infos, \@conn_info) if $conn_info[0];
+    }
+    \@connect_infos;
+}
+
+my $connect_infos = get_connect_infos();
+
+plan skip_all => 'This test needs some non-sqlite connect info!'
+    unless @$connect_infos;
+
+plan tests => (1 * @$connect_infos * $NKIDS * $CYCLES * @KILL_RATES) + 1;
+
+use_ok('DBICTest::Schema');
+
+foreach my $connect_info (@$connect_infos) {
+    foreach my $kill_rate (@KILL_RATES) {
+        stress_storage($connect_info, $NKIDS, $CYCLES, $kill_rate);
+    }
+}
index c5959d0..3eb80df 100644 (file)
@@ -7,7 +7,7 @@ use DBICTest;
 
 my $schema = DBICTest->init_schema();
 
-plan tests => 63;
+plan tests => 64;
 
 # figure out if we've got a version of sqlite that is older than 3.2.6, in
 # which case COUNT(DISTINCT()) doesn't work
@@ -255,7 +255,7 @@ ok($schema->storage(), 'Storage available');
   cmp_ok(@artsn, '==', 4, "Four artists returned");
   
   # make sure subclasses that don't set source_name are ok
-  ok($schema->source('ArtistSubclass', 'ArtistSubclass exists'));
+  ok($schema->source('ArtistSubclass'), 'ArtistSubclass exists');
 }
 
 my $newbook = $schema->resultset( 'Bookmark' )->find(1);
@@ -277,6 +277,7 @@ ok(!$@, "stringify to false value doesn't cause error");
 # test column_info
 {
   $schema->source("Artist")->{_columns}{'artistid'} = {};
+  $schema->source("Artist")->column_info_from_storage(1);
 
   my $typeinfo = $schema->source("Artist")->column_info('artistid');
   is($typeinfo->{data_type}, 'INTEGER', 'column_info ok');
@@ -284,6 +285,19 @@ ok(!$@, "stringify to false value doesn't cause error");
   ok($schema->source("Artist")->{_columns_info_loaded} == 1, 'Columns info flag set');
 }
 
+# test source_info
+{
+  my $expected = {
+    "source_info_key_A" => "source_info_value_A",
+    "source_info_key_B" => "source_info_value_B",
+    "source_info_key_C" => "source_info_value_C",
+  };
+
+  my $sinfo = $schema->source("Artist")->source_info;
+
+  is_deeply($sinfo, $expected, 'source_info data works');
+}
+
 # test remove_columns
 {
   is_deeply([$schema->source('CD')->columns], [qw/cdid artist title year/]);
diff --git a/t/63register_class.t b/t/63register_class.t
new file mode 100644 (file)
index 0000000..2fdc07c
--- /dev/null
@@ -0,0 +1,17 @@
+use strict;
+use warnings;  
+
+use Test::More tests => 2;
+use lib qw(t/lib);
+use DBICTest;
+use DBICTest::Schema;
+use DBICTest::Schema::Artist;
+
+DBICTest::Schema::Artist->source_name('MyArtist');
+DBICTest::Schema->register_class('FooA', 'DBICTest::Schema::Artist');
+
+my $schema = DBICTest->init_schema();
+
+my $a = $schema->resultset('FooA')->search;
+is($a->count, 3, 'have 3 artists');
+is($schema->class('FooA'), 'DBICTest::FooA', 'Correct artist class');
index 084bb8e..45c9b2f 100644 (file)
@@ -9,7 +9,7 @@ my $schema = DBICTest->init_schema();
 
 plan tests => 5;
 
-my $artist = DBICTest::Artist->find(1);
+my $artist = $schema->resultset("Artist")->find(1);
 ok($artist->find_related('twokeys', {cd => 1}), "find multiple pks using relationships + args");
 
 ok($schema->resultset("FourKeys")->search({ foo => 1, bar => 2 })->find({ hello => 3, goodbye => 4 }), "search on partial key followed by a find");
index 2e7c374..ea917f8 100644 (file)
@@ -5,7 +5,6 @@ use Test::More;
 use lib qw(t/lib);
 use DBICTest;
 
-DBICTest::Schema::CD->add_column('year');
 my $schema = DBICTest->init_schema();
 
 eval { require DateTime };
@@ -13,7 +12,9 @@ plan skip_all => "Need DateTime for inflation tests" if $@;
 
 plan tests => 20;
 
-DBICTest::Schema::CD->inflate_column( 'year',
+$schema->class('CD')
+#DBICTest::Schema::CD
+->inflate_column( 'year',
     { inflate => sub { DateTime->new( year => shift ) },
       deflate => sub { shift->year } }
 );
diff --git a/t/68inflate_resultclass_hashrefinflator.t b/t/68inflate_resultclass_hashrefinflator.t
new file mode 100644 (file)
index 0000000..221626a
--- /dev/null
@@ -0,0 +1,87 @@
+use strict;
+use warnings;  
+
+use Test::More qw(no_plan);
+use lib qw(t/lib);
+use DBICTest;
+use DBIx::Class::ResultClass::HashRefInflator;
+my $schema = DBICTest->init_schema();
+
+
+# Under some versions of SQLite if the $rs is left hanging around it will lock
+# So we create a scope here cos I'm lazy
+{
+    my $rs = $schema->resultset('CD');
+
+    # get the defined columns
+    my @dbic_cols = sort $rs->result_source->columns;
+
+    # use the hashref inflator class as result class
+    $rs->result_class('DBIx::Class::ResultClass::HashRefInflator');
+
+    # fetch first record
+    my $datahashref1 = $rs->first;
+
+    my @hashref_cols = sort keys %$datahashref1;
+
+    is_deeply( \@dbic_cols, \@hashref_cols, 'returned columns' );
+}
+
+
+sub check_cols_of {
+    my ($dbic_obj, $datahashref) = @_;
+    
+    foreach my $col (keys %$datahashref) {
+        # plain column
+        if (not ref ($datahashref->{$col}) ) {
+            is ($datahashref->{$col}, $dbic_obj->get_column($col), 'same value');
+        }
+        # related table entry (belongs_to)
+        elsif (ref ($datahashref->{$col}) eq 'HASH') {
+            check_cols_of($dbic_obj->$col, $datahashref->{$col});
+        }
+        # multiple related entries (has_many)
+        elsif (ref ($datahashref->{$col}) eq 'ARRAY') {
+            my @dbic_reltable = $dbic_obj->$col;
+            my @hashref_reltable = @{$datahashref->{$col}};
+  
+            is (scalar @hashref_reltable, scalar @dbic_reltable, 'number of related entries');
+
+            # for my $index (0..scalar @hashref_reltable) {
+            for my $index (0..scalar @dbic_reltable) {
+                my $dbic_reltable_obj       = $dbic_reltable[$index];
+                my $hashref_reltable_entry  = $hashref_reltable[$index];
+                
+                check_cols_of($dbic_reltable_obj, $hashref_reltable_entry);
+            }
+        }
+    }
+}
+
+# create a cd without tracks for testing empty has_many relationship
+$schema->resultset('CD')->create({ title => 'Silence is golden', artist => 3, year => 2006 });
+
+# order_by to ensure both resultsets have the rows in the same order
+my $rs_dbic = $schema->resultset('CD')->search(undef,
+    {
+        prefetch    => [ qw/ artist tracks / ],
+        order_by    => [ 'me.cdid', 'tracks.position' ],
+    }
+);
+my $rs_hashrefinf = $schema->resultset('CD')->search(undef,
+    {
+        prefetch    => [ qw/ artist tracks / ],
+        order_by    => [ 'me.cdid', 'tracks.position' ],
+    }
+);
+$rs_hashrefinf->result_class('DBIx::Class::ResultClass::HashRefInflator');
+
+my @dbic        = $rs_dbic->all;
+my @hashrefinf  = $rs_hashrefinf->all;
+
+for my $index (0..scalar @hashrefinf) {
+    my $dbic_obj    = $dbic[$index];
+    my $datahashref = $hashrefinf[$index];
+
+    check_cols_of($dbic_obj, $datahashref);
+}
index aeb73ea..3bbdaa1 100644 (file)
@@ -15,7 +15,7 @@ plan skip_all => 'Set $ENV{DBICTEST_MYSQL_DSN}, _USER and _PASS to run this test
 
 plan tests => 5;
 
-DBICTest::Schema->compose_connection('MySQLTest' => $dsn, $user, $pass);
+DBICTest::Schema->compose_namespace('MySQLTest' => $dsn, $user, $pass);
 
 my $dbh = MySQLTest->schema->storage->dbh;
 
index f0bb3f8..a3239ca 100644 (file)
--- a/t/72pg.t
+++ b/t/72pg.t
@@ -15,6 +15,7 @@ use DBICTest;
   __PACKAGE__->load_components(qw/PK::Auto Core/);
   __PACKAGE__->table('casecheck');
   __PACKAGE__->add_columns(qw/id name NAME uc_name/);
+  __PACKAGE__->column_info_from_storage(1);
   __PACKAGE__->set_primary_key('id');
 
 }
@@ -29,7 +30,7 @@ plan skip_all => 'Set $ENV{DBICTEST_PG_DSN}, _USER and _PASS to run this test'
 plan tests => 8;
 
 DBICTest::Schema->load_classes( 'Casecheck' );
-DBICTest::Schema->compose_connection('PgTest' => $dsn, $user, $pass);
+DBICTest::Schema->compose_namespace('PgTest' => $dsn, $user, $pass);
 
 my $dbh = PgTest->schema->storage->dbh;
 PgTest->schema->source("Artist")->name("testschema.artist");
index c0489ff..7ca5c41 100644 (file)
@@ -13,7 +13,7 @@ plan skip_all => 'Set $ENV{DBICTEST_ORA_DSN}, _USER and _PASS to run this test.
 
 plan tests => 6;
 
-DBICTest::Schema->compose_connection('OraTest' => $dsn, $user, $pass);
+DBICTest::Schema->compose_namespace('OraTest' => $dsn, $user, $pass);
 
 my $dbh = OraTest->schema->storage->dbh;
 
index ffb7a0b..82d3c2c 100644 (file)
@@ -14,7 +14,7 @@ plan skip_all => 'Set $ENV{DBICTEST_DB2_DSN}, _USER and _PASS to run this test'
 
 plan tests => 6;
 
-DBICTest::Schema->compose_connection('DB2Test' => $dsn, $user, $pass);
+DBICTest::Schema->compose_namespace('DB2Test' => $dsn, $user, $pass);
 
 my $dbh = DB2Test->schema->storage->dbh;
 
index 558ca62..745673b 100644 (file)
@@ -17,7 +17,7 @@ plan skip_all => 'Set $ENV{DBICTEST_DB2_400_DSN}, _USER and _PASS to run this te
 
 plan tests => 6;
 
-DBICTest::Schema->compose_connection('DB2Test' => $dsn, $user, $pass);
+DBICTest::Schema->compose_namespace('DB2Test' => $dsn, $user, $pass);
 
 my $dbh = DB2Test->schema->storage->dbh;
 
index 204a640..0bb43b6 100644 (file)
@@ -19,7 +19,7 @@ $storage_type = '::DBI::Sybase::MSSQL' if $dsn =~ /^dbi:Sybase:/;
 # Add more for others in the future when they exist (ODBC? ADO? JDBC?)
 
 DBICTest::Schema->storage_type($storage_type);
-DBICTest::Schema->compose_connection( 'MSSQLTest' => $dsn, $user, $pass );
+DBICTest::Schema->compose_namespace( 'MSSQLTest' => $dsn, $user, $pass );
 
 my $dbh = MSSQLTest->schema->storage->dbh;
 
index 5434387..4a7830f 100644 (file)
@@ -118,7 +118,7 @@ my $fail_code = sub {
   # Force txn_rollback() to throw an exception
   no warnings 'redefine';
   no strict 'refs';
-  local *{"DBIx::Class::Schema::txn_rollback"} = sub{die 'FAILED'};
+  local *{"DBIx::Class::Storage::DBI::SQLite::txn_rollback"} = sub{die 'FAILED'};
 
   eval {
     $schema->txn_do($fail_code, $artist);
index 92d90f2..095a878 100644 (file)
@@ -10,7 +10,7 @@ plan skip_all => 'SQL::Translator required' if $@;
 
 my $schema = DBICTest->init_schema;
 
-plan tests => 53;
+plan tests => 54;
 
 my $translator = SQL::Translator->new( 
   parser_args => {
@@ -24,6 +24,10 @@ $translator->producer('SQLite');
 
 my $output = $translator->translate();
 
+
+ok($output, "SQLT produced someoutput")
+  or diag($translator->error);
+
 # Note that the constraints listed here are the only ones that are tested -- if
 # more exist in the Schema than are listed here and all listed constraints are
 # correct, the test will still pass. If you add a class with UNIQUE or FOREIGN
index b1d484c..7bc1bed 100644 (file)
@@ -6,9 +6,11 @@ use Test::More;
 use lib qw(t/lib);
 use DBICTest;
 
+use POSIX qw(ceil);
+
 my $schema = DBICTest->init_schema();
 
-plan tests => 321;
+plan tests => 879;
 
 my $employees = $schema->resultset('Employee');
 $employees->delete();
@@ -23,20 +25,168 @@ hammer_rs( $employees );
 
 DBICTest::Employee->grouping_column('group_id');
 $employees->delete();
-foreach my $group_id (1..3) {
+foreach my $group_id (1..4) {
     foreach (1..6) {
         $employees->create({ name=>'temp', group_id=>$group_id });
     }
 }
 $employees = $employees->search(undef,{order_by=>'group_id,position'});
 
-foreach my $group_id (1..3) {
+foreach my $group_id (1..4) {
     my $group_employees = $employees->search({group_id=>$group_id});
     $group_employees->all();
     ok( check_rs($group_employees), "group intial positions" );
     hammer_rs( $group_employees );
 }
 
+my $group_3 = $employees->search({group_id=>3});
+my $to_group = 1;
+my $to_pos = undef;
+while (my $employee = $group_3->next) {
+       $employee->move_to_group($to_group, $to_pos);
+       $to_pos++;
+       $to_group = $to_group==1 ? 2 : 1;
+}
+foreach my $group_id (1..4) {
+    my $group_employees = $employees->search({group_id=>$group_id});
+    $group_employees->all();
+    ok( check_rs($group_employees), "group positions after move_to_group" );
+}
+
+my $employee = $employees->search({group_id=>4})->first;
+$employee->position(2);
+$employee->update;
+ok( check_rs($employees->search_rs({group_id=>4})), "overloaded update 1" );
+$employee = $employees->search({group_id=>4})->first;
+$employee->update({position=>3});
+ok( check_rs($employees->search_rs({group_id=>4})), "overloaded update 2" );
+$employee = $employees->search({group_id=>4})->first;
+$employee->group_id(1);
+$employee->update;
+ok(
+       check_rs($employees->search_rs({group_id=>1})) && check_rs($employees->search_rs({group_id=>4})),
+       "overloaded update 3"
+);
+$employee = $employees->search({group_id=>4})->first;
+$employee->update({group_id=>2});
+ok(
+       check_rs($employees->search_rs({group_id=>2})) && check_rs($employees->search_rs({group_id=>4})),
+       "overloaded update 4"
+);
+$employee = $employees->search({group_id=>4})->first;
+$employee->group_id(1);
+$employee->position(3);
+$employee->update;
+ok(
+       check_rs($employees->search_rs({group_id=>1})) && check_rs($employees->search_rs({group_id=>4})),
+       "overloaded update 5"
+);
+$employee = $employees->search({group_id=>4})->first;
+$employee->group_id(2);
+$employee->position(undef);
+$employee->update;
+ok(
+       check_rs($employees->search_rs({group_id=>2})) && check_rs($employees->search_rs({group_id=>4})),
+       "overloaded update 6"
+);
+$employee = $employees->search({group_id=>4})->first;
+$employee->update({group_id=>1,position=>undef});
+ok(
+       check_rs($employees->search_rs({group_id=>1})) && check_rs($employees->search_rs({group_id=>4})),
+       "overloaded update 7"
+);
+
+# multicol tests begin here
+DBICTest::Employee->grouping_column(['group_id', 'group_id_2']);
+$employees->delete();
+foreach my $group_id (1..4) {
+    foreach my $group_id_2 (1..4) {
+        foreach (1..4) {
+            $employees->create({ name=>'temp', group_id=>$group_id, group_id_2=>$group_id_2 });
+        }
+    }
+}
+$employees = $employees->search(undef,{order_by=>'group_id,group_id_2,position'});
+
+foreach my $group_id (1..3) {
+    foreach my $group_id_2 (1..3) {
+        my $group_employees = $employees->search({group_id=>$group_id, group_id_2=>$group_id_2});
+        $group_employees->all();
+        ok( check_rs($group_employees), "group intial positions" );
+        hammer_rs( $group_employees );
+    }
+}
+
+# move_to_group, specifying group by hash
+my $group_4 = $employees->search({group_id=>4});
+$to_group = 1;
+my $to_group_2_base = 7;
+my $to_group_2 = 1;
+$to_pos = undef;
+while (my $employee = $group_4->next) {
+       $employee->move_to_group({group_id=>$to_group, group_id_2=>$to_group_2}, $to_pos);
+       $to_pos++;
+    $to_group = ($to_group % 3) + 1;
+    $to_group_2_base++;
+    $to_group_2 = (ceil($to_group_2_base/3.0) %3) +1
+}
+foreach my $group_id (1..4) {
+    foreach my $group_id_2 (1..4) {
+        my $group_employees = $employees->search({group_id=>$group_id,group_id_2=>$group_id_2});
+        $group_employees->all();
+        ok( check_rs($group_employees), "group positions after move_to_group" );
+    }
+}
+
+$employees->delete();
+foreach my $group_id (1..4) {
+    foreach my $group_id_2 (1..4) {
+        foreach (1..4) {
+            $employees->create({ name=>'temp', group_id=>$group_id, group_id_2=>$group_id_2 });
+        }
+    }
+}
+$employees = $employees->search(undef,{order_by=>'group_id,group_id_2,position'});
+
+$employee = $employees->search({group_id=>4, group_id_2=>1})->first;
+$employee->group_id(1);
+$employee->update;
+ok( 
+    check_rs($employees->search_rs({group_id=>4, group_id_2=>1}))
+    && check_rs($employees->search_rs({group_id=>1, group_id_2=>1})), 
+    "overloaded multicol update 1" 
+);
+
+$employee = $employees->search({group_id=>4, group_id_2=>1})->first;
+$employee->update({group_id=>2});
+ok( check_rs($employees->search_rs({group_id=>4, group_id_2=>1}))
+    && check_rs($employees->search_rs({group_id=>2, group_id_2=>1})), 
+    "overloaded multicol update 2" 
+);
+
+$employee = $employees->search({group_id=>3, group_id_2=>1})->first;
+$employee->group_id(1);
+$employee->group_id_2(3);
+$employee->update();
+ok( check_rs($employees->search_rs({group_id=>3, group_id_2=>1}))
+    && check_rs($employees->search_rs({group_id=>1, group_id_2=>3})),
+    "overloaded multicol update 3" 
+);
+
+$employee = $employees->search({group_id=>3, group_id_2=>1})->first;
+$employee->update({group_id=>2, group_id_2=>3});
+ok( check_rs($employees->search_rs({group_id=>3, group_id_2=>1}))
+    && check_rs($employees->search_rs({group_id=>2, group_id_2=>3})), 
+    "overloaded multicol update 4" 
+);
+
+$employee = $employees->search({group_id=>3, group_id_2=>2})->first;
+$employee->update({group_id=>2, group_id_2=>4, position=>2});
+ok( check_rs($employees->search_rs({group_id=>3, group_id_2=>2}))
+    && check_rs($employees->search_rs({group_id=>2, group_id_2=>4})), 
+    "overloaded multicol update 5" 
+);
+
 sub hammer_rs {
     my $rs = shift;
     my $employee;
diff --git a/t/93nobindvars.t b/t/93nobindvars.t
new file mode 100644 (file)
index 0000000..b4e1adc
--- /dev/null
@@ -0,0 +1,65 @@
+use strict;
+use warnings;  
+
+# Copied from 71mysql.t, manually using NoBindVars.  This is to give that code
+#  wider testing, since virtually nobody who regularly runs the test suite
+#  is using DBD::Sybase+FreeTDS+MSSQL -- blblack
+
+use Test::More;
+use lib qw(t/lib);
+use DBICTest;
+use DBI::Const::GetInfoType;
+
+my ($dsn, $user, $pass) = @ENV{map { "DBICTEST_MYSQL_${_}" } qw/DSN USER PASS/};
+
+#warn "$dsn $user $pass";
+
+plan skip_all => 'Set $ENV{DBICTEST_MYSQL_DSN}, _USER and _PASS to run this test'
+  unless ($dsn && $user);
+
+plan tests => 4;
+
+{ # Fake storage driver for mysql + no bind variables
+    package DBIx::Class::Storage::DBI::MySQLNoBindVars;
+    use base qw/
+        DBIx::Class::Storage::DBI::mysql
+        DBIx::Class::Storage::DBI::NoBindVars
+    /;
+    $INC{'DBIx/Class/Storage/DBI/MySQLNoBindVars.pm'} = 1;
+}
+
+DBICTest::Schema->storage(undef); # just in case?
+DBICTest::Schema->storage_type('::DBI::MySQLNoBindVars');
+DBICTest::Schema->compose_namespace('MySQLTest' => $dsn, $user, $pass);
+
+my $dbh = MySQLTest->schema->storage->dbh;
+
+$dbh->do("DROP TABLE IF EXISTS artist;");
+
+$dbh->do("CREATE TABLE artist (artistid INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255), charfield CHAR(10));");
+
+#'dbi:mysql:host=localhost;database=dbic_test', 'dbic_test', '');
+
+MySQLTest::Artist->load_components('PK::Auto');
+
+# test primary key handling
+my $new = MySQLTest::Artist->create({ name => 'foo' });
+ok($new->artistid, "Auto-PK worked");
+
+# test LIMIT support
+for (1..6) {
+    MySQLTest::Artist->create({ name => 'Artist ' . $_ });
+}
+my $it = MySQLTest::Artist->search( {},
+    { rows => 3,
+      offset => 2,
+      order_by => 'artistid' }
+);
+is( $it->count, 3, "LIMIT count ok" );
+is( $it->next->name, "Artist 2", "iterator->next ok" );
+$it->next;
+$it->next;
+is( $it->next, undef, "next past end of resultset ok" );
+
+# clean up our mess
+$dbh->do("DROP TABLE artist");
diff --git a/t/94versioning.t b/t/94versioning.t
new file mode 100644 (file)
index 0000000..66ea346
--- /dev/null
@@ -0,0 +1,58 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+use Test::More;
+use File::Spec;
+
+BEGIN {
+    eval "use DBD::SQLite; use SQL::Translator;";
+    plan $@
+        ? ( skip_all => 'needs DBD::SQLite and SQL::Translator for testing' )
+        : ( tests => 6 );
+}
+
+use lib qw(t/lib);
+
+use_ok('DBICVersionOrig');
+
+my $db_file = "t/var/versioning.db";
+unlink($db_file) if -e $db_file;
+unlink($db_file . "-journal") if -e $db_file . "-journal";
+mkdir("t/var") unless -d "t/var";
+unlink('t/var/DBICVersion-Schema-1.0-SQLite.sql');
+
+my $schema_orig = DBICVersion::Schema->connect("dbi:SQLite:$db_file");
+# $schema->storage->ensure_connected();
+
+is($schema_orig->ddl_filename('SQLite', 't/var', '1.0'), File::Spec->catfile('t', 'var', 'DBICVersion-Schema-1.0-SQLite.sql'), 'Filename creation working');
+$schema_orig->create_ddl_dir('SQLite', undef, 't/var');
+
+ok(-f 't/var/DBICVersion-Schema-1.0-SQLite.sql', 'Created DDL file');
+## do this here or let Versioned.pm do it?
+# $schema->deploy();
+
+my $tvrs = $schema_orig->resultset('Table');
+is($schema_orig->exists($tvrs), 1, 'Created schema from DDL file');
+
+eval "use DBICVersionNew";
+my $schema_new = DBICVersion::Schema->connect("dbi:SQLite:$db_file");
+
+unlink('t/var/DBICVersion-Schema-2.0-SQLite.sql');
+unlink('t/var/DBICVersion-Schema-1.0-2.0-SQLite.sql');
+$schema_new->create_ddl_dir('SQLite', undef, 't/var', '1.0');
+ok(-f 't/var/DBICVersion-Schema-1.0-2.0-SQLite.sql', 'Created DDL upgrade file');
+
+## create new to pick up filedata for upgrade files we just made (on_connect)
+my $schema_upgrade = DBICVersion::Schema->connect("dbi:SQLite:$db_file");
+
+## do this here or let Versioned.pm do it?
+$schema_upgrade->upgrade();
+$tvrs = $schema_upgrade->resultset('Table');
+is($schema_upgrade->exists($tvrs), 1, 'Upgraded schema from DDL file');
+
+unlink($db_file) if -e $db_file;
+unlink($db_file . "-journal") if -e $db_file . "-journal";
+unlink('t/var/DBICVersion-Schema-1.0-SQLite.sql');
+unlink('t/var/DBICVersion-Schema-2.0-SQLite.sql');
+unlink('t/var/DBICVersion-Schema-1.0-2.0-SQLite.sql');
+unlink(<t/var/backup/*>);
index dc33199..1f4cd90 100644 (file)
@@ -15,9 +15,9 @@ use lib qw(t/lib);
 
 use_ok('DBICTest');
 
-DBICTest->init_schema();
+my $schema = DBICTest->init_schema();
 
-my $sql_maker = DBICTest->schema->storage->sql_maker;
+my $sql_maker = $schema->storage->sql_maker;
 
 $sql_maker->quote_char('`');
 $sql_maker->name_sep('.');
diff --git a/t/96file_column.t b/t/96file_column.t
new file mode 100644 (file)
index 0000000..4773861
--- /dev/null
@@ -0,0 +1,15 @@
+use strict;
+use warnings;  
+
+use Test::More;
+use lib qw(t/lib);
+use DBICTest;
+use IO::File;
+
+my $schema = DBICTest->init_schema();
+
+plan tests => 1;
+
+my $fh = new IO::File('t/96file_column.t','r');
+eval { $schema->resultset('FileColumn')->create({file => {handle => $fh, filename =>'96file_column.t'}})};
+ok(!$@,'FileColumn checking if file handled properly.');
diff --git a/t/bindtype_columns.t b/t/bindtype_columns.t
new file mode 100644 (file)
index 0000000..9d0ad92
--- /dev/null
@@ -0,0 +1,60 @@
+use strict;
+use warnings;  
+
+use Test::More;
+use lib qw(t/lib);
+use DBICTest;
+
+my ($dsn, $dbuser, $dbpass) = @ENV{map { "DBICTEST_PG_${_}" } qw/DSN USER PASS/};
+
+plan skip_all => 'Set $ENV{DBICTEST_PG_DSN}, _USER and _PASS to run this test'
+  unless ($dsn && $dbuser);
+  
+plan tests => 3;
+
+my $schema = DBICTest::Schema->connection($dsn, $dbuser, $dbpass);
+
+my $dbh = $schema->storage->dbh;
+
+$dbh->do(qq[
+
+       CREATE TABLE artist
+       (
+               artistid                serial  NOT NULL        PRIMARY KEY,
+               media                   bytea   NOT NULL,
+               name                    varchar NULL
+       );
+],{ RaiseError => 1, PrintError => 1 });
+
+
+$schema->class('Artist')->load_components(qw/ 
+
+       PK::Auto 
+       Core 
+/);
+
+$schema->class('Artist')->add_columns(
+       
+       "media", { 
+       
+               data_type => "bytea", 
+               is_nullable => 0,
+       },
+);
+
+# test primary key handling
+my $big_long_string    = 'abcd' x 250000;
+
+my $new = $schema->resultset('Artist')->create({ media => $big_long_string });
+
+ok($new->artistid, "Created a blob row");
+is($new->media,        $big_long_string, "Set the blob correctly.");
+
+my $rs = $schema->resultset('Artist')->find({artistid=>$new->artistid});
+
+is($rs->get_column('media'), $big_long_string, "Created the blob correctly.");
+
+$dbh->do("DROP TABLE artist");
+
+
+
index 71ccaed..07166e6 100644 (file)
@@ -16,9 +16,12 @@ BEGIN {
 use lib 't/lib';
 
 use_ok('DBICTest');
-DBICTest->init_schema();
 
-DBICTest::CD->load_components(qw/CDBICompat::Pager/);
+DBICTest::Schema::CD->load_components(qw/CDBICompat CDBICompat::Pager/);
+
+my $schema = DBICTest->init_schema(compose_connection => 1);
+
+DBICTest::CD->result_source_instance->schema->storage($schema->storage);
 
 my ( $pager, $it ) = DBICTest::CD->page(
     {},
diff --git a/t/lib/DBICNSTest/OtherRslt/D.pm b/t/lib/DBICNSTest/OtherRslt/D.pm
new file mode 100644 (file)
index 0000000..9a9aaf5
--- /dev/null
@@ -0,0 +1,6 @@
+package DBICNSTest::OtherRslt::D;
+use base qw/DBIx::Class/;
+__PACKAGE__->load_components(qw/PK::Auto Core/);
+__PACKAGE__->table('d');
+__PACKAGE__->add_columns('d');
+1;
diff --git a/t/lib/DBICNSTest/RSBase.pm b/t/lib/DBICNSTest/RSBase.pm
new file mode 100644 (file)
index 0000000..9786d5f
--- /dev/null
@@ -0,0 +1,3 @@
+package DBICNSTest::RSBase;
+use base qw/DBIx::Class::ResultSet/;
+1;
diff --git a/t/lib/DBICNSTest/RSet/A.pm b/t/lib/DBICNSTest/RSet/A.pm
new file mode 100644 (file)
index 0000000..4cb415f
--- /dev/null
@@ -0,0 +1,3 @@
+package DBICNSTest::RSet::A;
+use base qw/DBIx::Class::ResultSet/;
+1;
diff --git a/t/lib/DBICNSTest/RSet/C.pm b/t/lib/DBICNSTest/RSet/C.pm
new file mode 100644 (file)
index 0000000..c43a3fe
--- /dev/null
@@ -0,0 +1,3 @@
+package DBICNSTest::RSet::C;
+use base qw/DBIx::Class::ResultSet/;
+1;
diff --git a/t/lib/DBICNSTest/Result/A.pm b/t/lib/DBICNSTest/Result/A.pm
new file mode 100644 (file)
index 0000000..d2faecb
--- /dev/null
@@ -0,0 +1,6 @@
+package DBICNSTest::Result::A;
+use base qw/DBIx::Class/;
+__PACKAGE__->load_components(qw/PK::Auto Core/);
+__PACKAGE__->table('a');
+__PACKAGE__->add_columns('a');
+1;
diff --git a/t/lib/DBICNSTest/Result/B.pm b/t/lib/DBICNSTest/Result/B.pm
new file mode 100644 (file)
index 0000000..e9cdc37
--- /dev/null
@@ -0,0 +1,6 @@
+package DBICNSTest::Result::B;
+use base qw/DBIx::Class/;
+__PACKAGE__->load_components(qw/PK::Auto Core/);
+__PACKAGE__->table('b');
+__PACKAGE__->add_columns('b');
+1;
diff --git a/t/lib/DBICNSTest/ResultSet/A.pm b/t/lib/DBICNSTest/ResultSet/A.pm
new file mode 100644 (file)
index 0000000..c7a86aa
--- /dev/null
@@ -0,0 +1,3 @@
+package DBICNSTest::ResultSet::A;
+use base qw/DBIx::Class::ResultSet/;
+1;
diff --git a/t/lib/DBICNSTest/ResultSet/C.pm b/t/lib/DBICNSTest/ResultSet/C.pm
new file mode 100644 (file)
index 0000000..55ecf1d
--- /dev/null
@@ -0,0 +1,3 @@
+package DBICNSTest::ResultSet::C;
+use base qw/DBIx::Class::ResultSet/;
+1;
diff --git a/t/lib/DBICNSTest/Rslt/A.pm b/t/lib/DBICNSTest/Rslt/A.pm
new file mode 100644 (file)
index 0000000..686e329
--- /dev/null
@@ -0,0 +1,6 @@
+package DBICNSTest::Rslt::A;
+use base qw/DBIx::Class/;
+__PACKAGE__->load_components(qw/PK::Auto Core/);
+__PACKAGE__->table('a');
+__PACKAGE__->add_columns('a');
+1;
diff --git a/t/lib/DBICNSTest/Rslt/B.pm b/t/lib/DBICNSTest/Rslt/B.pm
new file mode 100644 (file)
index 0000000..fb02f3f
--- /dev/null
@@ -0,0 +1,6 @@
+package DBICNSTest::Rslt::B;
+use base qw/DBIx::Class/;
+__PACKAGE__->load_components(qw/PK::Auto Core/);
+__PACKAGE__->table('b');
+__PACKAGE__->add_columns('b');
+1;
index 97855cb..27c8549 100755 (executable)
@@ -55,7 +55,12 @@ sub init_schema {
     my $dbuser = $ENV{"DBICTEST_DBUSER"} || '';
     my $dbpass = $ENV{"DBICTEST_DBPASS"} || '';
 
-    my $schema = DBICTest::Schema->compose_connection('DBICTest' => $dsn, $dbuser, $dbpass);
+    my $compose_method = ($args{compose_connection}
+                           ? 'compose_connection'
+                           : 'compose_namespace');
+
+    my $schema = DBICTest::Schema->$compose_method('DBICTest')
+                                 ->connect($dsn, $dbuser, $dbpass);
     $schema->storage->on_connect_do(['PRAGMA synchronous = OFF']);
     if ( !$args{no_deploy} ) {
         __PACKAGE__->deploy_schema( $schema );
@@ -225,8 +230,8 @@ sub populate_schema {
     ]);
 
     $schema->populate('Link', [
-        [ qw/id title/ ],
-        [ 1, 'aaa' ]
+        [ qw/id url title/ ],
+        [ 1, '', 'aaa' ]
     ]);
 
     $schema->populate('Bookmark', [
index f8b2cd9..7ebd040 100644 (file)
@@ -9,6 +9,7 @@ __PACKAGE__->load_classes(qw/
   Artist
   Employee
   CD
+  FileColumn
   Link
   Bookmark
   #dummy
index 0bb49c4..90eb7bf 100644 (file)
@@ -4,10 +4,15 @@ package # hide from PAUSE
 use base 'DBIx::Class::Core';
 
 __PACKAGE__->table('artist');
+__PACKAGE__->source_info({
+    "source_info_key_A" => "source_info_value_A",
+    "source_info_key_B" => "source_info_value_B",
+    "source_info_key_C" => "source_info_value_C",
+});
 __PACKAGE__->add_columns(
   'artistid' => {
     data_type => 'integer',
-    is_auto_increment => 1
+    is_auto_increment => 1,
   },
   'name' => {
     data_type => 'varchar',
index c4c8a8b..c59bbe5 100644 (file)
@@ -2,7 +2,7 @@ package # hide from PAUSE
     DBICTest::Schema::ArtistSourceName;
 
 use base 'DBICTest::Schema::Artist';
-
+__PACKAGE__->table(__PACKAGE__->table);
 __PACKAGE__->source_name('SourceNameArtists');
 
 1;
index 78b3d16..7beb833 100644 (file)
@@ -19,6 +19,10 @@ __PACKAGE__->add_columns(
         data_type => 'integer',
         is_nullable => 1,
     },
+    group_id_2 => {
+        data_type => 'integer',
+        is_nullable => 1,
+    },
     name => {
         data_type => 'varchar',
         size      => 100,
diff --git a/t/lib/DBICTest/Schema/FileColumn.pm b/t/lib/DBICTest/Schema/FileColumn.pm
new file mode 100644 (file)
index 0000000..a6d768f
--- /dev/null
@@ -0,0 +1,19 @@
+package 
+DBICTest::Schema::FileColumn;
+
+use strict;
+use warnings;
+use base qw/DBIx::Class::Core/;
+
+__PACKAGE__->load_components(qw/InflateColumn::File/);
+
+__PACKAGE__->table('file_columns');
+
+__PACKAGE__->add_columns(
+  id => { data_type => 'integer', is_auto_increment => 1 },
+  file => { data_type => 'varchar', is_file_column => 1, file_column_path => '/tmp', size=>255 }
+);
+
+__PACKAGE__->set_primary_key('id');
+
+1;
index cdffa2f..a1e23db 100644 (file)
@@ -3,17 +3,17 @@ package # hide from PAUSE
 
 use base 'DBIx::Class::Core';
 
-DBICTest::Schema::FourKeys->table('fourkeys');
-DBICTest::Schema::FourKeys->add_columns(
+__PACKAGE__->table('fourkeys');
+__PACKAGE__->add_columns(
   'foo' => { data_type => 'integer' },
   'bar' => { data_type => 'integer' },
   'hello' => { data_type => 'integer' },
   'goodbye' => { data_type => 'integer' },
   'sensors' => { data_type => 'character' },
 );
-DBICTest::Schema::FourKeys->set_primary_key(qw/foo bar hello goodbye/);
+__PACKAGE__->set_primary_key(qw/foo bar hello goodbye/);
 
-DBICTest::Schema::FourKeys->has_many(
+__PACKAGE__->has_many(
   'fourkeys_to_twokeys', 'DBICTest::Schema::FourKeys_to_TwoKeys', {
     'foreign.f_foo' => 'self.foo',
     'foreign.f_bar' => 'self.bar',
@@ -21,7 +21,7 @@ DBICTest::Schema::FourKeys->has_many(
     'foreign.f_goodbye' => 'self.goodbye',
 });
 
-DBICTest::Schema::FourKeys->many_to_many(
+__PACKAGE__->many_to_many(
   'twokeys', 'fourkeys_to_twokeys', 'twokeys',
 );
 
index 168f311..0c82588 100644 (file)
@@ -3,8 +3,8 @@ package # hide from PAUSE
 
 use base qw/DBIx::Class::Core/;
 
-DBICTest::Schema::LinerNotes->table('liner_notes');
-DBICTest::Schema::LinerNotes->add_columns(
+__PACKAGE__->table('liner_notes');
+__PACKAGE__->add_columns(
   'liner_id' => {
     data_type => 'integer',
   },
@@ -13,8 +13,8 @@ DBICTest::Schema::LinerNotes->add_columns(
     size      => 100,
   },
 );
-DBICTest::Schema::LinerNotes->set_primary_key('liner_id');
-DBICTest::Schema::LinerNotes->belongs_to(
+__PACKAGE__->set_primary_key('liner_id');
+__PACKAGE__->belongs_to(
   'cd', 'DBICTest::Schema::CD', 'liner_id'
 );
 
index 1723390..1edda61 100644 (file)
@@ -3,13 +3,13 @@ package # hide from PAUSE
 
 use base 'DBIx::Class::Core';
 
-DBICTest::Schema::NoPrimaryKey->table('noprimarykey');
-DBICTest::Schema::NoPrimaryKey->add_columns(
+__PACKAGE__->table('noprimarykey');
+__PACKAGE__->add_columns(
   'foo' => { data_type => 'integer' },
   'bar' => { data_type => 'integer' },
   'baz' => { data_type => 'integer' },
 );
 
-DBICTest::Schema::NoPrimaryKey->add_unique_constraint(foo_bar => [ qw/foo bar/ ]);
+__PACKAGE__->add_unique_constraint(foo_bar => [ qw/foo bar/ ]);
 
 1;
index 4cc2918..63356ac 100644 (file)
@@ -3,8 +3,8 @@ package # hide from PAUSE
 
 use base 'DBIx::Class::Core';
 
-DBICTest::Schema::OneKey->table('onekey');
-DBICTest::Schema::OneKey->add_columns(
+__PACKAGE__->table('onekey');
+__PACKAGE__->add_columns(
   'id' => {
     data_type => 'integer',
     is_auto_increment => 1,
@@ -16,7 +16,7 @@ DBICTest::Schema::OneKey->add_columns(
     data_type => 'integer',
   },
 );
-DBICTest::Schema::OneKey->set_primary_key('id');
+__PACKAGE__->set_primary_key('id');
 
 
 1;
index 41610da..687dcd1 100644 (file)
@@ -3,11 +3,11 @@ package # hide from PAUSE
 
 use base 'DBIx::Class::Core';
 
-DBICTest::Schema::Serialized->table('serialized');
-DBICTest::Schema::Serialized->add_columns(
+__PACKAGE__->table('serialized');
+__PACKAGE__->add_columns(
   'id' => { data_type => 'integer' },
   'serialized' => { data_type => 'text' },
 );
-DBICTest::Schema::Serialized->set_primary_key('id');
+__PACKAGE__->set_primary_key('id');
 
 1;
diff --git a/t/lib/DBICVersionNew.pm b/t/lib/DBICVersionNew.pm
new file mode 100644 (file)
index 0000000..f92c3a5
--- /dev/null
@@ -0,0 +1,48 @@
+package DBICVersion::Table;
+
+use base 'DBIx::Class';
+use strict;
+use warnings;
+
+__PACKAGE__->load_components(qw/ Core/);
+__PACKAGE__->table('TestVersion');
+
+__PACKAGE__->add_columns
+    ( 'Version' => {
+        'data_type' => 'INTEGER',
+        'is_auto_increment' => 1,
+        'default_value' => undef,
+        'is_foreign_key' => 0,
+        'is_nullable' => 0,
+        'size' => ''
+        },
+      'VersionName' => {
+        'data_type' => 'VARCHAR',
+        'is_auto_increment' => 0,
+        'default_value' => undef,
+        'is_foreign_key' => 0,
+        'is_nullable' => 1,
+        'size' => '20'
+        },
+      );
+
+__PACKAGE__->set_primary_key('Version');
+
+package DBICVersion::Schema;
+use base 'DBIx::Class::Schema';
+use strict;
+use warnings;
+
+our $VERSION = '2.0';
+
+__PACKAGE__->register_class('Table', 'DBICVersion::Table');
+__PACKAGE__->load_components('+DBIx::Class::Schema::Versioned');
+__PACKAGE__->upgrade_directory('t/var/');
+__PACKAGE__->backup_directory('t/var/backup/');
+
+#sub upgrade_directory
+#{
+#    return 't/var/';
+#}
+
+1;
diff --git a/t/lib/DBICVersionOrig.pm b/t/lib/DBICVersionOrig.pm
new file mode 100644 (file)
index 0000000..5a12ce4
--- /dev/null
@@ -0,0 +1,46 @@
+package DBICVersion::Table;
+
+use base 'DBIx::Class';
+use strict;
+use warnings;
+
+__PACKAGE__->load_components(qw/ Core/);
+__PACKAGE__->table('TestVersion');
+
+__PACKAGE__->add_columns
+    ( 'Version' => {
+        'data_type' => 'INTEGER',
+        'is_auto_increment' => 1,
+        'default_value' => undef,
+        'is_foreign_key' => 0,
+        'is_nullable' => 0,
+        'size' => ''
+        },
+      'VersionName' => {
+        'data_type' => 'VARCHAR',
+        'is_auto_increment' => 0,
+        'default_value' => undef,
+        'is_foreign_key' => 0,
+        'is_nullable' => 0,
+        'size' => '10'
+        },
+      );
+
+__PACKAGE__->set_primary_key('Version');
+
+package DBICVersion::Schema;
+use base 'DBIx::Class::Schema';
+use strict;
+use warnings;
+
+our $VERSION = '1.0';
+
+__PACKAGE__->register_class('Table', 'DBICVersion::Table');
+__PACKAGE__->load_components('+DBIx::Class::Schema::Versioned');
+
+sub upgrade_directory
+{
+    return 't/var/';
+}
+
+1;
index 2ce5dad..c9de968 100644 (file)
@@ -11,6 +11,7 @@ CREATE TABLE employee (
   employee_id INTEGER PRIMARY KEY NOT NULL,
   position integer NOT NULL,
   group_id integer,
+  group_id_2 integer,  
   name varchar(100)
 );
 
@@ -128,6 +129,14 @@ CREATE TABLE link (
 );
 
 --
+-- Table: file_columns
+--
+CREATE TABLE file_columns (
+  id INTEGER PRIMARY KEY NOT NULL,
+  file varchar(255)
+);
+
+--
 -- Table: tags
 --
 CREATE TABLE tags (