Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/HuasoFoundries/phpPgAdmin6.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/Database/Traits/RowTrait.php')
-rw-r--r--src/Database/Traits/RowTrait.php418
1 files changed, 418 insertions, 0 deletions
diff --git a/src/Database/Traits/RowTrait.php b/src/Database/Traits/RowTrait.php
new file mode 100644
index 00000000..8ec7db35
--- /dev/null
+++ b/src/Database/Traits/RowTrait.php
@@ -0,0 +1,418 @@
+<?php
+
+/**
+ * PHPPgAdmin6
+ */
+
+namespace PHPPgAdmin\Database\Traits;
+
+/**
+ * Common trait for tables manipulation.
+ */
+trait RowTrait
+{
+ /**
+ * Returns a recordset of all columns in a table.
+ *
+ * @param string $table The name of a table
+ * @param array $key The associative array holding the key to retrieve
+ *
+ * @return \ADORecordSet|bool|int|string
+ */
+ public function browseRow($table, $key)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($table);
+
+ $sql = \sprintf(
+ 'SELECT * FROM "%s"."%s"',
+ $f_schema,
+ $table
+ );
+
+ if (\is_array($key) && 0 < \count($key)) {
+ $sql .= ' WHERE true';
+
+ foreach ($key as $k => $v) {
+ $this->fieldClean($k);
+ $this->clean($v);
+ $sql .= \sprintf(
+ ' AND "%s"=\'%s\'',
+ $k,
+ $v
+ );
+ }
+ }
+
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Get the fields for uniquely identifying a row in a table.
+ *
+ * @param string $table The table for which to retrieve the identifier
+ *
+ * @return array|int An array mapping attribute number to attribute name, empty for no identifiers
+ */
+ public function getRowIdentifier($table)
+ {
+ $oldtable = $table;
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $this->clean($table);
+
+ $status = $this->beginTransaction();
+
+ if (0 !== $status) {
+ return -1;
+ }
+
+ // Get the first primary or unique index (sorting primary keys first) that
+ // is NOT a partial index.
+ $sql = \sprintf(
+ '
+ SELECT indrelid, indkey
+ FROM pg_catalog.pg_index
+ WHERE indisunique AND indrelid=(
+ SELECT oid FROM pg_catalog.pg_class
+ WHERE relname=\'%s\' AND relnamespace=(
+ SELECT oid FROM pg_catalog.pg_namespace
+ WHERE nspname=\'%s\'
+ )
+ ) AND indpred IS NULL AND indexprs IS NULL
+ ORDER BY indisprimary DESC LIMIT 1',
+ $table,
+ $c_schema
+ );
+ $rs = $this->selectSet($sql);
+
+ // If none, check for an OID column. Even though OIDs can be duplicated, the edit and delete row
+ // functions check that they're only modiying a single row. Otherwise, return empty array.
+ if (0 === $rs->RecordCount()) {
+ // Check for OID column
+ $temp = [];
+
+ if ($this->hasObjectID($table)) {
+ $temp = ['oid'];
+ }
+ $this->endTransaction();
+
+ return $temp;
+ } // Otherwise find the names of the keys
+
+ $attnames = $this->getAttributeNames($oldtable, \explode(' ', $rs->fields['indkey']));
+
+ if (!\is_array($attnames)) {
+ $this->rollbackTransaction();
+
+ return -1;
+ }
+
+ $this->endTransaction();
+
+ return $attnames;
+ }
+
+ /**
+ * Adds a new row to a table.
+ *
+ * @param string $table The table in which to insert
+ * @param array $fields Array of given field in values
+ * @param array $values Array of new values for the row
+ * @param array $nulls An array mapping column => something if it is to be null
+ * @param array $format An array of the data type (VALUE or EXPRESSION)
+ * @param array $types An array of field types
+ *
+ * @return int|string
+ */
+ public function insertRow($table, $fields, $values, $nulls, $format, $types)
+ {
+ if (!\is_array($fields) || !\is_array($values) || !\is_array($nulls)
+ || !\is_array($format) || !\is_array($types)
+ || (\count($fields) !== \count($values))
+ ) {
+ return -1;
+ }
+
+ // Build clause
+ if (0 < \count($values)) {
+ // Escape all field names
+ $fields = \array_map(['\PHPPgAdmin\Database\Postgres', 'fieldClean'], $fields);
+ $f_schema = $this->_schema;
+ $this->fieldClean($table);
+ $this->fieldClean($f_schema);
+
+ $sql = '';
+
+ foreach ($values as $i => $value) {
+ // Handle NULL values
+ if (isset($nulls[$i])) {
+ $sql .= ',NULL';
+ } else {
+ $sql .= ',' . $this->formatValue($types[$i], $format[$i], $value);
+ }
+ }
+
+ $sql = \sprintf(
+ 'INSERT INTO "%s"."%s" ("',
+ $f_schema,
+ $table
+ ) . \implode('","', $fields) . '")
+ VALUES (' . \mb_substr($sql, 1) . ')';
+
+ return $this->execute($sql);
+ }
+
+ return -1;
+ }
+
+ /**
+ * Formats a value or expression for sql purposes.
+ *
+ * @param string $type The type of the field
+ * @param mixed $format VALUE or EXPRESSION
+ * @param mixed $value The actual value entered in the field. Can be NULL
+ *
+ * @return mixed The suitably quoted and escaped value
+ */
+ public function formatValue($type, $format, $value)
+ {
+ switch ($type) {
+ case 'bool':
+ case 'boolean':
+ if ('t' === $value) {
+ return 'TRUE';
+ }
+
+ if ('f' === $value) {
+ return 'FALSE';
+ }
+
+ if ('' === $value) {
+ return 'NULL';
+ }
+
+ return $value;
+
+ break;
+
+ default:
+ // Checking variable fields is difficult as there might be a size
+ // attribute...
+ if (0 === \mb_strpos($type, 'time')) {
+ // Assume it's one of the time types...
+ if ('' === $value) {
+ return "''";
+ }
+
+ if (0 === \strcasecmp($value, 'CURRENT_TIMESTAMP')
+ || 0 === \strcasecmp($value, 'CURRENT_TIME')
+ || 0 === \strcasecmp($value, 'CURRENT_DATE')
+ || 0 === \strcasecmp($value, 'LOCALTIME')
+ || 0 === \strcasecmp($value, 'LOCALTIMESTAMP')) {
+ return $value;
+ }
+
+ if ('EXPRESSION' === $format) {
+ return $value;
+ }
+ $this->clean($value);
+
+ return \sprintf(
+ '\'%s\'',
+ $value
+ );
+ }
+
+ if ('VALUE' === $format) {
+ $this->clean($value);
+
+ return \sprintf(
+ '\'%s\'',
+ $value
+ );
+ }
+
+ return $value;
+ }
+ }
+
+ // View functions
+
+ /**
+ * Updates a row in a table.
+ *
+ * @param string $table The table in which to update
+ * @param array $vars An array mapping new values for the row
+ * @param array $nulls An array mapping column => something if it is to be null
+ * @param array $format An array of the data type (VALUE or EXPRESSION)
+ * @param array $types An array of field types
+ * @param array $keyarr An array mapping column => value to update
+ *
+ * @return int
+ *
+ * @psalm-return -2|-1|0|1
+ */
+ public function editRow($table, $vars, $nulls, $format, $types, $keyarr)
+ {
+ if (!\is_array($vars) || !\is_array($nulls) || !\is_array($format) || !\is_array($types)) {
+ return -1;
+ }
+
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($table);
+ $sql = '';
+ // Build clause
+ if (0 < \count($vars)) {
+ foreach ($vars as $key => $value) {
+ $this->fieldClean($key);
+
+ $tmp = isset($nulls[$key]) ? 'NULL' : $this->formatValue($types[$key], $format[$key], $value);
+
+ if (0 < \mb_strlen($sql)) {
+ $sql .= \sprintf(
+ ', "%s"=%s',
+ $key,
+ $tmp
+ );
+ } else {
+ $sql = \sprintf(
+ 'UPDATE "%s"."%s" SET "%s"=%s',
+ $f_schema,
+ $table,
+ $key,
+ $tmp
+ );
+ }
+ }
+ $first = true;
+
+ foreach ($keyarr as $k => $v) {
+ $this->fieldClean($k);
+ $this->clean($v);
+
+ if ($first) {
+ $sql .= \sprintf(
+ ' WHERE "%s"=\'%s\'',
+ $k,
+ $v
+ );
+ $first = false;
+ } else {
+ $sql .= \sprintf(
+ ' AND "%s"=\'%s\'',
+ $k,
+ $v
+ );
+ }
+ }
+ }
+
+ // Begin transaction. We do this so that we can ensure only one row is
+ // edited
+ $status = $this->beginTransaction();
+
+ if (0 !== $status) {
+ $this->rollbackTransaction();
+
+ return -1;
+ }
+ $status = $this->execute($sql);
+
+ if (0 !== $status) {
+ // update failed
+ $this->rollbackTransaction();
+
+ return -1;
+ }
+
+ if (1 !== $this->conn->Affected_Rows()) {
+ // more than one row could be updated
+ $this->rollbackTransaction();
+
+ return -2;
+ }
+
+ // End transaction
+ return $this->endTransaction();
+ }
+
+ /**
+ * Delete a row from a table.
+ *
+ * @param string $table The table from which to delete
+ * @param array $key An array mapping column => value to delete
+ * @param string $schema the schema of the table
+ *
+ * @return int
+ *
+ * @psalm-return -2|-1|0|1
+ */
+ public function deleteRow($table, $key, $schema = '')
+ {
+ if (!\is_array($key)) {
+ return -1;
+ }
+
+ // Begin transaction. We do this so that we can ensure only one row is
+ // deleted
+ $status = $this->beginTransaction();
+
+ if (0 !== $status) {
+ $this->rollbackTransaction();
+
+ return -1;
+ }
+
+ if ('' === $schema) {
+ $schema = $this->_schema;
+ }
+
+ $status = $this->delete($table, $key, $schema);
+
+ if (0 !== $status || 1 !== $this->conn->Affected_Rows()) {
+ $this->rollbackTransaction();
+
+ return -2;
+ }
+
+ // End transaction
+ return $this->endTransaction();
+ }
+
+ abstract public function fieldClean(&$str);
+
+ abstract public function beginTransaction();
+
+ abstract public function rollbackTransaction();
+
+ abstract public function endTransaction();
+
+ abstract public function execute($sql);
+
+ abstract public function setComment($obj_type, $obj_name, $table, $comment, $basetype = null);
+
+ abstract public function selectSet($sql);
+
+ abstract public function clean(&$str);
+
+ abstract public function phpBool($parameter);
+
+ abstract public function hasCreateTableLikeWithConstraints();
+
+ abstract public function hasCreateTableLikeWithIndexes();
+
+ abstract public function hasTablespaces();
+
+ abstract public function delete($table, $conditions, $schema = '');
+
+ abstract public function fieldArrayClean(&$arr);
+
+ abstract public function hasCreateFieldWithConstraints();
+
+ abstract public function getAttributeNames($table, $atts);
+
+ abstract public function hasObjectID($table);
+}