The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

HoneyClient::DB - Perl extension to provide an abstract interface for storing HoneyClient data into a database.

VERSION

This documentation refers to HoneyClient::DB version 0.98.

SYNOPSIS

As a generic example, let's store data about superheroes.

DEFINE SCHEMAS

  # First, we define a schema for each superhero ability (child object).
  use HoneyClient::DB;
  package HoneyClient::DB::SuperHero::Ability;
  use base("HoneyClient::DB");

  # Define Ability Schema
  our %fields = (
      string => {
          # Each ability should have a name. 
          name => {
              # This name should be required.
              required => 1, # Must exist and is not null
          },
      },

      # Each ability may have an optional description.
      text => [ 'description' ],

      # Each ability may have an optional recharge time.
      int  => [ 'recharge_time' ],
  );
  
  # Next, we define a schema for each superhero (parent object).
  package HoneyClient::DB::SuperHero;
  use base("HoneyClient::DB");
  
  # Define SuperHero Schema 
  our %fields = (
      string => {
          # Each superhero should have a name.
          name => {
              # This name should be required.
              required => 1,
              key => $HoneyClient::DB::KEY_UNIQUE_MULT,
          },
          # Each superhero may have an optional real name.
          real_name => {
              key => $HoneyClient::DB::KEY_UNIQUE_MULT,
          },
          # If 2 SuperHero Objects have the same 'name' and 'real_name'
          # fields, then only the first object will be inserted succesfully
      },
      
      # Each superhero may have optional height and weight stats. 
      int => [ 'height', 'weight' ],

      # Each superhero must have a primary ability.
      ref => {
          primary_ability => {
              # Reference child object type.
              objclass=> "HoneyClient::DB::SuperHero::Ability",

              # This should be required.
              required => 1,
          },
      },

      # Each superhero may have optional abilities.
      array => {
          abilities => {
              # Reference child object type.
              objclass=> "HoneyClient::DB::SuperHero::Ability",
          },
      },

      # Each superhero should have a birth date.
      timestamp => {
          birth_date => {
              required => 1,
          },
      },
  );
  
  1;

USE SCHEMAS

  # Now, we start generating data to insert into our database.

  use HoneyClient::DB::SuperHero;
  use Data::Dumper;

  # Create a new superhero.
  my $hero = {
      name       => 'Superman',
      real_name  => 'Clark Kent',
      weight     => 225,
      height     => 75,
      birth_date => '1998-06-01 12:34:56', # YYYY-MM-DD HH:MM:SS
      primary_ability => {
          name              => 'Super Strength',
          description       => 'More powerful than a locomotive.',
      },
      abilities  => [
          {
              name          => 'Flight',
              description   => "It's a bird, it's a plane.",
          },
          {
              name          => 'Heat Vision',
              recharge_time => 5, # in seconds
          },
      ],
  };
    
  # Instantiate a new SuperHero object.
  # Upon creation, the data will be checked against the schema.
  # This call will croak if any errors occur. 
  $hero = HoneyClient::DB::SuperHero->new($hero);

  # Insert the data into the database.
  $hero->insert();
  
  # Retrieve the superhero.
  my $filter = {
      name => 'Superman',
  };
    
  # Retrieves rows in the SuperHero table where name is 'Superman'.
  # NOTE: At this time, the returned data is NOT identical to
  # the object inserted.
  my $inserted_hero = HoneyClient::DB::SuperHero->select($filter);

  # Printing the contents of the returned content should clarify
  # how the data looks.
  $Data::Dumper::Indent = 1;
  $Data::Dumper::Terse = 0;
  print Dumper($inserted_hero) . "\n";

DESCRIPTION

This library is an abstract class used to access and store HoneyClient within a database. The class is not to be used directly, but can be inherited by sub-classes, in order to indirectly store specific types of data into a database.

Note: Any calls made to this library will fail, if a database is not properly described in the <HoneyClient/><DB/> section of the etc/honeyclient.xml configuration file or if the library cannot establish a connection to the database.

SCHEMA DEFINITION

The schema for a HoneyClient::DB subclass is created from the %fields variable, a multi-level hash table.

FIRST LEVEL: DATA TYPE

The keys at the first level of %fields define the data types to be used for each column, which are named as keys in the second level. The following is a list of acceptable data types:

  • 'int'

    An integer.

  • 'string'

    A string no longer than 255 characters.

  • 'text'

    A string no longer than 65,535 characters.

  • 'timestamp'

    An ISO8601 compliant timestamp (i.e., 'MMDDYYYY HH:MM:SS').

  • 'array'

    An array. Used to represent one-to-many relationships.

    Note: If this type is specified, then the 'objclass' option must be set within each column name.

  • 'ref'

    A reference. Used to represent one-to-one relationships.

    Note: If this type is specified, then the 'objclass' option must be set within each column name.

