From f8fa64feb0a33b5712c8822a6fc58de918dcdaa4 Mon Sep 17 00:00:00 2001 From: chriskl Date: Mon, 11 Feb 2002 09:32:47 +0000 Subject: Initial revision --- classes/database/ADODB_base.php | 298 ++++ classes/database/BaseDB.php | 70 + classes/database/Postgres.php | 599 +++++++ classes/database/Postgres71.php | 428 +++++ conf/config.inc | 62 + lang/english.php | 31 + lang/template.php | 16 + libraries/adodb/adodb-access.inc.php | 54 + libraries/adodb/adodb-ado.inc.php | 522 +++++++ libraries/adodb/adodb-ado_access.inc.php | 38 + libraries/adodb/adodb-ado_mssql.inc.php | 36 + libraries/adodb/adodb-cryptsession.php | 245 +++ libraries/adodb/adodb-csv.inc.php | 147 ++ libraries/adodb/adodb-db2.inc.php | 163 ++ libraries/adodb/adodb-errorhandler.inc.php | 73 + libraries/adodb/adodb-errorpear.inc.php | 86 + libraries/adodb/adodb-fbsql.inc.php | 251 +++ libraries/adodb/adodb-ibase.inc.php | 349 +++++ libraries/adodb/adodb-mssql.inc.php | 279 ++++ libraries/adodb/adodb-mysql.inc.php | 352 +++++ libraries/adodb/adodb-mysqlt.inc.php | 53 + libraries/adodb/adodb-oci8.inc.php | 503 ++++++ libraries/adodb/adodb-odbc.inc.php | 369 +++++ libraries/adodb/adodb-odbc_mssql.inc.php | 38 + libraries/adodb/adodb-odbc_oracle.inc.php | 104 ++ libraries/adodb/adodb-oracle.inc.php | 243 +++ libraries/adodb/adodb-pear.inc.php | 348 +++++ libraries/adodb/adodb-postgres.inc.php | 377 +++++ libraries/adodb/adodb-postgres7.inc.php | 62 + libraries/adodb/adodb-proxy.inc.php | 28 + libraries/adodb/adodb-session.php | 228 +++ libraries/adodb/adodb-sybase.inc.php | 215 +++ libraries/adodb/adodb-vfp.inc.php | 79 + libraries/adodb/adodb.gif | Bin 0 -> 1089 bytes libraries/adodb/adodb.inc.php | 2332 ++++++++++++++++++++++++++++ libraries/adodb/adodb.png | Bin 0 -> 29073 bytes libraries/adodb/benchmark.php | 78 + libraries/adodb/client.php | 194 +++ libraries/adodb/crypt.inc.php | 60 + libraries/adodb/license.txt | 161 ++ libraries/adodb/readme.htm | 1518 ++++++++++++++++++ libraries/adodb/readme.txt | 57 + libraries/adodb/server.php | 92 ++ libraries/adodb/test.php | 436 ++++++ libraries/adodb/test2.php | 52 + libraries/adodb/test3.php | 30 + libraries/adodb/test4.php | 64 + libraries/adodb/test5.php | 35 + libraries/adodb/testcache.php | 20 + libraries/adodb/testdatabases.inc.php | 164 ++ libraries/adodb/testoci8.php | 43 + libraries/adodb/testpaging.php | 36 + libraries/adodb/testpear.php | 17 + libraries/adodb/testsessions.php | 12 + libraries/adodb/tohtml.inc.php | 150 ++ libraries/adodb/tute.htm | 273 ++++ public_html/browser.php | 46 + public_html/databases.php | 23 + public_html/index.php | 31 + public_html/intro.php | 22 + public_html/login.php | 68 + public_html/topbar.php | 24 + 62 files changed, 12784 insertions(+) create mode 100644 classes/database/ADODB_base.php create mode 100644 classes/database/BaseDB.php create mode 100755 classes/database/Postgres.php create mode 100644 classes/database/Postgres71.php create mode 100644 conf/config.inc create mode 100755 lang/english.php create mode 100644 lang/template.php create mode 100755 libraries/adodb/adodb-access.inc.php create mode 100755 libraries/adodb/adodb-ado.inc.php create mode 100755 libraries/adodb/adodb-ado_access.inc.php create mode 100755 libraries/adodb/adodb-ado_mssql.inc.php create mode 100755 libraries/adodb/adodb-cryptsession.php create mode 100755 libraries/adodb/adodb-csv.inc.php create mode 100755 libraries/adodb/adodb-db2.inc.php create mode 100755 libraries/adodb/adodb-errorhandler.inc.php create mode 100755 libraries/adodb/adodb-errorpear.inc.php create mode 100755 libraries/adodb/adodb-fbsql.inc.php create mode 100755 libraries/adodb/adodb-ibase.inc.php create mode 100755 libraries/adodb/adodb-mssql.inc.php create mode 100755 libraries/adodb/adodb-mysql.inc.php create mode 100755 libraries/adodb/adodb-mysqlt.inc.php create mode 100755 libraries/adodb/adodb-oci8.inc.php create mode 100755 libraries/adodb/adodb-odbc.inc.php create mode 100755 libraries/adodb/adodb-odbc_mssql.inc.php create mode 100755 libraries/adodb/adodb-odbc_oracle.inc.php create mode 100755 libraries/adodb/adodb-oracle.inc.php create mode 100755 libraries/adodb/adodb-pear.inc.php create mode 100755 libraries/adodb/adodb-postgres.inc.php create mode 100755 libraries/adodb/adodb-postgres7.inc.php create mode 100755 libraries/adodb/adodb-proxy.inc.php create mode 100755 libraries/adodb/adodb-session.php create mode 100755 libraries/adodb/adodb-sybase.inc.php create mode 100755 libraries/adodb/adodb-vfp.inc.php create mode 100755 libraries/adodb/adodb.gif create mode 100755 libraries/adodb/adodb.inc.php create mode 100755 libraries/adodb/adodb.png create mode 100755 libraries/adodb/benchmark.php create mode 100755 libraries/adodb/client.php create mode 100755 libraries/adodb/crypt.inc.php create mode 100755 libraries/adodb/license.txt create mode 100755 libraries/adodb/readme.htm create mode 100755 libraries/adodb/readme.txt create mode 100755 libraries/adodb/server.php create mode 100755 libraries/adodb/test.php create mode 100755 libraries/adodb/test2.php create mode 100755 libraries/adodb/test3.php create mode 100755 libraries/adodb/test4.php create mode 100755 libraries/adodb/test5.php create mode 100755 libraries/adodb/testcache.php create mode 100755 libraries/adodb/testdatabases.inc.php create mode 100755 libraries/adodb/testoci8.php create mode 100755 libraries/adodb/testpaging.php create mode 100755 libraries/adodb/testpear.php create mode 100755 libraries/adodb/testsessions.php create mode 100755 libraries/adodb/tohtml.inc.php create mode 100755 libraries/adodb/tute.htm create mode 100644 public_html/browser.php create mode 100755 public_html/databases.php create mode 100755 public_html/index.php create mode 100755 public_html/intro.php create mode 100755 public_html/login.php create mode 100755 public_html/topbar.php diff --git a/classes/database/ADODB_base.php b/classes/database/ADODB_base.php new file mode 100644 index 00000000..1fb1a22b --- /dev/null +++ b/classes/database/ADODB_base.php @@ -0,0 +1,298 @@ +conn->databaseType = $type; + $this->conn = &ADONewConnection($type); + $this->conn->setFetchMode($fetchMode); + } + + /** + * Cleans (escapes) a string + * @param $str The string to clean, by reference + * @return The cleaned string + */ + function clean(&$str) { + $str = addslashes($str); + return $str; + } + + /** + * Retrieves a ResultSet from a query + * @param $sql The SQL statement to be executed + * @return A recordset + */ + function selectSet($sql) { + // Execute the statement + $rs = $this->conn->Execute($sql); + + // If failure, return error value + if (!$rs) return $this->conn->ErrorNo(); + + return $rs; + } + + /** + * Retrieves a single value from a query + * + * @@ assumes that the query will return only one row - returns field value in the first row + * + * @param $sql The SQL statement to be executed + * @param $field The field name to be returned + * @return A single field value + * @return -1 No rows were found + */ + function selectField($sql, $field) { + // Execute the statement + $rs = $this->conn->Execute($sql); + + // If failure, or no rows returned, return error value + if (!$rs) return $this->conn->ErrorNo(); + elseif ($rs->RecordCount() == 0) return -1; + + return $rs->f[$field]; + } + + /** + * Delete from the database + * @param $table The name of the table + * @param $conditions (array) A map of field names to conditions + * @return 0 success + * @return -1 on referential integrity violation + * @return -2 on no rows deleted + */ + function delete($table, $conditions) { + $this->clean($table); + + reset($conditions); + + // Build clause + $sql = ''; + while(list($key, $value) = each($conditions)) { + $this->clean($key); + $this->clean($value); + if ($sql) $sql .= " AND {$key}='{$value}'"; + else $sql = "DELETE FROM {$table} WHERE {$key}='{$value}'"; + } + + // Check for failures + if (!$this->conn->Execute($sql)) { + // Check for referential integrity failure + if (stristr($this->conn->ErrorMsg(), 'referential')) + return -1; + } + + // Check for no rows modified + if ($this->conn->Affected_Rows() == 0) return -2; + + return $this->conn->ErrorNo(); + } + + /** + * Insert a set of values into the database + * @param $table The table to insert into + * @param $vars (array) A mapping of the field names to the values to be inserted + * @return 0 success + * @return -1 if a unique constraint is violated + * @return -2 if a referential constraint is violated + */ + function insert($table, $vars) { + $this->clean($table); + + reset($vars); + + // Build clause + $fields = ''; + $values = ''; + while(list($key, $value) = each($vars)) { + $this->clean($key); + $this->clean($value); + + if ($fields) $fields .= ", {$key}"; + else $fields = "INSERT INTO {$table} ({$key}"; + + if ($values) $values .= ", '{$value}'"; + else $values = ") VALUES ('{$value}'"; + } + + // Check for failures + if (!$this->conn->Execute($fields . $values . ')')) { + // Check for unique constraint failure + if (stristr($this->conn->ErrorMsg(), 'unique')) + return -1; + // Check for referential integrity failure + elseif (stristr($this->conn->ErrorMsg(), 'referential')) + return -2; + } + + return $this->conn->ErrorNo(); + } + + /** + * Update a row in the database + * @param $table The table that is to be updated + * @param $vars (array) A mapping of the field names to the values to be updated + * @param $where (array) A mapping of field names to values for the where clause + * @param $nulls (array, optional) An array of fields to be set null + * @return 0 success + * @return -1 if a unique constraint is violated + * @return -2 if a referential constraint is violated + * @return -3 on no rows deleted + */ + function update($table, $vars, $where, $nulls = array()) { + $this->clean($table); + + $setClause = ''; + $whereClause = ''; + + // Populate the syntax arrays + reset($vars); + while(list($key, $value) = each($vars)) { + $this->clean($key); + $this->clean($value); + if ($setClause) $setClause .= ", {$key}='{$value}'"; + else $setClause = "UPDATE {$table} SET {$key}='{$value}'"; + } + + reset($nulls); + while(list(, $value) = each($nulls)) { + $this->clean($value); + if ($setClause) $setClause .= ", {$value}=NULL"; + else $setClause = "UPDATE {$table} SET {$value}=NULL"; + } + + reset($where); + while(list($key, $value) = each($where)) { + $this->clean($key); + $this->clean($value); + if ($whereClause) $whereClause .= " AND {$key}='{$value}'"; + else $whereClause = " WHERE {$key}='{$value}'"; + } + + // Check for failures + if (!$this->conn->Execute($setClause . $whereClause)) { + // Check for unique constraint failure + if (stristr($this->conn->ErrorMsg(), 'unique')) + return -1; + // Check for referential integrity failure + elseif (stristr($this->conn->ErrorMsg(), 'referential')) + return -2; + } + + // Check for no rows modified + if ($this->conn->Affected_Rows() == 0) return -3; + + return $this->conn->ErrorNo(); + } + + /** + * Begin a transaction + * @return 0 success + */ + function beginTransaction() { + return !$this->conn->BeginTrans(); + } + + /** + * End a transaction + * @return 0 success + */ + function endTransaction() { + return !$this->conn->CommitTrans(); + } + + /** + * Roll back a transaction + * @return 0 success + */ + function rollbackTransaction() { + return !$this->conn->RollbackTrans(); + } + + // Type conversion routines + + /** + * Converts an array of identifiers into a bitset, given a bitset definition + * Duplicate flags are silently ignored. + * Note: This is not case insensitive. + * @param flags An array of identifiers + * @param allowed The definition of allowed identifiers, mapping identifier -> bit index + * @return A string representation of the bitset + */ + function dbBitSet(&$flags, &$allowed) { + $bitset = (int)0; + for ($i = 0; $i < sizeof($flags); $i++) { + if (isset($allowed[$flags[$i]])) { + $bitset |= (1 << $allowed[$flags[$i]]); + } + } + + // Left-pad the bitset to match the database size + // Important! + $bitset = decbin($bitset); + $bitset = str_pad($bitset, sizeof($allowed), '0', STR_PAD_LEFT); + + return 'b' . $bitset; + } + + /** + * Change an int from a database bitset field back into an array of identifiers + * @param $bitset The database bitset, in database format (B'10101') + * @param $allowed The definition of allowed identifiers, mapping identifier -> bit index + * @return An array of identifiers + */ + function phpBitSet($bitset, &$allowed) { + // @@ NOTE: Should we be doing better error handling here? + // @@ This condition will catch both NULL values (correctly) and borked values (incorrectly) + if (!ereg("^[01]+$", $bitset)) return array(); + + $intset = bindec($bitset); + + $temp = array(); + + reset($allowed); + while (list($k, $v) = each($allowed)) { + if ($intset & (1 << $v)) $temp[] = $k; + } + return $temp; + } + + /** + * Change the value of a parameter to 't' or 'f' depending on whether it evaluates to true or false + * @param $parameter the parameter + */ + function dbBool(&$parameter) { + if ($parameter) $parameter = 't'; + else $parameter = 'f'; + + return $parameter; + } + + /** + * Change a parameter from 't' or 'f' to a boolean, (others evaluate to false) + * @param $parameter the parameter + */ + function phpBool($parameter) { + $parameter = ($parameter == 't'); + return $parameter; + } + +} + +?> diff --git a/classes/database/BaseDB.php b/classes/database/BaseDB.php new file mode 100644 index 00000000..c5722abd --- /dev/null +++ b/classes/database/BaseDB.php @@ -0,0 +1,70 @@ +ADODB_base($type); + } + + /** + * Set object filtering for user + * @param $state (boolean) + */ + function setFilterTables($state) { + $this->$_filterTables = $state; + } + +/* + // Feature functions + + // Is "ALTER TABLE" with add column supported? + function supportsAlterTableWithAddColumn() {} + + // Is "ALTER TABLE" with drop column supported? + function supportsAlterTableWithDropColumn() + + // Are both data definition and data manipulation statements within a transaction supported? + function supportsDataDefinitionAndDataManipulationTransactions() + + // Are only data manipulation statements within a transaction supported? + function supportsDataManipulationTransactionsOnly() + + // Does the database treat mixed case unquoted SQL identifiers as case sensitive and as a result store them in mixed case? A JDBC CompliantTM driver will always return false. + function supportsMixedCaseIdentifiers() + + // Does the database treat mixed case quoted SQL identifiers as case sensitive and as a result store them in mixed case? A JDBC CompliantTM driver will always return true. + function supportsMixedCaseQuotedIdentifiers() + + // Can columns be defined as non-nullable? A JDBC CompliantTM driver always returns true. + function supportsNonNullableColumns() + + // Are stored procedure calls using the stored procedure escape syntax supported? + function supportsStoredProcedures() + + // Are transactions supported? If not, invoking the method commit is a noop and the isolation level is TRANSACTION_NONE. + function supportsTransactions() + + // Can you define your own aggregates? + function supportsAggregates() + + // Can you define your own operators? + function supportsOperators() + + // Database manipulation + +*/ +} + +?> \ No newline at end of file diff --git a/classes/database/Postgres.php b/classes/database/Postgres.php new file mode 100755 index 00000000..db43021b --- /dev/null +++ b/classes/database/Postgres.php @@ -0,0 +1,599 @@ +User = 'auadmin'; + $this->Password = 'bfd12hutz'; + + $this->BaseDB(); + } + + // Flag functions + + /** + * Retrieves the flags of the specified user + * @param $user_id The ID of the user + * @param $values (optional) Return array as values, rather than keys + * @return An array containing the flag names as it keys with values of true + */ + function &getUserFlags($user_id, $values = false) { + $this->clean($meal_id); + $sql = "SELECT fl.name FROM users_flags uf, medidiets_flags fl WHERE uf.flag_id = fl.flag_id AND uf.user_id = '{$user_id}'"; + $rs = $this->selectSet($sql); + + $flags = array(); + while (!$rs->EOF) { + if ($values) + $flags[] = $rs->f['name']; + else + $flags[$rs->f['name']] = true; + $rs->moveNext(); + } + + return $flags; + } + + /** + * Retrieves a user's profile and plan joined + * @param $user_id The ID of the user whose data is to be returned + * @return A recordset + */ + function &getProfileAndPlan($user_id) { + $this->clean($user_id); + + $sql = "SELECT * FROM users_profiles_tmp up, medidiets_plans mp WHERE up.user_id='$user_id' AND up.plan_id=mp.plan_id"; + + return $this->selectSet($sql); + } + + // Plan functions + + /** + * Returns all existing plans + * @return A recordset + */ + function &getPlans() { + $sql = "SELECT * FROM medidiets_plans ORDER BY calories"; + return $this->selectSet($sql); + } + + /* + * Finds a meal plan that matches the given number of calories most closely + * @param $cals The number of calories the plan should be + * @return (array) The ID of the plan found, and the actual cals + */ + function &findPlan($cals) { + $this->clean($cals); + + $sql = "SELECT plan_id, calories, ABS(calories::numeric - '$cals') AS diff FROM medidiets_plans ORDER BY diff LIMIT 1"; + $rs = $this->selectSet($sql); + + return array($rs->f['plan_id'], $rs->f['calories']); + } + + /* + * Finds all meals that adhere to the given options, randomly ordered + * @param $cals The number of calories the plan should be + * @param $when_id The meal of the day to find meals for + * @param $flags An array of flag names to be excluded + * @param $names (optional) Specify whether to return names as well, sorted + * @return A recordset + */ + function &findMeals($cals, $when_id, $flags, $names = false) { + $this->clean($cals); + $this->clean($when_id); + $flag_str = implode("','", $flags); + + if ($names) { + $params = 'meal_id, name'; + $order = 'name'; + } + else { + $params = 'meal_id'; + $order = 'RANDOM()'; + } + + $sql = " + SELECT + {$params} + FROM + medidiets_meals mm + WHERE + mm.calories='{$cals}' + AND mm.when_id='{$when_id}' + AND mm.visible + AND NOT mm.pending + AND mm.meal_id NOT IN ( + SELECT + DISTINCT (meal_id) + FROM + medidiets_flags_map mfp, medidiets_flags mf + WHERE + mfp.flag_id=mf.flag_id + AND mf.name IN ('{$flag_str}') + ) + ORDER BY {$order} + "; + + return $this->selectSet($sql); + } + + /* + * Inserts meals into a range of dates for a user + * @param $user_id The ID of the user we're inserting for + * @param $start_date The date at which to start the insertion + * @param $no_days The number of days to insert + * @return 0 success + * @return -1 transaction error + * @return -2 profile/plan retrieval error + * @return -3 meal list retrieval error + * @return -4 insertion failure + * @@ What happens if no breakfasts could be found?!?!? + */ + function createMealPlan($user_id, $start_date, $no_days) { + global $defaultCountryCode; + + // begin transaction + $status = $this->beginTransaction(); + if ($status != 0) return -1; + + // Get user data, joined with plan data? + $data = &$this->getProfileAndPlan($user_id); + $data->f['seasonal'] = $this->phpBool($data->f['seasonal']); + $flags = &$this->getUserFlags($user_id, true); + + // Seasonal menus + if ($data->f['seasonal']) { + if ($defaultCountryCode == 'AU') + $is_summer = in_array(date('m'), array(10, 11, 12, 1, 2, 3)); + else + $is_summer = in_array(date('m'), array(4, 5, 6, 7, 8, 9)); + + if ($is_summer) $flags[] = 'NOT_SUMMER'; + else $flags[] = 'NOT_WINTER'; + } + + // Convenience + $b_flags = $flags; + if ($data->f['mp_breakfast'] == 'C') $b_flags[] = 'NOT_CONVENIENT'; + $l_flags = $flags; + if ($data->f['mp_lunch'] == 'C') $l_flags[] = 'NOT_CONVENIENT'; + $d_flags = $flags; + if ($data->f['mp_dinner'] == 'C') $d_flags[] = 'NOT_CONVENIENT'; + + // Get lists of breakfasts, lunches, dinners and snacks, ordered + // randomly. + if ($data->f['breakfast'] > 0) { + $breakfasts = &$this->findMeals($data->f['breakfast'], 1, $b_flags); + if (!$breakfasts) { + $this->rollbackTransaction(); + return -3; + } + if ($breakfasts->recordCount() == 0) reportError("User {$user_id} could not find a {$data->f['breakfast']} cal breakfast for " . + implode(',', $b_flags) . " flags."); + } + if ($data->f['lunch'] > 0) { + $lunches = &$this->findMeals($data->f['lunch'], 2, $l_flags); + if (!$lunches) { + $this->rollbackTransaction(); + return -3; + } + if ($lunches->recordCount() == 0) reportError("User {$user_id} could not find a {$data->f['lunch']} cal lunch for " . + implode(',', $l_flags) . " flags."); + } + if ($data->f['dinner'] > 0) { + $dinners = &$this->findMeals($data->f['dinner'], 3, $d_flags); + if (!$dinners) { + $this->rollbackTransaction(); + return -3; + } + if ($dinners->recordCount() == 0) reportError("User {$user_id} could not find a {$data->f['dinner']} cal dinner for " . + implode(',', $d_flags) . " flags."); + } + if ($data->f['snack'] > 0) { + $snacks = &$this->findMeals($data->f['snack'], 4, $flags); + if (!$snacks) { + $this->rollbackTransaction(); + return -3; + } + if ($snacks->recordCount() == 0) reportError("User {$user_id} could not find a {$data->f['snack']} cal snack for " . + implode(',', $flags) . " flags."); + } + + // For each day, insert a breakfast, lunch, dinner and snack + list($sy, $sm, $sd) = explode('-', $start_date); + for ($i = 0; $i < $no_days; $i++) { + $temp = array(); + $temp['user_id'] = $user_id; + $temp['date'] = date('Y-m-d', mktime(0, 0, 0, $sm, $sd + $i, $sy)); + // Breakfast + if ($data->f['breakfast'] > 0 && $breakfasts->recordCount() > 0) { + $temp['breakfast_id'] = $breakfasts->f['meal_id']; + $breakfasts->moveNext(); + if ($breakfasts->EOF) $breakfasts->moveFirst(); + } + // Lunch + if ($data->f['lunch'] > 0 && $lunches->recordCount() > 0) { + $temp['lunch_id'] = $lunches->f['meal_id']; + $lunches->moveNext(); + if ($lunches->EOF) $lunches->moveFirst(); + } + // Dinner + if ($data->f['dinner'] > 0 && $dinners->recordCount() > 0) { + $temp['dinner_id'] = $dinners->f['meal_id']; + $dinners->moveNext(); + if ($dinners->EOF) $dinners->moveFirst(); + } + // Snack + if ($data->f['snack'] > 0 && $snacks->recordCount() > 0) { + $temp['snack_id'] = $snacks->f['meal_id']; + $snacks->moveNext(); + if ($snacks->EOF) $snacks->moveFirst(); + } + + $status = $this->insert('users_mealplans', $temp); + if ($status != 0) { + $this->rollbackTransaction(); + return -4; + } + unset($temp); + } + + // @@ Take care of overriding preferences + + return $this->endTransaction(); + } + + /** + * Records a user's meal substitution to the database + * @param $user_id The ID of the user to be updated + * @param $date The date to update + * @param $when_id The meal to replace + * @param $meal_id The new meal to substitute + * @return 0 success + */ + function setUserMeal($user_id, $date, $when_id, $meal_id) { + $fields = array('', 'breakfast_id', 'lunch_id', 'dinner_id', 'snack_id'); + return $this->update('users_mealplans', + array($fields[$when_id] => $meal_id), + array('user_id' => $user_id, 'date' => $date)); + } + + /** + * Retrieves a user's shopping list + * @param $user_id The ID fo the user to retrieve + * @param $date The date from which to retrieve + * @param $num_days The number of days from the date forward to retrieve + */ + function &getShoppingList($user_id, $from, $to) { + $this->clean($user_id); + $this->clean($date); + + $sql = " + SELECT description, food_id, name, measurement, base, type, name_pl, measurement_pl, qty, SUM(quantity) AS quantity FROM ( + (SELECT + mcf.description, mf.food_id, mf.name, mf.measurement, mf.base, mf.type, mf.name_pl, mf.measurement_pl, mf.quantity AS qty, mfm.quantity AS quantity + FROM + medidiets_categories_foods mcf, medidiets_foods mf, medidiets_foods_map mfm, users_mealplans um + WHERE + mcf.category_id=mf.category_id + AND mf.food_id=mfm.food_id + AND mfm.meal_id IN (um.breakfast_id, um.lunch_id, um.dinner_id, um.snack_id) + AND um.date BETWEEN '$from' AND '$to' + AND user_id='$user_id') + UNION ALL + (SELECT + mcf.description, mf.food_id, mf.name, mf.measurement, mf.base, mf.type, mf.name_pl, mf.measurement_pl, mf.quantity AS qty, mi.quantity AS quantity + FROM + medidiets_categories_foods mcf, medidiets_foods mf, medidiets_ingredients mi, medidiets_recipes_map mrm, users_mealplans um + WHERE + mcf.category_id=mf.category_id + AND mf.food_id=mi.food_id + AND mi.recipe_id=mrm.recipe_id + AND mrm.meal_id IN (um.breakfast_id, um.lunch_id, um.dinner_id, um.snack_id) + AND um.date BETWEEN '$from' AND '$to' + AND user_id='$user_id') + ) AS subselect + GROUP BY description, food_id, name, measurement, base, type, name_pl, measurement_pl, qty + "; + + return $this->selectSet($sql); + } + + // Miscellaneous functions + + /* + * Returns an array with the correct imperial or metric units + * @return Array containing measurements + */ + function getDefaultUnits() { + global $defaultMeasurements; + + if ($defaultMeasurement == 'imperial') { + $units = array('M' => 'oz', 'V' => 'fl.oz'); + } + else { + $units = array('M' => 'g', 'V' => 'mL'); + } + + return $units; + } + + /* + * A helper function to convert decimals to fractions + * @param A decimal number to convert + * @return The formatted version of the number + */ + function _fracConvert($num) { + $decpart = $num - floor($num); + + switch ($decpart * 4) { + case 0: + return number_format($num, 0); + break; + case 1: + if (floor($num) != 0) + return number_format(floor($num), 0) . ' 1/4'; + else + return '1/4'; + break; + case 2: + if (floor($num) != 0) + return number_format(floor($num), 0) . ' 1/2'; + else + return '1/2'; + break; + case 3: + if (floor($num) != 0) + return number_format(floor($num), 0) . ' 3/4'; + else + return '3/4'; + break; + default: + if ($decpart == 0.33) { + if (floor($num) != 0) + return number_format(floor($num), 0) . ' 1/3'; + else + return '1/3'; + } + elseif ($decpart == 0.66 || $decpart == 0.67) { + if (floor($num) != 0) + return number_format(floor($num), 0) . ' 2/3'; + else + return '2/3'; + } + else return number_format($num, 2); + + break; + } + } + + /** + * Return the string to be used to as the display for the ingredient + * + * The string is to be formatted depending upon the values of the measurement + * and base variables. The string will also use the $defaultMeasurement + * specified in the network config files. + * + * @param $name The name of the food of the ingredient + * @param $name The pluralised form of the name + * @param $quantity The amount of ingredient + * @param $measurement The measurement of the food of the ingredient ('' if none) + * @param $measurement The pluralised form of the measurement ('' if none) + * @param $base The base size of the food of the ingredient ('' if none) + * @param $type The base type of the food of the ingredient ('M' - mass, 'V' - volume) + * @param $show_qty (optional) If false, only gives the name, not the quantity + * @param $how How the ingredient is prepared. + * + */ + function getIngredientDisplay($name, $name_pl, $quantity, $measurement, $measurement_pl, $base, $type, $how, $show_qty = true) { + global $defaultMeasurement; + + // set display units depending on defaultMeasurement + $units = $this->getDefaultUnits(); + + // if quantity is an integer value show only the integer + if ($quantity == (int)$quantity) $quantity = (int)$quantity; + + // discard fractional part of base size, cos who can measure half a gram? + if ($base != '') { + $base = round($base); + if ($base == 0) $base = 1; + } + + if ($measurement != '' && $base != '') { + // both measurement and base are set + // eg. "2 1/2 375mL cans of Tomato Soup" + $display_qty = $this->_fracConvert($quantity) . ' '; + $display_nam = $base . $units[$type] . ' '; + $display_nam .= ($quantity > 1) ? $measurement_pl : $measurement; + $display_nam .= ' of ' . $name; + } + elseif ($measurement != '') { + // measurement is set but base is not + // eg. "4 2/3 slices of Bread" + $display_qty = $this->_fracConvert($quantity) . ' '; + $display_nam = ($quantity > 1) ? $measurement_pl : $measurement; + $display_nam .= ' of ' . $name; + } + elseif ($base != '') { + // base is set but measurement is not + // eg. "500g of Beef" + $display_qty = ceil($quantity * $base); + $display_nam = $units[$type] . ' of ' . $name; + } + else { + // neither measurement nor base is set + // eg. "1 1/2 Apples" + $display_qty = $this->_fracConvert($quantity) . ' '; + $display_nam = ($quantity > 1) ? $name_pl : $name; + } + // Add 'crumbed', etc. + if ($how != '') $display_nam .= ", {$how}"; + + if ($show_qty) + return $display_qty . $display_nam; + else + return $display_nam; + + } + + // Meal Manipulation Functions + + /** + * Retrieve the Nutritional Data for a Food associated with a given meal + * @param $meal_id The ID of the meal + * @param $food_id The ID of the food + * @return The set of nutritional data and food information + */ + function &getMealFood($meal_id, $food_id) { + $this->clean($meal_id); + $this->clean($food_id); + $sql = "SELECT f.*, fm.* FROM medidiets_foods_map fm, medidiets_foods f WHERE fm.food_id = f.food_id AND fm.meal_id = '{$meal_id}' AND fm.food_id = '{$food_id}'"; + return $this->selectSet($sql); + } + + /** + * Retrieves all categories in the database, with all fields, sorted + * alphabetically. This userland function excludes all categories with id's + * less than zero! + * @return A recordset + */ + function &getRecipeCategories() { + $sql = "SELECT * FROM medidiets_categories_rec WHERE category_id >= 0 ORDER BY description"; + return $this->selectSet($sql); + } + + /** + * Retrieve the Nutritional Data for a Food associated with a given recipe + * @param $recipe_id The ID of the recipe + * @param $food_id The ID of the food + * @return The set of nutritional data and food information + */ + function &getRecipeIngredient($recipe_id, $food_id) { + $this->clean($recipe_id); + $this->clean($food_id); + $sql = "SELECT f.*, fm.* FROM medidiets_ingredients fm, medidiets_foods f WHERE fm.food_id = f.food_id AND fm.recipe_id = '{$recipe_id}' AND fm.food_id = '{$food_id}'"; + return $this->selectSet($sql); + } + + /** + * Retrieve a particular recipe + * @param $recipe_id The ID of the recipe to retrieve + * @return a recordset + */ + function &getRecipe($recipe_id) { + $this->clean($recipe_id); + $sql = "SELECT * FROM medidiets_recipes WHERE recipe_id='{$recipe_id}'"; + return $this->selectSet($sql); + } + + /** + * Retrieve all recipes in a particular category, sorted alphabetically + * This userland version of the function doesn't show magic recipes. + * @param $category_id The ID of the category in which to search + * @param $data A boolean switch to retrieve the nutritional data for the recipe (default false) + * @return a recordset + */ + function &getRecipes($category_id, $data = false) { + $this->clean($category_id); + if ($data) { + $sql = "SELECT * FROM + medidiets_recipes r LEFT JOIN + (SELECT i.recipe_id, + sum(i.quantity * f.calories) AS calories, + sum(i.quantity * f.kilojoules) AS kilojoules, + sum(i.quantity * f.protein) AS protein, + sum(i.quantity * f.fat) AS fat, + sum(i.quantity * f.saturated_fat) AS saturated_fat, + sum(i.quantity * f.carbohydrate) AS carbohydrate, + sum(i.quantity * f.sugar) AS sugar, + sum(i.quantity * f.fiber) AS fiber, + sum(i.quantity * f.cholesterol) AS cholesterol, + sum(i.quantity * f.sodium) AS sodium, + sum(i.quantity * f.potassium) AS potassium, + sum(i.quantity * f.calcium) AS calcium, + sum(i.quantity * f.iron) AS iron, + sum(i.quantity * f.zinc) AS zinc + FROM + medidiets_ingredients i, + medidiets_foods f + WHERE i.food_id = f.food_id + GROUP BY i.recipe_id + ) AS sub + ON r.recipe_id = sub.recipe_id + AND r.category_id = '{$category_id}' + AND r.recipe_id >= 0 + ORDER BY r.name"; + } + else { + $sql = "SELECT * FROM medidiets_recipes WHERE category_id='{$category_id}' AND recipe_id >= 0 ORDER BY name"; + } + + return $this->selectSet($sql); + } + + /** + * Retrieve the nutritional data for the specified recipe + * @param $recipe_id The ID of the recipe to retrieve + * @return a recordset + */ + function &getRecipeData($recipe_id) { + $this->clean($recipe_id); + $sql = "SELECT * FROM + medidiets_recipes r LEFT JOIN + (SELECT i.recipe_id, + sum(i.quantity * f.calories) AS total_calories, + sum(i.quantity * f.kilojoules) AS total_kilojoules, + sum(i.quantity * f.protein) AS total_protein, + sum(i.quantity * f.fat) AS total_fat, + sum(i.quantity * f.saturated_fat) AS total_saturated_fat, + sum(i.quantity * f.carbohydrate) AS total_carbohydrate, + sum(i.quantity * f.sugar) AS total_sugar, + sum(i.quantity * f.fiber) AS total_fiber, + sum(i.quantity * f.cholesterol) AS total_cholesterol, + sum(i.quantity * f.sodium) AS total_sodium, + sum(i.quantity * f.potassium) AS total_potassium, + sum(i.quantity * f.calcium) AS total_calcium, + sum(i.quantity * f.iron) AS total_iron, + sum(i.quantity * f.zinc) AS total_zinc + FROM + medidiets_ingredients i, + medidiets_foods f + WHERE i.food_id = f.food_id + GROUP BY i.recipe_id + ) AS sub + ON r.recipe_id = sub.recipe_id + WHERE r.recipe_id = '{$recipe_id}'"; + return $this->selectSet($sql); + } + + /** + * Retrieve all ingredients for a recipe, sorted by their oid + * @param $recipe_id The ID of the recipe to which the ingredients are needed + * @return a recordset + */ + function &getRecipeIngredients($recipe_id) { + $this->clean($recipe_id); + // @@ i.quantity must be after the f.* in the select until f.quantity removed... + $sql = "SELECT f.*, i.quantity, i.how FROM medidiets_foods f, medidiets_ingredients i + WHERE f.food_id = i.food_id + AND i.recipe_id = '{$recipe_id}' + ORDER BY i.oid"; + + return $this->selectSet($sql); + } + +} + +?> \ No newline at end of file diff --git a/classes/database/Postgres71.php b/classes/database/Postgres71.php new file mode 100644 index 00000000..34239d76 --- /dev/null +++ b/classes/database/Postgres71.php @@ -0,0 +1,428 @@ +BaseDB('postgres7'); + +// $this->conn->host = $host; + //$this->Port = $port; + + $this->conn->connect($host, $user, $password, $database); + } + + /** + * Return all database available on the server + * @return A list of databases, sorted alphabetically + */ + function &getDatabases() { + $sql = "SELECT pdb.datname, pdb.datistemplate, pde.description FROM + pg_database pdb LEFT JOIN pg_description pde ON pdb.oid=pde.objoid + ORDER BY pdb.datname"; + return $this->selectSet($sql); + } + + /** + * Return all information about a particular database + * @param $database The name of the database to retrieve + * @return The database info + */ + function &getDatabase($database) { + $this->clean($database); + $sql = "SELECT * FROM pg_database WHERE datname='{$database}'"; + return $this->selectRow($sql); + } + + /** + * Drops a database + * @param $database The name of the database to retrieve + * @return 0 success + */ + function dropDatabase($database) { + $this->clean($database); + $sql = "DROP DATABASE \"{$database}\""; + } + + // Table functions + + /** + * Return all tables in current database + * @return All tables, sorted alphabetically + */ + function &getTables() { + $sql = "SELECT * FROM pg_class ORDER BY relname"; + return $this->selectSet($sql); + } + + /** + * Return all information relating to a table + * @param $table The name of the table + * @return Table information + */ + function &getTableByName($table) { + $this->clean($table); + $sql = "SELECT * FROM pg_class WHERE relname='{$table}'"; + return $this->selectRow($sql); + } + + // @@ Need create table - tricky!! + + /** + * Removes a table from the database + * @param $table + * @return 0 success + */ + function dropTable($table) { + $this->clean($table); + + $sql = "DROP TABLE \"{$table}\""; + + // @@ How do you do this? + return $this->execute($sql); + } + + /** + * Renames a table + * @param $table The table to be renamed + * @param $newName The new name for the table + * @return 0 success + */ + function renameTable($table, $newName) { + $this->clean($table); + $this->clean($newName); + $sql = "ALTER TABLE \"{$table}\" RENAME TO \"{$newName}\""; + + // @@ How do you do this? + return $this->execute($sql); + } + + /** + * Adds a check constraint to a table + * @param $table The table to which to add the check + * @param $definition The definition of the check + * @param $name (optional) The name to give the check, otherwise default name is assigned + * @return 0 success + */ + function addCheckConstraint($table, $definition, $name = '') { + $this->clean($table); + $this->clean($name); + // @@ how the heck do you clean definition??? + + if ($name != '') + $sql = "ALTER TABLE \"{$table}\" ADD CONSTRAINT \"{$name}\" CHECK ({$definition})"; + else + $sql = "ALTER TABLE \"{$table}\" ADD CHECK ({$definition})"; + + // @@ How do you do this? + return $this->execute($sql); + } + + /** + * Drops a check constraint from a table + * @param $table The table from which to drop the check + * @param $name The name of the check to be dropped + * @return 0 success + * @return -2 transaction error + * @return -3 lock error + * @return -4 check drop error + */ + function dropCheckConstraint($table, $name) { + $this->clean($table); + $this->clean($name); + + // Begin transaction + $status = $this->beginTransaction(); + if ($status != 0) return -2; + + // Properly lock the table + $sql = "LOCK TABLE \"{$table}\" IN ACCESS EXCLUSIVE MODE"; + $status = $this->execute($sql); + if ($status != 0) { + $this->rollbackTransaction(); + return -3; + } + + // Delete the check constraint + $sql = "DELETE FROM pg_relcheck WHERE rcrelid=(SELECT oid FROM pg_class WHERE relname='{$table}') AND rcname='{$name}'"; + $status = $this->execute($sql); + if ($status != 0) { + $this->rollbackTransaction(); + return -4; + } + + // Update the pg_class catalog to reflect the new number of checks + $sql = "UPDATE pg_class SET relchecks=(SELECT COUNT(*) FROM pg_relcheck WHERE + rcrelid=(SELECT oid FROM pg_class WHERE relname='{$table}')) + WHERE relname='{$table}'"; + $status = $this->execute($sql); + if ($status != 0) { + $this->rollbackTransaction(); + return -4; + } + + // Otherwise, close the transaction + return $this->endTransaction(); + } + + /** + * Adds a unique constraint to a table + * @param $table The table to which to add the unique + * @param $fields (array) An array of fields over which to add the unique + * @param $name (optional) The name to give the unique, otherwise default name is assigned + * @return 0 success + */ + function addUniqueConstraint($table, $fields, $name = '') { + $this->clean($table); + $this->arrayClean($fields); + $this->clean($name); + + if ($name != '') + $sql = "CREATE UNIQUE INDEX \"{$name}\" ON \"{$table}\"(\"" . join('","', $fields) . "\")"; + else return -99; // Not supported + + // @@ How do you do this? + return $this->execute($sql); + } + + /** + * Drops a unique constraint from a table + * @param $table The table from which to drop the unique + * @param $name The name of the unique + * @return 0 success + */ + function dropUniqueConstraint($table, $name) { + $this->clean($table); + $this->clean($name); + + $sql = "DROP INDEX \"{$name}\""; + + // @@ How do you do this? + return $this->execute($sql); + } + + /** + * Adds a primary key constraint to a table + * @param $table The table to which to add the primery key + * @param $fields (array) An array of fields over which to add the primary key + * @param $name (optional) The name to give the key, otherwise default name is assigned + * @return 0 success + */ + function addPrimaryKeyConstraint($table, $fields, $name = '') { + // This function can be faked with a unique index and a catalog twiddle, however + // how do we ensure that it's only used on NOT NULL fields? + return -99; // Not supported. + } + + /** + * Drops a primary key constraint from a table + * @param $table The table from which to drop the primary key + * @param $name The name of the primary key + * @return 0 success + */ + function dropPrimaryKeyConstraint($table, $name) { + $this->clean($table); + $this->clean($name); + + $sql = "DROP INDEX \"{$name}\""; + + // @@ How do you do this? + return $this->execute($sql); + } + + /** + * Changes the owner of a table + * @param $table The table whose owner is to change + * @param $owner The new owner (username) of the table + * @return 0 success + */ + function setOwnerOfTable($table, $owner) { + $this->clean($table); + $this->clean($owner); + + $sql = "ALTER TABLE \"{$table}\" OWNER TO \"{$owner}\""; + + // @@ How do you do this? + return $this->execute($sql); + } + + // Column Functions + + /** + * Add a new column to a table + * @param $table The table to add to + * @param $column The name of the new column + * @param $type The type of the column + * @param $size (optional) The optional size of the column (ie. 30 for varchar(30)) + * @return 0 success + */ + function addColumnToTable($table, $column, $type, $size = '') { + $this->clean($table); + $this->clean($column); + $this->clean($type); + $this->clean($size); + // @@ How the heck do you properly clean type and size? + + if ($size == '') + $sql = "ALTER TABLE \"{$table}\" ADD COLUMN \"{$column}\" {$type}"; + else + $sql = "ALTER TABLE \"{$table}\" ADD COLUMN \"{$column}\" {$type}({$size})"; + + // @@ How do you do this? + return $this->execute($sql); + } + + /** + * Drops a column from a table + * @param $table The table from which to drop + * @param $column The column name to drop + * @return 0 success + */ + function dropColumnFromTable($table, $column) { + return -99; // Not implemented + } + + /** + * Sets default value of a column + * @param $table The table from which to drop + * @param $column The column name to set + * @param $default The new default value + * @return 0 success + */ + function setColumnDefault($table, $column, $default) { + $this->clean($table); + $this->clean($column); + // @@ How the heck do you clean default clause? + + $sql = "ALTER TABLE \"{$table}\" ALTER COLUMN \"{$column}\" SET DEFAULT {$default}"; + + // @@ How do you do this? + return $this->execute($sql); + } + + /** + * Drops default value of a column + * @param $table The table from which to drop + * @param $column The column name to drop default + * @return 0 success + */ + function dropColumnDefault($table, $column) { + $this->clean($table); + $this->clean($column); + + $sql = "ALTER TABLE \"{$table}\" ALTER COLUMN \"{$column}\" DROP DEFAULT"; + + // @@ How do you do this? + return $this->execute($sql); + } + + /** + * Sets whether or not a column can contain NULLs + * @param $table The table that contains the column + * @param $column The column to alter + * @param $state True to set null, false to set not null + * @return 0 success + * @return -1 attempt to set not null, but column contains nulls + * @return -2 transaction error + * @return -3 lock error + * @return -4 update error + */ + function setColumnNull($table, $column, $state) { + $this->clean($table); + $this->clean($column); + + // Begin transaction + $status = $this->beginTransaction(); + if ($status != 0) return -2; + + // Properly lock the table + $sql = "LOCK TABLE \"{$table}\" IN ACCESS EXCLUSIVE MODE"; + $status = $this->execute($sql); + if ($status != 0) { + $this->rollbackTransaction(); + return -3; + } + + // Check for existing nulls + if (!$state) { + $sql = "SELECT COUNT(*) AS total FROM \"{$table}\" WHERE \"{$column}\" IS NULL"; + $result = $this->selectField($sql, 'total'); + if ($result > 0) { + $this->rollbackTransaction(); + return -1; + } + } + + // Otherwise update the table. Note the reverse-sensed $state variable + $sql = "UPDATE pg_attribute SET attnotnull = " . ($state) ? 'false' : 'true' . " + WHERE attrelid = (SELECT oid FROM pg_class WHERE relname = '{$table}') + AND attname = '{$column}'"; + $status = $this->execute($sql); + if ($status != 0) { + $this->rollbackTransaction(); + return -4; + } + + // Otherwise, close the transaction + return $this->endTransaction(); + } + + /** + * Renames a column in a table + * @param $table The table containing the column to be renamed + * @param $column The column to be renamed + * @param $newName The new name for the column + * @return 0 success + */ + function renameColumn($table, $column, $newName) { + $this->clean($table); + $this->clean($column); + $this->clean($newName); + + $sql = "ALTER TABLE \"{$table}\" RENAME COLUMN \"{$column}\" TO \"{$newName}\""; + + // @@ how? + return $this->execute($sql); + } +/* + function &getIndices() + function &getIndex() + function setIndex() + function delIndex() + + function &getSequences() + function &getSequence() + function setSequence() + function delSequence() + + // DML Functions + + function doSelect() + function doDelete() + function doUpdate() +*/ + + // Capabilities + function hasTables() { return true; } + function hasViews() { return true; } + function hasSequences() { return true; } + function hasFunctions() { return true; } + function hasTriggers() { return true; } + function hasOperators() { return true; } + function hasTypes() { return true; } + function hasAggregates() { return true; } + function hasRules() { return true; } + +} + +?> \ No newline at end of file diff --git a/conf/config.inc b/conf/config.inc new file mode 100644 index 00000000..617d1b49 --- /dev/null +++ b/conf/config.inc @@ -0,0 +1,62 @@ + \ No newline at end of file diff --git a/lang/english.php b/lang/english.php new file mode 100755 index 00000000..152d6b22 --- /dev/null +++ b/lang/english.php @@ -0,0 +1,31 @@ + + + +
+Host=".$argHostname."
version=$dbc->version
Host=".$argHostname."
version=$dbc->version
\$HTTP_SESSION_VARS['AVAR']={$HTTP_SESSION_VARS['AVAR']}
"; + + + Installation + ============ + 1. Create a new database in MySQL or Access "sessions" like +so: + + create table sessions ( + SESSKEY char(32) not null, + EXPIRY int(11) unsigned not null, + DATA text not null, + primary key (sesskey) + ); + + 2. Then define the following parameters in this file: + $ADODB_SESSION_DRIVER='database driver, eg. mysql or ibase'; + $ADODB_SESSION_CONNECT='server to connect to'; + $ADODB_SESSION_USER ='user'; + $ADODB_SESSION_PWD ='password'; + $ADODB_SESSION_DB ='database'; + $ADODB_SESSION_TBL = 'sessions' + + 3. Recommended is PHP 4.0.2 or later. There are documented +session bugs in + earlier versions of PHP. + +*/ + + +include_once('crypt.inc.php'); + +if (!defined('_ADODB_LAYER')) { + include ('adodb.inc.php'); +} + + + +if (!defined('ADODB_SESSION')) { + + define('ADODB_SESSION',1); + +GLOBAL $ADODB_SESSION_CONNECT, + $ADODB_SESSION_DRIVER, + $ADODB_SESSION_USER, + $ADODB_SESSION_PWD, + $ADODB_SESSION_DB, + $ADODB_SESS_CONN, + $ADODB_SESS_LIFE, + $ADODB_SESS_DEBUG, + $ADODB_SESS_INSERT; + + //$ADODB_SESS_DEBUG = true; + + /* SET THE FOLLOWING PARAMETERS */ +if (empty($ADODB_SESSION_DRIVER)) { + $ADODB_SESSION_DRIVER='mysql'; + $ADODB_SESSION_CONNECT='serverName'; + $ADODB_SESSION_USER ='PhpSessions'; + $ADODB_SESSION_PWD ='sessions'; + $ADODB_SESSION_DB ='sessions'; +} +if (empty($ADODB_SESSION_TBL)){ + $ADODB_SESSION_TBL = 'sessions'; +} + + +function ADODB_Session_Key() +{ +$ADODB_CRYPT_KEY = 'CRYPTED ADODB SESSIONS ROCK!'; + + /* USE THIS FUNCTION TO CREATE THE ENCRYPTION KEY FOR CRYPTED SESSIONS */ + /* Crypt the used key, $ADODB_CRYPT_KEY as key and session_ID as SALT */ + return crypt($ADODB_CRYPT_KEY, session_ID()); +} + +$ADODB_SESS_LIFE = get_cfg_var('session.gc_maxlifetime'); +if ($ADODB_SESS_LIFE <= 1) { + // bug in PHP 4.0.3 pl 1 -- how about other versions? + //print "Session Update: '.$ADODB_SESS_CONN->ErrorMsg().'
'; + + if ($ADODB_SESS_INSERT || $rs === false) { + $qry = "INSERT INTO $ADODB_SESSION_TBL(sesskey,expiry,data) VALUES ('$key',$expiry,'$val')"; + $rs = $ADODB_SESS_CONN->Execute($qry); + if ($rs) $rs->Close(); + else print 'Session Insert: '.$ADODB_SESS_CONN->ErrorMsg().'
'; + } + // bug in access driver (could be odbc?) means that info is not commited + // properly unless select statement executed in Win2000 + if ($ADODB_SESS_CONN->databaseType == 'access') $rs = $ADODB_SESS_CONN->Execute("select sesskey from $ADODB_SESSION_TBL WHERE sesskey='$key'"); + + return isset($rs); +} + +function adodb_sess_destroy($key) +{ + global $ADODB_SESS_CONN, $ADODB_SESSION_TBL; + + $qry = "DELETE FROM $ADODB_SESSION_TBL WHERE sesskey = '$key'"; + $rs = $ADODB_SESS_CONN->Execute($qry); + if ($rs) $rs->Close(); + return $rs; +} + +function adodb_sess_gc($maxlifetime) { + global $ADODB_SESS_CONN, $ADODB_SESSION_TBL; + + $qry = "DELETE FROM $ADODB_SESSION_TBL WHERE expiry < " . time(); + $rs = $ADODB_SESS_CONN->Execute($qry); + if ($rs) $rs->Close(); + + // suggested by Cameron, "GaM3R"\$HTTP_SESSION_VARS['AVAR']={$HTTP_SESSION_VARS['AVAR']}
"; +} +*/ +?> \ No newline at end of file diff --git a/libraries/adodb/adodb-csv.inc.php b/libraries/adodb/adodb-csv.inc.php new file mode 100755 index 00000000..e056df09 --- /dev/null +++ b/libraries/adodb/adodb-csv.inc.php @@ -0,0 +1,147 @@ +_insertid; + } + + function _affectedrows() + { + return $this->_affectedrows; + } + + function &MetaDatabases() + { + return false; + } + + + // returns true or false + function _connect($argHostname, $argUsername, $argPassword, $argDatabasename) + { + $this->_url = $argHostname; + return true; + } + + // returns true or false + function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename) + { + $this->_url = $argHostname; + return true; + } + + function &MetaColumns($table) + { + return false; + } + + + // parameters use PostgreSQL convention, not MySQL + function &SelectLimit($sql,$nrows=-1,$offset=-1,$arg3=false) + { + $url = $this->_url.'?sql='.urlencode($sql)."&nrows=$nrows&$offset=&offset&arg3=".urlencode($arg3); + $err = false; + $rs = csv2rs($url,$err,false); + if ($this->debug) print "$urlToo many parameters to ibase query $sql
"; + case 5: $ret = ibase_query($this->_transactionID,$sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4]); break; + } + } else $ret = ibase_query($this->_transactionID,$sql); + } else { + if (is_array($iarr)) { + switch(sizeof($iarr)) { + case 1: $ret = ibase_query($this->_connectionID,$sql,$iarr[0]); break; + case 2: $ret = ibase_query($this->_connectionID,$sql,$iarr[0],$iarr[1]); break; + case 3: $ret = ibase_query($this->_connectionID,$sql,$iarr[0],$iarr[1],$iarr[2]); break; + case 4: $ret = ibase_query($this->_connectionID,$sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3]); break; + default: print "Too many parameters to ibase query $sql
"; + case 5: $ret = ibase_query($this->_connectionID,$sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4]); break; + + } + } else $ret = ibase_query($this->_connectionID,$sql); + if ($ret === true) ibase_commit($this->_connectionID); + } + $this->_handleerror(); + return $ret; + } + + // returns true or false + function _close() + { + if ($this->autoCommit) ibase_commit($this->_connectionID); + else ibase_rollback($this->_connectionID); + + return @ibase_close($this->_connectionID); + } + + // returns array of ADOFieldObjects for current table + function &MetaColumns($table) + { + + if ($this->metaColumnsSQL) { + + $rs = $this->Execute(sprintf($this->metaColumnsSQL,strtoupper($table))); + if ($rs === false) return false; + + $retarr = array(); + while (!$rs->EOF) { //print_r($rs->fields); + $fld = new ADOFieldObject(); + $fld->name = $rs->fields[0]; + $tt = $rs->fields[1]; + switch($tt) + { + case 7: + case 8: + case 9:$tt = 'INTEGER'; break; + case 10: + case 27: + case 11:$tt = 'FLOAT'; break; + default: + case 40: + case 14:$tt = 'CHAR'; break; + case 35:$tt = 'DATE'; break; + case 37:$tt = 'VARCHAR'; break; + case 261:$tt = 'BLOB'; break; + case 13: + case 35:$tt = 'TIMESTAMP'; break; + } + $fld->type = $tt; + $fld->max_length = $rs->fields[2]; + $retarr[strtoupper($fld->name)] = $fld; + + $rs->MoveNext(); + } + $rs->Close(); + return $retarr; + } + return false; + } + + // warning - this code is experimental and might not be available in the future + function &BlobEncode( $blob ) + { + $blobid = ibase_blob_create( $this->_connectionID); + ibase_blob_add( $blobid, $blob ); + return ibase_blob_close( $blobid ); + } + + // warning - this code is experimental and might not be available in the future + function &BlobDecode( $blob ) + { + $blobid = ibase_blob_open( $blob ); + $realblob = ibase_blob_get( $blobid,299999); // 2nd param is max size of blob -- Kevin BoilletConnect: 1st argument should be left blank for $this->databaseType
"; + $this->_connectionID = OCIlogon($argUsername,$argPassword, $argDatabasename); + if ($this->_connectionID === false) return false; + if ($this->_initdate) { + $this->Execute("ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD'"); + } + return true; + } + // returns true or false + function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename) + { + if($argHostname) { // added by Jorma TuomainenConnect: 1st argument should be left blank for $this->databaseType
"; + $this->_connectionID = ora_logon($argUsername,$argPassword); + if ($this->_connectionID === false) return false; + if ($this->autoCommit) ora_commiton($this->_connectionID); + if ($this->_initdate) $this->Execute("ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD'"); + + return true; + } + // returns true or false + function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename) + { + if ($argHostname) putenv("ORACLE_HOME=$argHostname"); + //if ($argHostname) print "PConnect: 1st argument should be left blank for $this->databaseType
"; + $this->_connectionID = ora_plogon($argUsername,$argPassword); + if ($this->_connectionID === false) return false; + if ($this->autoCommit) ora_commiton($this->_connectionID); + if ($this->_initdate) $this->Execute("ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD'"); + + return true; + } + + // returns query ID if successful, otherwise false + function _query($sql,$inputarr) + { + $curs = ora_open($this->_connectionID); + + if ($curs === false) return false; + $this->_curs = $curs; + if (!ora_parse($curs,$sql)) return false; + if (ora_exec($curs)) return $curs; + + @ora_close($curs); + return false; + } + + // returns true or false + function _close() + { + if (!$this->autoCommit) ora_rollback($this->_connectionID); + return @ora_close($this->_connectionID); + } + + +} + +/*-------------------------------------------------------------------------------------- + Class Name: Recordset +--------------------------------------------------------------------------------------*/ + +class ADORecordset_oracle extends ADORecordSet { + + var $databaseType = "oracle"; + var $bind = false; + + function ADORecordset_oracle($queryID) + { + $this->_queryID = $queryID; + + $this->_inited = true; + $this->fields = array(); + if ($queryID) { + $this->_currentRow = 0; + $this->EOF = !$this->_fetch(); + @$this->_initrs(); + } else { + $this->_numOfRows = 0; + $this->_numOfFields = 0; + $this->EOF = true; + } + + return $this->_queryID; + } + + + + /* Returns: an object containing field information. + Get column information in the Recordset object. fetchField() can be used in order to obtain information about + fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by + fetchField() is retrieved. */ + + function FetchField($fieldOffset = -1) + { + $fld = new ADOFieldObject; + $fld->name = ora_columnname($this->_queryID, $fieldOffset); + $fld->type = ora_columntype($this->_queryID, $fieldOffset); + $fld->max_length = ora_columnsize($this->_queryID, $fieldOffset); + return $fld; + } + + /* Use associative array to get fields array */ + function Fields($colname) + { + if (!$this->bind) { + $this->bind = array(); + for ($i=0; $i < $this->_numOfFields; $i++) { + $o = $this->FetchField($i); + $this->bind[strtoupper($o->name)] = $i; + } + } + + return $this->fields[$this->bind[strtoupper($colname)]]; + + } + + function _initrs() + { + $this->_numOfRows = -1; + $this->_numOfFields = @ora_numcols($this->_queryID); + } + + + function _seek($row) + { + return false; + } + + function _fetch($ignore_fields=false) { + // should remove call by reference, but ora_fetch_into requires it in 4.0.3pl1 + return @ora_fetch_into($this->_queryID,&$this->fields,ORA_FETCHINTO_NULLS); + } + + /* close() only needs to be called if you are worried about using too much memory while your script + is running. All associated result memory for the specified result identifier will automatically be freed. */ + + function _close() { + return @ora_close($this->_queryID); + } + + function MetaType($t,$len=-1) + { + switch (strtoupper($t)) { + case 'VARCHAR': + case 'VARCHAR2': + case 'CHAR': + case 'VARBINARY': + case 'BINARY': + if ($len <= $this->blobSize) return 'C'; + case 'LONG': + case 'LONG VARCHAR': + case 'CLOB': + return 'X'; + case 'LONG RAW': + case 'LONG VARBINARY': + case 'BLOB': + return 'B'; + + case 'DATE': return 'D'; + + //case 'T': return 'T'; + + case 'BIT': return 'L'; + case 'INT': + case 'SMALLINT': + case 'INTEGER': return 'I'; + default: return 'N'; + } + } +} +?> \ No newline at end of file diff --git a/libraries/adodb/adodb-pear.inc.php b/libraries/adodb/adodb-pear.inc.php new file mode 100755 index 00000000..6d8385d9 --- /dev/null +++ b/libraries/adodb/adodb-pear.inc.php @@ -0,0 +1,348 @@ + | + * and Tomas V.V.CoxSession Update: '.$ADODB_SESS_CONN->ErrorMsg().'
'; + + if ($ADODB_SESS_INSERT || $rs === false) { + $qry = "INSERT INTO $ADODB_SESSION_TBL(sesskey,expiry,data) VALUES ('$key',$expiry,'$val')"; + $rs = $ADODB_SESS_CONN->Execute($qry); + if ($rs) $rs->Close(); + else print 'Session Insert: '.$ADODB_SESS_CONN->ErrorMsg().'
'; + } + // bug in access driver (could be odbc?) means that info is not commited + // properly unless select statement executed in Win2000 + if ($ADODB_SESS_CONN->databaseType == 'access') $rs = $ADODB_SESS_CONN->Execute("select sesskey from $ADODB_SESSION_TBL WHERE sesskey='$key'"); + + return isset($rs); +} + +function adodb_sess_destroy($key) +{ + global $ADODB_SESS_CONN, $ADODB_SESSION_TBL; + + $qry = "DELETE FROM $ADODB_SESSION_TBL WHERE sesskey = '$key'"; + $rs = $ADODB_SESS_CONN->Execute($qry); + if ($rs) $rs->Close(); + return $rs; +} + +function adodb_sess_gc($maxlifetime) { + global $ADODB_SESS_CONN, $ADODB_SESSION_TBL; + + $qry = "DELETE FROM $ADODB_SESSION_TBL WHERE expiry < " . time(); + $rs = $ADODB_SESS_CONN->Execute($qry); + if ($rs) $rs->Close(); + + // suggested by Cameron, "GaM3R"\$HTTP_SESSION_VARS['AVAR']={$HTTP_SESSION_VARS['AVAR']}
"; +} + +?> diff --git a/libraries/adodb/adodb-sybase.inc.php b/libraries/adodb/adodb-sybase.inc.php new file mode 100755 index 00000000..1bd01b00 --- /dev/null +++ b/libraries/adodb/adodb-sybase.inc.php @@ -0,0 +1,215 @@ +Execute('select @@identity'); + if ($rs == false || $rs->EOF) return false; + $id = $rs->fields[0]; + $rs->Close(); + return $id; + } + // might require begintrans -- committrans + function _affectedrows() + { + $rs = $this->Execute('select @@rowcount'); + if ($rs == false || $rs->EOF) return false; + $id = $rs->fields[0]; + $rs->Close(); + return $id; + } + + + function BeginTrans() + { + $this->Execute('BEGIN TRAN'); + return true; + } + + function CommitTrans() + { + $this->Execute('COMMIT TRAN'); + return true; + } + + function RollbackTrans() + { + $this->Execute('ROLLBACK TRAN'); + return true; + } + + + function SelectDB($dbName) { + $this->databaseName = $dbName; + if ($this->_connectionID) { + return @sybase_select_db($dbName); + } + else return false; + } + + /* Returns: the last error message from previous database operation + Note: This function is NOT available for Microsoft SQL Server. */ + + function ErrorMsg() { + $this->_errorMsg = sybase_get_last_message(); + return $this->_errorMsg; + } + + // returns true or false + function _connect($argHostname, $argUsername, $argPassword, $argDatabasename) + { + $this->_connectionID = sybase_connect($argHostname,$argUsername,$argPassword); + if ($this->_connectionID === false) return false; + if ($argDatabasename) return $this->SelectDB($argDatabasename); + return true; + } + // returns true or false + function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename) + { + $this->_connectionID = sybase_pconnect($argHostname,$argUsername,$argPassword); + if ($this->_connectionID === false) return false; + if ($argDatabasename) return $this->SelectDB($argDatabasename); + return true; + } + + // returns query ID if successful, otherwise false + function _query($sql,$inputarr) + { + //@sybase_free_result($this->_queryID); + return sybase_query($sql,$this->_connectionID); + } + + // returns true or false + function _close() + { + return @sybase_close($this->_connectionID); + } + + +} + +/*-------------------------------------------------------------------------------------- + Class Name: Recordset +--------------------------------------------------------------------------------------*/ +global $ADODB_sybase_mths; +$ADODB_sybase_mths = array('JAN'=>1,'FEB'=>2,'MAR'=>3,'APR'=>4,'MAY'=>5,'JUN'=>6,'JUL'=>7,'AUG'=>8,'SEP'=>9,'OCT'=>10,'NOV'=>11,'DEC'=>12); + +class ADORecordset_sybase extends ADORecordSet { + + var $databaseType = "sybase"; + var $canSeek = true; + // _mths works only in non-localised system + var $_mths = array('JAN'=>1,'FEB'=>2,'MAR'=>3,'APR'=>4,'MAY'=>5,'JUN'=>6,'JUL'=>7,'AUG'=>8,'SEP'=>9,'OCT'=>10,'NOV'=>11,'DEC'=>12); + + function ADORecordset_sybase($id) + { + return $this->ADORecordSet($id); + } + + + /* Returns: an object containing field information. + Get column information in the Recordset object. fetchField() can be used in order to obtain information about + fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by + fetchField() is retrieved. */ + function &FetchField($fieldOffset = -1) + { + if ($fieldOffset != -1) { + $o = @sybase_fetch_field($this->_queryID, $fieldOffset); + } + else if ($fieldOffset == -1) { /* The $fieldOffset argument is not provided thus its -1 */ + $o = @sybase_fetch_field($this->_queryID); + } + // older versions of PHP did not support type, only numeric + if ($o && !isset($o->type)) $o->type = ($o->numeric) ? 'float' : 'varchar'; + return $o; + } + + function _initrs() + { + global $ADODB_COUNTRECS; + $this->_numOfRows = ($ADODB_COUNTRECS)? @sybase_num_rows($this->_queryID):-1; + $this->_numOfFields = @sybase_num_fields($this->_queryID); + } + + function _seek($row) + { + return @sybase_data_seek($this->_queryID, $row); + } + + function _fetch($ignore_fields=false) { + $this->fields = @sybase_fetch_array($this->_queryID); + return ($this->fields == true); + } + + /* close() only needs to be called if you are worried about using too much memory while your script + is running. All associated result memory for the specified result identifier will automatically be freed. */ + function _close() { + return @sybase_free_result($this->_queryID); + } + + // sybase/mssql uses a default date like Dec 30 2000 12:00AM + function UnixDate($v) + { + global $ADODB_sybase_mths; + //Dec 30 2000 12:00AM + // added fix by Toni for day 15 Mar 2001 + if (!ereg( "([A-Za-z]{3})[-/\. ]([0-9 ]{1,2})[-/\. ]([0-9]{4}))" + ,$v, $rr)) return parent::UnixDate($v); + + if ($rr[3] <= 1970) return 0; + + $themth = substr(strtoupper($rr[1]),0,3); + $themth = $ADODB_sybase_mths[$themth]; + if ($themth <= 0) return false; + // h-m-s-MM-DD-YY + return mktime(0,0,0,$themth,$rr[2],$rr[3]); + } + + function UnixTimeStamp($v) + { + global $ADODB_sybase_mths; + //Dec 30 2000 12:00AM + if (!ereg( "([A-Za-z]{3})[-/\. ]([0-9]{1,2})[-/\. ]([0-9]{4}) +([0-9]{1,2}):([0-9]{1,2}) *([apAP]{0,1})" + ,$v, $rr)) return parent::UnixTimeStamp($v); + if ($rr[3] <= 1970) return 0; + + $themth = substr(strtoupper($rr[1]),0,3); + $themth = $ADODB_sybase_mths[$themth]; + if ($themth <= 0) return false; + + if (strtoupper($rr[6]) == 'P') { + if ($rr[4]<12) $rr[4] += 12; + } else { + if ($rr[4]==12) $rr[4] = 0; + } + // h-m-s-MM-DD-YY + return mktime($rr[4],$rr[5],0,$themth,$rr[2],$rr[3]); + } + +} +?> \ No newline at end of file diff --git a/libraries/adodb/adodb-vfp.inc.php b/libraries/adodb/adodb-vfp.inc.php new file mode 100755 index 00000000..dcde32cf --- /dev/null +++ b/libraries/adodb/adodb-vfp.inc.php @@ -0,0 +1,79 @@ +replaceQuote,$s))."'"; + return "'".$s."'"; + } + + // TOP requires ORDER BY for VFP + function &SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$arg3=false,$secs2cache=0) + { + if (!preg_match('/ORDER[ \t\r\n]+BY/i',$sql)) $sql .= ' ORDER BY 1'; + return ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$arg3,$secs2cache); + } + +}; + + +class ADORecordSet_vfp extends ADORecordSet_odbc { + + var $databaseType = "vfp"; + + + function ADORecordSet_vfp($id) + { + return $this->ADORecordSet_odbc($id); + } + + function MetaType($t,$len=-1) + { + switch (strtoupper($t)) { + case 'C': + if ($len <= $this->blobSize) return 'C'; + case 'M': + return 'X'; + + case 'D': return 'D'; + + case 'T': return 'T'; + + case 'L': return 'L'; + + case 'I': return 'I'; + + default: return 'N'; + } + } +} + +} //define +?> \ No newline at end of file diff --git a/libraries/adodb/adodb.gif b/libraries/adodb/adodb.gif new file mode 100755 index 00000000..47b6f2d4 Binary files /dev/null and b/libraries/adodb/adodb.gif differ diff --git a/libraries/adodb/adodb.inc.php b/libraries/adodb/adodb.inc.php new file mode 100755 index 00000000..299a4f9f --- /dev/null +++ b/libraries/adodb/adodb.inc.php @@ -0,0 +1,2332 @@ +Bad $rs in %s. Connection or SQL invalid. Try using $connection->debug=true;'); + + define('ADODB_FETCH_DEFAULT',0); + define('ADODB_FETCH_NUM',1); + define('ADODB_FETCH_ASSOC',2); + define('ADODB_FETCH_BOTH',3); + + GLOBAL + $ADODB_vers, // database version + $ADODB_Database, // last database driver used + $ADODB_COUNTRECS, // count number of records returned - slows down query + $ADODB_CACHE_DIR, // directory to cache recordsets + $ADODB_FETCH_MODE; // DEFAULT, NUM, ASSOC or BOTH. Default follows native driver default... + + $ADODB_FETCH_MODE = ADODB_FETCH_DEFAULT; + /** + * SET THE VALUE BELOW TO THE DIRECTORY WHERE THIS FILE RESIDES + * ADODB_RootPath has been renamed ADODB_DIR + */ + if (!defined('ADODB_DIR')) define('ADODB_DIR',dirname(__FILE__)); + + if (!isset($ADODB_CACHE_DIR)) $ADODB_CACHE_DIR = '/tmp'; + else if (strpos($ADODB_CACHE_DIR,':/') !== false) die("Illegal \$ADODB_CACHE_DIR"); + + //============================================================================================== + // CHANGE NOTHING BELOW UNLESS YOU ARE CODING + //============================================================================================== + + // using PHPCONFIG protocol overrides ADODB_DIR + //if (isset($PHPCONFIG_DIR)) $ADODB_DIR=$PHPCONFIG_DIR.'/../adodb'; + + srand(((double)microtime())*1000000); + /** + * Name of last database driver loaded into memory. + */ + $ADODB_Database = ''; + + /** + * ADODB version as a string. + */ + $ADODB_vers = 'V1.53 13 Nov 2001 (c) 2000, 2001 John Lim (jlim@natsoft.com.my). All rights reserved. Released BSD & LGPL.'; + + /** + * Determines whether recordset->RecordCount() is used. + * Set to false for highest performance -- RecordCount() will always return -1 then. + */ + $ADODB_COUNTRECS = true; + + /** + * Helper class for FetchFields -- holds info on a column + */ + class ADOFieldObject { + var $name = ''; + var $max_length=0; + var $type=""; + } + + + /** + * Connection object. For connecting to databases, and executing queries. + */ + class ADOConnection { + /* + * PUBLIC VARS + */ + var $dataProvider = 'native'; + var $databaseType = ''; // RDBMS currently in use, eg. odbc, mysql, mssql + var $database = ''; // Name of database to be used. + var $host = ''; //The hostname of the database server + var $user = ''; // The username which is used to connect to the database server. + var $password = ''; // Password for the username + var $debug = false; // if set to true will output sql statements + var $maxblobsize = 8000; // maximum size of blobs or large text fields -- some databases die otherwise like foxpro + var $concat_operator = '+'; // default concat operator -- change to || for Oracle/Interbase + var $fmtDate = "'Y-m-d'"; // used by DBDate() as the default date format used by the database + var $fmtTimeStamp = "'Y-m-d, h:i:s A'"; // used by DBTimeStamp as the default timestamp fmt. + var $true = '1'; // string that represents TRUE for a database + var $false = '0'; // string that represents FALSE for a database + var $replaceQuote = "\\'"; // string to use to replace quotes + var $hasInsertID = false; // supports autoincrement ID? + var $hasAffectedRows = false; // supports affected rows for update/delete? + var $autoCommit = true; + var $charSet=false; // character set to use - only for interbase + var $metaTablesSQL = ''; + var $hasTop = false; // support mssql/access SELECT TOP 10 * FROM TABLE + var $hasLimit = false; // support pgsql/mysql SELECT * FROM TABLE LIMIT 10 + var $readOnly = false; // this is a readonly database ? + var $hasMoveFirst = false; + var $hasGenID = false; // can generate sequences using GenID(); + var $genID = false; // sequence id used by GenID(); + var $raiseErrorFn = false; + + /* + * PRIVATE VARS + */ + var $_connectionID = false; // The returned link identifier whenever a successful database connection is made. */ + + var $_errorMsg = ''; // A variable which was used to keep the returned last error message. The value will + //then returned by the errorMsg() function + + var $_queryID = false; // This variable keeps the last created result link identifier. */ + + var $_isPersistentConnection = false; // A boolean variable to state whether its a persistent connection or normal connection. */ + + var $_bindInputArray = false; // set to true if ADOConnection.Execute() permits binding of array parameters. + + /** + * Constructor + */ + function ADOConnection() + { + die('Virtual Class -- cannot instantiate'); + } + + /** + * Connect to database + * + * @param [argHostname] Host to connect to + * @param [argUsername] Userid to login + * @param [argPassword] Associated password + * @param [argDatabaseName] database + * + * @return true or false + */ + function Connect($argHostname = "", $argUsername = "", $argPassword = "", $argDatabaseName = "") { + if ($argHostname != "") $this->host = $argHostname; + if ($argUsername != "") $this->user = $argUsername; + if ($argPassword != "") $this->password = $argPassword; // not stored for security reasons + if ($argDatabaseName != "") $this->database = $argDatabaseName; + + if ($this->_connect($this->host, $this->user, $this->password, $this->database)) + return true; + + if ($fn = $this->raiseErrorFn) { + $fn($this->databaseType,'CONNECT',$this->ErrorNo(),$this->ErrorMsg(),$this->host,$this->database); + } + if ($this->debug) print $this->host.': '.$this->ErrorMsg().'$ssInsert_ID error
'; + return false; + } + + /** + * @return # rows affected by UPDATE/DELETE + */ + function Affected_Rows() + { + if ($this->hasAffectedRows) { + $val = $this->_affectedrows(); + return ($val < 0) ? false : $val; + } + + if ($this->debug) print 'Affected_Rows error
'; + return false; + } + + /** + * @return the last error message + */ + function ErrorMsg() + { + return '!! '.strtoupper($this->dataProvider.' '.$this->databaseType).': '.$this->_errorMsg; + } + + + /** + * @return the last error number. Normally 0 means no error. + */ + function ErrorNo() + { + return ($this->_errorMsg) ? -1 : 0; + } + + /** + * @returns an array with the primary key columns in it. + */ + function MetaPrimaryKeys($table) + { + return false; + } + + /** + * Choose a database to connect to. Many databases do not support this. + * + * @param dbName is the name of the database to select + * @return true or false + */ + function SelectDB($dbName) + {return false;} + + + /** + * Will select, getting rows from $offset (1-based), for $nrows. + * This simulates the MySQL "select * from table limit $offset,$nrows" , and + * the PostgreSQL "select * from table limit $nrows offset $offset". Note that + * MySQL and PostgreSQL parameter ordering is the opposite of the other. + * eg. + * SelectLimit('select * from table',3); will return rows 1 to 3 (1-based) + * SelectLimit('select * from table',3,2); will return rows 3 to 5 (1-based) + * + * Uses SELECT TOP for Microsoft databases, and FIRST_ROWS CBO hint for Oracle 8+ + * BUG: Currently SelectLimit fails with $sql with LIMIT or TOP clause already set + * + * @param sql + * @param [offset] is the row to start calculations from (1-based) + * @param [rows] is the number of rows to get + * @param [inputarr] array of bind variables + * @param [arg3] is a private parameter only used by jlim + * @param [secs2cache] is a private parameter only used by jlim + * @return the recordset ($rs->databaseType == 'array') + */ + function &SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$arg3=false,$secs2cache=0) + { + if ($this->hasTop && $nrows > 0 && $offset <= 0) { + // suggested by Reinhard Balling. Access requires top after distinct + $sql = eregi_replace( + '(^select[\\t\\n ]*(distinct|distinctrow )?)','\\1 top '.$nrows.' ',$sql); + if ($secs2cache>0) return $this->CacheExecute($secs2cache, $sql,$inputarr,$arg3); + else return $this->Execute($sql,$inputarr,$arg3); + } else if ($this->dataProvider == 'oci8') { + $sql = eregi_replace('^select','SELECT /*+FIRST_ROWS*/',$sql); + if ($offset <= 0) { + /*if (preg_match('/\bwhere\b/i',$sql)) { + $sql = preg_replace('/where/i',"where rownum <= $nrows and ",$sql); + } else*/ + // doesn't work becoz sort is after rownum is executed - also preg_replace + // is a heuristic that might not work if there is an or + $sql = "select * from ($sql) where rownum <= :lens_sellimit_rownum"; + $inputarr['lens_sellimit_rownum'] = $nrows; + }/* else { + # THIS DOES NOT WORK -- WHY? + $sql = "select * from ($sql) where rownum between :lens_sellimit_rownum1 and :lens_sellimit_rownum2"; + $end = $offset+$nrows; + if ($offset < $end) { + $inputarr['lens_sellimit_rownum1'] = $offset; + $inputarr['lens_sellimit_rownum2'] = $end; + } else { + $inputarr['lens_sellimit_rownum1'] = $end; + $inputarr['lens_sellimit_rownum2'] = $offset; + } + $offset = -1; + $this->debug=true; + }*/ + } + if ($secs2cache>0) $rs = &$this->CacheExecute($secs2cache,$sql,$inputarr,$arg3); + else $rs = &$this->Execute($sql,$inputarr,$arg3); + if ($rs && !$rs->EOF) { + return $this->_rs2rs($rs,$nrows,$offset); + } + //print_r($rs); + return $rs; + } + + /** + * Convert recordset to an array recordset + * input recordset's cursor should be at beginning, and + * old $rs will be closed. + * + * @param rs the recordset to copy + * @param [nrows] number of rows to retrieve (optional) + * @param [offset] offset by number of rows (optional) + * @return the new recordset + */ + function &_rs2rs(&$rs,$nrows=-1,$offset=-1) + { + + $arr = &$rs->GetArrayLimit($nrows,$offset); + $flds = array(); + for ($i=0, $max=$rs->FieldCount(); $i < $max; $i++) + $flds[] = &$rs->FetchField($i); + + $rs->Close(); + $rs2 = new ADORecordSet_array(); + + $rs2->InitArrayFields($arr,$flds); + return $rs2; + } + + /** + * Return first element of first row of sql statement. Recordset is disposed + * for you. + * + * @param sql SQL statement + * @param [inputarr] input bind array + */ + function GetOne($sql,$inputarr=false) + { + $rs = $this->Execute($sql,$inputarr); + if ($rs && !$rs->EOF) { + $rs->Close(); + return $rs->fields[0]; + } + return false; + } + + /** + * Return all rows. Compat with PEAR DB + * + * @param sql SQL statement + * @param [inputarr] input bind array + */ + function GetAll($sql,$inputarr=false) + { + $rs = $this->Execute($sql,$inputarr); + if (!$rs) + if (defined('ADODB_PEAR')) return ADODB_PEAR_Error(); + else return false; + return $rs->GetArray(); + } + + /** + * Return one row of sql statement. Recordset is disposed for you. + * + * @param sql SQL statement + * @param [inputarr] input bind array + */ + function GetRow($sql,$inputarr=false) + { + $rs = $this->Execute($sql,$inputarr); + if ($rs && !$rs->EOF) { + $rs->Close(); + return $rs->fields; + } + return false; + } + + + + /** + * Will select, getting rows from $offset (1-based), for $nrows. + * This simulates the MySQL "select * from table limit $offset,$nrows" , and + * the PostgreSQL "select * from table limit $nrows offset $offset". Note that + * MySQL and PostgreSQL parameter ordering is the opposite of the other. + * eg. + * CacheSelectLimit(15,'select * from table',3); will return rows 1 to 3 (1-based) + * CacheSelectLimit(15,'select * from table',3,2); will return rows 3 to 5 (1-based) + * + * BUG: Currently CacheSelectLimit fails with $sql with LIMIT or TOP clause already set + * + * @param secs2cache seconds to cache data, set to 0 to force query + * @param sql + * @param [offset] is the row to start calculations from (1-based) + * @param [nrows] is the number of rows to get + * @param [inputarr] array of bind variables + * @param [arg3] is a private parameter only used by jlim + * @return the recordset ($rs->databaseType == 'array') + */ + function &CacheSelectLimit($secs2cache,$sql,$nrows=-1,$offset=-1,$inputarr=false, $arg3=false) + { + return $this->SelectLimit($sql,$nrows,$offset,$inputarr,$arg3,$secs2cache); + } + + function CacheFlush($sql) + { + $f = $this->_gencachename($sql); + adodb_write_file($f,''); + @unlink($f); + } + + function _gencachename($sql) + { + global $ADODB_CACHE_DIR; + + return $ADODB_CACHE_DIR.'/adodb_'.md5($sql.$this->databaseType.$this->database.$this->user).'.cache'; + } + /** + * Execute SQL, caching recordsets. + * + * @param secs2cache seconds to cache data, set to 0 to force query + * @param sql SQL statement to execute + * @param [inputarr] holds the input data to bind to + * @param [arg3] reserved for john lim for future use + * @return RecordSet or false + */ + function &CacheExecute($secs2cache,$sql,$inputarr=false,$arg3=false) + { + // cannot cache if $inputarr set + if ($inputarr) return $this->Execute($sql, $inputarr, $arg3); + + $md5file = $this->_gencachename($sql); + $err = ''; + + if ($secs2cache > 0)$rs = &csv2rs($md5file,$err,$secs2cache); + else { + $err='Timeout 1'; + $rs = false; + } + + if (!$rs) { + if ($this->debug) print " $md5file cache failure: $err