/** * Connect. * @param string|null $host * @return self * @throws Oppa\InvalidConfigException */ public final function connect(string $host = null) : self { // link is already active? if (isset($this->links[$host])) { return $this; } // set type as single as default $type = Link::TYPE_SINGLE; // get config as array $config = $this->config->toArray(); // get database directives from given config $database = $config['database'] ?? []; // is master/slave active? if (true === $this->config->get('sharding')) { $master = $database['master'] ?? []; $slaves = $database['slaves'] ?? []; switch ($host) { // act: master as default case null: case Link::TYPE_MASTER: $type = Link::TYPE_MASTER; $database = $database + $master; break; // act: slave // act: slave case Link::TYPE_SLAVE: $type = Link::TYPE_SLAVE; if (!empty($slaves)) { $slave = Util::arrayRand($slaves); $database = $database + $slave; } break; default: // given host is master's host? if ($host == ($master['host'] ?? '')) { $type = Link::TYPE_MASTER; $database = $database + $master; } else { // or given host is slaves's host? $type = Link::TYPE_SLAVE; foreach ($slaves as $slave) { if (isset($slave['host'], $slave['name']) && $slave['host'] == $host) { $database = $database + $slave; break; } } } } } // remove unused parts unset($config['database'], $database['master'], $database['slaves']); // merge configs $config = $config + (array) $database; if (!isset($config['host'], $config['name'], $config['username'], $config['password'])) { throw new InvalidConfigException('Please specify all needed credentials (host' . ', name, username, password) for a link!'); } // use host as a key for link stack $host = $config['host']; // create a new link if not exists if (!isset($this->links[$host])) { $link = new Link($type, $host, new Config($config)); $link->open(); $this->setLink($host, $link); } return $this; }
/** * Stringify query stack. * @return string * @throws \LogicException */ public final function toString() : string { // if any query if (!empty($this->query)) { if (empty($this->table)) { throw new \LogicException("Table is not defined yet! Call 'setTable()' to set target table first."); } // reset query $this->queryString = ''; // prepare for "SELECT" statement if (isset($this->query['select'])) { // add aggregate statements $aggregate = isset($this->query['aggregate']) ? ', ' . join(', ', $this->query['aggregate']) : ''; // add select fields $this->queryString .= sprintf('SELECT %s%s FROM %s', join(', ', $this->query['select']), $aggregate, $this->table); // add join statements if (isset($this->query['join'])) { foreach ($this->query['join'] as $value) { $this->queryString .= sprintf(' %s', $value); } } // add where statement if (isset($this->query['where'])) { $this->queryString .= sprintf(' WHERE (%s)', join(' ', $this->query['where'])); } // add group by statement if (isset($this->query['groupBy'])) { $this->queryString .= sprintf(' GROUP BY %s', join(', ', $this->query['groupBy'])); } // add having statement if (isset($this->query['having'])) { $this->queryString .= sprintf(' HAVING (%s)', join(' ', $this->query['having'])); } // add order by statement if (isset($this->query['orderBy'])) { $this->queryString .= sprintf(' ORDER BY %s', join(', ', $this->query['orderBy'])); } // add limit statement if (isset($this->query['limit'])) { $this->queryString .= !isset($this->query['limit'][1]) ? sprintf(' LIMIT %d', $this->query['limit'][0]) : sprintf(' LIMIT %d,%d', $this->query['limit'][0], $this->query['limit'][1]); } } elseif (isset($this->query['insert'])) { $agent = $this->link->getAgent(); if ($data = $this->query['insert'] ?? null) { $keys = $agent->escapeIdentifier(array_keys(current($data))); $values = []; foreach ($data as $d) { $values[] = '(' . $agent->escape(array_values($d)) . ')'; } $this->queryString = sprintf("INSERT INTO {$this->table} ({$keys}) VALUES %s", join(', ', $values)); } } elseif (isset($this->query['update'])) { $agent = $this->link->getAgent(); if ($data = $this->query['update'] ?? null) { // prepare "SET" data $set = []; foreach ($data as $key => $value) { $set[] = sprintf('%s = %s', $agent->escapeIdentifier($key), $agent->escape($value)); } // check again if (!empty($set)) { $this->queryString = sprintf("UPDATE {$this->table} SET %s", join(', ', $set)); // add criterias if (isset($this->query['where'])) { $this->queryString .= sprintf(' WHERE (%s)', join(' ', $this->query['where'])); } if (isset($this->query['orderBy'])) { $this->queryString .= sprintf(' ORDER BY %s', join(', ', $this->query['orderBy'])); } if (isset($this->query['limit'][0])) { $this->queryString .= sprintf(' LIMIT %d', $this->query['limit'][0]); } } } } elseif (isset($this->query['delete'])) { $agent = $this->link->getAgent(); $this->queryString = "DELETE FROM {$this->table}"; // add criterias if (isset($this->query['where'])) { $this->queryString .= sprintf(' WHERE (%s)', join(' ', $this->query['where'])); } if (isset($this->query['orderBy'])) { $this->queryString .= sprintf(' ORDER BY %s', join(', ', $this->query['orderBy'])); } if (isset($this->query['limit'][0])) { $this->queryString .= sprintf(' LIMIT %d', $this->query['limit'][0]); } } } return trim($this->queryString); }