简体   繁体   English

转换sql模式文件的git diff以应用/撤消sql脚本

[英]convert git diff of sql schema file to apply/undo sql scripts

I'm trying to make a simple bashscript, that given an output from git diff of a sql schema definition file, would be able to create an update script and undo script. 我正在尝试制作一个简单的bashscript,鉴于sql模式定义文件的git diff的输出,它将能够创建更新脚本和撤消脚本。 So having an input like this: 所以有这样的输入:

 create table xxx
 (
-       aaa numeric(18) primary key,
-       bbb numeric(18) not null,
-       ccc numeric(18) not null,
+       aaa INT UNSIGNED AUTO_INCREMENT primary key,
+       AlarmId INT UNSIGNED not null,
+       ccc INT UNSIGNED not null,
        ddd smallint not null,
        eee varchar(2),
        fff varchar(2),
    )

let's assume I want to make an update script. 假设我要制作一个更新脚本。 I change all create statements into alter 's, then strip all unnecessary rows, and finally replace the '+' marks with change statements (it;s mysql script). 我将所有create语句alteralter ,然后剥离所有不必要的行,最后用change语句(它是mysql脚本)替换'+'标记。 I do like so: 我喜欢这样:

sed "s/^\s*create/ALTER/g" < $infile | sed "/^\s\|@/d" | sed "/^-/d" | sed "s/^+\s*\(\`\?\w\+\`\?\)/\tCHANGE \1 \1/g"

So I finally get something like this: 所以我终于得到这样的东西:

ALTER table xxx
        CHANGE aaa aaa INT UNSIGNED AUTO_INCREMENT primary key,
        CHANGE bbb bbb INT UNSIGNED not null,
        CHANGE ccc ccc INT UNSIGNED not null,
        CHANGE ddd ddd smallint not null,
ALTER table yyy
        CHANGE aaa aaa INT UNSIGNED primary key,
        CHANGE bbb bbb smallint not null,
        CHANGE ccc ccc smallint not null,
        CHANGE ddd ddd INT UNSIGNED not null,
        CHANGE eee eee varchar(1024) not null
ALTER table zzz
(and so on)

One last thing I need to do is to complete each statement with a colon - and I got totally stuck there. 我需要做的最后一件事是用冒号完成每个语句-我完全陷入了困境。 Basically, I need to find each ALTER statement (or EOF), and add a colon at end of the line above it (possibly replacing an existing comma). 基本上,我需要找到每个ALTER语句(或EOF),并在其上方的行末添加一个冒号(可能替换现有的逗号)。 I was able to do it in vim using it's s command: 我用它是能够做到在vim s命令:

%s/\(,\)\=\_s\+\(ALTER.*\|\%$\)/;\r\2

But I failed to translate this to sed syntax. 但是我未能将其转换为sed语法。 It appears, that forcing sed to accept a multiline pattern is a hard job. 看来,强制sed接受多行模式是一项艰巨的任务。 So - can anyone tell me how to do this? 所以-谁能告诉我该怎么做? I guess sed is not the only option. 我猜sed不是唯一的选择。 It just was my first choice (not the best as it appeared :) ) Maybe there are some out-of-the-box solutions, and I'm just re-inventing the wheel? 这只是我的第一选择(不是最好的选择:))也许有一些现成的解决方案,而我只是在重新发明轮子?

Interesting approach (and fragile, too - imagine a change putting several columns on the same line). 有趣的方法(也很脆弱-想象一下将几列放在同一行的更改)。 Perl can help you with semicolons: Perl可以帮助您使用分号:

 perl -0777 -pe 's/[,\s]+ALTER/;\nALTER/g;
                 s/$/;/' < input > output
  • -0777 "slurps" the whole file (instead of reading it line by line) -0777 “吸取”整个文件(而不是逐行读取)
  • -p prints what's been read after processing it -p打印处理后的已读内容
  • [,\\s]+ matches whitespace and comma, there must be at least one such character (it prevents insertion of semicolon before the first ALTER). [,\\s]+匹配空格和逗号,必须至少有一个这样的字符(它防止在第一个ALTER之前插入分号)。
  • The second substitution adds the final semicolon. 第二次替换将添加最终的分号。
sed -n '
   /^[[:blank:]]*create/ {
      s//ALTER/
      H
      b
      }

   /^+\([[:blank:]]*\)\([^[:blank:]]\{1,\}\)/ {
      s//\1CHANGE \2 \2/
      H
      }
   $ !b

   x
   s/,\(\nALTER\)/;\1/g
   s/.\(.*\),$/\1;/p
   ' YourFile

You need to use holding buffer to work with all (several) lines together (action x , H here) 您需要使用保持缓冲区来与所有(几条)线一起使用(此处为动作xH

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM