Skip to content

Commit 73ed4ae

Browse files
authored
Merge pull request #54 from oracle/2024/2/22
NPX command, error diagnostic fixes, issue 52
2 parents e3571dd + 239d454 commit 73ed4ae

Some content is hidden

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

54 files changed

+746
-418
lines changed

CHANGELOG.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,13 @@ in test/profile.js (test for pk-fk chain of 333 tables, 3 column each; 268 ms fo
3131

3232
## [1.2.2] - 2024-2-15
3333

34-
Issue #47
34+
Issue #52
3535

3636
Fixed invalid 'Misaligned Table ...' error, exhibited in vscode QSQL extension (yet to be published).
3737

38+
39+
## [1.2.4] - 2024-2-22
40+
41+
NPX command
42+
43+
Error diagnostic fixes

README.md

+8
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ The Quick SQL Syntax and Grammar are documented [here](./doc/user/quick-sql-gram
4848

4949
See below for examples of how to use this library.
5050

51+
### Command Line Usage
52+
53+
NPXJS regitry already contains package with conflicting name. To disambiguate, please use command like this:
54+
55+
```
56+
npx @oracle/quicksql test/apex/department_employees.qsql > output.sql
57+
```
58+
5159
### DDL NodeJS ECMA Script Module (ESM) Example
5260

5361
```js

bin/index.js

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#! /usr/bin/env node
2+
import {quicksql,fromJSON} from "../src/ddl.js";
3+
4+
import fs from "fs";
5+
6+
try {
7+
let file = null;
8+
9+
let args = process.argv.slice(2);
10+
if( args.length < 1 ) {
11+
console.error('Please enter input filename (.qsql, or .json)');
12+
process.exit(1);
13+
}
14+
15+
file = args[0];
16+
17+
const text = fs.readFileSync(file)
18+
let input = text.toString();
19+
20+
let output = null;
21+
if( file.endsWith('.json') ) {
22+
let key = file.substring(0,file.length-'.json'.length);
23+
const sp = file.lastIndexOf('/');
24+
if( 0 < sp )
25+
key = key.substring(sp+1);
26+
output = fromJSON(input, key);
27+
} else {
28+
output = new quicksql(input).getDDL();
29+
}
30+
console.log(output);
31+
process.exit(0);
32+
33+
} catch(e) {
34+
console.error(e);
35+
process.exit(1);
36+
};

dist/quick-erd.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -739,7 +739,7 @@ class de {
739739
e.rearrangeDiagram(3, !1), this.paperScroller.centerContent();
740740
}
741741
}
742-
const ue = "1.2.2", fe = {
742+
const ue = "1.2.6", fe = {
743743
Diagram: de,
744744
version: ue
745745
};

dist/quick-erd.umd.cjs

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

dist/quick-sql.js

+258-262
Large diffs are not rendered by default.

dist/quick-sql.umd.cjs

+53-51
Large diffs are not rendered by default.

package.json

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@oracle/quicksql",
3-
"version": "1.2.2",
3+
"version": "1.2.6",
44
"description": "Quick SQL to DDL and ERD translator",
55
"main": "./dist/quick-sql.umd.cjs",
66
"module": "./dist/quick-sql.js",
@@ -18,6 +18,9 @@
1818
"engines": {
1919
"node": ">=16"
2020
},
21+
"bin": {
22+
"quicksql": "bin/index.js"
23+
},
2124
"config": {
2225
"ddlLibraryName": "quickSQL",
2326
"ddlLibraryFileName": "quick-sql",

src/ddl.js

+7-2
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export const quicksql = (function () {
3636
overridesettings: {label: 'Ignore toDDL() second parameter', value:'no',check:['yes','no']},
3737
prefix: {label: 'Object Prefix', value:'' },
3838
//ondelete: {label: 'On Delete', value:'Cascade',check:['restrict','cascade','set null']},
39-
pk: { label: 'Primary Key Maintenance', value: identityDataType, check: [identityDataType, guid,'SEQ', 'NONE']},
39+
pk: { label: 'Primary Key Maintenance', value: guid, check: [identityDataType, guid,'SEQ', 'NONE']},
4040
prefixpkwithtname: {label:'Prefix primary keys with table name', value:'no',check:['yes','no']},
4141
rowkey: {label: 'Alphanumeric Row Identifier', value:'no',check:['yes','no']},
4242
rowversion: {label: 'Row Version Number', value:'no',check:['yes','no']},
@@ -74,6 +74,7 @@ export const quicksql = (function () {
7474
this.errors = null;
7575
this.options = JSON.parse(JSON.stringify(defaultOptions));
7676
this.input = fullInput;
77+
this.postponedAlters = [];
7778

7879
this.getOptionValue = function( kEy ) {
7980
const key = kEy.toLowerCase();
@@ -226,7 +227,7 @@ export const quicksql = (function () {
226227
if( this.getOptionValue('prefix') != null )
227228
value = this.getOptionValue('prefix');
228229
ret = ret + value;
229-
if( value != '' )
230+
if( value != '' && !value.endsWith('_') )
230231
ret = ret + '_';
231232
return ret.toLowerCase();
232233
};
@@ -369,6 +370,10 @@ export const quicksql = (function () {
369370
output += this.forest[i].toDDL()+'\n';
370371
}
371372

373+
for ( let i = 0; i < this.postponedAlters.length; i++ ) {
374+
output += this.postponedAlters[i]+'\n';
375+
}
376+
372377
let j = 0;
373378
for( let i = 0; i < descendants.length; i++ ) {
374379
let trigger = descendants[i].generateTrigger();

src/errorMsgs.js

+20-38
Original file line numberDiff line numberDiff line change
@@ -59,23 +59,14 @@ const findErrors = (function () {
5959
function ref_error_in_view( ddl, node ) {
6060
var ret = [];
6161

62-
var line = node.content.toLowerCase();
6362
if( node.parseType() == 'view' ) {
64-
var chunks = split_str(line,' '); //line.split(' ');
65-
let pos = 0;
66-
for( var j = 0; j < chunks.length; j++ ) {
67-
pos += chunks[j].length;
68-
if( chunks[j] == ' ' )
69-
continue;
70-
if( chunks[j] == 'view' )
71-
continue;
72-
if( j == 1 )
73-
continue;
74-
var tbl = ddl.find(chunks[j]);
63+
var chunks = node.src;
64+
for( var j = 2; j < chunks.length; j++ ) {
65+
var tbl = ddl.find(chunks[j].value);
7566
if( tbl == null ) {
7667
ret.push( new SyntaxError(
77-
messages.undefinedObject+chunks[j],
78-
new Offset(node.line, pos-chunks[j].length)
68+
messages.undefinedObject+chunks[j].value,
69+
new Offset(node.line, chunks[j].begin)
7970
));
8071
}
8172
}
@@ -85,32 +76,23 @@ const findErrors = (function () {
8576

8677
function fk_ref_error( ddl, node ) {
8778
var ret = [];
88-
var line = node.content.toLowerCase();
89-
if( 0 < line.indexOf("/fk") || 0 < line.indexOf("/reference") ) {
90-
let chunks = split_str(line,' '); //line.split(' ');
91-
let pos = 0;
92-
let refIsNext = false;
93-
for( var j = 0; j < chunks.length; j++ ) {
94-
pos += chunks[j].length;
95-
if( chunks[j] == ' ' )
96-
continue;
97-
if( chunks[j] == "/fk" || 0 == chunks[j].indexOf("/reference") ) {
98-
refIsNext = true;
99-
continue;
100-
}
101-
if( !refIsNext )
102-
continue;
103-
var tbl = ddl.find(chunks[j]);
104-
if( tbl == null ) {
105-
ret.push( new SyntaxError(
106-
messages.undefinedObject+chunks[j],
107-
new Offset(node.line, pos-chunks[j].length)
108-
));
109-
break;
110-
}
79+
if( node.isOption("fk") || 0 < node.indexOf('reference', true) ) {
80+
let fk = null;
81+
let pos = node.indexOf('fk');
82+
if( pos < 0 )
83+
pos = node.indexOf('reference');
84+
pos++;
85+
if( node.src.length-1 < pos )
86+
return ret;
87+
var tbl = ddl.find(node.src[pos].value);
88+
if( tbl == null ) {
89+
ret.push( new SyntaxError(
90+
messages.undefinedObject+node.src[pos].value,
91+
new Offset(node.line, node.src[pos].begin)
92+
));
11193
}
11294
}
113-
return ret;
95+
return ret;
11496
}
11597

11698
function line_mismatch( lines ) {

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 }';
145+
output += '\n\n#settings = { genpk: false, drop: true, pk: identityDataType }';
146146

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

src/tree.js

+27-19
Original file line numberDiff line numberDiff line change
@@ -741,27 +741,34 @@ let tree = (function(){
741741
}
742742
}
743743
pad = tab+' '.repeat(this.maxChildNameLen() - fk.length);
744-
ret += tab + fk + _id + pad + type + '\n';
745-
ret += tab + tab+' '.repeat(this.maxChildNameLen()) + 'constraint '+objName+'_'+fk+'_fk\n';
746-
let onDelete = '';
747-
if( this.isOption('cascade'))
748-
onDelete = ' on delete cascade';
749-
else if( this.isOption('setnull'))
750-
onDelete = ' on delete set null';
751-
let notNull = '';
752-
for( let c in this.children ) {
753-
let child = this.children[c];
754-
if( fk == child.parseName() ) {
755-
if( child.isOption('nn') || child.isOption('notnull') )
756-
notNull = ' NOT NULL'.toLowerCase();
757-
if( child.isOption('cascade') )
758-
onDelete = ' on delete cascade';
759-
else if( this.isOption('setnull'))
760-
onDelete = ' on delete set null';
761-
break;
744+
ret += tab + fk + _id + pad + type;
745+
if( refNode.line < this.line || refNode.isMany2One() ) {
746+
ret += tab + tab+' '.repeat(this.maxChildNameLen()) + 'constraint '+objName+'_'+fk+'_fk\n';
747+
let onDelete = '';
748+
if( this.isOption('cascade'))
749+
onDelete = ' on delete cascade';
750+
else if( this.isOption('setnull'))
751+
onDelete = ' on delete set null';
752+
let notNull = '';
753+
for( let c in this.children ) {
754+
let child = this.children[c];
755+
if( fk == child.parseName() ) {
756+
if( child.isOption('nn') || child.isOption('notnull') )
757+
notNull = ' NOT NULL'.toLowerCase();
758+
if( child.isOption('cascade') )
759+
onDelete = ' on delete cascade';
760+
else if( this.isOption('setnull'))
761+
onDelete = ' on delete set null';
762+
break;
763+
}
762764
}
765+
ret += tab + tab+' '.repeat(this.maxChildNameLen()) + 'references '+ddl.objPrefix()+parent+onDelete+notNull+',\n';
766+
} else {
767+
ret += ',\n';
768+
const alter = 'alter table '+objName+' add constraint '+objName+'_'+fk+'_fk foreign key ('+fk+') references '+ddl.objPrefix()+parent+';\n'
769+
if( !ddl.postponedAlters.includes(alter) )
770+
ddl.postponedAlters.push(alter);
763771
}
764-
ret += tab + tab+' '.repeat(this.maxChildNameLen()) + 'references '+ddl.objPrefix()+parent+onDelete+notNull+',\n';
765772
}
766773

767774
if( ddl.optionEQvalue('rowkey',true) || this.isOption('rowkey') ) {
@@ -1650,6 +1657,7 @@ let tree = (function(){
16501657

16511658
if( poundDirective == null && t.value == '#' ) {
16521659
poundDirective = '';
1660+
lineNo++;
16531661
continue;
16541662
}
16551663
if( poundDirective != null ) {

test/Bug35756025/2.sql

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
create table bug35756025 (
2-
id number generated by default on null as identity
2+
id number default on null to_number(sys_guid(), 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX')
33
constraint bug35756025_id_pk primary key,
44
deptno number,
55
dname varchar2(14 char),

test/Bug35756025/3.sql

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
create table bug35756025 (
2-
id number generated by default on null as identity
2+
id number default on null to_number(sys_guid(), 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX')
33
constraint bug35756025_id_pk primary key,
44
deptno number not null,
55
dname varchar2(14 char),

test/Bug35756025/4.qsql

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
bug35756025
22
deptno num /nn /pk
33
dname vc14
4-
loc vc13
4+
loc vc13
5+
6+
#pk: identityDataType

test/JSON/car_racing/1.qsql

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ team /insert 1
77
name
88
points num
99

10-
#settings = { genpk: false, drop: true }
10+
#settings = { genpk: false, drop: true, pk: identityDataType }
1111

1212
#flattened =
1313
{

test/JSON/car_racing/2.qsql

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ driver /insert 2
1212
name
1313
finalPosition num
1414

15-
#settings = { genpk: false, drop: true }
15+
#settings = { genpk: false, drop: true, pk: identityDataType }
1616

1717
#flattened =
1818
{

test/JSON/donuts.qsql

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ donuts /insert 3
1212
id vc32 /pk
1313
type
1414

15-
#settings = { genpk: false, drop: true }
15+
#settings = { genpk: false, drop: true, pk: identityDataType }
1616

1717
#flattened =
1818
{

test/apex/department_employees.quicksql

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ departments /insert 2
1111

1212
emp_v = departments employees
1313

14-
# settings = { "prefix": null, "semantics": "CHAR", "DV": false }
14+
# settings = { "prefix": null, "semantics": "CHAR", "DV": false, pk: identityDataType }

test/apex/departments_employees_skills.quicksql

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ departments /insert 2
1212
proficiency num /check 1, 2, 3, 4, 5 [with 1 being a novice and 5 being a guru]
1313

1414
# "schema": null
15-
# "semantics": "char"
15+
# "semantics": "char"
16+
# pk: identityDataType
1617
--# DV : no

test/apex/empty_emp.quicksql

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
dept
22
name
33

4-
emp
4+
emp
5+
6+
#pk: identityDataType

test/apex/forrestclinic.quicksql

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,4 @@ doctor_procedures
3838
medical_procedure vc30
3939

4040
# settings = { "prefix": "FRC", "ondelete": "RESTRICT", "semantics": "CHAR",
41-
"auditcols": true, "language": "EN", "APEX": true }
41+
"auditcols": true, "language": "EN", "APEX": true, pk: identityDataType }

test/apex/medipay.quicksql

+1-1
Original file line numberDiff line numberDiff line change
@@ -74,4 +74,4 @@ lead_meetings
7474
notes vc4000
7575
confirmed vc1 /default N
7676

77-
# settings = { prefix: "MED", semantics: "CHAR", auditCols: true, rowVersion: true, language: "EN", APEX: true }
77+
# settings = { prefix: "MED", semantics: "CHAR", auditCols: true, rowVersion: true, language: "EN", APEX: true, pk: identityDataType }

test/apex/project_management.quicksql

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#apex: true, auditcols: true
2+
#pk: identityDataType
23
projects /insert 5
34
name /nn
45
owner

test/apex/timecard.quicksql

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@ employees /insert 50 /api
1919

2020
view employee_timecards employees timecards
2121

22-
# settings = { semantics: "CHAR", API: true, rowVersion: true, drop: true, language: "EN", APEX: true, dv: false }
22+
# settings = { semantics: "CHAR", API: true, rowVersion: true, drop: true, language: "EN", APEX: true, dv: false, pk: identityDataType }

test/apex/to_dos.quicksql

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#apex: true, auditcols: true
2+
#pk: identityDataType
23
assignees /insert 10
34
full_name /nn
45
email

test/bugs/35.qsql

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ app_feature_items
55
feature_master_id number /fk feature_masters
66
name vc255 /nn
77

8-
#api:y
8+
#api:y
9+
#pk: identityDataType

0 commit comments

Comments
 (0)