CINCH-APPS

Skillfully crafted, distinctive solutions

Active Record PHP Class

  • Introduction
  • Documentation
  • Method Reference
  • License/Purchase

This is an active record class based on PDO that understands MySQL and SQL Server databases and their accompanying metadata. 

General features:

  • Create, update, and delete records without using SQL.
  • Backup specific data via XML
  • Create HTML forms with a single command. 
  • Easy queries using primary key (or part of it), query-by-example, and sub-queries.

Chaining Objects

Chaining multiple active record objects in master/detail arrangements allows for complex, maintainable data extraction that joins either can not do or would prove too complex to efficiently maintain.  Running a new query on an object with detail objects (or moving to the next row in its recordset) results in a cascading effect on all detail objects under it.  Set a record from form data with a single command, and many other powerful features.

High Value from Complex Made Simple

An interesting use of this class would be for a complex registration process. Set up and work with the necessary active_record objects in anticipation of a database commit. Set a transaction around all of them and if there was any database issue, rollback the transaction, back all of the data up (via the backup_selected method), then throw it in an exception table that can be re-committed at a later date. The idea would be to keep your database clean without losing any data. At a later time, the exception could be viewed through an exception admin facility which would restore the backed up data to their respective active_record objects (via the not-yet-created restore method - coming soon, sorry!), modify data as necessary, then attempt to commit the data again.

Features continued:

  • This class serializes and de-serializes itself to allow for session storage.
  • This class normalizes and synchronizes data types between the database and PHP (and vice-versa).
    • For example, a bit in SQL Server will automatically transform to a boolean in PHP. 
    • Similarly, a datetime in MySQL will automatically transform to a DateTime object in PHP.
  • This class handles “data pools” automatically so you can “soft-segment” your data helping you avoid costly administration of structure changes in multiple tables vs. a single structure change in one table.
  • Concurrency controls have been implemented automatically to help prevent unintended data destruction after a read and before an update.
  • If your table has columns for the "who and when" records are created and updated, those columns are automatically updated for you.

Includes interesting attributes:

  • accumulate_results
    • This causes every query's results to accumulate in the workarea, instead of replacing the prior contents.
  • auto_trunc
    • If true, strings that are longer than the table can support are automatically truncated.
  • lazy_get
    • This prevents an error from being thrown when reading columns that do not exist.
  • load_defaults
    • If true, the defaults specified by the table's metadata are automatically loaded whenever the following methods are called:
      • clear
      • clear_record
      • clear_all_records
      • add_record
  • qbe_additional_criteria
    • In cases where more than one qbe method is called and some criteria elements are always the same, this can reduce the size of the criteria specified in each qbe. This criteria automatically merges with every criteria specified in the qbe method. In cases where criteria column references match in the qbe_additional_criteria and qbe call, the criteria in the qbe will overwrite criteria in the qbe_additional_criteria. This allows for maximum readability and flexibility.

Be sure to check the documentation tab for the full list of methods.

 

  SIMPLE DATA SELECT EXAMPLES

  Simplest Possible Select

DESCRIPTION

This example returns all records for the specified table.

CODE

$oTable=db_table('product','ecom');
if ( $oTable->select()) {
	print dump($oTable->get_all_rows());
	print dump($oTable->get_last_sql());
} else
	print 'No data!';

OUTPUT

 - Expand/Collapse
