Skip to content

Commit

Permalink
Merge pull request #75 from datajoint/stage
Browse files Browse the repository at this point in the history
Added support for {} in comments when creating tables
  • Loading branch information
guzman-raphael authored May 19, 2021
2 parents 54eff56 + 6f03ce9 commit cd31b05
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 33 deletions.
2 changes: 1 addition & 1 deletion LNX-docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ services:
- MYSQL_ROOT_PASSWORD=simple
fakeservices.datajoint.io:
<<: *net
image: raphaelguzman/nginx:v0.0.10
image: datajoint/nginx:v0.0.16
environment:
- ADD_db_TYPE=DATABASE
- ADD_db_ENDPOINT=db:3306
Expand Down
Binary file modified distribution/mexa64/mym.mexa64
Binary file not shown.
Binary file modified distribution/mexmaci64/mym.mexmaci64
Binary file not shown.
Binary file modified distribution/mexw64/mym.mexw64
Binary file not shown.
2 changes: 1 addition & 1 deletion local-docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ services:
# - ./mysql/data:/var/lib/mysql
fakeservices.datajoint.io:
<<: *net
image: raphaelguzman/nginx:v0.0.10
image: datajoint/nginx:v0.0.16
environment:
- ADD_db_TYPE=DATABASE
- ADD_db_ENDPOINT=db:3306
Expand Down
88 changes: 58 additions & 30 deletions src/mym.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ static void updateplugindir() {
mxDestroyArray(mym_fileparts[2]);
}
/**********************************************************************
*mysql(): Execute the actual action
* mysql(): Execute the actual action
* Which action we perform is based on the first input argument,
* which must be present and must be a character string:
* 'open', 'close', 'use', 'status', or a legitimate MySQL query.
Expand Down Expand Up @@ -694,11 +694,11 @@ void mexFunction(int nlhs, mxArray*plhs[], int nrhs, const mxArray*prhs[]) {
}
//******************PLACEHOLDER PROCESSING******************
// global placeholders variables and constant
const unsigned nex = nrhs-jarg-1; // expected number of placeholders
const unsigned expectedNumberOfPlaceholders = nrhs-jarg-1; // expected number of placeholders
unsigned query_flags = 0;
unsigned nb_flags = 0;
unsigned nac = 0; // actual number
size_t lq = strlen(query); // original query length, needed at some point
size_t lengthOfQuery = strlen(query); // Length of the query which is needed for mysql_real_query later
// Check for presence of query flags. This needs to be expanded once we have additional flags
for (int i=nrhs-1; i > jarg; --i) {
if (mxIsChar(prhs[i]) && (strcasecmp(getstring(prhs[i]), ML_FLAG_BIGINT_TO_DOUBLE)==0)) {
Expand All @@ -709,7 +709,8 @@ void mexFunction(int nlhs, mxArray*plhs[], int nrhs, const mxArray*prhs[]) {
}
}

if (nex) {
// If there is placeholders, parse them accordingly
if (expectedNumberOfPlaceholders) {
// local placeholders variables and constant
char** po = 0; // pointer to placeholders openning symbols
char** pc = 0; // pointer to placeholders closing symbols
Expand All @@ -718,10 +719,10 @@ void mexFunction(int nlhs, mxArray*plhs[], int nrhs, const mxArray*prhs[]) {
unsigned* ps = 0; // pointer to placeholders size (in bytes)
pfserial* pf = 0; // pointer to serialization function
// LOOK FOR THE PLACEHOLDERS
po = (char**)mxCalloc(nex+1, sizeof(char*));
pc = (char**)mxCalloc(nex+1, sizeof(char*));
po = (char**)mxCalloc(expectedNumberOfPlaceholders+1, sizeof(char*));
pc = (char**)mxCalloc(expectedNumberOfPlaceholders+1, sizeof(char*));
if ((po[nac++] = strstr(query, PH_OPEN)))
while (po[nac-1]&&nac<=nex) {
while (po[nac-1]&&nac<=expectedNumberOfPlaceholders) {
pc[nac-1] = strstr(po[nac-1]+1, PH_CLOSE);
if (pc[nac-1]==0)
mexErrMsgTxt("Placeholders are not correctly closed!");
Expand All @@ -730,10 +731,10 @@ void mexFunction(int nlhs, mxArray*plhs[], int nrhs, const mxArray*prhs[]) {
}
nac--;
// Adjust placeholders based on the number of flags present
if ((nac < nex) && (nac >= (nex-nb_flags))) {
nb_flags = nex-nac;
if ((nac < expectedNumberOfPlaceholders) && (nac >= (expectedNumberOfPlaceholders-nb_flags))) {
nb_flags = expectedNumberOfPlaceholders-nac;
}
else if (nac != nex) {
else if (nac != expectedNumberOfPlaceholders) {
mexErrMsgTxt("The number of placeholders differs from that of additional arguments!");
}
// now we have the correct number of placeholders
Expand Down Expand Up @@ -789,7 +790,7 @@ void mexFunction(int nlhs, mxArray*plhs[], int nrhs, const mxArray*prhs[]) {
nb += plen[i];
}
// create new query
char* nq = (char*)mxCalloc(2*nb+lq+1, sizeof(char)); // new query
char* nq = (char*)mxCalloc(2*nb+lengthOfQuery+1, sizeof(char)); // new query
char* pnq = nq; // running pointer to new query
const char* poq = query; // running pointer to old query
for (unsigned i = 0; i<nac; i++) {
Expand All @@ -800,12 +801,12 @@ void mexFunction(int nlhs, mxArray*plhs[], int nrhs, const mxArray*prhs[]) {
pd[i]=NULL;
mxFree(pd[i]);
}
memcpy(pnq, poq, lq-(poq-query)+1);
memcpy(pnq, poq, lengthOfQuery-(poq-query)+1);
// replace the old query by the new one
pnq += lq-(poq-query)+1;
pnq += lengthOfQuery-(poq-query)+1;
mxFree(query);
query = nq;
lq = (ulong)(pnq-nq);
lengthOfQuery = (ulong)(pnq-nq);
mxFree(po);
mxFree(pc);
mxFree(pec);
Expand All @@ -816,13 +817,41 @@ void mexFunction(int nlhs, mxArray*plhs[], int nrhs, const mxArray*prhs[]) {
if (pcmp!=NULL)
mxFree(pcmp);
}
else {
// check that no placeholders are present in the query
char*p_tmp_o = strstr(query, PH_OPEN);
char*p_tmp_c = strstr(query, PH_CLOSE);
if (p_tmp_o||p_tmp_c)
mexErrMsgTxt("The query contains placeholders, but no additional arguments!");
// Check that no placeholders are present in the query except for \{ and \}
char* parsedQueryString = (char*)mxCalloc(strlen(query), sizeof(char)); // Query string with escape character removed
size_t parsedQueryStringCurrentIndex = 0;

// Loop through the query string character by character
for (size_t i = 0; query[i] != '\0'; i++) {

if ((query[i] == '{' || query[i] == '}') && i != 0) {
if (query[i - 1] != '\\') {
// Curley bracket doesn't seem to be escaped thus throw and error
mxFree(parsedQueryString);
mexErrMsgTxt("The query contains placeholders, but no additional arguments!");
}
else {
// Valid curley bracket thus add it to the parsedQueryString with the \ removed
parsedQueryStringCurrentIndex--;
parsedQueryString[parsedQueryStringCurrentIndex] = query[i];
}
}
else {
// Non curley bracket thus add it to the parsedQueryString
parsedQueryString[parsedQueryStringCurrentIndex] = query[i];
}

// Increment the currentIndex counter
parsedQueryStringCurrentIndex++;
}
// Add ending character
parsedQueryString[parsedQueryStringCurrentIndex] = '\0';

// Update the query string
mxFree(query); // Free up the old string allocation
query = parsedQueryString;
lengthOfQuery = strlen(query); // Update the length of the query

// Process flags
for (int i=nrhs-nb_flags; i < nrhs; ++i) {
if (strcasecmp(getstring(prhs[i]), ML_FLAG_BIGINT_TO_DOUBLE)==0) {
Expand All @@ -832,7 +861,7 @@ void mexFunction(int nlhs, mxArray*plhs[], int nrhs, const mxArray*prhs[]) {

// Execute the query (data stays on server)
if (nac!=0) {
if (mysql_real_query(conn, query, lq))
if (mysql_real_query(conn, query, lengthOfQuery))
mexErrMsgTxt(mysql_error(conn));
}
else if (mysql_query(conn, query))
Expand Down Expand Up @@ -980,14 +1009,14 @@ void mexFunction(int nlhs, mxArray*plhs[], int nrhs, const mxArray*prhs[]) {
// serialize the matlab variable, it can be an array, cell, struct etc
//******************PLACEHOLDER PROCESSING******************
// global placeholders variables and constant
const unsigned nex = nrhs-jarg-1; // expected number of placeholders
const unsigned expectedNumberOfPlaceholders = nrhs-jarg-1; // expected number of placeholders
unsigned query_flags = 0;
unsigned nb_flags = 0;
unsigned nac = 0; // actual number
if (debug)
mexPrintf("Num of args = %d\n", (int) nex) ;
mexPrintf("Num of args = %d\n", (int) expectedNumberOfPlaceholders) ;

if (nex) {
if (expectedNumberOfPlaceholders) {
// local placeholders variables and constant
char** po = 0; // pointer to placeholders openning symbols
char** pc = 0; // pointer to placeholders closing symbols
Expand All @@ -996,10 +1025,10 @@ void mexFunction(int nlhs, mxArray*plhs[], int nrhs, const mxArray*prhs[]) {
unsigned* ps = 0; // pointer to placeholders size (in bytes)
pfserial* pf = 0; // pointer to serialization function
// LOOK FOR THE PLACEHOLDERS
po = (char**)mxCalloc(nex+1, sizeof(char*));
pc = (char**)mxCalloc(nex+1, sizeof(char*));
po = (char**)mxCalloc(expectedNumberOfPlaceholders+1, sizeof(char*));
pc = (char**)mxCalloc(expectedNumberOfPlaceholders+1, sizeof(char*));
if ((po[nac++] = strstr(query, PH_OPEN)))
while (po[nac-1]&&nac<=nex) {
while (po[nac-1]&&nac<=expectedNumberOfPlaceholders) {
pc[nac-1] = strstr(po[nac-1]+1, PH_CLOSE);
if (pc[nac-1]==0)
mexErrMsgIdAndTxt("mYm:Serialization:Placeholders",
Expand All @@ -1008,7 +1037,7 @@ void mexFunction(int nlhs, mxArray*plhs[], int nrhs, const mxArray*prhs[]) {
nac++;
}
nac--; // utilized to find {}s
if (nac != nex) {
if (nac != expectedNumberOfPlaceholders) {
mexErrMsgIdAndTxt("mYm:Serialization:Placeholders",
"The number of placeholders differs from that of additional arguments!");
}
Expand Down Expand Up @@ -1127,7 +1156,7 @@ void mexFunction(int nlhs, mxArray*plhs[], int nrhs, const mxArray*prhs[]) {
"There must be only one input and one output variable\n");
}
}
else if (q == VERSION) {
else if (q==VERSION) {
if (nrhs > (jarg+1))
mexErrMsgTxt("Version command does not take additional inputs");
if (nlhs == 0) {
Expand Down Expand Up @@ -1423,7 +1452,6 @@ char* serializeArray(size_t &rnBytes, const mxArray *rpArray, const char *rpArg,




// Serialize a sparse matrix
char* serializeSparse(size_t &rnBytes, const mxArray *rpArray,
const char *rpArg, const bool rhead)
Expand Down
2 changes: 1 addition & 1 deletion src/mym.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
// mym version information
#define MYM_VERSION_MAJOR 2
#define MYM_VERSION_MINOR 8
#define MYM_VERSION_BUGFIX 0
#define MYM_VERSION_BUGFIX 1


// some local defintion
Expand Down
1 change: 1 addition & 0 deletions tests/Main.m
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
classdef Main < ...
TestConnection & ...
TestDeclare & ...
TestExternal & ...
TestInsertFetch & ...
TestTls
Expand Down
25 changes: 25 additions & 0 deletions tests/TestDeclare.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
classdef TestDeclare < Prep
% TestDeclare tests typical connection scenarios.
methods (Test)
function TestDeclare_delcareTable(testCase)
% Test table declare with comments that has \{ or \}
st = dbstack;
disp(['---------------' st(1).name '---------------']);
conn1 = mym(-1, 'open', testCase.CONN_INFO.host, ...
testCase.CONN_INFO.user, testCase.CONN_INFO.password, ...
'false');

mym(conn1, ['create database `' testCase.PREFIX '_declare`']);
mym(['create table {S}(id int, data varchar(30) default null) COMMENT "\{username\}_\{subject_nickname\}"'], ...
sprintf('`%s_%s`.`%s`', testCase.PREFIX, 'declare', 'test_table'));
query_string = mym(sprintf('SHOW CREATE TABLE `%s_%s`.`%s`', testCase.PREFIX, 'declare', 'test_table'));

if ~strfind(query_string.('Create Table'){1}, 'COMMENT=''{username}_{subject_nickname}''')
throw(MException('TestDeclare:invalidDeclareTable',...
'Table comments got inserted incorrectly'));
end
mym(conn1, ['drop database `' testCase.PREFIX '_declare`']);
mym(conn1, 'close');
end
end
end

0 comments on commit cd31b05

Please sign in to comment.