-
Notifications
You must be signed in to change notification settings - Fork 3
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
WIP: auto crud #51
base: master
Are you sure you want to change the base?
WIP: auto crud #51
Changes from all commits
b5e31bd
b927bc1
c46a484
ebf681b
c506e2d
293eb09
75e3c49
cba32f2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
docs | ||
node_modules/**/* | ||
.idea* | ||
*.log | ||
.vscode | ||
docs | ||
node_modules/**/* | ||
.idea* | ||
*.log | ||
.vscode | ||
package-lock.json |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
module.exports = (binding) => { | ||
let columns = binding.fields.filter(f => !f.identity).map(f => `[${f.column}]`).join(', '); | ||
return ` | ||
CREATE PROCEDURE ${binding.spName} | ||
@data ${binding.tt} READONLY | ||
AS | ||
SET NOCOUNT ON | ||
DECLARE @result ${binding.tt} | ||
BEGIN TRY | ||
INSERT INTO ${binding.name} (${columns}) | ||
OUTPUT INSERTED.* INTO @result | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No praticular reason. Just thought that storing the data in a table type would be easier to return all the data as a named resultset at the end. |
||
SELECT ${columns} | ||
FROM @data | ||
|
||
SELECT 'data' AS resultSetName | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we discuss if 'data' is good as name? If we call multiple procedures as part of a bigger one, it is better each to return different name for the resultset. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure. Instead of 'data' it can be the table name. e.g. 'customer.customer', 'customer.organization', etc. |
||
SELECT * from @result | ||
END TRY | ||
BEGIN CATCH | ||
IF @@TRANCOUNT != 0 | ||
ROLLBACK TRANSACTION | ||
DECLARE | ||
@errmsg NVARCHAR(2048), | ||
@severity TINYINT, | ||
@state TINYINT, | ||
@errno INT, | ||
@proc sysname, | ||
@lineno INT | ||
SELECT | ||
@errmsg = error_message(), | ||
@severity = error_severity(), | ||
@state = error_state(), | ||
@errno = error_number(), | ||
@proc = error_procedure(), | ||
@lineno = error_line() | ||
IF @errmsg NOT LIKE '***%' | ||
BEGIN | ||
SELECT @errmsg = '*** ' + COALESCE(QUOTENAME(@proc), '<dynamic SQL>') + | ||
', Line ' + LTRIM(STR(@lineno)) + '. Errno ' + | ||
LTRIM(STR(@errno)) + ': ' + @errmsg | ||
END | ||
RAISERROR('%s', @severity, @state, @errmsg) | ||
RETURN 55555 | ||
END CATCH | ||
`; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
module.exports = (binding) => { | ||
const pkField = binding.fields.find(f => !!f.identity); | ||
if (!pkField) { | ||
return ''; | ||
} | ||
const pk = `[${pkField.column}]`; | ||
return ` | ||
CREATE PROCEDURE ${binding.spName} | ||
@data ${binding.tt} READONLY | ||
AS | ||
SET NOCOUNT ON | ||
DECLARE @result ${binding.tt} | ||
BEGIN TRY | ||
DELETE target | ||
OUTPUT DELETED.* INTO @result | ||
FROM ${binding.name} target | ||
JOIN @data source ON target.${pk} = source.${pk} | ||
|
||
SELECT 'data' AS resultSetName | ||
SELECT * from @result | ||
END TRY | ||
BEGIN CATCH | ||
IF @@TRANCOUNT != 0 | ||
ROLLBACK TRANSACTION | ||
DECLARE | ||
@errmsg NVARCHAR(2048), | ||
@severity TINYINT, | ||
@state TINYINT, | ||
@errno INT, | ||
@proc sysname, | ||
@lineno INT | ||
SELECT | ||
@errmsg = error_message(), | ||
@severity = error_severity(), | ||
@state = error_state(), | ||
@errno = error_number(), | ||
@proc = error_procedure(), | ||
@lineno = error_line() | ||
IF @errmsg NOT LIKE '***%' | ||
BEGIN | ||
SELECT @errmsg = '*** ' + COALESCE(QUOTENAME(@proc), '<dynamic SQL>') + | ||
', Line ' + LTRIM(STR(@lineno)) + '. Errno ' + | ||
LTRIM(STR(@errno)) + ': ' + @errmsg | ||
END | ||
RAISERROR('%s', @severity, @state, @errmsg) | ||
RETURN 55555 | ||
END CATCH | ||
`; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
const crud = { | ||
create: require('./create'), | ||
read: require('./read'), | ||
update: require('./update'), | ||
delete: require('./delete') | ||
}; | ||
|
||
module.exports = { | ||
actions: Object.keys(crud), | ||
generate: (binding, action) => { | ||
let name; | ||
let suffix; | ||
if (binding.name.match(/]$/)) { | ||
name = binding.name.slice(0, -1); | ||
suffix = ']'; | ||
} else { | ||
name = binding.name; | ||
suffix = ''; | ||
} | ||
binding.spName = `${name}.${action}${suffix}`; | ||
binding.tt = `${name}TT${suffix}`; | ||
binding.ttu = `${name}TTU${suffix}`; | ||
return crud[action](binding); | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module.exports = () => { | ||
return ``; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module.exports = () => { | ||
return ``; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,11 +6,14 @@ | |
"fs-plus": "3.0.2", | ||
"json-stringify-deterministic": "1.0.1", | ||
"lodash.merge": "4.6.0", | ||
"through2": "2.0.3", | ||
"mssql": "4.1.0", | ||
"through2": "2.0.3", | ||
"uuid": "3.2.1", | ||
"xml2js": "0.4.19" | ||
}, | ||
"peerDependencies": { | ||
"tedious": "^2.0.0" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't this already a peer dependency of mssql? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is a dependency of mssql. And I saw it is directly required here so I had to add it to the package.json. If we end up with 2 different versions of tedious that patch won't work. |
||
}, | ||
"devDependencies": { | ||
"ut-tools": "^5.32.5", | ||
"pegjs": "0.10.0" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we also have a generic logic for checking for already existing records and raising standard errors?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I just wrote some generic SQL code which I didn't mean to be final ... just to test the concept.
We can change the bodies and the names of the procedures however we like. My main idea was to align with you whether the changes in index.js are fine. Maybe @mlessevsg can help with the SQL.