==================================================

(c) Softerra LLC 2000, 2001

==================================================
1. Classes and Functions


1.1. MySQL DB support 

#
# lib.cfg.php          - library configuration settings
#

This file contains some predefined variables for the library.
The variable names are self-explanatory we refer to lib.cfg.php file.


#
# corban.lib.php       - debug output library
#

Displays queries and data for debugging purposes

/*
cd ($val, $name=0, $comment=0, $die=false)	{ alias for corban_dear () }
ci ($name=0) 				        { alias for corban_inittimer () }
cs ($name=0, $comment=0)			{ alias for corban_showtimer () }
*/

/*
corban_dear ($val, $name=0, $comment=0, $die=false)
$val - variable
$comment - some comment text (on the right)
$name - variable name (if you wish to see it - the most right)
$die - to die or not after displaying
*/
Shows specified variable.

/*
corban_inittimer ($name=0)
$name - timer name
*/
Inits the specified timer. (To start mesure SQL queries timings)

/*
corban_showtimer ($name=0, $comment=0)
$name - timer name
$comment - some comment text (on the right)
*/
Displays timer value.


#
# sqlcompose.lib.php   - query compose library
# 
# Contains basic function to create SQL queries
#

/*
function quotedValue ($value)
*/
Returns quoted $value with slashed symbols:
single quote ('), double quote ("), backslash (\) and NUL (the null byte).

/*
function prepareValueOrExpression (&$value)
$value - 
function prepareValuesOrExpressions (&$values)
$value - array
*/
These functions prepare value(s) for using in SQL statements.

/*
function withTablePrefix ($fields, $table)
$fields - array of fields
$table - name of the table
*/
Adds table name to the fields.

/*
function composeInsertQuery ($table, $values)
function composeUpdateQuery ($table, $values, $conditions)
function composeSelectQuery ($tables, $fields, $conditions)
function composeDeleteQuery ($table, $conditions)

$table - table name. (May be array for Select)
$values - value array where indexes are field names
$fields - fields array
$condition - string or array. If array - indexes are field names.
*/
Compose insert/delete/update/select queries.

/*
function simpleConditions ($conditions)
$conditions - string or array
*/
Produces condition of SQL query. Here will be used '=' and 'like'
operations with logical operation AND.

/*
function complexConditions ($conditions, $operations)
$conditions - array of structures: $field, $value
$operations - array of structures: $relation, $value (consequent list of logical operations)
*/
Produces condition of SQL query. Here will be used operations specified
by arrays (like, =, <, >, <>, <=, >=, in, not in, between, not between).

/*
function homogenicConditions ($conditions, $relation="=", $operation="and")
function equalityConditions ($conditions)
$conditions - array of structures: $field, $value
*/
Produces condition of SQL query.
In equalityConditions will be used '=' and 'like' operations depending on $value type.
In homogenicConditions will be used specified operations.
/*
function composeQueryConditions ($conditions, $type=CND_EQUALITY, $limit=0, $parameters=0)
$conditions - array of structures: $field, $condition, $value
$type - CND_COMPLEX or CND_HOMOGENIC or CND_EQUALITY
$limit - array of two elements (start, end)
$parameters - 
*/
Produces condition section of SQL query.


#
# sqlsearch.lib.php    - search library
#

Library for search in database by keywords
The synatax is similar to Altavista
 e.g.: word1 word2 +word3 -word4 "word5 word6"
 +  with this word
 -  without this word
 ?  any character
 *  any sequence of characters


#
# sqlstorage.class.php - DB access class
#

In this file we collect functions which works with SQL.
Here's full list:
    function getServer ()
    function debugOn ()
    function debugOff ()
    function connect ($host, $user, $password, $name)
    function close ()
    function select_db ($database)
    function list_dbs ()
    function list_tables ($database=0)
    function list_fields ($table, $database=0)
    function error ()
    function free_result ()
    function query ($query)
    function affected_rows ()
    function select ($tables, $fields="*", $conditions=0)
    function update ($table, $values, $conditions=0)
    function insert ($table, $values)
    function delete ($table, $conditions=0)
    function result ($row=0, $field=0) {
    function num_rows ()
    function num_fields ()
    function fetch_row ()
    function fetch_array ()
    function fetch_object ($type=0)
    function fetch_field ($offset)
    function fetch_fields ()
    function fetch_result ($format=fmtRow)
    function fetch_rows ()
    function fetch_arrays ()
    function fetch_objects ()
    function insert_id ()
    function queryresult_exists ()
    function queryresult_record ()
    function queryresult_column ()
    function select_exists ($tables, $conditions=0)
    function select_count ($tables, $conditions=0)
    function select_record ($tables, $fields, $conditions=0)
    function select_row ($tables, $fields, $conditions=0)
    function select_column ($tables, $fields, $conditions=0)
    function select_result ($tables, $fields, $conditions=0, $format=fmtArr)
    function search ($expression, $table, $field="", $fields="*", $type=SQL_PATTERN, $limit=0)

1.2. Grid class
        
#
# grid3.lib.php        - DB grid drawing
#

Here's an example of using grid without Registry:
(in the example directory we used Registry to store all these values)

==== START =================================================================================
	$ExtraColumnPatterns  = array(
		"<a href='subdep.php?depid=%d'>View Sdep.</a>",
		"<a href='depedit.php?mode=update&depid=%d&sf=$sf&sr=$sr&d=$d'>edit</a>",
		"<a href='depedit.php?mode=delete&depid=%d&sf=$sf&sr=$sr&d=$d'
			onclick='return confirm($WarningMessage);'>del</a>");
	$ExtraColumnVariables = array("DEP_ID","DEP_ID","DEP_ID");

	class depGrid extends softerraGrid
	{

		function depGrid ($cusid)
		{
			// call parent constructor
			global $session_uid;
			global $session_type;
			global $print;

			$this->softerraGrid ("",false);
			$this->sFormName = "dep"; 

			// set query
			$this->vQryTable  = array (TBL_DEPS);
			$this->aQryFields = array ("AS400_ID", "DEP_NAME", "DEP_ID");
			$this->vQryConditions = "WHERE CUSID=". $cusid ." AND PARENT_DEP=0 GROUP BY DEP_ID";
			$this->nBodyColCount = 2;
				
			$this->sTableAttributes = TABLE_ATTRUBUTES;
			$this->sNavigAttributes = NAVIGATION_ATTRIBUTES;

			if (isset($print)) $this->nExtraColCount = 0;
			else $this->nExtraColCount = 3;

			$this->sOddRow = BODY_ODD_ROW;
			$this->sEvenRow = BODY_EVEN_ROW;

			$this->sNavigLeftCell = NAVIG_LEFT_CELL_ATTRIBUTES;
			$this->sNavigCenterCell = NAVIG_CENTER_CELL_ATTRIBUTES;
			$this->sNavigRightCell  = NAVIG_RIGHT_CELL_ATTRIBUTES;

			$this->aBodyColumns[DEFAULT_KEY] = array ();
			$this->aBodyColumns[DEFAULT_KEY][COLUMN_TITLE_KEY] = COLUMN_TITLE_DEFAULT;
			$this->aBodyColumns[DEFAULT_KEY][TITLE_ATTRS_KEY] = COLUMN_TITLE_ATTRIBUTES ;
			$this->aBodyColumns[DEFAULT_KEY][TITLE_HREF_ATTRS_KEY] = COLUMN_HREF_TITLE_ATTRIBUTES ;
			$this->aBodyColumns[DEFAULT_KEY][BODY_ATTRS_KEY] = COLUMN_BODY_ATTRIBUTES;
			$this->aBodyColumns[DEFAULT_KEY][HTML_ATTRS_KEY] = COLUMN_HTML_ATTRIBUTES;
			for ($i=0; $i<$this->nBodyColCount; $i++)
			{
				$this->aBodyColumns[$i][TITLE_ATTRS_KEY] = COLUMN_TITLE_ATTRIBUTES;
				$this->aBodyColumns[$i][TITLE_HREF_ATTRS_KEY] = COLUMN_HREF_TITLE_ATTRIBUTES ;
				$this->aBodyColumns[$i][BODY_ATTRS_KEY] = COLUMN_BODY_ATTRIBUTES;
				$this->aBodyColumns[$i][HTML_ATTRS_KEY] = 0;
			}

			$this->aExtraColumns[DEFAULT_KEY] = array ();
			$this->aExtraColumns[DEFAULT_KEY][TITLE_ATTRS_KEY] = EXTRACOLUMN_TITLE_ATTRIBUTES ;
			$this->aExtraColumns[DEFAULT_KEY][BODY_ATTRS_KEY] = EXTRACOLUMN_BODY_ATTRIBUTES;
			$this->aExtraColumns[DEFAULT_KEY][EXTRA_COLUMN_TYPE_KEY] = EXTRA_COLUMN_RIGHT;

			$this->aExtraColumns[LEFT_EXTRA_KEY]  = RIGHT_EXTRACOLUMN_ATTRIBUTES;
			$this->aExtraColumns[RIGHT_EXTRA_KEY] = RIGHT_EXTRACOLUMN_ATTRIBUTES;

			$this->sNoDataMessage = "<b>Departments table is empty</b>";
		}
	}

	$grid = new depGrid($session_cusid);

	for ($i=0; $i<$grid->nBodyColCount; $i++)
		$grid->aBodyColumns[$i][COLUMN_TITLE_KEY] = $ColumnTitles[$i];

	for ($i=0; $i<$grid->nExtraColCount; $i++)
	{
	$titleattrs = EXTRACOLUMN_TITLE_ATTRIBUTES;
	$bodyattrs  = EXTRACOLUMN_BODY_ATTRIBUTES;
	$pattern    = $ExtraColumnPatterns[$i];
	$variables =  explode(",",$ExtraColumnVariables[$i]);

	$grid->aExtraColumns[EXTRA_COLUMN_RIGHT][] = array (
		TITLE_ATTRS_KEY => $titleattrs,
		BODY_ATTRS_KEY => $bodyattrs,
		EXTRA_TEXT_PATTERN_KEY => $pattern,
		EXTRA_VARIABLES_KEY => $variables);
	}

At last we describe our grid.... Wow!
Now we need only call drawing function:

	$grid->renderGrid();
	
That's all!

1.3. Registry

#
# registry.lib.php     - Registry support library
# example/regedit.php  - Registry editor
#

You can store variables in the DB instead of file. This allow you change them via
RegistryEditor (i.e. via HTTP. Just imagine you needn't upload file on server if you want
change the value of the variable from 1 to 2).

This table will contain all variables

========== start ================
CREATE TABLE REGISTRY (
   REGKEY varchar(255) NOT NULL,
   VALUE text NOT NULL,
   PRIMARY KEY (REGKEY)
);
========== end ================

As you can see the only limitation is REGKEY length. So you should choose short names for
your keys.

Registry editor in most cases the only tool you need to use rRegistry in you project.

Registry support library contains all the functions you need to work with Registry:
    function REG_CONNECT ($host=REGISTRY_HOST, $user=REGISTRY_USER, $password=REGISTRY_PASSWORD, $database=REGISTRY_DATABASE)
    function REG_EXIT ($result, $error)
    function regLastError ()
    function regValidName ($name)
    function regValidKey ($key)
    function regNameFromKey ($key)
    function regPathFromKey ($key)
    function regKeyFromPathAndName ($path, $name)
    function regExplodeKey ($key)
    function regKeyExists ($key)
    function regCreateKey ($key)
    function regDeleteKey ($key)
    function regRenameKey ($key, $name)
    function regCopySubTree ($dest, $source)
    function regGetValue ($key)
    function regSetValue ($key, $value)
    function regSubKeys ($key)
    function regSubKeysCount ($key)
    function regGetSubValues ($key)
    function regTagAttributes ($key)
    
    

1.4. Additional libraries

Array support library 

#
# array.lib.php        - array-specific functions
#

HTML controls library

#
# stdctrl.lib.php      - create selects/checkboxes/radiobuttons from array
#


2. MySQL DB support. HOW TO USE

If you decide to use this library and write a piece of code....
First of all you need set $cfg_dir and $lib_dir variables, edit the database.cfg.php
file (DB server, user name, password) and add the following lines in your script:

	include ($cfg_dir . "database.cfg.php");
	include ($lib_dir . "sqlstorage.class.php");

Below you'll find SQL queries and corresponding PHP code examples.
Lets assume we have everal tables in our DB: 
PRODUCTS, DEPARTMENTS, MAINTENANCE, VEHICLES and USERS

2.1. The first step is getting all the data from the PRODUCTS table

You need this line to create sqlStorage class instance

	$storage = new sqlStorage ();

So, the string

	$result = $storage->select_result ("PRODUCTS", "*", "ORDER BY PRODUCT_NAME");

will produce the following query

	SELECT *
	FROM PRODUCTS
	ORDER BY PRODUCT_NAME

2.2. Lets use functions

If we want to hide DB structure we can move all the queries to the separate class.
Lets define new class, e.g. pStorage

class pStorage extends sqlStorage {
	var $userID;

	function pStorage ($bDebug=false)
	{
		global $session_uid;
		$this->connect (DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
		$this->userID = isset($session_uid) ? intval($session_uid) : -1;
		if ($bDebug) $this->debugOn ();
	}
}

We wish to get the name of the certain product (by ID). Here's the function we'll add
to our class

	function getProduct ($id) {
		$condition = array ("PRODUCT_ID" => intval($id));
		$result = $this->select_column ("PRODUCTS", "PRODUCT_NAME", $condition);
		return is_array($result) ? $result[0] : false;
	}

We call the function  
	$pstorage = new pStorage (true); // debug info is enabled
	$prod_data = $pstorage->getProduct (7);

and get the query
	
	SELECT PRODUCT_NAME
	FROM PRODUCTS 
	WHERE PRODUCT_ID = 7
	

2.3. Now we'll get data from 2 tables
 
	function getProductMaint () {
		$tables = array ("PRODUCTS AS P", "MAINTENANCE AS M");
		$fields = array ("M.MAINTENANCE_PROCEDURE", "P.PRODUCT_NAME");
		$condition = array (
			"M.PRODUCT_ID" => EXP_FLAG . "P.PRODUCT_ID",
			"PRODUCT_TYPE" => 'maint'
		);
		$result = $this->select_result ($tables, $fields, $condition);
		return is_array($result) ? $result : false;
	}
	
	SELECT M.MAINTENENCE_PROCEDURE, P.PRODUCT_NAME
	FROM PRODUCTS AS P, MAINTENANCE AS M
	WHERE M.PRODUCT_ID = P.PRODUCT_ID AND PRODUCT_TYPE = 'maint'
	
2.4. Finally, lets write the query with left outer join

	function getDepartment ($id, $secure=true) {
		if (!isset($id)) return false;
		$table = "DEPARTMENTS AS SD left outer join DEPARTMENTS AS D on (SD.PARENT_DEPARTMENT=D.DEPARTMENT_ID)";
		$condition["SD.DEPARTMENT_ID"] = $id;
		if ($secure) $condition["SD.USER_ID"] = $this->user_id;
		$fields = "SD.DEPARTMENT_NAME," .
			" IF(SD.PARENT_DEPARTMENT<>0, D.DEPARTMENT_NAME, 'N/A') AS PARENT_DEPARTMENT";
		$result = $this->select_row ($table, $fields, $condition);
		return is_array($result) ? $result : false;
	}

If we call this function in a such way (lets assume USER_ID = 12345)

	$dep_data = $storage->getDepartment (93)
	
we'll get the query
	
	SELECT SD.DEPARTMENT_NAME, IF(SD.PARENT_DEPARTMENT<>0,D.DEPARTMENT_NAME,'N/A') AS PARENT_DEPARTMENT
	FROM DEPARTMENTS AS SD left outer join DEPARTMENTS AS D on (SD.PARENT_DEPARTMENT=D.DEPARTMENT_ID)
	WHERE SD.DEPARTMENT_ID = 93 and SD.USER_ID = 12345


