Skip to content

Commit 8be42f7

Browse files
Merge pull request #61 from oracle/2024/3/13
Resolves #57, Resolves #62, Resolves #63
2 parents cc6054a + 3aea322 commit 8be42f7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+2699
-2367
lines changed

CHANGELOG.md

+17
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,20 @@ Fixed invalid 'Misaligned Table ...' error, exhibited in vscode QSQL extension (
4141
NPX command
4242

4343
Error diagnostic fixes
44+
45+
## [1.2.10] - 2024-3-22
46+
47+
#41
48+
49+
## [1.2.11] - 2024-3-22
50+
51+
#57
52+
#62
53+
#63
54+
55+
## [1.2.12] - 2024-4-2
56+
57+
Misindented error diagnostics, one more time
58+
Table and column directive syntax check
59+
60+

dist/quick-erd.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ class T {
365365
});
366366
}
367367
}
368-
const _ = "1.2.10", R = {
368+
const _ = "1.2.12", R = {
369369
Diagram: T,
370370
version: _
371371
};

dist/quick-erd.umd.cjs

+1-1
Large diffs are not rendered by default.

dist/quick-sql.js

+2,081-1,986
Large diffs are not rendered by default.

dist/quick-sql.umd.cjs

+205-206
Large diffs are not rendered by default.

doc/user/quick-sql-grammar.md

+3-5
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@
7979
| /compress, /compressed | Table will be created compressed. |
8080
| /insert NN | Generate NN SQL INSERT statement(s) with random data, for example: /INSERT 20. (Maximum = 1000) |
8181
| /rest | Generate REST enablement of the table using Oracle REST Data Services (ORDS) |
82-
| /select | Generate SQL SELECT statement after generating data for each table |
8382
| /unique, /uk | Generate table level unique constraint |
8483
| /pk | Generate primary key constraint (on table level it is usually a composite key) |
8584
<!-- markdownlint-enable MD013 -->
@@ -122,11 +121,9 @@ and is usually omitted from QSQL schema definition.
122121
| /lower | Forces column values to lower case |
123122
| /nn, /not null | Adds a not null constraint on the column |
124123
| /between | Adds a between check constraint on the column, for example /between 1 and 100 |
125-
| /hidden, /invisible | Hidden columns are not displayed using select * from table. |
126124
| /references, /reference, /fk | Foreign key references e.g. /references table_name. Note you can reference tables that are not part of your model. |
127125
| /cascade | on delete cascade |
128126
| /setnull | on delete set null |
129-
| /references, /reference, /fk | Foreign key references e.g. /references table_name. Note you can reference tables that are not part of your model. |
130127
| /pk | Identifies column as the primary key of the table. It is recommended not manually specify primary keys and let this app create primary key columns automatically. |
131128
| --, [comments] | Enclose comments using square brackets or using dash dash syntax |
132129
<!-- markdownlint-enable MD013 -->
@@ -467,9 +464,10 @@ tableDirective::= '/'
467464
|'compress'|'compressed'
468465
|'insert' integer
469466
|'rest'
470-
|'select'
471467
|'unique' | 'uk'
472468
|'pk'
469+
|'check'
470+
|'cascade'
473471
)
474472
475473
columnDirective::= '/'
@@ -483,8 +481,8 @@ columnDirective::= '/'
483481
|'lower'
484482
|'nn'|'not null'
485483
|'between'
486-
|'hidden'|'invisible'
487484
|'references'|'reference'
485+
|'cascade'|'setnull'
488486
|'fk'
489487
|'pk'
490488
)

package-lock.json

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@oracle/quicksql",
3-
"version": "1.2.10",
3+
"version": "1.2.12",
44
"description": "Quick SQL to DDL and ERD translator",
55
"main": "./dist/quick-sql.umd.cjs",
66
"module": "./dist/quick-sql.js",

src/ddl.js