$ => Array (10)
(
|    ['0'] => Array (16)
|    (
|    |    ['data_pool_id'] = Integer(1) 2
|    |    ['product_type'] = String(0) ""
|    |    ['product_subtype'] = String(0) ""
|    |    ['product_code'] = String(7) "IPOD4GB"
|    |    ['mfg_code'] = String(5) "APPLE"
|    |    ['product_name'] = String(10) "Apple iPod"
|    |    ['short_descr'] = NULL(0) NULL
|    |    ['long_descr'] = NULL(0) NULL
|    |    ['sales_tax_code'] = NULL(0) NULL
|    |    ['status'] = String(6) "ACTIVE"
|    |    ['web_status'] = String(6) "ONLINE"
|    |    ['addoper'] = NULL(0) NULL
|    |    ['adddate'] = NULL(0) NULL
|    |    ['modoper'] = NULL(0) NULL
|    |    ['moddate'] = NULL(0) NULL
|    |    ['concurrency'] = Integer(1) 0
|    )
|    ['1'] => Array (16)
|    (
|    |    ['data_pool_id'] = Integer(1) 2
|    |    ['product_type'] = String(10) "MEMBERSHIP"
|    |    ['product_subtype'] = String(7) "APP-FEE"
|    |    ['product_code'] = String(9) "MA-FELLOW"
|    |    ['mfg_code'] = NULL(0) NULL
|    |    ['product_name'] = String(26) "Fellowship Application Fee"
|    |    ['short_descr'] = NULL(0) NULL
|    |    ['long_descr'] = NULL(0) NULL
|    |    ['sales_tax_code'] = NULL(0) NULL
|    |    ['status'] = String(6) "ACTIVE"
|    |    ['web_status'] = String(6) "ONLINE"
|    |    ['addoper'] = NULL(0) NULL
|    |    ['adddate'] = NULL(0) NULL
|    |    ['modoper'] = NULL(0) NULL
|    |    ['moddate'] = NULL(0) NULL
|    |    ['concurrency'] = Integer(1) 0
|    )
|    ['2'] => Array (16)
|    (
|    |    ['data_pool_id'] = Integer(1) 2
|    |    ['product_type'] = String(10) "MEMBERSHIP"
|    |    ['product_subtype'] = String(4) "TYPE"
|    |    ['product_code'] = String(9) "MT-FELLOW"
|    |    ['mfg_code'] = NULL(0) NULL
|    |    ['product_name'] = String(13) "Fellow Member"
|    |    ['short_descr'] = NULL(0) NULL
|    |    ['long_descr'] = NULL(0) NULL
|    |    ['sales_tax_code'] = NULL(0) NULL
|    |    ['status'] = String(6) "ACTIVE"
|    |    ['web_status'] = String(6) "ONLINE"
|    |    ['addoper'] = NULL(0) NULL
|    |    ['adddate'] = NULL(0) NULL
|    |    ['modoper'] = NULL(0) NULL
|    |    ['moddate'] = NULL(0) NULL
|    |    ['concurrency'] = Integer(1) 0
|    )
|    ['3'] => Array (16)
|    (
|    |    ['data_pool_id'] = Integer(1) 2
|    |    ['product_type'] = String(10) "MEMBERSHIP"
|    |    ['product_subtype'] = String(4) "TYPE"
|    |    ['product_code'] = String(13) "MT-INDIVIDUAL"
|    |    ['mfg_code'] = NULL(0) NULL
|    |    ['product_name'] = String(17) "Individual Member"
|    |    ['short_descr'] = NULL(0) NULL
|    |    ['long_descr'] = NULL(0) NULL
|    |    ['sales_tax_code'] = NULL(0) NULL
|    |    ['status'] = String(6) "ACTIVE"
|    |    ['web_status'] = String(6) "ONLINE"
|    |    ['addoper'] = NULL(0) NULL
|    |    ['adddate'] = NULL(0) NULL
|    |    ['modoper'] = NULL(0) NULL
|    |    ['moddate'] = NULL(0) NULL
|    |    ['concurrency'] = Integer(1) 0
|    )
|    ['4'] => Array (16)
|    (
|    |    ['data_pool_id'] = Integer(1) 2
|    |    ['product_type'] = String(10) "MEMBERSHIP"
|    |    ['product_subtype'] = String(4) "TYPE"
|    |    ['product_code'] = String(11) "MT-INDUSTRY"
|    |    ['mfg_code'] = NULL(0) NULL
|    |    ['product_name'] = String(15) "Industry Member"
|    |    ['short_descr'] = NULL(0) NULL
|    |    ['long_descr'] = NULL(0) NULL
|    |    ['sales_tax_code'] = NULL(0) NULL
|    |    ['status'] = String(6) "ACTIVE"
|    |    ['web_status'] = String(6) "ONLINE"
|    |    ['addoper'] = NULL(0) NULL
|    |    ['adddate'] = NULL(0) NULL
|    |    ['modoper'] = NULL(0) NULL
|    |    ['moddate'] = NULL(0) NULL
|    |    ['concurrency'] = Integer(1) 0
|    )
|    ['5'] => Array (16)
|    (
|    |    ['data_pool_id'] = Integer(1) 2
|    |    ['product_type'] = String(10) "MEMBERSHIP"
|    |    ['product_subtype'] = String(4) "TYPE"
|    |    ['product_code'] = String(7) "MT-LIFE"
|    |    ['mfg_code'] = NULL(0) NULL
|    |    ['product_name'] = String(11) "Life Member"
|    |    ['short_descr'] = NULL(0) NULL
|    |    ['long_descr'] = NULL(0) NULL
|    |    ['sales_tax_code'] = NULL(0) NULL
|    |    ['status'] = String(6) "ACTIVE"
|    |    ['web_status'] = String(6) "ONLINE"
|    |    ['addoper'] = NULL(0) NULL
|    |    ['adddate'] = NULL(0) NULL
|    |    ['modoper'] = NULL(0) NULL
|    |    ['moddate'] = NULL(0) NULL
|    |    ['concurrency'] = Integer(1) 0
|    )
|    ['6'] => Array (16)
|    (
|    |    ['data_pool_id'] = Integer(1) 2
|    |    ['product_type'] = String(10) "MEMBERSHIP"
|    |    ['product_subtype'] = String(4) "TYPE"
|    |    ['product_code'] = String(10) "MT-RETIRED"
|    |    ['mfg_code'] = NULL(0) NULL
|    |    ['product_name'] = String(14) "Retired Member"
|    |    ['short_descr'] = NULL(0) NULL
|    |    ['long_descr'] = NULL(0) NULL
|    |    ['sales_tax_code'] = NULL(0) NULL
|    |    ['status'] = String(6) "ACTIVE"
|    |    ['web_status'] = String(6) "ONLINE"
|    |    ['addoper'] = NULL(0) NULL
|    |    ['adddate'] = NULL(0) NULL
|    |    ['modoper'] = NULL(0) NULL
|    |    ['moddate'] = NULL(0) NULL
|    |    ['concurrency'] = Integer(1) 0
|    )
|    ['7'] => Array (16)
|    (
|    |    ['data_pool_id'] = Integer(1) 2
|    |    ['product_type'] = String(10) "MEMBERSHIP"
|    |    ['product_subtype'] = String(4) "TYPE"
|    |    ['product_code'] = String(10) "MT-STUDENT"
|    |    ['mfg_code'] = NULL(0) NULL
|    |    ['product_name'] = String(14) "Student Member"
|    |    ['short_descr'] = NULL(0) NULL
|    |    ['long_descr'] = NULL(0) NULL
|    |    ['sales_tax_code'] = NULL(0) NULL
|    |    ['status'] = String(6) "ACTIVE"
|    |    ['web_status'] = String(6) "ONLINE"
|    |    ['addoper'] = NULL(0) NULL
|    |    ['adddate'] = NULL(0) NULL
|    |    ['modoper'] = NULL(0) NULL
|    |    ['moddate'] = NULL(0) NULL
|    |    ['concurrency'] = Integer(1) 0
|    )
|    ['8'] => Array (16)
|    (
|    |    ['data_pool_id'] = Integer(1) 2
|    |    ['product_type'] = String(10) "MEMBERSHIP"
|    |    ['product_subtype'] = String(8) "DISCOUNT"
|    |    ['product_code'] = String(15) "ONLINE_DISCOUNT"
|    |    ['mfg_code'] = NULL(0) NULL
|    |    ['product_name'] = String(15) "Online Discount"
|    |    ['short_descr'] = NULL(0) NULL
|    |    ['long_descr'] = NULL(0) NULL
|    |    ['sales_tax_code'] = NULL(0) NULL
|    |    ['status'] = String(6) "ACTIVE"
|    |    ['web_status'] = String(7) "OFFLINE"
|    |    ['addoper'] = NULL(0) NULL
|    |    ['adddate'] = NULL(0) NULL
|    |    ['modoper'] = NULL(0) NULL
|    |    ['moddate'] = NULL(0) NULL
|    |    ['concurrency'] = Integer(1) 0
|    )
|    ['9'] => Array (16)
|    (
|    |    ['data_pool_id'] = Integer(1) 2
|    |    ['product_type'] = String(0) ""
|    |    ['product_subtype'] = String(0) ""
|    |    ['product_code'] = String(11) "STUDIOXPS16"
|    |    ['mfg_code'] = String(4) "DELL"
|    |    ['product_name'] = String(13) "Studio XPS 16"
|    |    ['short_descr'] = NULL(0) NULL
|    |    ['long_descr'] = NULL(0) NULL
|    |    ['sales_tax_code'] = NULL(0) NULL
|    |    ['status'] = String(6) "ACTIVE"
|    |    ['web_status'] = String(6) "ONLINE"
|    |    ['addoper'] = NULL(0) NULL
|    |    ['adddate'] = NULL(0) NULL
|    |    ['modoper'] = NULL(0) NULL
|    |    ['moddate'] = NULL(0) NULL
|    |    ['concurrency'] = Integer(1) 0
|    )
)
 - Expand/Collapse
$ => Array (3)
(
|    ['count'] = Integer(2) 10
|    ['sql'] = String(47) "select * from `product` where `data_pool_id`=? "
|    ['values'] => Array (1)
|    (
|    |    ['0'] = Integer(1) 2
|    )
)
  Single Record Select with Data Pool

DESCRIPTION

So where's the data pool reference? That's right, we don't have to worry about it. It's defined in the $aEnv array which is read by the db_table function. The key is we don't ever have to worry about specifying it in our query. All of that is handled automatically by the class.

Notice in the select that we're specifying the primary key. If we don't specify it at all, we will get back all the records for the specified data pool configuration (as defined in the $aEnv array and as applicable). If the primary key is multi-column, we can specify a partial primary key and potentially get back multiple rows. If we specify the exact primary key we will get back 0-1 rows.

If the select returns at least one row, then print them all out, else complain.

CODE

$oTable=db_table('product','ecom');
if ( $oTable->select('IPOD4GB')) {
	print dump($oTable->get_all_rows());
	print dump($oTable->get_last_sql());
} else
	print 'No data!';

