-
Notifications
You must be signed in to change notification settings - Fork 41
Modify update to allow nullable updates for strings/date #213
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
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
236a4d0
Fix update issue and add appropriate schema + tests.
guzman-raphael 54dd02b
Merge pull request #212 from guzman-raphael/fix-update-date-null
guzman-raphael 9bc424f
Fix travis.
guzman-raphael fd21e7c
Update test structure and add docs on how to run tests locally.
guzman-raphael cf6570a
Merge pull request #214 from guzman-raphael/fix-update-date-null
guzman-raphael 4354bc6
Fix issue in reading schema MySQL8.
guzman-raphael c907c35
Merge pull request #215 from guzman-raphael/fix-update-date-null
guzman-raphael c1e3af3
Fix linting.
guzman-raphael 74198dc
Merge pull request #223 from guzman-raphael/fix-update-date-null
guzman-raphael 1916bf0
Fix linting2.
guzman-raphael 1dd9c55
Merge pull request #224 from guzman-raphael/fix-update-date-null
guzman-raphael File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -343,40 +343,32 @@ function update(self, attrname, value) | |
| % update(v2p.Mice & key, 'mouse_dob', '2011-01-01') | ||
| % update(v2p.Scan & key, 'lens') % set the value to NULL | ||
|
|
||
| assert(count(self)==1, 'Update is only allowed on one tuple at a time') | ||
| isNull = nargin<3; | ||
| assert(count(self)==1, 'Update is only allowed on one tuple at a time'); | ||
| header = self.header; | ||
| ix = find(strcmp(attrname,header.names)); | ||
| assert(numel(ix)==1, 'invalid attribute name') | ||
| assert(~header.attributes(ix).iskey, 'cannot update a key value. Use insert(..,''REPLACE'') instead') | ||
| assert(numel(ix)==1, 'invalid attribute name'); | ||
| assert(~header.attributes(ix).iskey, ... | ||
| 'cannot update a key value. Use insert(..,''REPLACE'') instead'); | ||
| isNull = nargin<3 || (header.attributes(ix).isNumeric && isnan(value)) || ... | ||
| (~header.attributes(ix).isNumeric && ~ischar(value) && isempty(value)); | ||
|
|
||
| switch true | ||
| case isNull | ||
| assert(header.attributes(ix).isnullable, ... | ||
| 'attribute `%s` is not nullable.', attrname); | ||
| valueStr = 'NULL'; | ||
| value = {}; | ||
| case header.attributes(ix).isString | ||
| assert(dj.lib.isString(value), 'Value must be a string') | ||
| assert(dj.lib.isString(value), 'Value must be a string'); | ||
| valueStr = '"{S}"'; | ||
| value = {char(value)}; | ||
| case header.attributes(ix).isBlob | ||
| if isempty(value) && header.attributes(ix).isnullable | ||
| valueStr = 'NULL'; | ||
| value = {}; | ||
| else | ||
| valueStr = '"{M}"'; | ||
| value = {value}; | ||
| end | ||
| valueStr = '"{M}"'; | ||
|
Member
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. how is NULL handled here?
Member
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. oh, I see, it's already handled together for all attribute types. |
||
| value = {value}; | ||
| case header.attributes(ix).isNumeric | ||
| assert(isscalar(value) && isnumeric(value), 'Numeric value must be scalar') | ||
| if isnan(value) | ||
| assert(header.attributes(ix).isnullable, ... | ||
| 'attribute `%s` is not nullable. NaNs not allowed', attrname) | ||
| valueStr = 'NULL'; | ||
| value = {}; | ||
| else | ||
| valueStr = sprintf('%1.16g',value); | ||
| value = {}; | ||
| end | ||
| valueStr = sprintf('%1.16g',value); | ||
| value = {}; | ||
| otherwise | ||
| error 'invalid update command' | ||
| end | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,89 +1,96 @@ | ||
| function createSchema(package,parentdir,db) | ||
| % DJ.CREATESCHEMA - interactively create a new DataJoint schema | ||
| % | ||
| % INPUT: | ||
| % (optional) package - name of the package to be associated with the schema | ||
| % (optional) parentdir - name of the dirctory where to create new package | ||
| % (optional) db - database name to associate with the schema | ||
|
|
||
| if nargin < 3 | ||
| dbname = input('Enter database name >> ','s'); | ||
| else | ||
| dbname = db; | ||
| end | ||
|
|
||
| if ~dbname | ||
| disp 'No database name entered. Quitting.' | ||
| elseif isempty(regexp(dbname,'^[a-z][a-z0-9_]*$','once')) | ||
| error 'Invalid database name. Begin with a letter, only lowercase alphanumerical and underscores.' | ||
| else | ||
| % create database | ||
| s = query(dj.conn, ... | ||
| sprintf('SELECT schema_name FROM information_schema.schemata WHERE schema_name = "%s"', dbname)); | ||
|
|
||
| if ~isempty(s.schema_name) | ||
| disp 'database already exists' | ||
| % DJ.CREATESCHEMA - interactively create a new DataJoint schema | ||
| % | ||
| % INPUT: | ||
| % (optional) package - name of the package to be associated with the schema | ||
| % (optional) parentdir - name of the dirctory where to create new package | ||
| % (optional) db - database name to associate with the schema | ||
|
|
||
| if nargin < 3 | ||
| dbname = input('Enter database name >> ','s'); | ||
| else | ||
| query(dj.conn, sprintf('create schema %s',dbname)) | ||
| disp 'database created' | ||
| dbname = db; | ||
| end | ||
|
|
||
| if nargin < 1 | ||
| if usejava('desktop') | ||
| disp 'Please select a package folder. Opening UI...' | ||
| folder = uigetdir('./','Select a package folder'); | ||
|
|
||
| if ~dbname | ||
| disp 'No database name entered. Quitting.' | ||
| elseif isempty(regexp(dbname,'^[a-z][a-z0-9_]*$','once')) | ||
| error(['Invalid database name. Begin with a letter, only lowercase alphanumerical and ' ... | ||
| 'underscores.']) | ||
| else | ||
| % create database | ||
| s = query(dj.conn, ... | ||
| sprintf(['SELECT schema_name as `schema_name` ' ... | ||
| 'FROM information_schema.schemata WHERE schema_name = "%s"'], dbname)); | ||
|
|
||
| if ~isempty(s.schema_name) | ||
| disp 'database already exists' | ||
| else | ||
| folder = input('Enter package folder path >> ','s'); | ||
| query(dj.conn, sprintf('create schema %s',dbname)) | ||
| disp 'database created' | ||
| end | ||
| else | ||
| if nargin < 3 | ||
|
|
||
| if nargin < 1 | ||
| if usejava('desktop') | ||
| fprintf('Please select folder to create package %s in. Opening UI...\n', ['+', package]) | ||
| folder = uigetdir('./', sprintf('Select folder to create package %s in', ['+', package])); | ||
| disp 'Please select a package folder. Opening UI...' | ||
| folder = uigetdir('./','Select a package folder'); | ||
| else | ||
| folder = input('Enter parent folder path >> ','s'); | ||
| folder = input('Enter package folder path >> ','s'); | ||
| end | ||
| else | ||
| folder = parentdir; | ||
| end | ||
|
|
||
| if folder | ||
| folder = fullfile(folder, ['+', package]); | ||
| mkdir(folder) | ||
| end | ||
| end | ||
|
|
||
| if ~folder | ||
| disp 'No package selected. Cancelled.' | ||
| else | ||
| [filepath,package] = fileparts(folder); | ||
| if package(1)~='+' | ||
| error 'Package folders must start with a +' | ||
| if nargin < 3 | ||
| if usejava('desktop') | ||
| fprintf('Please select folder to create package %s in. Opening UI...\n', ... | ||
| ['+', package]) | ||
| folder = uigetdir('./', sprintf('Select folder to create package %s in', ... | ||
| ['+', package])); | ||
| else | ||
| folder = input('Enter parent folder path >> ','s'); | ||
| end | ||
| else | ||
| folder = parentdir; | ||
| end | ||
|
|
||
| if folder | ||
| folder = fullfile(folder, ['+', package]); | ||
| mkdir(folder) | ||
| end | ||
| end | ||
| package = package(2:end); % discard + | ||
|
|
||
| % create the getSchema function | ||
| schemaFile = fullfile(folder,'getSchema.m'); | ||
| if exist(schemaFile,'file') | ||
| fprintf('%s.getSchema.m already exists\n', package) | ||
|
|
||
| if ~folder | ||
| disp 'No package selected. Cancelled.' | ||
| else | ||
| f = fopen(schemaFile,'wt'); | ||
| assert(-1 ~= f, 'Could not open %s', f) | ||
|
|
||
| fprintf(f,'function obj = getSchema\n'); | ||
| fprintf(f,'persistent schemaObject\n'); | ||
| fprintf(f,'if isempty(schemaObject)\n'); | ||
| fprintf(f,' schemaObject = dj.Schema(dj.conn, ''%s'', ''%s'');\n', package, dbname); | ||
| fprintf(f,'end\n'); | ||
| fprintf(f,'obj = schemaObject;\n'); | ||
| fprintf(f,'end\n'); | ||
| fclose(f); | ||
| end | ||
|
|
||
| % test that getSchema is on the path | ||
| whichpath = which(sprintf('%s.getSchema',package)); | ||
| if isempty(whichpath) | ||
| warning('Could not open %s.getSchema. Ensure that %s is on the path', package, filepath) | ||
| [filepath,package] = fileparts(folder); | ||
| if package(1)~='+' | ||
| error 'Package folders must start with a +' | ||
| end | ||
| package = package(2:end); % discard + | ||
|
|
||
| % create the getSchema function | ||
| schemaFile = fullfile(folder,'getSchema.m'); | ||
| if exist(schemaFile,'file') | ||
| fprintf('%s.getSchema.m already exists\n', package) | ||
| else | ||
| f = fopen(schemaFile,'wt'); | ||
| assert(-1 ~= f, 'Could not open %s', f) | ||
|
|
||
| fprintf(f,'function obj = getSchema\n'); | ||
| fprintf(f,'persistent schemaObject\n'); | ||
| fprintf(f,'if isempty(schemaObject)\n'); | ||
| fprintf(f,' schemaObject = dj.Schema(dj.conn, ''%s'', ''%s'');\n', ... | ||
| package, dbname); | ||
| fprintf(f,'end\n'); | ||
| fprintf(f,'obj = schemaObject;\n'); | ||
| fprintf(f,'end\n'); | ||
| fclose(f); | ||
| end | ||
|
|
||
| % test that getSchema is on the path | ||
| whichpath = which(sprintf('%s.getSchema',package)); | ||
| if isempty(whichpath) | ||
| warning('Could not open %s.getSchema. Ensure that %s is on the path', ... | ||
| package, filepath) | ||
| end | ||
| end | ||
| end | ||
| end | ||
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| function res = compareVersions(verArray, verComp) | ||
| % compareVersions - Semantic version comparison (greater than or equal) | ||
| % | ||
| % This function evaluates if an array of semantic versions is greater than | ||
| % or equal to a reference version. | ||
| % | ||
| % DISTRIBUTION: | ||
| % GitHub: https://github.com/guzman-raphael/compareVersions | ||
| % FileExchange: https://www.mathworks.com/matlabcentral/fileexchange/71849-compareversions | ||
| % | ||
| % res = compareVersions(verArray, verComp) | ||
| % INPUT: | ||
| % verArray: Cell array with the following conditions: | ||
| % - be of length >= 1, | ||
| % - contain only string elements, and | ||
| % - each element must be of length >= 1. | ||
| % verComp: String or Char array that verArray will compare against for | ||
| % greater than evaluation. Must be: | ||
| % - be of length >= 1, and | ||
| % - a string. | ||
| % OUTPUT: | ||
| % res: Logical array that identifies if each cell element in verArray | ||
| % is greater than or equal to verComp. | ||
| % TESTS: | ||
| % Tests included for reference. From root package directory, | ||
| % use command: runtests | ||
| % | ||
| % EXAMPLES: | ||
| % output = compareVersions({'3.2.4beta','9.5.2.1','8.0'}, '8.0.0'); %logical([0 1 1]) | ||
| % | ||
| % NOTES: | ||
| % Tests included for reference. From root package directory, | ||
| % use command: runtests | ||
| % | ||
| % Tested: Matlab 9.5.0.944444 (R2018b) Linux | ||
| % Author: Raphael Guzman, DataJoint | ||
| % | ||
| % $License: MIT (use/copy/change/redistribute on own risk) $ | ||
| % $File: compareVersions.m $ | ||
| % History: | ||
| % 001: 2019-06-12 11:00, First version. | ||
| % | ||
| % OPEN BUGS: | ||
| % - None | ||
| res_n = length(verArray); | ||
| if ~res_n || max(cellfun(@(c) ~ischar(c) && ... | ||
| ~isstring(c),verArray)) > 0 || min(cellfun('length',verArray)) == 0 | ||
| msg = { | ||
| 'compareVersions:Error:CellArray' | ||
| 'Cell array to verify must:' | ||
| '- be of length >= 1,' | ||
| '- contain only string elements, and' | ||
| '- each element must be of length >= 1.' | ||
| }; | ||
| error('compareVersions:Error:CellArray', sprintf('%s\n',msg{:})); | ||
| end | ||
| if ~ischar(verComp) && ~isstring(verComp) || length(verComp) == 0 | ||
| msg = { | ||
| 'compareVersions:Error:VersionRef' | ||
| 'Version reference must:' | ||
| '- be of length >= 1, and' | ||
| '- a string.' | ||
| }; | ||
| error('compareVersions:Error:VersionRef', sprintf('%s\n',msg{:})); | ||
| end | ||
| res = false(1, res_n); | ||
| for i = 1:res_n | ||
| shortVer = strsplit(verArray{i}, '.'); | ||
| shortVer = cellfun(@(x) str2double(regexp(x,'\d*','Match')), shortVer(1,:)); | ||
| longVer = strsplit(verComp, '.'); | ||
| longVer = cellfun(@(x) str2double(regexp(x,'\d*','Match')), longVer(1,:)); | ||
| shortVer_p = true; | ||
| longVer_p = false; | ||
| shortVer_s = length(shortVer); | ||
| longVer_s = length(longVer); | ||
|
|
||
| if shortVer_s > longVer_s | ||
| [longVer shortVer] = deal(shortVer,longVer); | ||
| [longVer_s shortVer_s] = deal(shortVer_s,longVer_s); | ||
| [longVer_p shortVer_p] = deal(shortVer_p,longVer_p); | ||
| end | ||
|
|
||
| shortVer = [shortVer zeros(1,longVer_s - shortVer_s)]; | ||
| diff = shortVer - longVer; | ||
| match = diff ~= 0; | ||
|
|
||
| if ~match | ||
| res(i) = true; | ||
| else | ||
| pos = 1:longVer_s; | ||
| pos = pos(match); | ||
| val = diff(pos(1)); | ||
| if val > 0 | ||
| res(i) = shortVer_p; | ||
| elseif val < 0 | ||
| res(i) = longVer_p; | ||
| end | ||
| end | ||
| end | ||
| end |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
beautifully handled