diff --git a/src/think/Model.php b/src/think/Model.php index 0c29e3c..7501d4f 100644 --- a/src/think/Model.php +++ b/src/think/Model.php @@ -85,6 +85,9 @@ class Model // 数据表名(不包含表前缀) protected $tableName = ''; + // 数据表后缀 + protected $suffix = ''; + // 实际数据表名(包含表前缀) protected $trueTableName = ''; @@ -1022,6 +1025,11 @@ protected function _parseOptions($options = []) $fields = $this->getDbFields(); } + // 拼接数据表后缀 + if (!empty($this->suffix)) { + $options['table'] .= $this->suffix; + } + // 数据表别名 if (!empty($options['alias'])) { $options['table'] .= ' ' . $options['alias']; @@ -2194,6 +2202,28 @@ protected function parseSql($sql, $parse) return $sql; } + /** + * 设置当前模型数据表的后缀 + * @access public + * @param $suffix + * @return $this + */ + public function setSuffix($suffix) + { + $this->suffix = $suffix; + return $this; + } + + /** + * 获取当前模型的数据表后缀 + * @access public + * @return string + */ + public function getSuffix() + { + return $this->suffix ?: ''; + } + /** * 切换当前的数据库连接 * @access public @@ -2760,6 +2790,18 @@ public function forceMasterDB() return $this->hint('FORCE_MASTER'); } + /** + * 设置当前查询所在的分区 + * @access public + * @param string|array $partition 分区名称 + * @return $this + */ + public function partition($partition) + { + $this->options['partition'] = $partition; + return $this; + } + /** * 增加hint标识 * @param $hintContent @@ -2775,7 +2817,8 @@ public function hint($hintContent) * 禁用DB after event 回调,防止死循环事件产生 * @return $this */ - public function disableDBAfter(){ + public function disableDBAfter() + { $this->options['disable_db_after'] = true; return $this; } diff --git a/src/think/db/Driver.php b/src/think/db/Driver.php index 274dec9..fb92800 100644 --- a/src/think/db/Driver.php +++ b/src/think/db/Driver.php @@ -93,7 +93,7 @@ abstract class Driver ]; // 查询表达式 - protected $selectSql = '%HINT% SELECT%DISTINCT% %FIELD% FROM %TABLE%%FORCE%%JOIN%%WHERE%%GROUP%%HAVING%%ORDER%%LIMIT% %UNION%%LOCK%%COMMENT%'; + protected $selectSql = '%HINT% SELECT%DISTINCT% %FIELD% FROM %TABLE%%PARTITION%%FORCE%%JOIN%%WHERE%%GROUP%%HAVING%%ORDER%%LIMIT% %UNION%%LOCK%%COMMENT%'; // 查询次数 protected $queryTimes = 0; @@ -279,7 +279,7 @@ public function query($str, $fetchSql = false, $master = false) } else { return $this->getResult(); } - } catch (\PDOException | \Exception | \Throwable $e) { + } catch (\PDOException|\Exception|\Throwable $e) { if ($this->transTimes > 0) { // 当前是开启了事务 避免多层事务失效 直接重置事务计数 if ($this->isBreak($e)) { @@ -361,7 +361,7 @@ public function execute($str, $fetchSql = false) } return $this->numRows; } - } catch (\PDOException | \Exception | \Throwable $e) { + } catch (\PDOException|\Exception|\Throwable $e) { if ($this->transTimes > 0) { // 当前是开启了事务 避免多层事务失效 直接重置事务计数 if ($this->isBreak($e)) { @@ -569,19 +569,19 @@ protected function parseSet($data) if (false !== strpos($key, '->')) { // 处理局部json字段数据更新 - [$key, $name] = explode('->', $key, 2); - $item = $this->parseKey($key); + [$key, $name] = explode('->', $key, 2); + $item = $this->parseKey($key); - if(is_array($val)){ + if (is_array($val)) { // json数据格式保持原样不转义 $val = json_encode($val); $jsonSql = 'JSON_SET(' . $item . ', \'$.' . $name . '\', CAST(\'' . $val . '\' AS JSON))'; - }else{ + } else { $jsonSql = 'JSON_SET(' . $item . ', \'$.' . $name . '\', \'' . $val . '\')'; } - $set[] = $item.'='.$jsonSql; - }elseif (isset($val[0]) && 'exp' == $val[0]) { + $set[] = $item . '=' . $jsonSql; + } elseif (isset($val[0]) && 'exp' == $val[0]) { $set[] = $this->parseKey($key) . '=' . $val[1]; } elseif (is_null($val)) { $set[] = $this->parseKey($key) . '=NULL'; @@ -1000,6 +1000,25 @@ protected function parseHint($hint) return !empty($hint) ? '/*' . $hint . '*/' : ''; } + + /** + * Partition 分析 + * @param $partition + * @return string + */ + protected function parsePartition($partition) + { + if ('' == $partition) { + return ''; + } + + if (is_string($partition)) { + $partition = explode(',', $partition); + } + + return ' PARTITION (' . implode(' , ', $partition) . ') '; + } + /** * distinct分析 * @access protected @@ -1111,7 +1130,7 @@ public function insert($data, $options = [], $replace = false) } // 兼容数字传入方式 $replace = (is_numeric($replace) && $replace > 0) ? true : $replace; - $sql = (true === $replace ? 'REPLACE' : 'INSERT') . ' INTO ' . $this->parseTable($options['table']) . ' (' . implode(',', $fields) . ') VALUES (' . implode(',', $values) . ')' . $this->parseDuplicate($replace); + $sql = (true === $replace ? 'REPLACE' : 'INSERT') . ' INTO ' . $this->parseTable($options['table']) . $this->parsePartition(!empty($options['partition']) ? $options['partition'] : '') . ' (' . implode(',', $fields) . ') VALUES (' . implode(',', $values) . ')' . $this->parseDuplicate($replace); $sql .= $this->parseComment(!empty($options['comment']) ? $options['comment'] : ''); return $this->execute($sql, !empty($options['fetch_sql']) ? true : false); } @@ -1157,7 +1176,7 @@ public function insertAll($dataSet, $options = [], $replace = false) } $values[] = 'SELECT ' . implode(',', $value); } - $sql = 'INSERT INTO ' . $this->parseTable($options['table']) . ' (' . implode(',', $fields) . ') ' . implode(' UNION ALL ', $values); + $sql = 'INSERT INTO ' . $this->parseTable($options['table']) . $this->parsePartition(!empty($options['partition']) ? $options['partition'] : '') . ' (' . implode(',', $fields) . ') ' . implode(' UNION ALL ', $values); $sql .= $this->parseComment(!empty($options['comment']) ? $options['comment'] : ''); return $this->execute($sql, !empty($options['fetch_sql']) ? true : false); } @@ -1205,7 +1224,7 @@ public function update($data, $options) $this->model = $options['model']; $this->parseBind(!empty($options['bind']) ? $options['bind'] : []); $table = $this->parseTable($options['table']); - $sql = 'UPDATE ' . $table . $this->parseSet($data); + $sql = 'UPDATE ' . $table . $this->parsePartition(!empty($options['partition']) ? $options['partition'] : '') . $this->parseSet($data); if (strpos($table, ',')) { // 多表更新支持JOIN操作 $sql .= $this->parseJoin(!empty($options['join']) ? $options['join'] : ''); @@ -1236,7 +1255,7 @@ public function delete($options = []) $this->model = $options['model']; $this->parseBind(!empty($options['bind']) ? $options['bind'] : []); $table = $this->parseTable($options['table']); - $sql = 'DELETE FROM ' . $table; + $sql = 'DELETE FROM ' . $table . $this->parsePartition(!empty($options['partition']) ? $options['partition'] : ''); if (strpos($table, ',')) { // 多表删除支持USING和JOIN操作 if (!empty($options['using'])) { @@ -1306,6 +1325,7 @@ public function parseSql($sql, $options = []) [ '%HINT%', '%TABLE%', + '%PARTITION%', '%DISTINCT%', '%FIELD%', '%JOIN%', @@ -1322,6 +1342,7 @@ public function parseSql($sql, $options = []) [ $this->parseHint(!empty($options['hint']) ? $options['hint'] : ''), $this->parseTable($options['table']), + $this->parsePartition(!empty($options['partition']) ? $options['partition'] : ''), $this->parseDistinct(isset($options['distinct']) ? $options['distinct'] : false), $this->parseField(!empty($options['field']) ? $options['field'] : '*'), $this->parseJoin(!empty($options['join']) ? $options['join'] : ''),