-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathParser.pde
223 lines (183 loc) · 7.87 KB
/
Parser.pde
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
/**
*This file contains the code used to parse the database schema.
*If you need to write your own parser, all it needs to find are
* 1 - the name of every entity in the database
* 2 - the name and type of every attribute associated with each entity, including primary keys
* 3 - every relationship in the database along with the name of each foreign key
*Replace the 4 regular expressions in to the code below,
*and you should be in business.
*Processing has helper functions for Java Regular Expressions. The two commands you need are:
*match() -- http://processingjs.org/reference/match_/
*matchAll() -- http://processingjs.org/reference/matchAll_/
*You still need to use Java Regex syntax, unfortunately.
These regexes are all string literals so don't forget the extra '\'!
*If you create a new parser, please share it.
*/
/*****
This method will parse output of a mysqldump command
You probably want to use the --no-data flag to keep the file small,
but the parser will ignore any lines of data, so it won't choke if you have a full dump.
For documentation on using this command see:
http://dev.mysql.com/doc/refman/5.1/en/mysqldump.html
It has to cycle through the file twice.
Once to get all the Entities, their attributes, and primary key(s).
Another time to get the foreign keys and set up the relationships.
This parser was designed for INNODB schemas.
It will work on a MyISAM database, but it will not create the relationships,
since MyISAM does not make them explicit in the schema.
******/
void parseMySQLDump(String[] lines) {
for (int i = 0; i < lines.length; i++) {
//get names of all Entities in the schema
//m[0][1] is the name of the Entity
String[][] m = matchAll(lines[i], "CREATE\\sTABLE\\s`(\\w+)`");
if (m != null) {
//finds (and creates) a new Entity
Entity en = createEntity(m[0][1]);
//finds (and creates) the Entity's Attributes, and adds them to the Entity
for(int j = i+1; j < lines.length; j++) {
// stop if the line reads ";"
String[] end = match(lines[j], ";");
if (end == null) {
//get Attribute names and types
//attr[0][1] = name, attr[0][2] = datatype
String[][] attr = matchAll(lines[j], "^\\s*`(\\w+)`\\s+(\\w+)");
if(attr != null) {
Attribute at = createAttribute(attr[0][2], attr[0][1]);
en.addAttribute(at);
}
//find primary key(s) -- if you have a composite key, it will find all the components
String[][] p = matchAll(lines[j], "PRIMARY\\sKEY\\s\\(`(.*)`\\)");
if (p != null) {
String priK = p[0][1];
String[] list_keys = split(priK, "`,`");
for (int k = 0; k < list_keys.length; k++) {
en.getPrimaryKey(list_keys[k]);
}
}
} else break;
}
}
}
for (int i = 0; i < lines.length; i++) {
//get all relationships in the schema
//First get the name of the Entity from the first line
//m[0][1] is the name of the Entity
String[][] m = matchAll(lines[i], "CREATE\\sTABLE\\s`(\\w+)`");
if (m != null) {
Entity en = findEntity(m[0][1]);
//finds references foreign keys and creates relationships for that specific entity
for(int j = i+1; j < lines.length; j++) {
// stop if the line reads ";"
String[] end = match(lines[j], ";");
if (end == null) {
//en.name = entityTo fk[0][1] = foreign key, fk[0][] = entityFrom
String[][] fk = matchAll(lines[j], "FOREIGN\\sKEY\\s\\(`(\\w+)`\\)\\sREFERENCES\\s`(\\w+)`");
if (fk != null) {
en.getForeignKey(fk[0][1]);
findEntity(fk[0][2]);
createRelationship(fk[0][2],en.name);
}
} else break;
}
}
}
}
/*****
This method will parse output of a Django manage.py sql command
For documentation on using this command see:
https://docs.djangoproject.com/en/dev/ref/django-admin/#sql-appname-appname
You can list all the apps you want displayed and then pipe them to a file
For example
>>python manage.py sql places people organizations > schema.sql
******/
void parseDjangoSql(String[] lines) {
for (int i = 0; i < lines.length; i++) {
//get names of all Entities in the schema
//m[0][1] is the name of the Entity
String[][] m = matchAll(lines[i], "CREATE\\sTABLE\\s`(\\w+)`");
if (m != null) {
//finds (and creates) a new Entity
Entity en = createEntity(m[0][1]);
//finds (and creates) the Entity's Attributes, and adds them to the Entity
for(int j = i+1; j < lines.length; j++) {
// stop if the line reads ";"
String[] end = match(lines[j], ";");
if (end == null) {
//get Attribute names and types
//attr[0][1] = name, attr[0][2] = datatype
String[][] attr = matchAll(lines[j], "\\s+`(\\w+)`\\s+(\\w+)");
//test if attribute is primary key
String[] priKey = match(lines[j], "PRIMARY");
if(attr != null && priKey != null) {
Attribute at = createAttribute("primary key", attr[0][1]);
en.addAttribute(at);
at.primary_key = true;
}
else if(attr != null && priKey == null) {
Attribute at = createAttribute(attr[0][2], attr[0][1]);
en.addAttribute(at);
}
} else break;
}
}
}
for (int i = 0; i < lines.length; i++) {
//get all relationships in the schema
//fk[0][1] = entityTo, fk[0][3] = foreign key, fk[0][4] = entityFrom
String[][] fk = matchAll(lines[i], "ALTER\\sTABLE\\s`(\\w+)`(.*)FOREIGN\\sKEY\\s\\(`(\\w+)`\\)\\sREFERENCES\\s`(\\w+)`");
if (fk != null) {
Entity en = findEntity(fk[0][1]);
en.getForeignKey(fk[0][3]);
findEntity(fk[0][4]);
createRelationship(fk[0][4],en.name);
}
}
}
/****
This method will parse the schema.rb file of a Rails 2.x app.
It automatically adds a primary key named "id" to every Entity
It also assumes you are using SQL statements to create foreign key constraints
If this does not match your schema, then make the appropriate adjustments
If you do use this schema, be sure to change the name of the parsed file at
the beginning of the DAVILA.pde file from schema.sql to schema.rb.
****/
void parseRails2fkcSchema(String[] lines) {
for (int i = 0; i < lines.length; i++) {
//get names of all Entities in the schema
//m[0][1] is the name of the Entity
String[][] m = matchAll(lines[i], "\\s+create_table\\s\"(\\w+)\"");
if (m != null) {
//finds (and creates) a new Entity
Entity en = createEntity(m[0][1]);
//Creates the primary key "id" added by Rails to every Entity but not specified in the schema
Attribute id = createAttribute("primary key", "id");
id.primary_key = true;
en.addAttribute(id);
//finds (and creates) the Entity's Attributes, and adds them to the Entity
for(int j = i+1; j < lines.length; j++) {
// stop if the line reads "end"
String[] end = match(lines[j], "\\s+end");
if (end == null) {
//get Attribute names and types
//attr[0][1] = name, attr[0][2] = datatype
String[][] attr = matchAll(lines[j], "\\s+t.(\\w+)\\s+\"(\\w+)\"");
if(attr != null) {
Attribute at = createAttribute(attr[0][1], attr[0][2]);
en.addAttribute(at);
}
} else break;
}
}
//get all relationships in the schema, including the foreign keys
//this parses a SQL 92 foreign key constraint
//fk[0][1] = entityTo, fk[0][2] = foreign key, fk[0][3] = entityFrom
String[][] fk = matchAll(lines[i], "\\s+add_foreign_key\\s\"(\\w+)\",\\s\\[\"(\\w+)\"\\],\\s\"(\\w+)\"");
if (fk != null) {
Entity en = findEntity(fk[0][1]);
en.getForeignKey(fk[0][2]);
findEntity(fk[0][3]);
createRelationship(fk[0][3], en.name);
}
}
}