📄 schema.pm
字号:
name => {TYPE => 'varchar(32)', NOTNULL => 1}, value => {TYPE => 'varchar(32)', NOTNULL => 1}, sortindex => {TYPE => 'INT2', NOTNULL => 1}, ], INDEXES => [ setting_value_nv_unique_idx => {FIELDS => [qw(name value)], TYPE => 'UNIQUE'}, setting_value_ns_unique_idx => {FIELDS => [qw(name sortindex)], TYPE => 'UNIQUE'}, ], }, profile_setting => { FIELDS => [ user_id => {TYPE => 'INT3', NOTNULL => 1}, setting_name => {TYPE => 'varchar(32)', NOTNULL => 1}, setting_value => {TYPE => 'varchar(32)', NOTNULL => 1}, ], INDEXES => [ profile_setting_value_unique_idx => {FIELDS => [qw(user_id setting_name)], TYPE => 'UNIQUE'}, ], }, # SCHEMA STORAGE # -------------- bz_schema => { FIELDS => [ schema_data => {TYPE => 'LONGBLOB', NOTNULL => 1}, version => {TYPE => 'decimal(3,2)', NOTNULL => 1}, ], },};use constant FIELD_TABLE_SCHEMA => { FIELDS => [ id => {TYPE => 'SMALLSERIAL', NOTNULL => 1, PRIMARYKEY => 1}, value => {TYPE => 'varchar(64)', NOTNULL => 1}, sortkey => {TYPE => 'INT2', NOTNULL => 1, DEFAULT => 0}, isactive => {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'TRUE'}, ], # Note that bz_add_field_table should prepend the table name # to these index names. INDEXES => [ value_idx => {FIELDS => ['value'], TYPE => 'UNIQUE'}, sortkey_idx => ['sortkey', 'value'], ],};#--------------------------------------------------------------------------=head1 METHODSNote: Methods which can be implemented generically for all DBs areimplemented in this module. If needed, they can be overridden withDB-specific code in a subclass. Methods which are prefixed with C<_>are considered protected. Subclasses may override these methods, butother modules should not invoke these methods directly.=cut#--------------------------------------------------------------------------sub new {=over=item C<new> Description: Public constructor method used to instantiate objects of this class. However, it also can be used as a factory method to instantiate database-specific subclasses when an optional driver argument is supplied. Parameters: $driver (optional) - Used to specify the type of database. This routine C<die>s if no subclass is found for the specified driver. $schema (optional) - A reference to a hash. Callers external to this package should never use this parameter. Returns: new instance of the Schema class or a database-specific subclass=cut my $this = shift; my $class = ref($this) || $this; my $driver = shift; if ($driver) { (my $subclass = $driver) =~ s/^(\S)/\U$1/; $class .= '::' . $subclass; eval "require $class;"; die "The $class class could not be found ($subclass " . "not supported?): $@" if ($@); } die "$class is an abstract base class. Instantiate a subclass instead." if ($class eq __PACKAGE__); my $self = {}; bless $self, $class; $self = $self->_initialize(@_); return($self);} #eosub--new#--------------------------------------------------------------------------sub _initialize {=item C<_initialize> Description: Protected method that initializes an object after instantiation with the abstract schema. All subclasses should override this method. The typical subclass implementation should first call the C<_initialize> method of the superclass, then do any database-specific initialization (especially define the database-specific implementation of the all abstract data types), and then call the C<_adjust_schema> method. Parameters: $abstract_schema (optional) - A reference to a hash. If provided, this hash will be used as the internal representation of the abstract schema instead of our default abstract schema. This is intended for internal use only by deserialize_abstract. Returns: the instance of the Schema class=cut my $self = shift; my $abstract_schema = shift; if (!$abstract_schema) { # While ABSTRACT_SCHEMA cannot be modified, $abstract_schema can be. # So, we dclone it to prevent anything from mucking with the constant. $abstract_schema = dclone(ABSTRACT_SCHEMA); # Let extensions add tables, but make sure they can't modify existing # tables. If we don't lock/unlock keys, lock_value complains. lock_keys(%$abstract_schema); foreach my $table (keys %{ABSTRACT_SCHEMA()}) { lock_value(%$abstract_schema, $table) if exists $abstract_schema->{$table}; } unlock_keys(%$abstract_schema); Bugzilla::Hook::process('db_schema-abstract_schema', { schema => $abstract_schema }); unlock_hash(%$abstract_schema); } $self->{schema} = dclone($abstract_schema); $self->{abstract_schema} = $abstract_schema; return $self;} #eosub--_initialize#--------------------------------------------------------------------------sub _adjust_schema {=item C<_adjust_schema> Description: Protected method that alters the abstract schema at instantiation-time to be database-specific. It is a generic enough routine that it can be defined here in the base class. It takes the abstract schema and replaces the abstract data types with database-specific data types. Parameters: none Returns: the instance of the Schema class=cut my $self = shift; # The _initialize method has already set up the db_specific hash with # the information on how to implement the abstract data types for the # instantiated DBMS-specific subclass. my $db_specific = $self->{db_specific}; # Loop over each table in the abstract database schema. foreach my $table (keys %{ $self->{schema} }) { my %fields = (@{ $self->{schema}{$table}{FIELDS} }); # Loop over the field definitions in each table. foreach my $field_def (values %fields) { # If the field type is an abstract data type defined in the # $db_specific hash, replace it with the DBMS-specific data type # that implements it. if (exists($db_specific->{$field_def->{TYPE}})) { $field_def->{TYPE} = $db_specific->{$field_def->{TYPE}}; } # Replace abstract default values (such as 'TRUE' and 'FALSE') # with their database-specific implementations. if (exists($field_def->{DEFAULT}) && exists($db_specific->{$field_def->{DEFAULT}})) { $field_def->{DEFAULT} = $db_specific->{$field_def->{DEFAULT}}; } } } return $self;} #eosub--_adjust_schema#--------------------------------------------------------------------------sub get_type_ddl {=item C<get_type_ddl> Description: Public method to convert abstract (database-generic) field specifiers to database-specific data types suitable for use in a C<CREATE TABLE> or C<ALTER TABLE> SQL statment. If no database-specific field type has been defined for the given field type, then it will just return the same field type. Parameters: a hash or a reference to a hash of a field containing the following keys: C<TYPE> (required), C<NOTNULL> (optional), C<DEFAULT> (optional), C<PRIMARYKEY> (optional), C<REFERENCES> (optional) Returns: a DDL string suitable for describing a field in a C<CREATE TABLE> or C<ALTER TABLE> SQL statement=cut my $self = shift; my $finfo = (@_ == 1 && ref($_[0]) eq 'HASH') ? $_[0] : { @_ }; my $type = $finfo->{TYPE}; die "A valid TYPE was not specified for this column." unless ($type); my $default = $finfo->{DEFAULT}; # Replace any abstract default value (such as 'TRUE' or 'FALSE') # with its database-specific implementation. if ( defined $default && exists($self->{db_specific}->{$default}) ) { $default = $self->{db_specific}->{$default}; } my $fkref = $self->{enable_references} ? $finfo->{REFERENCES} : undef; my $type_ddl = $self->convert_type($type); # DEFAULT attribute must appear before any column constraints # (e.g., NOT NULL), for Oracle $type_ddl .= " DEFAULT $default" if (defined($default)); $type_ddl .= " NOT NULL" if ($finfo->{NOTNULL}); $type_ddl .= " PRIMARY KEY" if ($finfo->{PRIMARYKEY}); $type_ddl .= "\n\t\t\t\tREFERENCES $fkref" if $fkref; return($type_ddl);} #eosub--get_type_ddlsub convert_type {=item C<convert_type>Converts a TYPE from the L</ABSTRACT_SCHEMA> format into the real SQL type.=cut my ($self, $type) = @_; return $self->{db_specific}->{$type} || $type;}sub get_column {=item C<get_column($table, $column)> Description: Public method to get the abstract definition of a column. Parameters: $table - the table name $column - a column in the table Returns: a hashref containing information about the column, including its type (C<TYPE>), whether or not it can be null (C<NOTNULL>), its default value if it has one (C<DEFAULT), etc. Returns undef if the table or column does not exist.=cut my($self, $table, $column) = @_; # Prevent a possible dereferencing of an undef hash, if the # table doesn't exist. if (exists $self->{schema}->{$table}) { my %fields = (@{ $self->{schema}{$table}{FIELDS} }); return $fields{$column}; } return undef;} #eosub--get_columnsub get_table_list {=item C<get_table_list> Description: Public method for discovering what tables should exist in the Bugzilla database. Parameters: none Returns: an array of table names=cut my $self = shift; return(sort(keys %{ $self->{schema} }));} #eosub--get_table_list#--------------------------------------------------------------------------sub get_table_columns {=item C<get_table_columns> Description: Public method for discovering what columns are in a given table in the Bugzilla database. Parameters: $table - the table name Returns: array of column names=cut my($self, $table) = @_; my @ddl = (); my $thash = $self->{schema}{$table}; die "Table $table does not exist in the database schema." unless (ref($thash)); my @columns = (); my @fields = @{ $thash->{FIELDS} }; while (@fields) { push(@columns, shift(@fields)); shift(@fields); } return @columns;} #eosub--get_table_columnssub get_table_indexes_abstract { my ($self, $table) = @_; my $table_def = $self->get_table_abstract($table); my %indexes = @{$table_def->{INDEXES} || []}; return \%indexes;}sub get_create_database_sql { my ($self, $name) = @_; return ("CREATE DATABASE $name");}sub get_table_ddl {=item C<get_table_ddl> Description: Public method to generate the SQL statements needed to create the a given table and its indexes in the Bugzilla database. Subclasses may override or extend this method, if needed, but subclasses probably should override C<_get_create_table_ddl> or C<_get_create_index_ddl> instead. Parameters: $table - the table name Returns: an array of strings containing SQL statements=cut my($self, $table) = @_; my @ddl = (); die "Table $table does not exist in the database schema." unless (ref($self->{schema}{$table})); my $create_table = $self->_get_create_table_ddl($table); push(@ddl, $create_table) if $create_table;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -