Skip to content

Resolves #57, Resolves #62, Resolves #63 #61

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Apr 11, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,20 @@ Fixed invalid 'Misaligned Table ...' error, exhibited in vscode QSQL extension (
NPX command

Error diagnostic fixes

## [1.2.10] - 2024-3-22

#41

## [1.2.11] - 2024-3-22

#57
#62
#63

## [1.2.12] - 2024-4-2

Misindented error diagnostics, one more time
Table and column directive syntax check


2 changes: 1 addition & 1 deletion dist/quick-erd.js
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ class T {
});
}
}
const _ = "1.2.10", R = {
const _ = "1.2.12", R = {
Diagram: T,
version: _
};
Expand Down
2 changes: 1 addition & 1 deletion dist/quick-erd.umd.cjs

Large diffs are not rendered by default.

4,070 changes: 2,084 additions & 1,986 deletions dist/quick-sql.js

Large diffs are not rendered by default.

411 changes: 205 additions & 206 deletions dist/quick-sql.umd.cjs

Large diffs are not rendered by default.

7 changes: 3 additions & 4 deletions doc/user/quick-sql-grammar.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@
| /compress, /compressed | Table will be created compressed. |
| /insert NN | Generate NN SQL INSERT statement(s) with random data, for example: /INSERT 20. (Maximum = 1000) |
| /rest | Generate REST enablement of the table using Oracle REST Data Services (ORDS) |
| /select | Generate SQL SELECT statement after generating data for each table |
| /unique, /uk | Generate table level unique constraint |
| /pk | Generate primary key constraint (on table level it is usually a composite key) |
<!-- markdownlint-enable MD013 -->
Expand Down Expand Up @@ -122,11 +121,9 @@ and is usually omitted from QSQL schema definition.
| /lower | Forces column values to lower case |
| /nn, /not null | Adds a not null constraint on the column |
| /between | Adds a between check constraint on the column, for example /between 1 and 100 |
| /hidden, /invisible | Hidden columns are not displayed using select * from table. |
| /references, /reference, /fk | Foreign key references e.g. /references table_name. Note you can reference tables that are not part of your model. |
| /cascade | on delete cascade |
| /setnull | on delete set null |
| /references, /reference, /fk | Foreign key references e.g. /references table_name. Note you can reference tables that are not part of your model. |
| /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. |
| --, [comments] | Enclose comments using square brackets or using dash dash syntax |
<!-- markdownlint-enable MD013 -->
Expand Down Expand Up @@ -467,9 +464,10 @@ tableDirective::= '/'
|'compress'|'compressed'
|'insert' integer
|'rest'
|'select'
|'unique' | 'uk'
|'pk'
|'check'
|'cascade'
)

columnDirective::= '/'
Expand All @@ -485,6 +483,7 @@ columnDirective::= '/'
|'between'
|'hidden'|'invisible'
|'references'|'reference'
|'cascade'|'setnull'
|'fk'
|'pk'
)
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@oracle/quicksql",
"version": "1.2.10",
"version": "1.2.12",
"description": "Quick SQL to DDL and ERD translator",
"main": "./dist/quick-sql.umd.cjs",
"module": "./dist/quick-sql.js",
Expand Down
58 changes: 53 additions & 5 deletions src/ddl.js
Original file line number Diff line number Diff line change
Expand Up @@ -269,14 +269,62 @@ export const quicksql = (function () {

output.items.push(item);

let id = descendants[i].getGenIdColName();
if( id != null )
item.columns.push({name: id, datatype: "number"});

let idColName = descendants[i].getGenIdColName();
if( idColName != null && !descendants[i].isOption('pk') ) {
item.columns.push({name: idColName, datatype: "number"});
} else {
let pkName = descendants[i].getExplicitPkName();
if( pkName != null && pkName.indexOf(',') < 0 ) {
let type = 'number';
const child = descendants[i].findChild(pkName);
if( child != null )
type = child.parseType();
item.columns.push({name: pkName, datatype: type});
}
}

descendants[i].lateInitFks();
for( let fk in descendants[i].fks ) {
let parent = descendants[i].fks[fk];
if( 0 < fk.indexOf(',') ) {
let refNode = this.find(parent);
var chunks = split_str(fk,', ');
for( var ii = 0; ii < chunks.length; ii++ ) {
var col = chunks[ii];
if( col == ',' )
continue;
const pChild = refNode.findChild(col);
item.columns.push({name: col, datatype: pChild.parseType(pure=>true)});
}
continue;
}
let type = 'number';
const attr = descendants[i].findChild(fk);
if( attr != null )
type = attr.parseType('fk');
let refNode = this.find(parent);
let _id = '';
if( refNode != null ) {
const rname = refNode.getExplicitPkName();
if( rname != null && rname.indexOf(',') < 0 )
type = refNode.getPkType();
} else {
refNode = this.find(fk);
if( refNode.isMany2One() & !fk.endsWith('_id') ) {
parent = fk;
fk = singular(fk);
_id = '_id';
}
}
item.columns.push({name: fk, datatype: type});
}

for( let j = 0; j < descendants[i].children.length; j++ ) {
let child = descendants[i].children[j];
if( child.parseType() == 'table' )
continue;
if( child.refId() != null )
continue;
item.columns.push({name: child.parseName(''), datatype: child.parseType(pure=>true)});
if( 0 < child.indexOf('file') ) {
const col = child.parseName();
Expand All @@ -289,7 +337,7 @@ export const quicksql = (function () {

const nodeContent = descendants[i].trimmedContent().toUpperCase();
if( this.optionEQvalue('rowkey',true) || 0 < nodeContent.indexOf('/ROWKEY') ) {
item.columns.push({name: 'row_key', datatype: 'varchar2(30 char)'});
item.columns.push({name: 'row_key', datatype: 'varchar2(30'+this.semantics()+ ')'});
}
if( this.optionEQvalue('rowVersion','yes') || 0 < nodeContent.indexOf('/ROWVERSION') ) {
item.columns.push({name: 'row_version', datatype: 'integer'});
Expand Down
106 changes: 80 additions & 26 deletions src/errorMsgs.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@ const findErrors = (function () {

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

ret = ret.concat(line_mismatch(lines));
let branches = []
for( var i = 0; i < parsed.forest.length; i++ ) {
if( parsed.forest[i].parseType() == 'table' )
branches = branches.concat(parsed.forest[i].descendants());
}
ret = ret.concat(line_mismatch(branches));
const descendants = ddl.descendants();

for( let i = 0; i < descendants.length; i++ ) {
Expand All @@ -43,19 +48,53 @@ const findErrors = (function () {
continue;
}
const src1 = node.src[1];
if( 1 < node.src.length && 0 < src1.value.indexOf('0') ) {
if( 1 < node.src.length && src1.value.length == 3 && 0 < src1.value.indexOf('0') ) { // vc0
const depth = src1.begin;
ret.push(new SyntaxError( messages.invalidDatatype, new Offset(node.line,depth) ));
continue;
}

ret = ret.concat(ref_error_in_view(ddl,node));
ret = ret.concat(fk_ref_error(ddl,node));
ret = ret.concat(directive_typo(ddl,node));
}

return ret;
}

function directive_typo( ddl, node ) {
const isTable = node.parseType() == 'table';
var ret = [];

var chunks = node.src;
var sawSlash = false;
for( var j = 1; j < chunks.length; j++ ) {
if( chunks[j].value == '/' ) {
sawSlash = true;
continue;
}
if( sawSlash ) {
sawSlash = false;
if( isTable && tableDirectives.indexOf(chunks[j].value.toLowerCase()) < 0 )
ret.push( new SyntaxError(
messages.tableDirectiveTypo,
new Offset(node.line, chunks[j].begin),
new Offset(node.line, chunks[j].begin+chunks[j].value.length)
));
if( !isTable && columnDirectives.indexOf(chunks[j].value.toLowerCase()) < 0 )
ret.push( new SyntaxError(
messages.columnDirectiveTypo,
new Offset(node.line, chunks[j].begin),
new Offset(node.line, chunks[j].begin+chunks[j].value.length)
));

continue;
}
}
return ret;
}


function ref_error_in_view( ddl, node ) {
var ret = [];

Expand Down Expand Up @@ -85,6 +124,8 @@ const findErrors = (function () {
pos++;
if( node.src.length-1 < pos )
return ret;
if( node.src[pos].value == '/' )
return ret;
var tbl = ddl.find(node.src[pos].value);
if( tbl == null ) {
ret.push( new SyntaxError(
Expand All @@ -103,19 +144,14 @@ const findErrors = (function () {
var indent = guessIndent( lines )

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

var priorIndent = depth(priorline);
var lineIndent = depth(line);

if( lineIndent == 0 )
continue;

if( priorIndent < lineIndent && lineIndent < priorIndent+indent )

if( lineIndent%indent != 0 )
ret.push(new SyntaxError(
messages.misalignedAttribute+indent,
new Offset(i, lineIndent)
new Offset(line.line, lineIndent)
)
);
}
Expand All @@ -125,7 +161,37 @@ const findErrors = (function () {
return checkSyntax;
}());


const tableDirectives = [
'api'
,'audit','auditcols',//'audit cols','audit columns'
,'check'
,'colprefix'
,'compress','compressed'
,'insert'
,'rest'
,'select'
,'unique' , 'uk'
,'pk'
,'cascade','setnull' //'set null'
];

const columnDirectives = [
'idx','index','indexed'
,'unique','uk'
,'check'
,'constant'
,'default'
,'values'
,'upper'
,'lower'
,'nn','not'//,'not null'
,'between'
,'hidden','invisible'
,'references','reference'
,'cascade','setnull' //'set null'
,'fk'
,'pk'
];

function guessIndent( lines ) {
let depths = [];
Expand Down Expand Up @@ -156,21 +222,7 @@ function guessIndent( lines ) {
}

function depth( line ) {
var chunks = line.split(/ |\t/);
var offset = 0;
for( var j = 0; j < chunks.length; j++ ) {
var chunk = chunks[j];
if( "\t" == chunk ) {
offset += 4; //TODO;
}
if( "" == chunk ) {
offset++;
continue;
}
if( !/[^.a-zA-Z0-9_"]/.test(chunk) )
return offset;
}
return 0;
return line.src[0].begin;
}

function parentIndex( depths, lineNo ) {
Expand All @@ -186,6 +238,8 @@ const messages = {
invalidDatatype: 'Invalid Datatype',
undefinedObject: 'Undefined Object: ',
misalignedAttribute: 'Misaligned Table or Column; apparent indent = ',
tableDirectiveTypo: 'Unknown Table directive',
columnDirectiveTypo: 'Unknown Column directive',
}

export default {findErrors, messages};
2 changes: 1 addition & 1 deletion src/json2qsql.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ var json2qsql = (function () {
let output = tc.output(name+signature(obj), obj, 0);

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

output += '\n\n#flattened = \n';
const tableContent = {};
Expand Down
Loading
Loading