SECOND LEVEL: COLUMN NAMES

Column names are defined as keys in the second level of %fields. If each column does not need any special options (e.g., making the column required), then an array reference can hold all the column names. For example, the following schema defines 3 default integer fields:

  %our fields = {
      int => [
          'col_a',
          'col_b',
          'col_c',
      ],
  };

However, if some of the columns need special options set (e.g., making 'col_b' required), then a sub-hash table should be defined instead, as follows:

  %our fields = {
      int => { 
          'col_a' => {},
          'col_b' => {
              'required' => 1,
          },
          'col_c' => {},
      },
  };

THIRD LEVEL: OPTIONS

If needed, options are defined in the third level of %fields. These options are described as follows:

  • 'check_func'

    If defined, then this contains a reference to a subroutine that will verify the actual column data is in a proper format. This overrides the default internal check function for the data type of that column.

  • 'init_val'

    If defined, then this value will be the default value that the database will assign to the column, if empty data is inserted into this column.

  • 'key'

    If defined, then this value creates an index for the column. Possible values are:

    • $HoneyClient::DB::KEY_INDEX

      If set, an index will be created in the database to improve the search time of this column. This option is only recommended for very frequently searched columns.

    • $HoneyClient:DB::KEY_UNIQUE

      If set, a UNIQUE index is created for the column. If a record is inserted that has a match with this column in a previously existing record, the insert will fail on the database side, but the 'id' of that existing record will be returned.

    • $HoneyClient:DB::KEY_UNIQUE_MULT

      If set, the column is added to a UNIQUE index comprised of all other columns with the KEY_UNIQUE_MULT key option. This index is used to ensure ALL VALUES for the columns in the index are distinct. An insert of a record matching an existing record will return the ID of that record.

  • 'objclass'

    This option is required and only used by the 'array' and 'ref' data types. The value should be a string which contains the package name of the schema to include as a child.

  • 'required'

    If defined and set to 1, then this option will cause all subsequent HoneyClient::DB::*->new($data) operations to fail, if the $data does not contain the required field.

DATABASE CONFIGURATION

This library expects to connect to a MySQL v5.0 or greater database. To specify which database this library should use, see the <HoneyClient/><DB/> section of the etc/honeyclient.xml configuration file for further details.

METHODS

Object Creation

new

Receives an unblessed hash, imports the schema (if necessary), checks that required fields contain the proper data, and returns the blessed object.

It must be called using an object class derived from HoneyClient::DB. For Example:

  $my_obj = new HoneyClient::DB::SomeObj->new({
          field_a => "foo",
          field_b => "bar"
  });

Database Operations

insert

Creates and executes a SQL INSERT statement for the referenced object. The object must be initialized at the time this method is called.

  $my_obj->insert();

Input

There are no parameters, however the calling object is used as input for the insert operation.

Return Value

Returns the 'id' of the (parent) object inserted.

select

Creates and executes a SQL SELECT statement and returns an array of hash refs containing result rows. If no fields are specified, all fields are returned. The first parameter is a hash reference to a query filter. The filter may be followed by a list of field names to retrieve.

  @my_objects = HoneyClient::DB::SomeObj->select($my_filter,@columns);

or

  $my_objects_ref = HoneyClient::DB::SomeObj->select($my_filter,@columns);

Input

The first parameter is a hash_ref containing a filter. The filter is used to generate a SQL query.

The filter is followed by a list of column to select.

Both parameters are optional. If the first parameter is a scalar, it is assumed that there is no filter.

**NOTE** Currently it is not possible to include a child object (ref or array type) in the filter. Only 'id's of child objects are accepted.

Return Value

Returns the 'id' of the (parent) object inserted.

Utility Functions

get_fields

Retrieves a list of fields as defined by the schema, excluding array fields. Can be used in conjunction with calls to HoneyClient::DB::select to execute a SELECT query that retrieves all fields.

BUGS & ASSUMPTIONS

It is assumed that the <HoneyClient/><DB/> section of the etc/honeyclient.xml configuration file is properly configured and the host refered to in that section has MySQL v5.0 or greater running.

SEE ALSO

http://www.honeyclient.org/trac

REPORTING BUGS

http://www.honeyclient.org/trac/newticket

ACKNOWLEDGEMENTS

Tim Bunce for developing DBI

Jochen Wiedmann for developing DBD::mysql

AUTHORS

Matthew Briggs, <mbriggs@mitre.org>

Darien Kindlund, <kindlund@mtre.org>

COPYRIGHT & LICENSE

Copyright (C) 2007 The MITRE Corporation. All rights reserved.

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, using version 2 of the License.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.