From 524f3dd4374322f9fcfded3b0e613b8d31f6980f Mon Sep 17 00:00:00 2001 From: wintercoder Date: Sat, 7 Apr 2018 16:56:42 +0800 Subject: [PATCH 01/17] Initial commit --- LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e38c84c --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 wintercoder + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From a2d287819ca7204104191392f54881c069e4bb4e Mon Sep 17 00:00:00 2001 From: wintercoder Date: Sat, 7 Apr 2018 16:57:35 +0800 Subject: [PATCH 02/17] first commit --- README.MD | 63 +++++++ conf/common.ini | 40 +++++ conf/local.ini | 0 favicon.png | Bin 0 -> 726 bytes gensql.php | 325 ++++++++++++++++++++++++++++++++++++ index.php | 427 ++++++++++++++++++++++++++++++++++++++++++++++++ sqlparse.php | 218 ++++++++++++++++++++++++ 7 files changed, 1073 insertions(+) create mode 100644 README.MD create mode 100644 conf/common.ini create mode 100644 conf/local.ini create mode 100644 favicon.png create mode 100644 gensql.php create mode 100644 index.php create mode 100644 sqlparse.php diff --git a/README.MD b/README.MD new file mode 100644 index 0000000..0e63059 --- /dev/null +++ b/README.MD @@ -0,0 +1,63 @@ +# 在线MYSQL测试数据生成工具 + +根据SQL表结构生成Mysql测试数据,根据字段名猜测类型,生成默认值 + + +## 生成规则 + +普通规则见[官网](http://datamake.online/),此处讲个规则的组合使用 + +**自增日期(组自增) + 常量(指定列表)** + +使用场景: 一个肯德基总店下有一堆子店,希望生成[每个子店每天]的数据,一行记录包含一个店一天的汇总数据 + +使用方法: 在子店ID 字段上选择 `常量(指定列表)` 用逗号分隔写上各店的ID,日期选择 `自增日期(组自增)` 即可 + +## 个性化 +你可以通过部署到自己的服务器上,对一些字段进行默认值配置,非常**适合公司内网** +部署也方便,代码里无任何框架依赖,能跑PHP就行 + +### 配置 +`/conf/common.ini` 为通用配置 +`/conf/local.ini` 为个性化配置,适合不宜暴露的默认值,如测试账号ID等,该文件已加入 `.gitignore` 里 + +配置样例: + +``` +[0] +key = index_day +method = INCR_DAY +value = 20180301 +way = match +[1] +key = url +method = RAND_PIC_LIST +value = 300,400 +way = search +``` +`key` : 字段名 +`method` : 生成规则,如下表 +`value` : 给前端的输入框值 +`way` : 输入的key跟配置文件的key匹配规则,目前支持 `match` 完全相等、`search` 字符串包含,默认为`match` + + +| 规则英文 | 中文 | 参数 | +|----------|------|------| +| RAND_INT | 随机int | from,to : 生成[from,to]闭区间整数 +| INCR_INT | 自增int | from : 从from开始自增,步长1 +| INCR_DAY | 日期自增 | from : 从from开始自增,步长1天,格式20180304 +| INCR\_DAY\_GROUPLY | 日期自增(组模式) | 同上,但每组值里的这个日期不变,下条SQL才变 +| RAND_TIMESTAMP | 随机时间戳 | from,to : 生成[from,to]这些天里的秒级时间戳,如 20180304,20180305 +| IGNORE | 不生成该列 | +| CONST_STR | 常量 | 常量值 +| CONST\_STR\_LIST | 常量(指定列表) | 输入 a,b,每条SQL都输出 a,b,此时组数固定 +| RAND_STR | 随机串 | length : 英文串长度 +| RAND\_STR\_LIST | 随机串(指定列表) | a,b,c : 该字段只出现a,b,c之一,可重复出现 +| INCR\_STR\_SUFFIX | 前缀+自增数字 | 输入 小王,输出 小王1,小王2,用于人名等 +| RAND\_PIC\_LIST | 图片地址 | width,height : 图片的宽高 + + + +## License + +**The MIT License** \ No newline at end of file diff --git a/conf/common.ini b/conf/common.ini new file mode 100644 index 0000000..3c375cf --- /dev/null +++ b/conf/common.ini @@ -0,0 +1,40 @@ +[0] +key = avatar +method = RAND_PIC_LIST +value = 300,400 +way = search +[1] +key = photo +method = RAND_PIC_LIST +value = 300,400 +way = search +[2] +key = picture +method = RAND_PIC_LIST +value = 300,400 +way = search +[3] +key = url +method = RAND_PIC_LIST +value = 300,400 +way = search +[4] +key = time +method = RAND_TIMESTAMP +value = 20180407,20180408 +way = search +[5] +key = phone +method = RAND_INT +value = 15602000001,15602009999 +way = search +[6] +key = insert_day +method = INCR_DAY_GROUPLY +value = 20180301 +way = match +[7] +key = index_day +method = INCR_DAY +value = 20180301 +way = match diff --git a/conf/local.ini b/conf/local.ini new file mode 100644 index 0000000..e69de29 diff --git a/favicon.png b/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..36145569303246365221718dc072d5274d36d91e GIT binary patch literal 726 zcmV;{0xA88P){oQaU9B7vC%Z{ch?)bPAFyqDJ784QLn=bm6xuy(owk00-Ss58&y7W!y+I$oomi zv#_#cvQDxQf{}Xnt;(5Q9|ABZFOc5_{1Vvkn;-jGf@GcJbbr@mV{s5?>YoARIlWoC-yL}n^w6pto8PGb zUOEv4002BRE3VD9X)?SMdA^fWEOqSFZBxN9!9Ivv&C&6{l&|w#L!f{16vC09dV&0r zO$CdxTsJBZFnF#EccTKpHB~LjjH#jk%!Bg@c&{q3?7XVrRR#Y~EeK8N3tO@k6>Kx5 zp)KFgK;%isW^L4xCED^usa$DHc4WzPb>FNs?17S7GqMv+wRvhmXzP}iY-?*~Cof#k zw6QRgtmdI#&`?4r9(W@I@n9>KjG?pLT#QV&V;k87OBUb%FMGUXKNn(!PXGV_07*qo IM6N<$f)l|fy8r+h literal 0 HcmV?d00001 diff --git a/gensql.php b/gensql.php new file mode 100644 index 0000000..bd87687 --- /dev/null +++ b/gensql.php @@ -0,0 +1,325 @@ +incrInt($inputArr,$groupSize,$sqlCounter); + $ret = []; + foreach ($intArr as $intVal){ + $str = $pre . $intVal; + $ret []= $str; + } + return $ret; + } + + /** + * 随机图片,目前是 http://lorempixel.com/ + * 也可以考虑用百度的 http://image.baidu.com/channel/listjson?pn=0&rn=30&tag1=%E7%BE%8E%E5%A5%B3&tag2=%E5%85%A8%E9%83%A8&ie=utf8 + * @param $input + * @param $groupSize int 每组多少条合并成一个数组,也是该次函数返回的数组大小 + * @return array + */ + public function randPicUrl($input,$groupSize){ + $exp = explode(',',$input); + $width = !empty($exp[0]) ? intval($exp[0]) : 300; + $height = !empty($exp[1]) ? intval($exp[1]) : 300; + $url = "http://lorempixel.com/{$width}/{$height}/"; + + return explode(',',str_repeat($url.',',$groupSize)); + } +} + +class WorkHandler{ + + public function checkParams($input){ + $input = json_decode($input,true); //json转数组 + if(empty($input) || empty($input['list'])){ + echo "参数不是JSON格式";exit(); + } + $input['count'] = intval($input['count']); + $input['group_size'] = intval($input['group_size']); + if( $input['count'] <= 0 || $input['group_size'] <= 0 + || $input['count']>= 5000 || $input['group_size']>= 5000) { + echo "条数、组数只能是 1 到 5000 以内";exit(); + } + } + + public function execute($input){ + $this->checkParams($input); + + $input = json_decode($input,true); //json转数组 + $inputList = $input['list']; + + //对于自增ID等忽略的类型,删除它并重排下标,不能用 array_splice ,删除多个时会乱 + foreach ($inputList as $key => $item){ + if($item['method'] == 'ignore'){ + unset($inputList[$key]); + } + } + $inputList = array_values($inputList); //从0开始 重建下标 + + $genCount = $input['count']; + $tableName = $input['table_name']; + $groupSize = $input['group_size']; //每个SQL有多少value组 + + $keyArr = array_column($inputList,'key'); + + $generator = new ValueGenerator(); + + $sql = ''; + //insert的SQL条数 + for($genI = 1; $genI <= $genCount; $genI++) { + + $genResult = []; //生成结果数组: key => 生成方法+下标 防止同样的方法覆盖数据,value => 按该方法生成的数据数组 + foreach ($inputList as $itemIndex => $item){ + $genService = $this->camelize($item['method']); //方法名转驼峰 + $genResult [ $item['method'].$itemIndex ] = $generator->$genService($item['value'],$groupSize,$genI ); + } + $valueStr = ''; + + //每个SQ有多少value组 + for($cnt = 0; $cnt < $groupSize; $cnt++){ + + $valueStr .= '('; + //取每个字段的值,单引号引起来 + foreach ($genResult as $result) { + $valueStr .= "'{$result[$cnt]}',"; + } + $valueStr = rtrim($valueStr,','); + $valueStr .= '),'; + } + $valueStr = rtrim($valueStr,','); + $valueStr .= ';'; + $sql .= "INSERT INTO {$tableName} (" . implode(",",$keyArr) .") VALUES $valueStr"; + $sql .= "\n"; + $sql .= "\n"; + } + echo $sql; + } + + /** + * 下划线转驼峰 + * @param $str + * @param string $separator + * @return string + */ + private function camelize($str,$separator='_') + { + $str = $separator. str_replace($separator, " ", strtolower($str)); + return ltrim(str_replace(" ", "", ucwords($str)), $separator ); + } +} + + +date_default_timezone_set("Asia/Shanghai"); + +$postData = file_get_contents('php://input'); //提交的是JSON,不能直接$post获取 +if(empty($postData)){ + echo "我是空白"; + exit(); +} +//echo ($postData);exit(); + + +$handler = new WorkHandler(); +$handler->execute($postData); +exit(); + +/* +$parser = new CreateSqlParser(); +$ret = $parser->execute($sql); +if(0 == ($ret['error'])){ + + $input = json_encode($ret['data']); + $handler = new WorkHandler(); + $handler->execute($input); +} else{ + echo json_encode($ret);exit(); + +} + +*/ \ No newline at end of file diff --git a/index.php b/index.php new file mode 100644 index 0000000..c94e12b --- /dev/null +++ b/index.php @@ -0,0 +1,427 @@ + + + SQL测试数据生成 + + + + + + + + + + + + + + + + + + + + + + +

