From 59d1b4d8afcf2176378cf896456373c1f2e7ff24 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Mon, 14 Jun 2010 00:41:04 +0200 Subject: [PATCH] first bunch of changes toward nested set groups added some general improvements to the database model --- backend/lib/model/channel.php | 20 ++- backend/lib/model/databaseobject.php | 83 +++++---- backend/lib/model/group.php | 42 ++--- backend/lib/model/nesteddatabaseobject.php | 84 +++++++++ backend/lib/model/user.php | 6 +- backend/volkszaehler.conf.default.php | 11 +- share/sql/demo/data.structure.dummy.sql | 190 ++++++++++----------- share/sql/mysql.sql | 116 ++++++------- share/tools/tests.php | 4 +- 9 files changed, 313 insertions(+), 243 deletions(-) create mode 100644 backend/lib/model/nesteddatabaseobject.php diff --git a/backend/lib/model/channel.php b/backend/lib/model/channel.php index f9adea8..e4eadf8 100644 --- a/backend/lib/model/channel.php +++ b/backend/lib/model/channel.php @@ -150,7 +150,17 @@ abstract class Channel extends DatabaseObject implements ChannelInterface { if (!class_exists($object['type']) || !is_subclass_of($object['type'], 'Channel')) { throw new InvalidArgumentException('\'' . $object['type'] . '\' is not a valid channel type'); } - return new $object['type']((array) $object); + + // code duplication from DatabaseObject::factory() + if (!isset(self::$instances[self::table])) { + self::$instances[self::table] = array(); + } + + if (!isset(self::$instances[self::table][$object['id']])) { + self::$instances[self::table][$object['id']] = new $object['type']($object); // create singleton instance of database object + } + + return self::$instances[self::table][$object['id']]; // return singleton instance of database object } public function __get($key) { @@ -180,16 +190,16 @@ abstract class Channel extends DatabaseObject implements ChannelInterface { } static protected function buildFilterQuery($filters, $conjunction, $columns = array('id')) { - $sql = 'SELECT ' . static::table . '.* FROM ' . static::table; + $sql = 'SELECT ' . self::table . '.* FROM ' . self::table; // join groups if (key_exists('group', $filters)) { - $sql .= ' LEFT JOIN group_channel AS rel ON rel.channel_id = ' . static::table . '.id'; - $filters['group_id'] = $filters['group']; + $sql .= ' LEFT JOIN channels_in_groups ON channels_in_groups.channel_id = ' . self::table . '.id'; + $filters['channels_in_groups.group_id'] = $filters['group']; unset($filters['group']); } - $sql .= static::buildFilterCondition($filters, $conjunction); + $sql .= self::buildFilterCondition($filters, $conjunction); return $sql; } } \ No newline at end of file diff --git a/backend/lib/model/databaseobject.php b/backend/lib/model/databaseobject.php index 0ec16c0..51c9c89 100644 --- a/backend/lib/model/databaseobject.php +++ b/backend/lib/model/databaseobject.php @@ -25,8 +25,8 @@ abstract class DatabaseObject { private $dirty; // do we need to update the database? private $data = array(); - static private $instances = array(); // singletons of objects - + static protected $instances = array(); // singletons of objects + /* * magic functions */ @@ -44,10 +44,12 @@ abstract class DatabaseObject { } public function __set($key, $value) { // TODO untested - if ($key != 'id') { - $this->data[$key] = $value; - $this->dirty = true; + if ($key == 'id' || $key == 'uuid') { + throw new DatabaseException($key . ' will be generated automatically'); } + + $this->data[$key] = $value; + $this->dirty = true; } final public function __sleep() { @@ -58,34 +60,44 @@ abstract class DatabaseObject { final public function __wakeup() { $this->dbh = Database::getConnection(); } - + final public function __isset($key) { return isset($this->data[$key]); } - - static protected function factory($object) { - return new static($object); - } /* * insert oder update the database representation of the object */ public function save() { if ($this->id) { // just update - foreach ($this->data as $column => $value) { - if ($column != 'id') { - $columns[] = $column . ' = ' . $this->dbh->escape($value); - } - } - - $sql = 'UPDATE ' . static::table . ' SET ' . implode(', ', $columns) . ' WHERE id = ' . (int) $this->id; - $this->dbh->execute($sql); + $this->update(); } else { // insert new row - $sql = 'INSERT INTO ' . static::table . ' (' . implode(', ', array_keys($this->data)) . ') VALUES (' . implode(', ', array_map(array($this->dbh, 'escape'), $this->data)) . ')'; - $this->dbh->execute($sql); - $this->id = $this->dbh->lastInsertId(); + $this->insert(); } + + } + + private function insert() { + $this->uuid = Uuid::mint(); + + $sql = 'INSERT INTO ' . static::table . ' (' . implode(', ', array_keys($this->data)) . ') VALUES (' . implode(', ', array_map(array($this->dbh, 'escape'), $this->data)) . ')'; + $this->dbh->execute($sql); + $this->id = $this->dbh->lastInsertId(); + + $this->dirty = false; + } + + private function update() { + foreach ($this->data as $column => $value) { + if ($column != 'id') { + $columns[] = $column . ' = ' . $this->dbh->escape($value); + } + } + + $sql = 'UPDATE ' . static::table . ' SET ' . implode(', ', $columns) . ' WHERE id = ' . (int) $this->id; + $this->dbh->execute($sql); + $this->dirty = false; } @@ -114,19 +126,31 @@ abstract class DatabaseObject { $this->dbh->execute('DELETE FROM ' . static::table . ' WHERE id = ' . (int) $this->id); // delete from database unset($this->data['id']); } - + /* * simple self::getByFilter() wrapper */ public static function getByUuid($uuid) { $obj = current(self::getByFilter(array('uuid' => $uuid))); - + if ($obj === false) { throw new InvalidArgumentException('No such object!'); } - + return $obj; } + + static protected function factory($object) { + if (!isset(self::$instances[static::table])) { + self::$instances[static::table] = array(); + } + + if (!isset(self::$instances[static::table][$object['id']])) { + self::$instances[static::table][$object['id']] = new static($object); // create singleton instance of database object + } + + return self::$instances[static::table][$object['id']]; // return singleton instance of database object + } /* * data filtering @@ -135,16 +159,9 @@ abstract class DatabaseObject { $sql = static::buildFilterQuery($filters, $conjunction); $result = Database::getConnection()->query($sql); - if (!isset(self::$instances[static::table])) { - self::$instances[static::table] = array(); - } - $instances = array(); foreach ($result as $object) { - if (!isset(self::$instances[static::table][$object['id']])) { - self::$instances[static::table][$object['id']] = static::factory($object); // create singleton instance of database object - } - $instances[$object['id']] = self::$instances[static::table][$object['id']]; // return singleton instance of database object + $instances[$object['id']] = static::factory($object); } return $instances; @@ -153,7 +170,7 @@ abstract class DatabaseObject { static protected function buildFilterQuery($filters, $conjunction) { return 'SELECT ' . static::table . '.* FROM ' . static::table . static::buildFilterCondition($filters, $conjunction); } - + static protected function buildFilterCondition($filters, $conjunction) { $dbh = Database::getConnection(); diff --git a/backend/lib/model/group.php b/backend/lib/model/group.php index 1c5dc95..bf2afa7 100644 --- a/backend/lib/model/group.php +++ b/backend/lib/model/group.php @@ -24,51 +24,41 @@ * * the group class groups users, channels and groups */ -class Group extends DatabaseObject { +class Group extends NestedDatabaseObject { const table = 'groups'; - public function getGroups($recursive = false) { - $groups = Group::getByFilter(array('group' => $this)); - if ($recursive === true) { - foreach ($groups as $subGroup) { - $groups += $subGroup->getGroups(true); - } - } - return $groups; - } - - public function getUsers($recursive = false) { + public function getUsers($recursive = false) { // TODO rework for nested sets $groups[$this->id] = $this; if ($recursive === true) { - $groups += $this->getGroups(true); + $groups += $this->getChilds(); } return User::getByFilter(array('group' => $groups)); } - public function getChannels($recursive = false) { + public function getChannels($recursive = false) { // TODO rework for nested sets $groups[$this->id] = $this; if ($recursive === true) { - $groups += $this->getGroups(true); + $groups += $this->getChilds(); } return Channel::getByFilter(array('group' => $groups)); } - static protected function buildFilterQuery($filters, $conjunction, $columns = array('id')) { - $sql = 'SELECT ' . static::table . '.* FROM ' . static::table; - - // join groups - if (key_exists('group', $filters)) { - $sql .= ' LEFT JOIN group_group AS rel ON rel.child_id = ' . static::table . '.id'; - $filters['parent_id'] = $filters['group']; - unset($filters['group']); - } + static protected function buildFilterQuery($filters, $conjunction, $columns = array('id')) { // TODO rework for nested sets + $sql = 'SELECT ' . self::table . '.* FROM ' . self::table; // join users if (key_exists('user', $filters)) { - $sql .= ' LEFT JOIN group_user AS rel ON rel.group_id = ' . static::table . '.id'; - $filters['user_id'] = $filters['user']; + $sql .= ' LEFT JOIN users_in_groups ON users_in_groups.group_id = ' . self::table . '.id'; + $filters['users_in_groups.user_id'] = $filters['user']; unset($filters['user']); } + + // join channels + if (key_exists('channel', $filters)) { + $sql .= ' LEFT JOIN channels_in_groups ON channels_in_groups.group_id = ' . self::table . '.id'; + $filters['channels_in_groups.channel_id'] = $filters['channel']; + unset($filters['channel']); + } $sql .= static::buildFilterCondition($filters, $conjunction); return $sql; diff --git a/backend/lib/model/nesteddatabaseobject.php b/backend/lib/model/nesteddatabaseobject.php new file mode 100644 index 0000000..b11d991 --- /dev/null +++ b/backend/lib/model/nesteddatabaseobject.php @@ -0,0 +1,84 @@ + + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License (either version 2 or + * version 3) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * For more information on the GPL, please go to: + * http://www.gnu.org/copyleft/gpl.html + */ + +/* + * DatabaseObject which is structured by nested sets + */ +class NestedDatabaseObject extends DatabaseObject { + public function addChild(NestedDatabaseObject $child) { + if (isset($child->id)) { + throw new DatabaseException('group is already part of the tree'); + } + + // TODO start transaction + $this->dbh->execute('UPDATE ' . static::table . ' SET left = left + 2 WHERE left > ' . $this->right); + $this->dbh->execute('UPDATE ' . static::table . ' SET right = right + 2 WHERE right >= ' . $this->right); + + $child->left = $this->right; + $child->right = $this->right + 1; + $child->insert(); + } + + public function getChilds() { + $sql = 'SELECT * FROM ' . static::table . ' WHERE id != ' . $this->id . ' && left BETWEEN ' . $this->left . ' AND ' . $this->right; + $result = $this->dbh->query($sql); + + $groups = array(); + foreach ($result as $group) { + $groups[$group['id']] = static::factory($group); + } + + return $groups; + } + + public function delete() { + $move = floor(($this->right - $this->left) / 2); + $move = 2 * (1 + $move); + + // TODO start transaction + + // delete nodes + $this->dbh->execute('DELETE FROM ' . static::table . ' WHERE AND left BETWEEN ' . $this->left . ' AND ' . $this->right); // TODO SQL92 compilant? + + // move the rest of the nodes ... + $this->dbh->execute('UPDATE ' . static::table . ' SET left = left - ' . $move . ' WHERE left > ' . $this->right); + $this->dbh->execute('UPDATE ' . static::table . ' SET right = right - ' . $move . ' WHERE right > ' . $this->right); + + // TODO unset singleton instances in DatabaseObject::$instances + } + + public function contains(NestedDatabaseObject $child) { // TODO untested + if (array_search($child, $this->getChilds(), true) === false) { + return false; + } + else { + return true; + } + } + + public function moveTo(NestedDatabaseObject $obj) { // TODO implement + // $this->getChilds + // $this->delete + // $group->addChilds + } +} + +?> \ No newline at end of file diff --git a/backend/lib/model/user.php b/backend/lib/model/user.php index e910799..1bc1fcd 100644 --- a/backend/lib/model/user.php +++ b/backend/lib/model/user.php @@ -63,11 +63,11 @@ class User extends DatabaseObject { } static protected function buildQuery($filters, $conjunction, $columns = array('id')) { - $sql = 'SELECT ' . static::table . '.* FROM ' . static::table; + $sql = 'SELECT ' . self::table . '.* FROM ' . self::table; // join groups if (key_exists('group', $filters)) { - $sql .= ' LEFT JOIN group_user AS rel ON rel.user_id = ' . static::table . '.id'; - $filters['group_id'] = $filters['group']; + $sql .= ' LEFT JOIN users_in_groups ON users_in_groups.user_id = ' . self::table . '.id'; + $filters['users_in_groups.group_id'] = $filters['group']; unset($filters['group']); } $sql .= static::buildFilter($filters, $conjunction); diff --git a/backend/volkszaehler.conf.default.php b/backend/volkszaehler.conf.default.php index 458435d..3e3d34e 100644 --- a/backend/volkszaehler.conf.default.php +++ b/backend/volkszaehler.conf.default.php @@ -21,16 +21,19 @@ $config['db']['backend'] = 'mysql'; $config['db']['host'] = 'localhost'; -$config['db']['user'] = 'smreader'; +$config['db']['user'] = 'volkszaehler'; $config['db']['password'] = ''; -$config['db']['database'] = 'volkszaehler'; -$config['db']['prefix'] = 'vz'; +$config['db']['database'] = 'volkszaehler_nested'; -$config['passthru']['enabled'] = true; +$config['passthru']['enabled'] = false; $config['passthru']['url'] = 'http://volkszaehler.org/httplog/httplog.php?&passthru=yes'; + $config['debug'] = false; +// insert configuration into registry Registry::set('config', $config); + +// unset registry from page context unset($config); ?> diff --git a/share/sql/demo/data.structure.dummy.sql b/share/sql/demo/data.structure.dummy.sql index 716f6b3..5ae2bb5 100644 --- a/share/sql/demo/data.structure.dummy.sql +++ b/share/sql/demo/data.structure.dummy.sql @@ -3,7 +3,7 @@ -- http://www.phpmyadmin.net -- -- Host: localhost --- Erstellungszeit: 13. Juni 2010 um 14:22 +-- Erstellungszeit: 14. Juni 2010 um 00:36 -- Server Version: 5.1.41 -- PHP-Version: 5.3.2-1ubuntu4.2 @@ -16,7 +16,7 @@ SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO"; /*!40101 SET NAMES utf8 */; -- --- Datenbank: `volkszaehler` +-- Datenbank: `volkszaehler_nested` -- -- -------------------------------------------------------- @@ -25,7 +25,8 @@ SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO"; -- Tabellenstruktur für Tabelle `channels` -- -CREATE TABLE IF NOT EXISTS `channels` ( +DROP TABLE IF EXISTS `channels`; +CREATE TABLE `channels` ( `id` int(11) NOT NULL AUTO_INCREMENT, `uuid` varchar(36) CHARACTER SET latin1 NOT NULL COMMENT 'Universally Unique Identifier', `type` varchar(255) COLLATE utf8_unicode_ci DEFAULT 'Channel' COMMENT 'maps meter to classname (caseinsensitive)', @@ -33,7 +34,7 @@ CREATE TABLE IF NOT EXISTS `channels` ( `cost` int(11) DEFAULT '0', `description` varchar(255) CHARACTER SET latin1 DEFAULT NULL, PRIMARY KEY (`id`), - UNIQUE KEY `ucid` (`uuid`) + UNIQUE KEY `uuid` (`uuid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='channels with detailed data' AUTO_INCREMENT=22 ; -- @@ -51,11 +52,39 @@ INSERT INTO `channels` (`id`, `uuid`, `type`, `resolution`, `cost`, `description -- -------------------------------------------------------- +-- +-- Tabellenstruktur für Tabelle `channels_in_groups` +-- + +DROP TABLE IF EXISTS `channels_in_groups`; +CREATE TABLE `channels_in_groups` ( + `channel_id` int(11) NOT NULL, + `group_id` int(11) NOT NULL, + KEY `channel_id` (`channel_id`), + KEY `group_id` (`group_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + +-- +-- Daten für Tabelle `channels_in_groups` +-- + +INSERT INTO `channels_in_groups` (`channel_id`, `group_id`) VALUES +(1, 1), +(2, 1), +(17, 3), +(18, 3), +(19, 5), +(20, 5), +(21, 5); + +-- -------------------------------------------------------- + -- -- Tabellenstruktur für Tabelle `data` -- -CREATE TABLE IF NOT EXISTS `data` ( +DROP TABLE IF EXISTS `data`; +CREATE TABLE `data` ( `channel_id` int(11) NOT NULL, `timestamp` bigint(20) NOT NULL COMMENT 'in seconds since 1970', `value` float NOT NULL COMMENT 'absolute sensor value or pulse since last timestamp (dependening on "meters.type")', @@ -6437,95 +6466,30 @@ INSERT INTO `data` (`channel_id`, `timestamp`, `value`) VALUES -- Tabellenstruktur für Tabelle `groups` -- -CREATE TABLE IF NOT EXISTS `groups` ( +DROP TABLE IF EXISTS `groups`; +CREATE TABLE `groups` ( `id` int(11) NOT NULL AUTO_INCREMENT, + `left` int(11) NOT NULL, + `right` int(11) NOT NULL, `uuid` varchar(36) COLLATE utf8_unicode_ci NOT NULL COMMENT 'Universally Unique Identifier', - `description` varchar(255) COLLATE utf8_unicode_ci NOT NULL, + `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL, + `description` text COLLATE utf8_unicode_ci NOT NULL, PRIMARY KEY (`id`), - UNIQUE KEY `ugid` (`uuid`) + UNIQUE KEY `uuid` (`uuid`), + KEY `right` (`right`), + KEY `left` (`left`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=6 ; -- -- Daten für Tabelle `groups` -- -INSERT INTO `groups` (`id`, `uuid`, `description`) VALUES -(1, '6185b05b-72b8-4d14-bbcf-cacadb2e35ec', 'Zähler von Steffen'), -(2, '530171f0-34aa-4787-bc86-0c3ee1a55398', 'Temperatursensoren'), -(3, 'efe83f57-3d41-4cde-9c6b-77783112891b', '1-Wire Sensoren mit digitemp'), -(4, 'c288c9fa-3f81-45f7-9583-0a66d4909436', 'Temperatursensoren Subgruppe'), -(5, '17f3d6fa-44fa-4070-8126-6accc50e3c34', 'Temperatursensoren SubSubgruppe'); - --- -------------------------------------------------------- - --- --- Tabellenstruktur für Tabelle `group_channel` --- - -CREATE TABLE IF NOT EXISTS `group_channel` ( - `channel_id` int(11) NOT NULL, - `group_id` int(11) NOT NULL, - KEY `channel_id` (`channel_id`), - KEY `group_id` (`group_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; - --- --- Daten für Tabelle `group_channel` --- - -INSERT INTO `group_channel` (`channel_id`, `group_id`) VALUES -(1, 1), -(2, 1), -(17, 3), -(18, 3), -(19, 5), -(20, 5), -(21, 5); - --- -------------------------------------------------------- - --- --- Tabellenstruktur für Tabelle `group_group` --- - -CREATE TABLE IF NOT EXISTS `group_group` ( - `parent_id` int(11) NOT NULL, - `child_id` int(11) NOT NULL, - KEY `parent_id` (`parent_id`), - KEY `child_id` (`child_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; - --- --- Daten für Tabelle `group_group` --- - -INSERT INTO `group_group` (`parent_id`, `child_id`) VALUES -(2, 3), -(2, 4), -(4, 5); - --- -------------------------------------------------------- - --- --- Tabellenstruktur für Tabelle `group_user` --- - -CREATE TABLE IF NOT EXISTS `group_user` ( - `group_id` int(11) NOT NULL, - `user_id` int(11) NOT NULL, - `role` enum('member','owner') NOT NULL, - KEY `user_id` (`user_id`), - KEY `group_id` (`group_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- --- Daten für Tabelle `group_user` --- - -INSERT INTO `group_user` (`group_id`, `user_id`, `role`) VALUES -(1, 1, 'member'), -(2, 1, 'member'), -(2, 2, 'member'); +INSERT INTO `groups` (`id`, `left`, `right`, `uuid`, `name`, `description`) VALUES +(1, 0, 9, '6185b05b-72b8-4d14-bbcf-cacadb2e35ec', '', 'Zähler von Steffen'), +(2, 1, 8, '530171f0-34aa-4787-bc86-0c3ee1a55398', '', 'Temperatursensoren'), +(3, 2, 3, 'efe83f57-3d41-4cde-9c6b-77783112891b', '', '1-Wire Sensoren mit digitemp'), +(4, 4, 7, 'c288c9fa-3f81-45f7-9583-0a66d4909436', '', 'Temperatursensoren Subgruppe'), +(5, 5, 6, '17f3d6fa-44fa-4070-8126-6accc50e3c34', '', 'Temperatursensoren SubSubgruppe'); -- -------------------------------------------------------- @@ -6533,7 +6497,8 @@ INSERT INTO `group_user` (`group_id`, `user_id`, `role`) VALUES -- Tabellenstruktur für Tabelle `users` -- -CREATE TABLE IF NOT EXISTS `users` ( +DROP TABLE IF EXISTS `users`; +CREATE TABLE `users` ( `id` int(11) NOT NULL AUTO_INCREMENT, `uuid` varchar(36) COLLATE utf8_unicode_ci NOT NULL COMMENT 'Universally Unique Identifier', `email` varchar(255) CHARACTER SET latin1 NOT NULL COMMENT 'also used for login', @@ -6551,10 +6516,41 @@ INSERT INTO `users` (`id`, `uuid`, `email`, `password`) VALUES (1, '54373541-3560-4d09-9d6e-93072e4fa69a', 'info@steffenvogel.de', '787a154eb0a10fa2053ac11e03b2a792ab5ea676'), (2, '7d1225c4-1ff6-4562-a4c2-14e552d1bb64', 't.vogel@griesm.de', 'a94a8fe5ccb19ba61c4c0873d391e987982fbbd3'); +-- -------------------------------------------------------- + +-- +-- Tabellenstruktur für Tabelle `users_in_groups` +-- + +DROP TABLE IF EXISTS `users_in_groups`; +CREATE TABLE `users_in_groups` ( + `group_id` int(11) NOT NULL, + `user_id` int(11) NOT NULL, + `role` enum('member','owner') NOT NULL, + KEY `user_id` (`user_id`), + KEY `group_id` (`group_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Daten für Tabelle `users_in_groups` +-- + +INSERT INTO `users_in_groups` (`group_id`, `user_id`, `role`) VALUES +(1, 1, 'owner'), +(2, 1, 'member'), +(2, 2, 'owner'); + -- -- Constraints der exportierten Tabellen -- +-- +-- Constraints der Tabelle `channels_in_groups` +-- +ALTER TABLE `channels_in_groups` + ADD CONSTRAINT `channels_in_groups_ibfk_3` FOREIGN KEY (`channel_id`) REFERENCES `channels` (`id`) ON DELETE CASCADE, + ADD CONSTRAINT `channels_in_groups_ibfk_4` FOREIGN KEY (`group_id`) REFERENCES `groups` (`id`) ON DELETE CASCADE; + -- -- Constraints der Tabelle `data` -- @@ -6562,22 +6558,8 @@ ALTER TABLE `data` ADD CONSTRAINT `data_ibfk_1` FOREIGN KEY (`channel_id`) REFERENCES `channels` (`id`) ON DELETE CASCADE; -- --- Constraints der Tabelle `group_channel` +-- Constraints der Tabelle `users_in_groups` -- -ALTER TABLE `group_channel` - ADD CONSTRAINT `group_channel_ibfk_3` FOREIGN KEY (`channel_id`) REFERENCES `channels` (`id`) ON DELETE CASCADE, - ADD CONSTRAINT `group_channel_ibfk_4` FOREIGN KEY (`group_id`) REFERENCES `groups` (`id`) ON DELETE CASCADE; - --- --- Constraints der Tabelle `group_group` --- -ALTER TABLE `group_group` - ADD CONSTRAINT `group_group_ibfk_3` FOREIGN KEY (`parent_id`) REFERENCES `groups` (`id`) ON DELETE CASCADE, - ADD CONSTRAINT `group_group_ibfk_4` FOREIGN KEY (`child_id`) REFERENCES `groups` (`id`) ON DELETE CASCADE; - --- --- Constraints der Tabelle `group_user` --- -ALTER TABLE `group_user` - ADD CONSTRAINT `group_user_ibfk_3` FOREIGN KEY (`group_id`) REFERENCES `groups` (`id`) ON DELETE CASCADE, - ADD CONSTRAINT `group_user_ibfk_4` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE; +ALTER TABLE `users_in_groups` + ADD CONSTRAINT `users_in_groups_ibfk_3` FOREIGN KEY (`group_id`) REFERENCES `groups` (`id`) ON DELETE CASCADE, + ADD CONSTRAINT `users_in_groups_ibfk_4` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE; diff --git a/share/sql/mysql.sql b/share/sql/mysql.sql index 04c5d51..c43874a 100644 --- a/share/sql/mysql.sql +++ b/share/sql/mysql.sql @@ -3,7 +3,7 @@ -- http://www.phpmyadmin.net -- -- Host: localhost --- Erstellungszeit: 13. Juni 2010 um 14:23 +-- Erstellungszeit: 14. Juni 2010 um 00:36 -- Server Version: 5.1.41 -- PHP-Version: 5.3.2-1ubuntu4.2 @@ -16,7 +16,7 @@ SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO"; /*!40101 SET NAMES utf8 */; -- --- Datenbank: `volkszaehler` +-- Datenbank: `volkszaehler_nested` -- -- -------------------------------------------------------- @@ -34,11 +34,25 @@ CREATE TABLE `channels` ( `cost` int(11) DEFAULT '0', `description` varchar(255) CHARACTER SET latin1 DEFAULT NULL, PRIMARY KEY (`id`), - UNIQUE KEY `ucid` (`uuid`) + UNIQUE KEY `uuid` (`uuid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='channels with detailed data'; -- -------------------------------------------------------- +-- +-- Tabellenstruktur für Tabelle `channels_in_groups` +-- + +DROP TABLE IF EXISTS `channels_in_groups`; +CREATE TABLE `channels_in_groups` ( + `channel_id` int(11) NOT NULL, + `group_id` int(11) NOT NULL, + KEY `channel_id` (`channel_id`), + KEY `group_id` (`group_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + +-- -------------------------------------------------------- + -- -- Tabellenstruktur für Tabelle `data` -- @@ -60,57 +74,19 @@ CREATE TABLE `data` ( DROP TABLE IF EXISTS `groups`; CREATE TABLE `groups` ( `id` int(11) NOT NULL AUTO_INCREMENT, + `left` int(11) NOT NULL, + `right` int(11) NOT NULL, `uuid` varchar(36) COLLATE utf8_unicode_ci NOT NULL COMMENT 'Universally Unique Identifier', - `description` varchar(255) COLLATE utf8_unicode_ci NOT NULL, + `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL, + `description` text COLLATE utf8_unicode_ci NOT NULL, PRIMARY KEY (`id`), - UNIQUE KEY `ugid` (`uuid`) + UNIQUE KEY `uuid` (`uuid`), + KEY `right` (`right`), + KEY `left` (`left`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; -- -------------------------------------------------------- --- --- Tabellenstruktur für Tabelle `group_channel` --- - -DROP TABLE IF EXISTS `group_channel`; -CREATE TABLE `group_channel` ( - `channel_id` int(11) NOT NULL, - `group_id` int(11) NOT NULL, - KEY `channel_id` (`channel_id`), - KEY `group_id` (`group_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; - --- -------------------------------------------------------- - --- --- Tabellenstruktur für Tabelle `group_group` --- - -DROP TABLE IF EXISTS `group_group`; -CREATE TABLE `group_group` ( - `parent_id` int(11) NOT NULL, - `child_id` int(11) NOT NULL, - KEY `parent_id` (`parent_id`), - KEY `child_id` (`child_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; - --- -------------------------------------------------------- - --- --- Tabellenstruktur für Tabelle `group_user` --- - -DROP TABLE IF EXISTS `group_user`; -CREATE TABLE `group_user` ( - `group_id` int(11) NOT NULL, - `user_id` int(11) NOT NULL, - `role` enum('member','owner') NOT NULL, - KEY `user_id` (`user_id`), - KEY `group_id` (`group_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- -------------------------------------------------------- - -- -- Tabellenstruktur für Tabelle `users` -- @@ -126,10 +102,32 @@ CREATE TABLE `users` ( UNIQUE KEY `uuid` (`uuid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='users with detailed data'; +-- -------------------------------------------------------- + +-- +-- Tabellenstruktur für Tabelle `users_in_groups` +-- + +DROP TABLE IF EXISTS `users_in_groups`; +CREATE TABLE `users_in_groups` ( + `group_id` int(11) NOT NULL, + `user_id` int(11) NOT NULL, + `role` enum('member','owner') NOT NULL, + KEY `user_id` (`user_id`), + KEY `group_id` (`group_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + -- -- Constraints der exportierten Tabellen -- +-- +-- Constraints der Tabelle `channels_in_groups` +-- +ALTER TABLE `channels_in_groups` + ADD CONSTRAINT `channels_in_groups_ibfk_3` FOREIGN KEY (`channel_id`) REFERENCES `channels` (`id`) ON DELETE CASCADE, + ADD CONSTRAINT `channels_in_groups_ibfk_4` FOREIGN KEY (`group_id`) REFERENCES `groups` (`id`) ON DELETE CASCADE; + -- -- Constraints der Tabelle `data` -- @@ -137,22 +135,8 @@ ALTER TABLE `data` ADD CONSTRAINT `data_ibfk_1` FOREIGN KEY (`channel_id`) REFERENCES `channels` (`id`) ON DELETE CASCADE; -- --- Constraints der Tabelle `group_channel` +-- Constraints der Tabelle `users_in_groups` -- -ALTER TABLE `group_channel` - ADD CONSTRAINT `group_channel_ibfk_3` FOREIGN KEY (`channel_id`) REFERENCES `channels` (`id`) ON DELETE CASCADE, - ADD CONSTRAINT `group_channel_ibfk_4` FOREIGN KEY (`group_id`) REFERENCES `groups` (`id`) ON DELETE CASCADE; - --- --- Constraints der Tabelle `group_group` --- -ALTER TABLE `group_group` - ADD CONSTRAINT `group_group_ibfk_3` FOREIGN KEY (`parent_id`) REFERENCES `groups` (`id`) ON DELETE CASCADE, - ADD CONSTRAINT `group_group_ibfk_4` FOREIGN KEY (`child_id`) REFERENCES `groups` (`id`) ON DELETE CASCADE; - --- --- Constraints der Tabelle `group_user` --- -ALTER TABLE `group_user` - ADD CONSTRAINT `group_user_ibfk_3` FOREIGN KEY (`group_id`) REFERENCES `groups` (`id`) ON DELETE CASCADE, - ADD CONSTRAINT `group_user_ibfk_4` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE; +ALTER TABLE `users_in_groups` + ADD CONSTRAINT `users_in_groups_ibfk_3` FOREIGN KEY (`group_id`) REFERENCES `groups` (`id`) ON DELETE CASCADE, + ADD CONSTRAINT `users_in_groups_ibfk_4` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE; diff --git a/share/tools/tests.php b/share/tools/tests.php index ef6b67c..d10547e 100644 --- a/share/tools/tests.php +++ b/share/tools/tests.php @@ -21,9 +21,9 @@ include '../../backend/init.php'; -$meter = current(Channel::getByFilter(array('id' => 1))); +$channel = current(Channel::getByType('PowerMeter')); -$data = $meter->getPulses(1270062000000, 1270666800000, 400); +$data = $channel->getData(1270062000000, 1270666800000, 400); echo ''; foreach ($data as $i => $reading) {