@instawp/cli 0.0.1-beta.1 → 0.0.1-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,289 @@
1
+ #!/usr/bin/awk -f
2
+
3
+ # Authors: @esperlu, @artemyk, @gkuenning, @dumblob
4
+
5
+ # FIXME detect empty input file and issue a warning
6
+
7
+ function printerr( s ){ print s | "cat >&2" }
8
+
9
+ BEGIN {
10
+ if( ARGC != 2 ){
11
+ printerr( \
12
+ "USAGE:\n"\
13
+ " mysql2sqlite dump_mysql.sql > dump_sqlite3.sql\n" \
14
+ " OR\n" \
15
+ " mysql2sqlite dump_mysql.sql | sqlite3 sqlite.db\n" \
16
+ "\n" \
17
+ "NOTES:\n" \
18
+ " Dash in filename is not supported, because dash (-) means stdin." )
19
+ no_END = 1
20
+ exit 1
21
+ }
22
+
23
+ # Find INT_MAX supported by both this AWK (usually an ISO C signed int)
24
+ # and SQlite.
25
+ # On non-8bit-based architectures, the additional bits are safely ignored.
26
+
27
+ # 8bit (lower precision should not exist)
28
+ s="127"
29
+ # "63" + 0 avoids potential parser misbehavior
30
+ if( (s + 0) "" == s ){ INT_MAX_HALF = "63" + 0 }
31
+ # 16bit
32
+ s="32767"
33
+ if( (s + 0) "" == s ){ INT_MAX_HALF = "16383" + 0 }
34
+ # 32bit
35
+ s="2147483647"
36
+ if( (s + 0) "" == s ){ INT_MAX_HALF = "1073741823" + 0 }
37
+ # 64bit (as INTEGER in SQlite3)
38
+ s="9223372036854775807"
39
+ if( (s + 0) "" == s ){ INT_MAX_HALF = "4611686018427387904" + 0 }
40
+ # # 128bit
41
+ # s="170141183460469231731687303715884105728"
42
+ # if( (s + 0) "" == s ){ INT_MAX_HALF = "85070591730234615865843651857942052864" + 0 }
43
+ # # 256bit
44
+ # s="57896044618658097711785492504343953926634992332820282019728792003956564819968"
45
+ # if( (s + 0) "" == s ){ INT_MAX_HALF = "28948022309329048855892746252171976963317496166410141009864396001978282409984" + 0 }
46
+ # # 512bit
47
+ # s="6703903964971298549787012499102923063739682910296196688861780721860882015036773488400937149083451713845015929093243025426876941405973284973216824503042048"
48
+ # if( (s + 0) "" == s ){ INT_MAX_HALF = "3351951982485649274893506249551461531869841455148098344430890360930441007518386744200468574541725856922507964546621512713438470702986642486608412251521024" + 0 }
49
+ # # 1024bit
50
+ # s="89884656743115795386465259539451236680898848947115328636715040578866337902750481566354238661203768010560056939935696678829394884407208311246423715319737062188883946712432742638151109800623047059726541476042502884419075341171231440736956555270413618581675255342293149119973622969239858152417678164812112068608"
51
+ # if( (s + 0) "" == s ){ INT_MAX_HALF = "44942328371557897693232629769725618340449424473557664318357520289433168951375240783177119330601884005280028469967848339414697442203604155623211857659868531094441973356216371319075554900311523529863270738021251442209537670585615720368478277635206809290837627671146574559986811484619929076208839082406056034304" + 0 }
52
+ # # higher precision probably not needed
53
+
54
+ FS=",$"
55
+ print "PRAGMA synchronous = OFF;"
56
+ print "PRAGMA journal_mode = MEMORY;"
57
+ print "BEGIN TRANSACTION;"
58
+ }
59
+
60
+ # historically 3 spaces separate non-argument local variables
61
+ function bit_to_int( str_bit, powtwo, i, res, bit, overflow ){
62
+ powtwo = 1
63
+ overflow = 0
64
+ # 011101 = 1*2^0 + 0*2^1 + 1*2^2 ...
65
+ for( i = length( str_bit ); i > 0; --i ){
66
+ bit = substr( str_bit, i, 1 )
67
+ if( overflow || ( bit == 1 && res > INT_MAX_HALF ) ){
68
+ printerr( \
69
+ NR ": WARN Bit field overflow, number truncated (LSBs saved, MSBs ignored)." )
70
+ break
71
+ }
72
+ res = res + bit * powtwo
73
+ # no warning here as it might be the last iteration
74
+ if( powtwo > INT_MAX_HALF ){ overflow = 1; continue }
75
+ powtwo = powtwo * 2
76
+ }
77
+ return res
78
+ }
79
+
80
+ # CREATE TRIGGER statements have funny commenting. Remember we are in trigger.
81
+ /^\/\*.*(CREATE.*TRIGGER|create.*trigger)/ {
82
+ gsub( /^.*(TRIGGER|trigger)/, "CREATE TRIGGER" )
83
+ print
84
+ inTrigger = 1
85
+ next
86
+ }
87
+ # The end of CREATE TRIGGER has a stray comment terminator
88
+ /(END|end) \*\/;;/ { gsub( /\*\//, "" ); print; inTrigger = 0; next }
89
+ # The rest of triggers just get passed through
90
+ inTrigger != 0 { print; next }
91
+
92
+ # CREATE VIEW looks like a TABLE in comments
93
+ /^\/\*.*(CREATE.*TABLE|create.*table)/ {
94
+ inView = 1
95
+ next
96
+ }
97
+ # end of CREATE VIEW
98
+ /^(\).*(ENGINE|engine).*\*\/;)/ {
99
+ inView = 0
100
+ next
101
+ }
102
+ # content of CREATE VIEW
103
+ inView != 0 { next }
104
+
105
+ # skip comments
106
+ /^\/\*/ { next }
107
+
108
+ # skip PARTITION statements
109
+ /^ *[(]?(PARTITION|partition) +[^ ]+/ { next }
110
+
111
+ # print all INSERT lines
112
+ ( /^ *\(/ && /\) *[,;] *$/ ) || /^(INSERT|insert|REPLACE|replace)/ {
113
+ prev = ""
114
+
115
+ # first replace \\ by \_ that mysqldump never generates to deal with
116
+ # sequnces like \\n that should be translated into \n, not \<LF>.
117
+ # After we convert all escapes we replace \_ by backslashes.
118
+ gsub( /\\\\/, "\\_" )
119
+
120
+ # single quotes are escaped by another single quote
121
+ gsub( /\\'/, "''" )
122
+ gsub( /\\n/, "\n" )
123
+ gsub( /\\r/, "\r" )
124
+ gsub( /\\"/, "\"" )
125
+ gsub( /\\\032/, "\032" ) # substitute char
126
+
127
+ gsub( /\\_/, "\\" )
128
+
129
+ # sqlite3 is limited to 16 significant digits of precision
130
+ while( match( $0, /0x[0-9a-fA-F]{17}/ ) ){
131
+ hexIssue = 1
132
+ sub( /0x[0-9a-fA-F]+/, substr( $0, RSTART, RLENGTH-1 ), $0 )
133
+ }
134
+ if( hexIssue ){
135
+ printerr( \
136
+ NR ": WARN Hex number trimmed (length longer than 16 chars)." )
137
+ hexIssue = 0
138
+ }
139
+ print
140
+ next
141
+ }
142
+
143
+ # CREATE DATABASE is not supported
144
+ /^(CREATE DATABASE|create database)/ { next }
145
+
146
+ # print the CREATE line as is and capture the table name
147
+ /^(CREATE|create)/ {
148
+ if( $0 ~ /IF NOT EXISTS|if not exists/ || $0 ~ /TEMPORARY|temporary/ ){
149
+ caseIssue = 1
150
+ printerr( \
151
+ NR ": WARN Potential case sensitivity issues with table/column naming\n" \
152
+ " (see INFO at the end)." )
153
+ }
154
+ if( match( $0, /`[^`]+/ ) ){
155
+ tableName = substr( $0, RSTART+1, RLENGTH-1 )
156
+ }
157
+ aInc = 0
158
+ prev = ""
159
+ firstInTable = 1
160
+ print
161
+ next
162
+ }
163
+
164
+ # Replace `FULLTEXT KEY` (probably other `XXXXX KEY`)
165
+ /^ (FULLTEXT KEY|fulltext key)/ { gsub( /[A-Za-z ]+(KEY|key)/, " KEY" ) }
166
+
167
+ # Get rid of field lengths in KEY lines
168
+ / (PRIMARY |primary )?(KEY|key)/ { gsub( /\([0-9]+\)/, "" ) }
169
+
170
+ aInc == 1 && /PRIMARY KEY|primary key/ { next }
171
+
172
+ # Replace COLLATE xxx_xxxx_xx statements with COLLATE BINARY
173
+ / (COLLATE|collate) [a-z0-9_]*/ { gsub( /(COLLATE|collate) [a-z0-9_]*/, "COLLATE BINARY" ) }
174
+
175
+ # Print all fields definition lines except the `KEY` lines.
176
+ /^ / && !/^( (KEY|key)|\);)/ {
177
+ if( match( $0, /[^"`]AUTO_INCREMENT|auto_increment[^"`]/) ){
178
+ aInc = 1
179
+ gsub( /AUTO_INCREMENT|auto_increment/, "PRIMARY KEY AUTOINCREMENT" )
180
+ }
181
+ gsub( /(UNIQUE KEY|unique key) (`.*`|".*") /, "UNIQUE " )
182
+ gsub( /(CHARACTER SET|character set) [^ ]+[ ,]/, "" )
183
+ # FIXME
184
+ # CREATE TRIGGER [UpdateLastTime]
185
+ # AFTER UPDATE
186
+ # ON Package
187
+ # FOR EACH ROW
188
+ # BEGIN
189
+ # UPDATE Package SET LastUpdate = CURRENT_TIMESTAMP WHERE ActionId = old.ActionId;
190
+ # END
191
+ gsub( /(ON|on) (UPDATE|update) (CURRENT_TIMESTAMP|current_timestamp)(\(\))?/, "" )
192
+ gsub( /(DEFAULT|default) (CURRENT_TIMESTAMP|current_timestamp)(\(\))?/, "DEFAULT current_timestamp")
193
+ gsub( /(COLLATE|collate) [^ ]+ /, "" )
194
+ gsub( /(ENUM|enum)[^)]+\)/, "text " )
195
+ gsub( /(SET|set)\([^)]+\)/, "text " )
196
+ gsub( /UNSIGNED|unsigned/, "" )
197
+ gsub( /_utf8mb3/, "" )
198
+ gsub( /` [^ ]*(INT|int|BIT|bit)[^ ]*/, "` integer" )
199
+ gsub( /" [^ ]*(INT|int|BIT|bit)[^ ]*/, "\" integer" )
200
+ ere_bit_field = "[bB]'[10]+'"
201
+ if( match($0, ere_bit_field) ){
202
+ sub( ere_bit_field, bit_to_int( substr( $0, RSTART +2, RLENGTH -2 -1 ) ) )
203
+ }
204
+
205
+ # remove USING BTREE and other suffixes for USING, for example: "UNIQUE KEY
206
+ # `hostname_domain` (`hostname`,`domain`) USING BTREE,"
207
+ gsub( / USING [^, ]+/, "" )
208
+
209
+ # field comments are not supported
210
+ gsub( / (COMMENT|comment).+$/, "" )
211
+ # Get commas off end of line
212
+ gsub( /,.?$/, "" )
213
+ if( prev ){
214
+ if( firstInTable ){
215
+ print prev
216
+ firstInTable = 0
217
+ }
218
+ else {
219
+ print "," prev
220
+ }
221
+ }
222
+ else {
223
+ # FIXME check if this is correct in all cases
224
+ if( match( $1,
225
+ /(CONSTRAINT|constraint) ["].*["] (FOREIGN KEY|foreign key)/ ) ){
226
+ print ","
227
+ }
228
+ }
229
+ prev = $1
230
+ }
231
+
232
+ / ENGINE| engine/ {
233
+ if( prev ){
234
+ if( firstInTable ){
235
+ print prev
236
+ firstInTable = 0
237
+ }
238
+ else {
239
+ print "," prev
240
+ }
241
+ }
242
+ prev=""
243
+ print ");"
244
+ next
245
+ }
246
+ # `KEY` lines are extracted from the `CREATE` block and stored in array for later print
247
+ # in a separate `CREATE KEY` command. The index name is prefixed by the table name to
248
+ # avoid a sqlite error for duplicate index name.
249
+ /^( (KEY|key)|\);)/ {
250
+ if( prev ){
251
+ if( firstInTable ){
252
+ print prev
253
+ firstInTable = 0
254
+ }
255
+ else {
256
+ print "," prev
257
+ }
258
+ }
259
+ prev = ""
260
+ if( $0 == ");" ){
261
+ print
262
+ }
263
+ else {
264
+ if( match( $0, /`[^`]+/ ) ){
265
+ indexName = substr( $0, RSTART+1, RLENGTH-1 )
266
+ }
267
+ if( match( $0, /\([^()]+/ ) ){
268
+ indexKey = substr( $0, RSTART+1, RLENGTH-1 )
269
+ }
270
+ # idx_ prefix to avoid name clashes (they really happen!)
271
+ key[tableName] = key[tableName] "CREATE INDEX \"idx_" \
272
+ tableName "_" indexName "\" ON \"" tableName "\" (" indexKey ");\n"
273
+ }
274
+ }
275
+
276
+ END {
277
+ if( no_END ){ exit 1}
278
+ # print all KEY creation lines.
279
+ for( table in key ){ printf key[table] }
280
+
281
+ print "END TRANSACTION;"
282
+
283
+ if( caseIssue ){
284
+ printerr( \
285
+ "INFO Pure sqlite identifiers are case insensitive (even if quoted\n" \
286
+ " or if ASCII) and doesnt cross-check TABLE and TEMPORARY TABLE\n" \
287
+ " identifiers. Thus expect errors like \"table T has no column named F\".")
288
+ }
289
+ }