+53-5
Original file line numberDiff line numberDiff line change
@@ -269,14 +269,62 @@ export const quicksql = (function () {
269269

270270
output.items.push(item);
271271

272-
let id = descendants[i].getGenIdColName();
273-
if( id != null )
274-
item.columns.push({name: id, datatype: "number"});
275-
272+
let idColName = descendants[i].getGenIdColName();
273+
if( idColName != null && !descendants[i].isOption('pk') ) {
274+
item.columns.push({name: idColName, datatype: "number"});
275+
} else {
276+
let pkName = descendants[i].getExplicitPkName();
277+
if( pkName != null && pkName.indexOf(',') < 0 ) {
278+
let type = 'number';
279+
const child = descendants[i].findChild(pkName);
280+
if( child != null )
281+
type = child.parseType();
282+
item.columns.push({name: pkName, datatype: type});
283+
}
284+
}
285+
286+
descendants[i].lateInitFks();
287+
for( let fk in descendants[i].fks ) {
288+
let parent = descendants[i].fks[fk];
289+
if( 0 < fk.indexOf(',') ) {
290+
let refNode = this.find(parent);
291+
var chunks = split_str(fk,', ');
292+
for( var ii = 0; ii < chunks.length; ii++ ) {
293+
var col = chunks[ii];
294+
if( col == ',' )
295+
continue;
296+
const pChild = refNode.findChild(col);
297+
item.columns.push({name: col, datatype: pChild.parseType(pure=>true)});
298+
}
299+
continue;
300+
}
301+
let type = 'number';
302+
const attr = descendants[i].findChild(fk);
303+
if( attr != null )
304+
type = attr.parseType('fk');
305+
let refNode = this.find(parent);
306+
let _id = '';
307+
if( refNode != null ) {
308+
const rname = refNode.getExplicitPkName();
309+
if( rname != null && rname.indexOf(',') < 0 )
310+
type = refNode.getPkType();
311+
} else {
312+
refNode = this.find(fk);
313+
if( refNode.isMany2One() & !fk.endsWith('_id') ) {
314+
parent = fk;
315+
fk = singular(fk);
316+
_id = '_id';
317+
}
318+
}
319+
item.columns.push({name: fk, datatype: type});
320+
}
321+
276322
for( let j = 0; j < descendants[i].children.length; j++ ) {
277323
let child = descendants[i].children[j];
278324
if( child.parseType() == 'table' )
279325
continue;
326+
if( child.refId() != null )
327+
continue;
280328
item.columns.push({name: child.parseName(''), datatype: child.parseType(pure=>true)});
281329
if( 0 < child.indexOf('file') ) {
282330
const col = child.parseName();
@@ -289,7 +337,7 @@ export const quicksql = (function () {
289337

290338
const nodeContent = descendants[i].trimmedContent().toUpperCase();
291339
if( this.optionEQvalue('rowkey',true) || 0 < nodeContent.indexOf('/ROWKEY') ) {
292-
item.columns.push({name: 'row_key', datatype: 'varchar2(30 char)'});
340+
item.columns.push({name: 'row_key', datatype: 'varchar2(30'+this.semantics()+ ')'});
293341
}
294342
if( this.optionEQvalue('rowVersion','yes') || 0 < nodeContent.indexOf('/ROWVERSION') ) {
295343
item.columns.push({name: 'row_version', datatype: 'integer'});

src/errorMsgs.js

+78-26
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,12 @@ const findErrors = (function () {
2626

2727
const lines = input.split("\n");
2828

29-
ret = ret.concat(line_mismatch(lines));
29+
let branches = []
30+
for( var i = 0; i < parsed.forest.length; i++ ) {
31+
if( parsed.forest[i].parseType() == 'table' )
32+
branches = branches.concat(parsed.forest[i].descendants());
33+
}
34+
ret = ret.concat(line_mismatch(branches));
3035
const descendants = ddl.descendants();
3136

3237
for( let i = 0; i < descendants.length; i++ ) {
@@ -43,19 +48,53 @@ const findErrors = (function () {
4348
continue;
4449
}
4550
const src1 = node.src[1];
46-
if( 1 < node.src.length && 0 < src1.value.indexOf('0') ) {
51+
if( 1 < node.src.length && src1.value == 'vc0' ) {
4752
const depth = src1.begin;
4853
ret.push(new SyntaxError( messages.invalidDatatype, new Offset(node.line,depth) ));
4954
continue;
5055
}
5156

5257
ret = ret.concat(ref_error_in_view(ddl,node));
5358
ret = ret.concat(fk_ref_error(ddl,node));
59+
ret = ret.concat(directive_typo(ddl,node));
5460
}
5561

5662
return ret;
5763
}
5864

65+
function directive_typo( ddl, node ) {
66+
const isTable = node.parseType() == 'table';
67+
var ret = [];
68+
69+
var chunks = node.src;
70+
var sawSlash = false;
71+
for( var j = 1; j < chunks.length; j++ ) {
72+
if( chunks[j].value == '/' ) {
73+
sawSlash = true;
74+
continue;
75+
}
76+
if( sawSlash ) {
77+
sawSlash = false;
78+
if( isTable && tableDirectives.indexOf(chunks[j].value.toLowerCase()) < 0 )
79+
ret.push( new SyntaxError(
80+
messages.tableDirectiveTypo,
81+
new Offset(node.line, chunks[j].begin),
82+
new Offset(node.line, chunks[j].begin+chunks[j].value.length)
83+
));
84+
if( !isTable && columnDirectives.indexOf(chunks[j].value.toLowerCase()) < 0 )
85+
ret.push( new SyntaxError(
86+
messages.columnDirectiveTypo,
87+
new Offset(node.line, chunks[j].begin),
88+
new Offset(node.line, chunks[j].begin+chunks[j].value.length)
89+
));
90+
91+
continue;
92+
}
93+
}
94+
return ret;
95+
}
96+
97+
5998
function ref_error_in_view( ddl, node ) {
6099
var ret = [];
61100

@@ -85,6 +124,8 @@ const findErrors = (function () {
85124
pos++;
86125
if( node.src.length-1 < pos )
87126
return ret;
127+
if( node.src[pos].value == '/' )
128+
return ret;
88129
var tbl = ddl.find(node.src[pos].value);
89130
if( tbl == null ) {
90131
ret.push( new SyntaxError(
@@ -103,19 +144,14 @@ const findErrors = (function () {
103144
var indent = guessIndent( lines )
104145

105146
for( var i = 1; i < lines.length; i++ ) {
106-
var priorline = lines[i-1];
107147
var line = lines[i];
108148

109-
var priorIndent = depth(priorline);
110149
var lineIndent = depth(line);
111-
112-
if( lineIndent == 0 )
113-
continue;
114-
115-
if( priorIndent < lineIndent && lineIndent < priorIndent+indent )
150+
151+
if( lineIndent%indent != 0 )
116152
ret.push(new SyntaxError(
117153
messages.misalignedAttribute+indent,
118-
new Offset(i, lineIndent)
154+
new Offset(line.line, lineIndent)
119155
)
120156
);
121157
}
@@ -125,7 +161,35 @@ const findErrors = (function () {
125161
return checkSyntax;
126162
}());
127163

128-
164+
const tableDirectives = [
165+
'api'
166+
,'audit','auditcols',//'audit cols','audit columns'
167+
,'check'
168+
,'colprefix'
169+
,'compress','compressed'
170+
,'insert'
171+
,'rest'
172+
,'unique' , 'uk'
173+
,'pk'
174+
,'cascade','setnull' //'set null'
175+
];
176+
177+
const columnDirectives = [
178+
'idx','index','indexed'
179+
,'unique','uk'
180+
,'check'
181+
,'constant'
182+
,'default'
183+
,'values'
184+
,'upper'
185+
,'lower'
186+
,'nn','not'//,'not null'
187+
,'between'
188+
,'references','reference'
189+
,'cascade','setnull' //'set null'
190+
,'fk'
191+
,'pk'
192+
];
129193

130194
function guessIndent( lines ) {
131195
let depths = [];
@@ -156,21 +220,7 @@ function guessIndent( lines ) {
156220
}
157221

158222
function depth( line ) {
159-
var chunks = line.split(/ |\t/);
160-
var offset = 0;
161-
for( var j = 0; j < chunks.length; j++ ) {
162-
var chunk = chunks[j];
163-
if( "\t" == chunk ) {
164-
offset += 4; //TODO;
165-
}
166-
if( "" == chunk ) {
167-
offset++;
168-
continue;
169-
}
170-
if( !/[^.a-zA-Z0-9_"]/.test(chunk) )
171-
return offset;
172-
}
173-
return 0;
223+
return line.src[0].begin;
174224
}
175225

176226
function parentIndex( depths, lineNo ) {
@@ -186,6 +236,8 @@ const messages = {
186236
invalidDatatype: 'Invalid Datatype',
187237
undefinedObject: 'Undefined Object: ',
188238
misalignedAttribute: 'Misaligned Table or Column; apparent indent = ',
239+
tableDirectiveTypo: 'Unknown Table directive',
240+
columnDirectiveTypo: 'Unknown Column directive',
189241
}
190242

191243
export default {findErrors, messages};

src/json2qsql.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ var json2qsql = (function () {
142142
let output = tc.output(name+signature(obj), obj, 0);
143143

144144
//output += "\n\ndv "+name+"_dv "+name +"";
145-
output += '\n\n#settings = { genpk: false, drop: true, pk: identityDataType }';
145+
output += '\n\n#settings = { genpk: false, drop: true, pk: identityDataType, semantics: char }';
146146

147147
output += '\n\n#flattened = \n';
148148
const tableContent = {};

0 commit comments

Comments
 (0)