OUTPUT

 - Expand/Collapse
$ => Array (1)
(
|    ['0'] => Array (16)
|    (
|    |    ['data_pool_id'] = Integer(1) 2
|    |    ['product_type'] = String(0) ""
|    |    ['product_subtype'] = String(0) ""
|    |    ['product_code'] = String(7) "IPOD4GB"
|    |    ['mfg_code'] = String(5) "APPLE"
|    |    ['product_name'] = String(10) "Apple iPod"
|    |    ['short_descr'] = NULL(0) NULL
|    |    ['long_descr'] = NULL(0) NULL
|    |    ['sales_tax_code'] = NULL(0) NULL
|    |    ['status'] = String(6) "ACTIVE"
|    |    ['web_status'] = String(6) "ONLINE"
|    |    ['addoper'] = NULL(0) NULL
|    |    ['adddate'] = NULL(0) NULL
|    |    ['modoper'] = NULL(0) NULL
|    |    ['moddate'] = NULL(0) NULL
|    |    ['concurrency'] = Integer(1) 0
|    )
)
 - Expand/Collapse
$ => Array (3)
(
|    ['count'] = Integer(1) 1
|    ['sql'] = String(68) "select * from `product` where `data_pool_id`=? and `product_code`=? "
|    ['values'] => Array (2)
|    (
|    |    ['0'] = Integer(1) 2
|    |    ['1'] = String(7) "IPOD4GB"
|    )
)

  CONFIGURATION

  Specifying Database Credentials

Active Record is compatible with MySQL and SQL Server databases. Have a different database in mind? Let us know.

Before we go too much farther, let's simplify how an Active Record object is created through the db_table function.

$oCustomer=db_table('customer');

Pretty easy right?

Modify the db_table function to suit your needs, but here is the stock copy.

function db_table ( $tTable, $tSchema=null ) {
	global $aEnv;
	$oTable=new active_record($aEnv['active_record_args']);
	if ( isset($aEnv['schema_override']))
		$oTable->init_table(array('table'=>$tTable,'schema'=>$aEnv['schema_override']));
	else {
		if ( $tSchema === null )
			$oTable->init_table(array('table'=>$tTable));
		else
			$oTable->init_table(array('table'=>$tTable,'schema'=>$tSchema));
	}
	return $oTable;
}

The 'schema_override' element is useful if the schema you refer to in one environment is restricted to a single schema in another environment (shared hosting is a great example of where this might apply).

MySQL

The following code is an example of what a database credential array might look like for MySQL.

$aEnv['active_record_args']=array (
	'db_cred'=>array (
		'db_driver' => 'native:mysql',
		'db_server' => '127.0.0.1',
		'db_un' => 'myusername',
		'db_pw' => 'mypassword'
	)
);

SQL Server

Here is an example of what that array might look like for connecting to SQL Server.

$aEnv['active_record_args']=array (
	'db_cred'=>array (
		'db_driver' => 'odbc:sqlserver:SQL Server',
		'db_server' => 'SQLSVR',
		'db_database' => 'mydatabase',
		'db_un' => 'myusername',
		'db_pw' => 'mypassword' 
	)
);

You'll notice a third sub-parameter under db_driver in the example above. This is the name of the ODBC driver which defaults to "SQL Server" (which makes it unnecessary in this example -- you could just use 'odbc:sqlserver'). If your ODBC SQL Server driver has a different name, be sure to place that here.

  Data Pools

Data pools are completely optional. Please feel free to skip ahead to the next section.

Data pools as implemented by Active Record are records in a table grouped by data pool IDs. A column in the table is designated as the data pool ID column (data_pool_id by default). This column must be an integer. If your table's data pool column goes by a name other than 'data_pool_id', you can set it with set_attr('data_pool_id_column','your_column_name') or send it along in the 'attr' array when you create the object. If you choose to call set_attr, make sure you do this prior to calling the init_table method.

Once a data pool configuration has been specified, Active Record refers to the data pool ID column transparently. This means that:

  • Data selects (select, qbe) only refer to the data pool(s) allowed by the data pool configuration for selects.
  • Data inserts (insert, insert_or_update) only allow records to be inserted using the designated "insert" data pool ID. The designated "insert" data pool ID is settable via set_insert_data_pool and defaults to the first element of the data pool configuration for inserts. Any data pool ID in the data pool configuration for inserts can be set as the designated "insert" data pool ID.
  • Data updates (insert_or_update, update) only allow records to be updated that belong to the data pool(s) allowed by the data pool configuration for updates.
  • Data deletions (delete) only allow records to be deleted that belong to the data pool(s) allowed by the data pool configuration for deletes.

Sounds like a lot of flexibility, but it doesn't have to be complex.

The data pool configuration is an array which can take a variety of forms.

Remember that the 'data_pool_config' element is another element in the 'active_record_args' array, just like 'db_cred'.

$aEnv['active_record_args']=array (
	'db_cred'=>array (
		'db_driver' => 'native:mysql',
		'db_server' => '127.0.0.1',
		'db_un' => 'myusername',
		'db_pw' => 'mypassword'
	),
	'data_pool_config' => array ( 'data_pool_id' => 3 )
);

The simplest is:

array ( 'data_pool_id' => 3 )

This means set the select, insert, update and delete data pool arrays to a data pool ID of 3.

When 'data_pool_id' is set, this is shorthand for setting the select, insert, update and delete data pool arrays so you don't have to re-specify the same data pools for each data pool array type.

What if you had more than one data pool?

array ( 'data_pool_id' => array ( 3, 5, 8 ))

This would set the select, insert, update and delete data pool arrays equal to { 3, 5, 8 }.

What if one of the data pools is supposed to be read-only?

array (
	'data_pool_id' => array ( 3, 5 ),
	'select' => 8 )

This sets the select, insert, update and delete data pool arrays equal to { 3, 5 }.

An additional element is added to the select array for data pool ID 8. Notice that 8 wasn't referenced in 'data_pool_id' which makes it read-only.

A nonsense example

array (
	'data_pool_id' => array ( 3, 5 ),
	'select' => 8,
	'insert' => array ( 11, 15 ),
	'update' => array ( 1, 9 ),
	'delete' => 4 )

This sets the select data pool array to { 3, 5, 8 }, the insert data pool array to { 3, 5, 11, 15 }, the update data pool array to { 3, 5, 1, 9 }, and the delete data pool array to { 3, 5, 4 }.

You can specify the data pool configuration when you create the Active Record object (via 'data_pool_config' element in arguments array) or after instantiation through the init_data_pool method.

  Configuring Sequences

The sequence support as described here is completely optional. If you'd prefer to keep your existing setup whether it be via your own sequencing, auto-increment, etc. please feel free to skip ahead to the next section.

If you choose to have sequences managed from a table of sequence values, Active Record can help automate their creation. If a table supports sequences and data pools, the sequence counter for one data pool is independent from the sequence counter for a different data pool.

While you can use a sequence table and function of a different name (we use a function to get the next sequence), Active Record will expect certain columns to exist in the table.

MySQL SQL Server
Default Name for Sequence Table general.seq dbo.seq
Default Name for Sequence Function general.get_seq dbo.get_seq