SQL测试数据生成

+ +
+
+
+ + + +
+
+ + + 从 show create table tablename 获得 + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + +
列名生成规则参数
+ + + +
+ +
+
+
+
+
+ +
+ +
+
+
+ +
+
+
+
+ +
+ +
+
+
+ + + + +



+ +
+ +
+ +
+
+
+ + + + +

AltStyle によって変換されたページ (->オリジナル) /

+ + diff --git a/sqlparse.php b/sqlparse.php new file mode 100644 index 0000000..4776351 --- /dev/null +++ b/sqlparse.php @@ -0,0 +1,218 @@ +getApiReturn(self::errorParseError, '不是建表SQL,未包含 CREATE TABLE', []); + } + $ret['table_name'] = $matches[1]; + + //解析字段 + $pattern = "#`(.+)` (.+)\((.+)\)(.+)#i"; + preg_match_all($pattern, $sql, $matches); + $ret['list'] = []; + if (empty($matches[0])) { + return $this->getApiReturn(self::errorParseError, '未查找到SQL字段', []); + } +// echo json_encode($matches); exit(); + + //解析后拿到 + // match[1]: 字段名 + // match[2]: 类型 (int) + // match[3]: 长度 int(10)中的10 + // match[4]: 其他,NOT NULL AUTO_INCREMENT COMMENT '我是注释' 这种 + for ($cnt = 0; $cnt < count($matches[0]); $cnt++) { + $item = $this->genDefaultAttribute($matches[1][$cnt], $matches[2][$cnt], $matches[3][$cnt], $matches[4][$cnt]); + $item['key'] = $matches[1][$cnt]; + $ret['list'] [] = $item; + } + $ret['group_size'] = 5; //组大小 + $ret['count'] = 3; //多少条SQL + + return $this->getApiReturn(0, '', $ret); + } + + /** + * @param $key + * @param $type string SQL的字段类型 varchar,int + * @param $size string SQL的字段类型后跟随的大小 如 varchar(10) 中的10 + * @param $others string varchar(10) 后面的一串其他完整内容,包含 自增、非空、默认值等 + * @return array item 必备包含 'key' 字段名 'method' 生成规则 'value' 默认值 + */ + private function genDefaultAttribute($key, $type, $size, $others) + { + $item = []; + $type = trim($type); + $incrStrPre = ['老王', '射击狮', '测试店', '产品经理', '程序员', '码农', '攻城狮', 'SB']; + + switch ($type) { + case 'varchar': + $item = [ + 'desc' => '前缀+自增', + 'method' => self::INCR_STR_PREFIX, + 'value' => $incrStrPre[rand(0, count($incrStrPre) - 1)], + ]; + break; + case 'int': + $item = [ + 'desc' => '随机整数', + 'method' => self::RAND_INT, + 'value' => '100,500', + ]; + break; + case 'bigint': + $item = [ + 'desc' => '随机整数', + 'method' => self::RAND_INT, + 'value' => "1000000,99999999", + ]; + break; + case 'tinyint': + $item = [ + 'desc' => '随机整数', + 'method' => self::RAND_INT, + 'value' => "0,{$size}", //tinyint(4) 一般是0-4的枚举值 + ]; + break; + case 'float': + $item = [ + 'desc' => '随机浮点', + 'method' => self::RAND_FLOAT, + 'value' => '0,255', + ]; + break; + } + + //自增ID + $autoInc = stripos($others, "AUTO_INCREMENT"); + if ($autoInc) { + $item = [ + 'method' => self::IGNORE, + 'desc' => '自增ID,忽略', + ]; + } + + //注释 + $expComment = explode("COMMENT ", $others); + if (!empty($expComment)) { + $item['comment'] = trim($expComment[1], "',"); + } + + //通用配置 + $commonItem = $this->parseFileForAttribute('conf/common.ini',$key); + if(!empty($localItem)){ + $item = $commonItem; + } + + //个性化配置 + //针对你、你公司 常用的字段设置默认值,存放不可告人的数据秘密,配置文件在.gitignore里 + $localItem = $this->parseFileForAttribute('conf/local.ini',$key); + if(!empty($localItem)){ + $item = $localItem; + } + return $item; + } + + /** + * 解析ini文件拿到自定义默认值,根据字段名猜测用户想要的是哪个类型,配置文件样例如下,目前只支持 模糊查找 和 精确匹配 + [0] + key = avatar + method = RAND_PIC_LIST + value = 300,400 + way = search 跟key的匹配方式,search为模糊搜索,输入key包含 avatar 就走这个匹配 + + [1] + key = index_day + method = INCR_DAY + value = 20180301 + way = match match为精确匹配,输入key 等于 index_day 就走这个匹配 + * + * + * @param $fileName string 配置文件路径 + * @param $key string 字段名 + * @return array + */ + private function parseFileForAttribute($fileName,$key) + { + if(!file_exists($fileName)){ + return []; + } + $item = []; + $matchArray = parse_ini_file($fileName,true); + + foreach ($matchArray as $match) { + if(empty($match['way'])){ //默认key规则为相等 + $match['way'] = 'match'; + } + if($match['way'] == 'search' && false !== stripos($key, $match['key'])){ + $item = $match; + $item['method'] = strtolower($item['method']); + }else if ($match['way'] == 'match' && $key == $match['key']) { + $item = $match; + $item['method'] = strtolower($item['method']); + } + } + unset($item['way']); + return $item; + } + + +} +date_default_timezone_set("Asia/Shanghai"); + + +$defaultSql = " +CREATE TABLE `test` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `supplier_id` int(11) NOT NULL DEFAULT '0', + `content` varchar(255) COLLATE utf8_bin NOT NULL, + `create_time` int(11) NOT NULL, + `insert_day` int(11) NOT NULL, + `is_deleted` tinyint(2) NOT NULL, + `up_count` int(11) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;"; + + +$sql = $_POST['sql']; +$parser = new CreateSqlParser(); +if(empty($sql)){ + $sql = $defaultSql; +} +$ret = $parser->execute($sql); +echo json_encode($ret);exit(); From 4e4a277a6f2278e691585f40fe838524eaea696c Mon Sep 17 00:00:00 2001 From: wintercoder Date: Sat, 7 Apr 2018 23:31:59 +0800 Subject: [PATCH 03/17] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E5=8A=A8=E7=94=BB=EF=BC=8Cfix=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common.ini | 40 ++++++++++++++++++++++++++++++++++++++++ index.php | 19 +++++++++++++------ sqlparse.php | 3 +-- 3 files changed, 54 insertions(+), 8 deletions(-) create mode 100644 common.ini diff --git a/common.ini b/common.ini new file mode 100644 index 0000000..3c375cf --- /dev/null +++ b/common.ini @@ -0,0 +1,40 @@ +[0] +key = avatar +method = RAND_PIC_LIST +value = 300,400 +way = search +[1] +key = photo +method = RAND_PIC_LIST +value = 300,400 +way = search +[2] +key = picture +method = RAND_PIC_LIST +value = 300,400 +way = search +[3] +key = url +method = RAND_PIC_LIST +value = 300,400 +way = search +[4] +key = time +method = RAND_TIMESTAMP +value = 20180407,20180408 +way = search +[5] +key = phone +method = RAND_INT +value = 15602000001,15602009999 +way = search +[6] +key = insert_day +method = INCR_DAY_GROUPLY +value = 20180301 +way = match +[7] +key = index_day +method = INCR_DAY +value = 20180301 +way = match diff --git a/index.php b/index.php index c94e12b..676ab4e 100644 --- a/index.php +++ b/index.php @@ -110,7 +110,7 @@ function onImportBtnClick() { - +
@@ -123,12 +123,12 @@ function onImportBtnClick() {
列名
- +