As you may have guessed, the sequence table/function used depends on whether you're working with a MySQL or SQL Server table. This may not be desirable under all circumstances so please let us know if we need to make this more flexible.

It's important to note that if you change the name of the sequence table, in addition to specifying the new name in the 'attr' array when you create a new Active Record object (or using set_attr prior to init_table), you'll also need to change the reference to it in the sequence function.

If the table doesn't support data pools, the Active Record class sends a data pool of 0 to the sequence function.

-- --------------------------------------------------------------------------------
-- Routine DDL
-- Note: comments before and after the routine body will not be stored by the server
-- --------------------------------------------------------------------------------
DELIMITER $$

CREATE DEFINER=`root`@`localhost` FUNCTION `get_seq`(nDataPoolID int, tSchema varchar(50),
	tTable varchar(50), tColumn varchar(50)) RETURNS int(11)
begin
set @retval=0;

update	general.seq
set	next_value=@retval:=next_value+1
where	data_pool_id=nDataPoolID
and	schema_name=tSchema
and	table_name=tTable
and	column_name=tColumn;

return @retval-1;
end

The structure of the sequence table is as follows.

This is as one would expect with one enhancement -- the format column allows you to optionally format the value returned "sprintf style." A format value of "%08d" would yield a zero-padded number which might be useful for a uniform definition for customer IDs. A format value of "C%08d" would yield the same type of number format with a "C" in front...maybe to separate companies from individuals in a more deliberate manner. These are just a couple of ideas on how we've used the functionality in our own code -- you can do anything the sprintf function allows with respect to an integer value.

  Instantiating an Active Record Object

There are a couple of different arrays within the arguments array you should be aware of.

One array type is 'db_cred' as was described here.

Another array type is 'data_pool_config' which is optional and described here.

Another important type is 'attr' which is also optional and described here.

Consider simplifying each Active Record instantiation by grouping all the array types into a single array like this:

$aEnv['active_record_args']=array (
	'db_cred' => array (
		'db_driver' => 'native:mysql',
		'db_server' => '127.0.0.1',
		'db_un' => 'myusername',
		'db_pw' => 'mypassword' 
	),
	'data_pool_config' => array (
		'data_pool_id' => array ( 3, 5 ),
		'select' => 8 
	),
	'attr' => array (
		'sequence_table' => 'my_sequence',
		'sequence_function' => 'get_my_sequence' 
	)
);

In this way, each time you need to instantiate an Active Record class, you need only specify the following:

$oMyTable=new active_record($aEnv['active_record_args']);
$oMyTable->init_table(array('table'=>'product','schema'=>'ecom'));

Or, simply by using our db_table function:

$oMyTable=db_table('product','ecom');

Please note that just because you send 'data_pool_config' does not imply that the table must have data pool support. Feel free to send the extra information -- the object will use the information if it needs to, else it will ignore it.

 

Method Categories

Magic Methods

Private Methods

C

D, F

G

I

L

N, O, P, Q

R

S

T, U

  CONFIGURATION METHODS

Method Action/Info Returns
  __construct ( array args )

Creates PDO object and sets attributes.

Void

Notes: The PDO attribute(s) set are PDO:ATTR_CASE=>PDO::CASE_LOWER so all the column names are all lower-cased. This makes it easier for the class to make all column references case-insensitive for those methods that refer to columns. You can further define the PDO object used with get_db.

Argument list:

  • data_pool_config (array)
  • db_connect (object)
    • By default, a new PDO object is created for each active_record object.
    • If you want to share a database connection between multiple active_record objects, you can set db_connect to a PDO or active_record object.
  • db_cred (array, required)
    • db_database (string)
      • The database to use on the specified server
    • db_driver (string)
      • MySQL
        • native:mysql
      • SQL Server
        • odbc:sqlserver
        • odbc:sqlserver:SQL Server
          • The 3rd sub-parameter "SQL Server" is unnecessary as it defaults to "SQL Server", but if the name of your ODBC driver is not "SQL Server", specify its name here.
    • db_port (int)
      • MySQL
        • Defaults to 3306
      • SQL Server
        • Defaults to 1433
    • db_protocol (string)
      • SQL Server
        • Defaults to 'tcpip'
    • db_pw (string)
      • The database password to use
    • db_schema (string)
      • MySQL
        • Sets schema to use (init_table will need a schema if you don't specify this here)
      • SQL Server
        • Defaults to 'dbo'
    • db_server (string)
      • The database server to use:
        • 127.0.0.1
        • localhost
        • mysql.mydomain.com
        • sqlserver.mydomain.com
        • DEV-DB
        • PROD
    • db_un (string)
      • The database username to use
  • attr (array)
    • This is a series of attributes that could be set via set_attr, but may be more conveniently set here. Some examples of attributes you might want to set this way would be attributes that are always the same, but always different from their default values (like sequence_table and sequence_function).
  __destruct()

Destroys PDO object (unless borrowing a connection via constructor's db_connect argument)

Void

  __sleep()

Serializes everything except the PDO object

Void

  __wakeup()

Re-creates PDO object (unless borrowing a connection via constructor's db_connect argument)

Void

  init_data_pool ( array args )

Argument list (specify one or the other):

  • org_cust_id
    • If this is 0, then read/write access to all data pools (as defined in account.data_pool) is granted.
      • select data_pool_id, 0 as read_only from account.data_pool
    • If this is a specific org_cust_id, then only the specific access granted to data pools for that org_cust_id is granted.
      • select data_pool_id, read_only from account.org_cust_data_pool where org_cust_id={args['org_cust_id']}
  • data_pool_id
    • Sending a specific data pool id grants read/write access to that data pool.
Void
  init_table ( array args )

Imports table structure, PK and sequences. Calls clear_all_rows.

If this table uses data pools and a sequence definition exists for data pool 0 but no sequence for this data pool exists, one is automatically created. This check occurs for every sequenced column in the sequence definition for data pool 0.

Argument list:

  • schema (string)
    • This is not necessary if it's defaulted in the constructor (either by specifying it as an argument via db_schema or if it's defaulted automatically - as is the case with SQL Server, although you can still specify it to override the default).
  • table (string, required)
    • The name of the table
  • data_pool_config (array)
Void
  set_attr ( string attribute, var value )

Sets the specified attribute with the specified value

  • accumulate_results (boolean=false)
    • This causes every query's results to accumulate in the workarea, instead of replacing the prior contents.
  • add_oper_column (string='addoper')
    • If a table contains a column matching this name, then anytime a record is inserted, the value of the this column will be $_SESSION['username'] if it exists, else 'SYSTEM'.
  • add_date_column (string='adddate')
    • If a table contains a column matching this name, then anytime a record is inserted, the value of this column will be the server's date/time.
  • auto_trim (boolean=false)
    • Applies to the set method and more specifically, executes at the _set method level.
    • If true, trims string values of excess preceding and suffixing spaces.
    • If true, executes prior to auto_trunc attribute.
  • auto_trunc (boolean=false)
    • Applies to the set method and more specifically, executes at the _set method level.
    • If true, strings that are longer than the table can support are automatically truncated.
  • concurrency_column (string='concurrency')
    • If your table has concurrency control, this indicates which column is in charge of maintaining that concurrency. This column must be numeric, preferably an integer.
  • data_pool_id_column (string='data_pool_id')
    • If your table is segmented into data pools, this indicates which column is in charge of that segmentation.
  • lazy_get (boolean)
    • This prevents an error from being thrown when reading columns that do not exist.
  • load_defaults (boolean=false)
  • mod_oper_column (string='modoper')
    • If a table contains a column matching this name, then anytime a record is updated, it updates the value of this column to $_SESSION['username'] if it exists, else 'SYSTEM'.
  • mod_date_column (string='moddate')
    • If a table contains a column matching this name, then anytime a record is updated, it updates the value of this column to the server's date/time.
  • qbe_additional_criteria (array)
    • In cases where more than one qbe method is called and some criteria elements are always the same, this can reduce the size of the criteria specified in each qbe. This criteria automatically merges with every criteria specified in the qbe method. In cases where criteria column references match in the qbe_additional_criteria and qbe call, the criteria in the qbe will overwrite criteria in the qbe_additional_criteria. This allows for maximum readability and flexibility.
  • read_only (array=array('get_attr:data_pool_id','get_attr:concurrency_column'))
    • The 'get_attr:' prefix indicates that every time get_attr is called for 'read_only' it will execute get_attr on the attributes that follow. In this way, you can reference other attributes within an attribute. Only the 'read_only' attribute supports this feature.
  • select_suffix (string)
    • The intent of this attribute was to easily add "order by" clauses.
Void
  set_insert_data_pool ( int data_pool_id )

By default, the lowest value data pool ID in the "insert" data pool array is used for any insert operation.

If a different data pool ID is desired for inserts, use this method to set it.

True if this table has a data pool ID and the specified ID exists in the array of data pool IDs allowed for insertion, else false

  LINKED TABLE METHODS

Method Action/Info Returns
  link_detail_table ( active_record detail_table, var column_map )

Links another active_record object (detail) to this one (master).

If column_map is a string, then it is assumed we are only mapping a single column which is the same name in both tables.

If column_map is an array, it can consist of the following configurations per element:

  • column name
    • This implies that both master and detail tables have the referenced column name.
  • detail_column_name => master_column_name
    • These refer to different column names in the master and detail tables that must value match. These can of course be the same name, but it's more convenient to just specify the colum name once as described in the preceding bulletpoint.
  • detail_column_name => /string_value/
    • This is useful if you want to match a column in the detail table for a particular string value. A forward-slash prefix and suffix are necessary to differentiate this from a column name.
  • detail_column_name => value
    • If "value" is anything other than a string, then it is assumed to be a value you're attempting to match against.
Void
  link_master_table ( active_record master_table, var column_map )

Links another active_record object (master) to this one (detail). This is essentially the same thing as link_detail_table from the master table perspective.

If column_map is a string, then it is assumed we are only mapping a single column which is the same name in both tables.

If column_map is an array, it can consist of the following configurations per element:

  • column name
    • This implies that both master and detail tables have the referenced column name.
  • master_column_name => detail_column_name
    • NOTE: This column map option is the only difference in perspective from link_detail_table
    • These refer to different column names in the master and detail tables that must value match. These can of course be the same name, but it's more convenient to just specify the colum name once as described in the preceding bulletpoint.
  • detail_column_name => /string_value/
    • NOTE: The reason this isn't from a master column perspective is because it's always the detail table that feeds off the master table, not the other way around.
    • This is useful if you want to match a column in the detail table for a particular string value. A forward-slash prefix and suffix are necessary to differentiate this from a column name.
  • detail_column_name => value
    • NOTE: The reason this isn't from a master column perspective is because it's always the detail table that feeds off the master table, not the other way around.
    • If "value" is anything other than a string, then it is assumed to be a value you're attempting to match against.
Void
  refresh_detail_tables()

Re-queries all linked detail tables based on data in the current row of the workarea.

This method is called from the following methods:

Void

  ROW POINTER METHODS

Method Action/Info Returns
  first_row() Moves row pointer to first row True if not already on the first row, else false
  get_record_count() The number of records returned from the last select or qbe - if the accumulate_results attribute is used, then this is the cumulative number of records returned.
  get_row_count() The number of rows in the workarea - there is always at least one row in the workarea. Further, the workarea can be expanded and contracted by using the add_row and delete_row methods.
  get_row_index() The row pointer value (0 is the first row)
  last_row() Moves row pointer to last row True if not already on the last row, else false
  next_row() Moves row pointer to next row True if not already on the last row, else false
  offset_row ( int offset ) Moves row pointer up or down the specified number of rows - if offset is negative, this moves the pointer towards the first row, else this moves the pointer towards the last row. True if the row pointer actually moves from its current position, else false
  prev_row() Moves row pointer to previous row True if not already on the first row, else false
  select_all_rows() Selects all rows Void
  select_row ( int row=current_row ) Selects specified row Void
  set_row_index ( int row )
  toggle_row ( int row ) Selects specified row if it is not selected, un-selects specified row if it is selected Void
  unselect_all_rows() Un-selects any rows that were selected Void
  unselect_row ( int row ) Un-selects specified row Void

  META-DATA METHODS

Method Action/Info Returns
  get_attr ( string attribute )   The value of the desired attribute
  get_db() Each active_record object on __construct(), creates a PDO object it uses throughout its lifetime. This same PDO object is destroyed on __destruct(). Feel free to use this PDO object to further modify PDO object attributes or anything else you may need it for. The PDO object that represents this active_record object
  get_clear_row()   An array containing an empty record representation (default values are included if the 'load_defaults' attribute is set to true
  get_column()   An array with the column names
  get_data_pool ( string type=null )

Each data pool array is modeled after various SQL command (like select, insert, etc.). One or more integers may be present in each array which indicate which data pools may be affected by the associated SQL command.

  • select
  • update
  • delete
  • insert

The data pool(s) associated with this active_record object, else false if there is no data pool column in this object's specified table.

If a specific data pool type is requested then an integer array is returned, else an array of integer arrays.

  get_default ( string column=null )   The default value for the column (if specified), else an array containing an empty record representation including default values
  get_last_sql()   An array based on the last SQL operation containing integer 'count' (number of records returned/affected), string 'sql' (the SQL statement used), and array 'values' (an array of the values bound to the SQL)
  get_maxlength() This is a short-hand function for get_struct to return the maximum character length of the column sent.

e.g. get_struct('email','character_maximum_length');

The maximum length of the specified column in the table.
  get_pk()   An array containing the primary key column(s)
  get_schema()   The schema name of this table
  get_stmt() This object is refreshed whenever an SQL operation occurs (e.g. the select method calls the prepare, bindvalue, and execute methods of this object). The PDOStatement object that represents this active_record object
  get_struct ( string column=null, string attribute=null )
MySQL SQL Server
  • column_name
  • ordinal_position
  • column_default
  • is_nullable
  • data_type
  • character_maximum_length
  • character_octet_length
  • numeric_precision
  • numeric_scale
  • pk_ordinal_position
  • column_type
    • MySQL specific
  • extra
    • MySQL specific
  • normalized_type
  • column_name
  • ordinal_position
  • column_default
  • is_nullable
  • data_type
  • character_maximum_length
  • character_octet_length
  • numeric_precision
  • numeric_scale
  • numeric_precision_radix
    • `SQL Server specific
  • datetime_precision
    • SQL Server specific
  • pk_ordinal_position
  • normalized_type
If column is null, then return the full structure definition array for the table -- else if column is set, only return the structure definition array for that column -- else if attribute is also set, only return that specific attribute value (variant) of the specified column definition
  get_table()   The table name
  get_type ( string column=null, string attribute=null )

A normalized type is the mapping of a specific data type to a more general type. This allows for simpler, cross-database coding where data type has an effect and also makes it easier for 'apples-to-apples' comparisons between different databases.

The following shows the normalized data type followed by specific data types that are mapped to it. If the database already supports the normalized type as a specific type, the mapping is implied.

MySQL SQL Server
  • int
    • tinyint
    • smallint
    • mediumint
    • bigint
    • integer
  • real
    • float
    • double
  • boolean
    • bit
  • text
    • longtext
    • mediumtext
    • tinytext
  • datetime
    • date
  • decimal
    • money
    • smallmoney
  • char
    • nchar
  • text
    • ntext
    • xml
  • varchar
    • nvarchar
  • int
    • tinyint
    • smallint
    • bigint
  • datetime
    • smalldatetime
  • real
    • float
    • numeric
  • boolean
    • bit

If column is null, returns all type information for all columns in an array of arrays. If column is specified, returns all type information for the specified column in an array, else if attribute is specified, only return the specified type attribute for the specified column.

  • data_type
    • This is the native data type for the database
  • normalized_type
    • This is a normalized version of the data type
  • param_type
    • This is the type used in the bindvalue method.
      • Default is PDO::PARAM_STR
      • normalized_type ( int, real, decimal ) yields PDO::PARAM_INT
      • normalized_type ( boolean ) yields PDO::PARAM_INT (MySQL), PDO::PARAM_BOOL (SQL Server)

 

  WORKAREA METHODS

Method Action/Info Returns
  clear ( string column, int row=current_row )

Clears the column at the specified row

Void

  clear_all_rows()

Replaces the workarea with a single, cleared row

Void

  clear_row ( int row=current_row )

Clears the row specified

Void

  delete_row ( int row=current_row ) Deletes the specified row in the workarea - at a minimum, one clear row will remain Void
  get ( string column, int row=current_row )

The value of the specified column at the specified row

  get_all_pk_values()

An array of the primary key values for all records

  get_all_rows()

The entire workarea array

  get_column_values ( string column )

An array of all values for the specified column

  get_max ( string column )

Largest number in workarea for the specified column

  get_min ( string column )

Smallest number in workarea for the specified column

  get_pk_values ( int row=current_row )

An array of the primary key values for the specified row

  get_row ( int row=current_row )

The workarea array at the specified row

  get_sum ( string column ) The sum of the specified column in the workarea
  insert_row() Adds a new row to the end of the workarea - this does not adjust get_record_count but does adjust get_total_rows. Void
  revert_rows()

Reverts the workarea to the state it was in after the last query. This could be helpful if changes were made to the workarea that were no longer desired (without having to re-query the information).

The "accumulate_results" attribute must be false for this to work (which it is by default).

True if the "accumulate_results" attribute is false (which it is by default), else false
  set ( string column, var value, int row=current_row )

The column is set if the following conditions are true.

  1. It is not a read-only column that was just read from the database.
  2. The column exists in the table

True if the column was set, else false

  set_seq ( string column, int row=current_row )

This method is special in that it refers to the general.get_seq custom database function to get the next sequence. Once that is retrieved, it optionally formats the value per general.seq.format string via sprintf formatting rules. This is useful (for example), to zero-pad the string automatically and consistently.

general.get_seq custom database function snippet:

update	general.seq
set	next_value=@retval:=next_value+1
where	data_pool_id=nDataPoolID
and	schema_name=tSchema
and	table_name=tTable
and	column_name=tColumn;

return @retval-1;

As you can see, while the update statement increments the value, it also sets the return value to that new value – all within the same SQL statement. It is a trivial thing to subtract one from this value – which now represents what the next value “used” to be. This seems to be a very clean way to guarantee that no 2 processes get the same “next value”.

Important: Keep in mind that you shouldn’t normally need to use the set_seq method. This is because the insert method automatically calls the set_seq method on sequenced columns that are null. If however, you plan on doing a lot of inserts – it may be more efficient (and clear) to call set_seq rather than nulling the column(s) or clearing the entire workarea with clear_all_rows.

The sequence value set to the specified column or a false if the column wasn’t settable (see set rules) or the column is not specified as a sequenced column

  DATA SELECT/CHANGE METHODS

Method Action/Info Returns
  insert ( int row=current_row )

Inserts a new record with the information specified by the specified row in the workarea.

If a data pool column exists and is null, it will be populated with the assigned insert data pool id.

If the add operator column exists, it will be populated with the $_SESSION['username'] value if it exists, else 'SYSTEM'.

If the add date column exists, it will be populated with the server's date/time.

If the concurrency column exists, it will be populated with a 0 value.

Any sequenced columns that are null will be populated with the next sequenced value.

True on successful insert, else false

Since failure can only be determined when the SQL is executed, the workarea is saved prior to any content change (data pool, sequenced columns, add date, etc.) and restored on failure.

The caveat is even though the row is restored to its original contents prior to the call, sequences that would have been committed to the database on success are effectively lost.

  delete ( int row=current_row )

If data pools are being used in this table, a check is made to see if the data pool represented in the row is a data pool we have rights to delete from.

The intended use of this method is to read the record in first, then issue a delete on it.

This method does not respect concurrency. If the concurrency read is different from the concurrency in the table, the record is deleted.

True on successful delete, else false
  delete_selected() This method calls the delete method for each selected row Void
  insert_or_update( int row=current_row ) This method attempts to insert the specified row first. If that fails, it attempts to update the row. True if successful create/update, else false
  load ( array primary_key )
This method loads up the workarea with records matching the array of primary keys sent. Each row in the array is a call to the select method in accumulate mode. The accumulate_results attribute's value is saved and temporarily set to true prior to the method looping through the array. After it's finished, the accumulate_results attribute's value is restored to its value prior to the call. Void
  qbe ( array criteria )

The basic criteria format is a column/value pair for equality comparisons.

qbe ( array (	
	'city' => 'Chicago',
	'state' => 'IL' ));

If a different operator is desired, the format is similar:

qbe ( array (
	'customer_id' => 2993,
	'amount' >= array ( 'operator' => '>', 'value' => 100 ),
	'order_date' => array ( 'operator' => '<', 'value' => new DateTime()),
	'status' => array ( 'operator' => '<>', 'value' => 'COMPLETED' ))) 

The order of inspection on the value:

  1. If the value is a null, then substitute "is not" if the operator is '<>' -- else substitute "is".
  2. If the value is an array, then wrap the deeper comparison in parenthesis and chain the deeper comparison(s) together with "or".
  3. If the value has a % sign at the beginning and/or the end, then substitute "not like" if the operator is '<>' -- else substitute "like".
True on successful select of at least one row, else false
  raw_sql ( string sql )

Useful for shooting a quick SQL statement through the existing PDO connection.

This bypasses most of the active_record functionality including the workarea. Use the return value or get_stmt method to fetch data. Works with get_last_sql method.

Return value from get_stmt method if successful, else false
  recurse ( array criteria, array column_map )   True if the "accumulate_results" attribute is true, else false
  recurse_pk ( array criteria, array column_map )    
  select ( var pk1, var pk2, var pk3, ... )

- or -

select ( array pk_array )

Selects data from the current table based on primary key values sent.

This method expects you to send the primary key values in their respective ordinal position, but does not expect more than one primary key value.

This method will interpret the % sign as a "like" operation if the value is prefixed and/or suffixed with it.

True if at least one record selected, else false
  subquery ( array criteria ) Conducts a simple subquery on the rows in the workarea (applies only to rows selected from the table, not added manually with insert_row). Argument structure similar to qbe, but no support for "like" (%) or "or" logic. All logic is "and". An array of rows matching the specified criteria
  update( int row=current_row )

Updates an existing record with the information specified by the specified row in the workarea.

There must be at least one column in the workarea for the specified row that has changed. This might be a bad idea if you're checking the return code (false) and expecting that maybe the table was updated through an alternate means -- however, it's nice from the perspective of not performing an unnecessary update.

This method can handle a change in primary key values.

If the modified operator column exists, it will be populated with the $_SESSION['username'] value if it exists, else 'SYSTEM'.

If the modified date column exists, it will be populated with the server's date/time.

If the concurrency column exists, it will be populated with a 0 value.

True on successful update, else false

Since failure can only be determined when the SQL is executed, the workarea is saved prior to any content change (modified operator/date, concurrency, etc.) and restored on failure.

  POWER METHODS

Method Action/Info Returns
  backup_selected ( string label ) Serializes (via XML) all selected rows in the workarea and writes them to general.xml_storage. The label argument allows you to tie together many recordsets from many different active_record objects. True if record successfully created, false if not. Returns true if no rows selected.
  generate_form ( array args )

Arguments list:

  • action (string)
    • The action attribute of the form tag.
    • If omitted and the current page ends with ".php" then it will be modified to include "_post" prior to the ".php" -- else the current page is used.
  • attributes (array)
    • column_name (array)
      • This is an array of key/values where the key is the name of the attribute and the value is the value of it. Applies only to textarea fields which appear with normalized types of "text".
  • current_row (int)
    • Defaults to 0.
  • form_dependence_mode (boolean)
    • If true, then this is part of a larger form, else form tags will be generated.
  • hidden_fields (array)
    • An array of column names that are not to be shown
  • hidden_values (array)
    • A set of key/values that populate hidden fields
  • html (array)
  • labels (array)
    • column_name (array)
      • A set of key/value pairs where key=column_name and value="Label"
      • If a column is not represented here, the default representation is the english interpretation of the column.
  • max_size (int)
    • Renders the size attribute of input tags of type text and password to a maximum size. If maximum size of the table column is smaller than this value, then the maximum size of the table column is used.
  • mode (string)
    • "insert"
      • Form is for the purpose of creating a new record, so no fields are pre-populated with any data from an existing record in the workarea
    • "update"
      • Assumes a record update form so fields are pre-populated with existing data from a record in the workarea
    • "read_only"
      • This is a way to leverage the form generator method in a way that produces no form fields, just yields the values from an existing record in the workarea.
  • multi_row
    • extra_rows
      • Adds extra rows (rows for inserting new data rows) to the end of the form
    • max_rows
      • Limits maximum number of rows - will enforce maximum row limit even if number of selected rows is greater - this could also result in 0 rows for inserting new data
    • max_rows_soft
      • Limits maximum number of rows, but if over maximum, still allows all selected rows + 1 insert row -- so this is not a true limit in that sense
    • min_rows
      • Ensures no matter how few selected rows, there will be a minimum number of rows - yields to max_rows
    • links
  • omitted_fields
  • read_only_fields
  • redirect
    • success
    • failure
  • submit (string)
    • Determines text of submit button
    • If omitted, defaults to "Create Table Name" or "Update Table Name" (depending on the value of the mode argument) where "Table Name" is the english conversion of the actual table name.
  • table_dependence_mode (boolean)
    • If true, then this is part of a larger table, else table tags will be generated.
  • values
    • column_name
The HTML generated
  set_row ( array args, int row=current_row )
  Void

  PRIVATE METHODS

Method Action/Info Returns
  _cast_type ( string column, var value )

This is the gateway of data type conversion from the database to PHP. To simplify things, the normalized type is used to determine the conversion as follows:

  • real
    • Cast to a PHP float
  • decimal
    • Cast to a PHP float
  • int
    • Cast to a PHP int
  • datetime
    • If already a PHP DateTime object, then nothing is changed
    • If a string:
      • If the value equals 'getdate()' then creates a new DateTime object (the current datetime)
      • else, create DateTime object based on value sent
  • boolean
    • If value equals 1, then set to True
    • Else, set to False
  • all others
    • The value sent "as is"

A conversion of the value sent to the appropriate PHP type

See also: _format_value

  _delete_allowed ( boolean delete, int row )  

The boolean value sent unless the table has a data pool column -- if a data pool column exists for table and the data pool configuration for that data pool does not allow deletes, then returns false, else returns the boolean value sent.

Used by: delete

  _delim ( string value )

MySQL uses an accent (`) for both left and right delimiters where SQL Server uses left and right brackets for delimiters.

Delimiters are used to wrap table and column names to ensure they do not get confused with any of the database's keywords.

The value sent wrapped by delimiters used by the database used

  _empty_array ( var value=null )  

An array keyed by table column names populated by the value sent

Used by: get_clear_row, clear_row, clear_all_rows, insert_row, _execute_query_and_populate_buffers

  _execute_query_and_populate_buffers()

This method deals with everything that needs to happen after a data selection query has been built, but not yet sent.

  • accumulate_results attribute
  • workarea array
  • control array
  • original primary key array
  • counts (record count and total rows)
  • refreshing detail tables

True if no errors and at least one record was returned, else False

Used by: select, qbe

  _format_value ( string column, var value )

This method converts a PHP type/value to an equivalent type/value the database would expect based on the normalized type:

  • datetime
    • If DateTime object, then format as string via DateTime format method 'Y-m-d H:i:s'
  • boolean
    • If True, then format as 1 (integer), else 0 (integer)
  • all others
    • The value sent "as is"

The PHP value converted for the database

See also: _cast_type

  _restore_row_state ( array row_state, int row )
This is used by the insert method as a way to restore the state of the specified row if the insert operation fails. See _store_row_state for more information. Void
  _set ( string column, var value, int row=current_row )
This is the lowest level method for setting a value to a row/column in the workarea. It is responsible for administering the effect of the auto_trim attribute, the auto_trunc attribute, preserving original primary key values, converting the sent value into the appropriate PHP type per the normalized database type, and setting the control array to "S" (set) for the specified column and row.

Void

Used by: insert, set, set_seq, update

  _settable ( string column, int row=current_row )

Determines set-ability based on the following criteria:

  • Read-only columns are not settable if they have been selected from the database (control status='R').
  • Columns that do not exist are not settable.

True if column is settable on that row, else false

Used by: set, set_seq

  _store_row_state ( int row )

This is used by the insert method as a way to store the row's state prior to auto-setting various special column values (data pool, sequenced columns, date added, etc.) which occurs prior to attempting to perform the actual insert. If the insert fails for any reason, the insert method uses _restore_row_state with the return value of this method.

This method and its sister method (_restore_row_state) may be used by other methods for similar reasons.

An array holding the workarea and control information for the specified row.

  • work
  • control
  _update_allowed ( boolean update, int row )

The boolean value sent unless the table has a data pool column -- if a data pool column exists for table and the data pool configuration for that data pool does not allow updates, then returns false, else returns the boolean value sent.

Used by: update

Please read this software license agreement carefully. By clicking the "I Agree" button at the bottom of this agreement, you acknowledge that you have read and understand this agreeement and agree to be bound by its terms and conditions. If you do not agree to these terms, please click the "I Disagree" button.

Software License Agreement

YOU MUST READ AND AGREE TO THE TERMS OF THIS SOFTWARE LICENSE AGREEMENT BEFORE SOFTWARE CAN BE DOWNLOADED OR INSTALLED OR USED. BY DOWNLOADING SOFTWARE, OR INSTALLING SOFTWARE, OR USING SOFTWARE, OR CLICKING ON THE "ACCEPT" BUTTON OF THIS SOFTWARE LICENSE AGREEMENT, YOU ARE AGREEING TO BE BOUND BY THE TERMS AND CONDITIONS OF THIS SOFTWARE LICENSE AGREEMENT. IF YOU DO NOT AGREE WITH THE TERMS AND CONDITIONS OF THIS SOFTWARE LICENSE AGREEMENT, YOU SHOULD NOT DOWNLOAD OR INSTALL OR USE SOFTWARE. BY DOING SO, YOU FOREGO ANY IMPLIED OR STATED RIGHTS TO DOWNLOAD OR INSTALL OR USE SOFTWARE. IF YOU ARE AGREEING TO THIS SOFTWARE LICENSE AGREEMENT ON BEHALF OF A COMPANY, YOU REPRESENT THAT YOU ARE AUTHORIZED TO BIND THE COMPANY TO THIS SOFTWARE LICENSE AGREEMENT.

DEFINITIONS
For the purpose of this Software License Agreement, the following terms shall have the following meanings:

  • "SLA" means this software license agreement in its entirety
  • "Software" means the Active Record PHP class, supporting code, and example code in source code form (including obsfucated and encrypted source code) and associated documentation that are included in any source files or web site pages that may be downloaded from the cinchapps.com web site
  • "Licensor" refers to the owner of the Software, Tom Wesson d/b/a CINCH-APPS.
  • "Licensee" means the company, entity or individual who submits the registration form at the end of this Software License Agreement, or on whose behalf such registration form is submitted.

1. This is an agreement between Licensor and Licensee, who is being licensed to use the named Software.

2. Licensee acknowledges that this is only a limited nonexclusive license. Licensor is and remains the owner of all titles, rights, and interests in the Software.

3. This SLA permits Licensee to install the Software on more than one computer system, as long as the Software will not be used on more than one computer system simultaneously. Licensee will not make copies of the Software or allow copies of the Software to be made by others, unless authorized by this SLA. Licensee may make copies of the Software for backup purposes only.

4. Licensee may not modify or change the Software in any manner.

5. Licensee acknowledges that while Licensor may offer limited support and maintenance, Licensor is under no obligation to offer said support and/or maintenance of the Software.

6. This Software is subject to a limited warranty. Licensor warrants to Licensee that the physical medium on which this Software is distributed is free from defects in materials and workmanship under normal use, the Software will perform according to its printed documentation, and to the best of Licensor's knowledge Licensee's use of this Software according to the printed documentation is not an infringement of any third party's intellectual property rights. This limited warranty lasts for a period of 30 days after delivery. To the extent permitted by law, THE ABOVE-STATED LIMITED WARRANTY REPLACES ALL OTHER WARRANTIES, EXPRESS OR IMPLIED, AND LICENSOR DISCLAIMS ALL IMPLIED WARRANTIES INCLUDING ANY IMPLIED WARRANTY OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, OR OF FITNESS FOR A PARTICULAR PURPOSE. No agent of Licensor is authorized to make any other warranties or to modify this limited warranty. Any action for breach of this limited warranty must be commenced within one year of the expiration of the warranty. Because some jurisdictions do not allow any limit on the length of an implied warranty, the above limitation may not apply to this Licensee. If the law does not allow disclaimer of implied warranties, then any implied warranty is limited to 30 days after delivery of the Software to Licensee. Licensee has specific legal rights pursuant to this warranty and, depending on Licensee's jurisdiction, may have additional rights.

7. In case of a breach of the Limited Warranty, Licensee's exclusive remedy is as follows: Licensee will return all copies of the Software to Licensor, at Licensee's cost, along with proof of purchase. (Licensee can obtain a step-by-step explanation of this procedure, including a return authorization code, by contacting Licensor at CINCH-APPS, P.O. Box 1032, Lombard, IL 60148, (630) 376-6566.) At Licensor's option, Licensor will either send Licensee a replacement copy of the Software, at Licensor's expense, or issue a full refund.

8. Notwithstanding the foregoing, LICENSOR IS NOT LIABLE TO LICENSEE FOR ANY DAMAGES, INCLUDING COMPENSATORY, SPECIAL, INCIDENTAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL DAMAGES, CONNECTED WITH OR RESULTING FROM THIS SLA OR LICENSEE'S USE OF THIS SOFTWARE. Licensee's jurisdiction may not allow such a limitation of damages, so this limitation may not apply.

9. Licensee agrees to defend and indemnify Licensor and hold Licensor harmless from all claims, losses, damages, complaints, or expenses connected with or resulting from Licensee's business operations.

10. Licensor has the right to terminate this SLA and Licensee's right to use this Software upon any material breach by Licensee.

11. Licensee agrees to return to Licensor or to destroy all copies of the Software upon termination of the License.

12. This SLA is the entire and exclusive agreement between Licensor and Licensee regarding this Software. This SLA replaces and supersedes all prior negotiations, dealings, and agreements between Licensor and Licensee regarding this Software.

13. If any provision of this SLA shall be held to be invalid or unenforceable for any reason, the remaining provisions shall continue to be valid and enforceable.  If a court finds that any provision of this SLA is invalid or unenforceable, then such provision shall be deemed to be written, construed, and enforced as so limited.

14. The failure of Licensor to enforce any provision of this SLA shall not be construed as a waiver or limitation of Licensor's right to subsequently enforce and compel strict compliance with every provision of this SLA.

15. This SLA is governed by the law of Illinois applicable to Illinois contracts.

16. This SLA is valid without Licensor's signature. It becomes effective upon the earlier of Licensee's signature or Licensee's use of the Software.

By clicking the "I Agree" button, you acknowledge that you have read and understand this agreement and agree to be bound to its terms and conditions. If you do not agree to these terms, please click "I Disagree".


(Your account activation and subsequent software download instructions will be e-mailed to this address.)
     

CINCH-APPS

Copyright © 2012 CINCH-APPS