Skip to content
Toggle navigation
Projects
Groups
Snippets
Help
public
/
sequelize
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
不要怂,就是干,撸起袖子干!
Commit c075cacb
authored
Sep 12, 2013
by
Jan Aagaard Meier
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Change ordering to use fn and col
1 parent
667cae4f
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
185 additions
and
59 deletions
lib/dialects/abstract/query-generator.js
lib/sequelize.js
lib/utils.js
test/mysql/query-generator.test.js
test/postgres/query-generator.test.js
test/sqlite/query-generator.test.js
lib/dialects/abstract/query-generator.js
View file @
c075cac
...
...
@@ -292,23 +292,12 @@ module.exports = (function() {
return
this
.
quoteIdentifiers
(
obj
,
force
)
}
else
if
(
Array
.
isArray
(
obj
))
{
return
this
.
quote
(
obj
[
0
],
force
)
+
' '
+
obj
[
1
]
}
else
{
// assumes object
var
s
=
''
if
(
obj
.
raw
)
{
s
=
obj
.
raw
}
else
if
(
obj
.
fn
)
{
s
+=
obj
.
fn
+
'('
s
+=
obj
.
cols
.
map
(
function
(
elem
)
{
return
this
.
quote
(
elem
,
force
)
}.
bind
(
this
)).
join
(
', '
)
+
')'
}
if
(
obj
.
direction
)
{
s
+=
' '
+
obj
.
direction
}
return
s
}
else
if
(
obj
instanceof
Utils
.
fn
||
obj
instanceof
Utils
.
col
)
{
return
obj
.
toString
(
this
)
}
else
if
(
Utils
.
_
.
isObject
(
obj
)
&&
'raw'
in
obj
)
{
return
obj
.
raw
}
else
{
throw
new
Error
(
'Unknown structure passed to order / group: '
+
JSON
.
stringify
(
ojb
))
}
},
...
...
lib/sequelize.js
View file @
c075cac
...
...
@@ -318,5 +318,13 @@ module.exports = (function() {
}).
run
()
}
Sequelize
.
prototype
.
fn
=
function
(
fn
)
{
return
new
Utils
.
fn
(
fn
,
Array
.
prototype
.
slice
.
call
(
arguments
,
1
))
}
Sequelize
.
prototype
.
col
=
function
(
col
)
{
return
new
Utils
.
col
(
col
)
}
return
Sequelize
})()
lib/utils.js
View file @
c075cac
...
...
@@ -468,9 +468,33 @@ var Utils = module.exports = {
removeTicks
:
function
(
s
,
tickChar
)
{
tickChar
=
tickChar
||
Utils
.
TICK_CHAR
return
s
.
replace
(
new
RegExp
(
tickChar
,
'g'
),
""
)
},
/*
* Utility functions for representing SQL functions, and columns that should be escaped.
* Please do not use these functions directly, use Sequelize.fn and Sequelize.col instead.
*/
fn
:
function
(
fn
,
args
)
{
this
.
fn
=
fn
this
.
args
=
args
},
col
:
function
(
col
)
{
this
.
col
=
col
}
}
Utils
.
fn
.
prototype
.
toString
=
function
(
queryGenerator
)
{
return
this
.
fn
+
'('
+
this
.
args
.
map
(
function
(
arg
)
{
if
(
arg
instanceof
Utils
.
fn
||
arg
instanceof
Utils
.
col
)
{
return
arg
.
toString
(
queryGenerator
)
}
else
{
return
queryGenerator
.
escape
(
arg
)
}
}).
join
(
', '
)
+
')'
}
Utils
.
col
.
prototype
.
toString
=
function
(
queryGenerator
)
{
return
queryGenerator
.
quote
(
this
.
col
)
}
Utils
.
CustomEventEmitter
=
require
(
__dirname
+
"/emitters/custom-event-emitter"
)
Utils
.
QueryChainer
=
require
(
__dirname
+
"/query-chainer"
)
Utils
.
Lingo
=
require
(
"lingo"
)
Utils
.
Lingo
=
require
(
"lingo"
)
\ No newline at end of file
test/mysql/query-generator.test.js
View file @
c075cac
...
...
@@ -175,33 +175,62 @@ if (dialect.match(/^mysql/)) {
expectation
:
"SELECT * FROM `myTable` ORDER BY `id` DESC;"
,
context
:
QueryGenerator
},
{
arguments
:
[
'myTable'
,
{
order
:
[{
raw
:
'f1(f2(id))'
,
direction
:
'DESC'
}]}],
title
:
'raw arguments are neither quoted nor escaped'
,
arguments
:
[
'myTable'
,
{
order
:
[[{
raw
:
'f1(f2(id))'
},
'DESC'
]]}],
expectation
:
"SELECT * FROM `myTable` ORDER BY f1(f2(id)) DESC;"
,
context
:
QueryGenerator
},
{
// Function-ception!
arguments
:
[
'myTable'
,
{
order
:
[{
fn
:
'f1'
,
cols
:
[
{
fn
:
'f2'
,
cols
:
[
'id'
]}],
direction
:
'DESC'
}]}],
expectation
:
"SELECT * FROM `myTable` ORDER BY f1(f2(`id`)) DESC;"
,
context
:
QueryGenerator
},
{
arguments
:
[
'myTable'
,
{
order
:
[[{
fn
:
'max'
,
cols
:
[
'id'
]},
'DESC'
],
{
fn
:
'min'
,
cols
:
[
'first'
,
'second'
],
direction
:
'ASC'
}]}],
expectation
:
"SELECT * FROM `myTable` ORDER BY max(`id`) DESC, min(`first`, `second`) ASC;"
,
context
:
QueryGenerator
},
{
title
:
'functions can take functions as arguments'
,
arguments
:
[
'myTable'
,
function
(
sequelize
)
{
return
{
order
:
[[
sequelize
.
fn
(
'f1'
,
sequelize
.
fn
(
'f2'
,
sequelize
.
col
(
'id'
))),
'DESC'
]]
}
}],
expectation
:
"SELECT * FROM `myTable` ORDER BY f1(f2(`id`)) DESC;"
,
context
:
QueryGenerator
,
needsSequelize
:
true
},
{
title
:
'functions can take all types as arguments'
,
arguments
:
[
'myTable'
,
function
(
sequelize
)
{
return
{
order
:
[
[
sequelize
.
fn
(
'f1'
,
sequelize
.
col
(
'myTable.id'
)),
'DESC'
],
[
sequelize
.
fn
(
'f2'
,
12
,
'lalala'
,
new
Date
(
Date
.
UTC
(
2011
,
2
,
27
,
10
,
1
,
55
))),
'ASC'
]
]
}
}],
expectation
:
"SELECT * FROM `myTable` ORDER BY f1(`myTable`.`id`) DESC, f2(12, 'lalala', '2011-03-27 10:01:55') ASC;"
,
context
:
QueryGenerator
,
needsSequelize
:
true
},
{
title
:
'single string argument is not quoted'
,
arguments
:
[
'myTable'
,
{
group
:
"name"
}],
expectation
:
"SELECT * FROM `myTable` GROUP BY name;"
,
context
:
QueryGenerator
},
{
arguments
:
[
'myTable'
,
{
group
:
[
"name"
]
}],
arguments
:
[
'myTable'
,
{
group
:
[
"name"
]
}],
expectation
:
"SELECT * FROM `myTable` GROUP BY `name`;"
,
context
:
QueryGenerator
},
{
arguments
:
[
'myTable'
,
{
group
:
[{
fn
:
'max'
,
cols
:
[
'id'
]}]}],
expectation
:
"SELECT * FROM `myTable` GROUP BY max(`id`);"
,
context
:
QueryGenerator
},
{
arguments
:
[
'myTable'
,
{
group
:
[
"name"
,
"title"
]}],
expectation
:
"SELECT * FROM `myTable` GROUP BY `name`, `title`;"
,
context
:
QueryGenerator
title
:
'functions work for group by'
,
arguments
:
[
'myTable'
,
function
(
sequelize
)
{
return
{
group
:
[
sequelize
.
fn
(
'YEAR'
,
sequelize
.
col
(
'createdAt'
))]
}
}],
expectation
:
"SELECT * FROM `myTable` GROUP BY YEAR(`createdAt`);"
,
context
:
QueryGenerator
,
needsSequelize
:
true
},
{
title
:
'It is possible to mix sequelize.fn and string arguments to group by'
,
arguments
:
[
'myTable'
,
function
(
sequelize
)
{
return
{
group
:
[
sequelize
.
fn
(
'YEAR'
,
sequelize
.
col
(
'createdAt'
)),
'title'
]
}
}],
expectation
:
"SELECT * FROM `myTable` GROUP BY YEAR(`createdAt`), `title`;"
,
context
:
QueryGenerator
,
needsSequelize
:
true
},
{
arguments
:
[
'myTable'
,
{
group
:
"name"
,
order
:
"id DESC"
}],
expectation
:
"SELECT * FROM `myTable` GROUP BY name ORDER BY id DESC;"
,
...
...
@@ -451,9 +480,12 @@ if (dialect.match(/^mysql/)) {
describe
(
suiteTitle
,
function
()
{
tests
.
forEach
(
function
(
test
)
{
var
title
=
test
.
title
||
'MySQL correctly returns '
+
test
.
expectation
+
' for '
+
util
.
inspect
(
test
.
arguments
)
it
(
title
,
function
(
done
)
{
it
(
title
,
function
(
done
)
{
// Options would normally be set by the query interface that instantiates the query-generator, but here we specify it explicitly
var
context
=
test
.
context
||
{
options
:
{}};
if
(
test
.
needsSequelize
)
{
test
.
arguments
[
1
]
=
test
.
arguments
[
1
](
this
.
sequelize
)
}
QueryGenerator
.
options
=
context
.
options
var
conditions
=
QueryGenerator
[
suiteTitle
].
apply
(
QueryGenerator
,
test
.
arguments
)
expect
(
conditions
).
to
.
deep
.
equal
(
test
.
expectation
)
...
...
test/postgres/query-generator.test.js
View file @
c075cac
...
...
@@ -260,27 +260,60 @@ if (dialect.match(/^postgres/)) {
expectation
:
'SELECT * FROM "myTable" ORDER BY "id" DESC;'
,
context
:
QueryGenerator
},
{
arguments
:
[
'myTable'
,
{
order
:
[{
raw
:
'f1(f2(id))'
,
direction
:
'DESC'
}]}],
title
:
'raw arguments are neither quoted nor escaped'
,
arguments
:
[
'myTable'
,
{
order
:
[[{
raw
:
'f1(f2(id))'
},
'DESC'
]]}],
expectation
:
'SELECT * FROM "myTable" ORDER BY f1(f2(id)) DESC;'
,
context
:
QueryGenerator
},
{
// Function-ception!
arguments
:
[
'myTable'
,
{
order
:
[{
fn
:
'f1'
,
cols
:
[
{
fn
:
'f2'
,
cols
:
[
'id'
]}],
direction
:
'DESC'
}]}],
expectation
:
'SELECT * FROM "myTable" ORDER BY f1(f2("id")) DESC;'
,
context
:
QueryGenerator
},
{
arguments
:
[
'myTable'
,
{
order
:
[[{
fn
:
'max'
,
cols
:
[
'id'
]},
'DESC'
],
{
fn
:
'min'
,
cols
:
[
'first'
,
'second'
],
direction
:
'ASC'
}]}],
expectation
:
'SELECT * FROM "myTable" ORDER BY max("id") DESC, min("first", "second") ASC;'
,
context
:
QueryGenerator
},
{
title
:
'functions can take functions as arguments'
,
arguments
:
[
'myTable'
,
function
(
sequelize
)
{
return
{
order
:
[[
sequelize
.
fn
(
'f1'
,
sequelize
.
fn
(
'f2'
,
sequelize
.
col
(
'id'
))),
'DESC'
]]
}
}],
expectation
:
'SELECT * FROM "myTable" ORDER BY f1(f2("id")) DESC;'
,
context
:
QueryGenerator
,
needsSequelize
:
true
},
{
title
:
'functions can take all types as arguments'
,
arguments
:
[
'myTable'
,
function
(
sequelize
)
{
return
{
order
:
[
[
sequelize
.
fn
(
'f1'
,
sequelize
.
col
(
'myTable.id'
)),
'DESC'
],
[
sequelize
.
fn
(
'f2'
,
12
,
'lalala'
,
new
Date
(
Date
.
UTC
(
2011
,
2
,
27
,
10
,
1
,
55
))),
'ASC'
]
]
}
}],
expectation
:
'SELECT * FROM "myTable" ORDER BY f1("myTable"."id") DESC, f2(12, \'lalala\', \'2011-03-27 10:01:55.000 +00:00\') ASC;'
,
context
:
QueryGenerator
,
needsSequelize
:
true
},
{
title
:
'single string argument is not quoted'
,
arguments
:
[
'myTable'
,
{
group
:
"name"
}],
expectation
:
"SELECT * FROM \"myTable\" GROUP BY name;"
},
{
arguments
:
[
'myTable'
,
{
group
:
[
"name"
]}],
expectation
:
"SELECT * FROM \"myTable\" GROUP BY \"name\";"
},
{
arguments
:
[
'myTable'
,
{
group
:
[{
fn
:
'max'
,
cols
:
[
'id'
]}]}],
expectation
:
"SELECT * FROM \"myTable\" GROUP BY max(\"id\");"
title
:
'functions work for group by'
,
arguments
:
[
'myTable'
,
function
(
sequelize
)
{
return
{
group
:
[
sequelize
.
fn
(
'YEAR'
,
sequelize
.
col
(
'createdAt'
))]
}
}],
expectation
:
"SELECT * FROM \"myTable\" GROUP BY YEAR(\"createdAt\");"
,
needsSequelize
:
true
},{
title
:
'It is possible to mix sequelize.fn and string arguments to group by'
,
arguments
:
[
'myTable'
,
function
(
sequelize
)
{
return
{
group
:
[
sequelize
.
fn
(
'YEAR'
,
sequelize
.
col
(
'createdAt'
)),
'title'
]
}
}],
expectation
:
"SELECT * FROM \"myTable\" GROUP BY YEAR(\"createdAt\"), \"title\";"
,
context
:
QueryGenerator
,
needsSequelize
:
true
},
{
arguments
:
[
'myTable'
,
{
group
:
[
"name"
,
"title"
]}],
expectation
:
"SELECT * FROM \"myTable\" GROUP BY \"name\", \"title\";"
},
{
...
...
@@ -819,6 +852,9 @@ if (dialect.match(/^postgres/)) {
it
(
title
,
function
(
done
)
{
// Options would normally be set by the query interface that instantiates the query-generator, but here we specify it explicitly
var
context
=
test
.
context
||
{
options
:
{}};
if
(
test
.
needsSequelize
)
{
test
.
arguments
[
1
]
=
test
.
arguments
[
1
](
this
.
sequelize
)
}
QueryGenerator
.
options
=
context
.
options
var
conditions
=
QueryGenerator
[
suiteTitle
].
apply
(
QueryGenerator
,
test
.
arguments
)
expect
(
conditions
).
to
.
deep
.
equal
(
test
.
expectation
)
...
...
test/sqlite/query-generator.test.js
View file @
c075cac
...
...
@@ -154,18 +154,35 @@ if (dialect === 'sqlite') {
expectation
:
"SELECT * FROM `myTable` ORDER BY `id` DESC;"
,
context
:
QueryGenerator
},
{
arguments
:
[
'myTable'
,
{
order
:
[{
raw
:
'f1(f2(id))'
,
direction
:
'DESC'
}]}],
title
:
'raw arguments are neither quoted nor escaped'
,
arguments
:
[
'myTable'
,
{
order
:
[[{
raw
:
'f1(f2(id))'
},
'DESC'
]]}],
expectation
:
"SELECT * FROM `myTable` ORDER BY f1(f2(id)) DESC;"
,
context
:
QueryGenerator
},
{
// Function-ception!
arguments
:
[
'myTable'
,
{
order
:
[{
fn
:
'f1'
,
cols
:
[
{
fn
:
'f2'
,
cols
:
[
'id'
]}],
direction
:
'DESC'
}]}],
expectation
:
"SELECT * FROM `myTable` ORDER BY f1(f2(`id`)) DESC;"
,
context
:
QueryGenerator
},
{
arguments
:
[
'myTable'
,
{
order
:
[[{
fn
:
'max'
,
cols
:
[
'id'
]},
'DESC'
],
{
fn
:
'min'
,
cols
:
[
'first'
,
'second'
],
direction
:
'ASC'
}]}],
expectation
:
"SELECT * FROM `myTable` ORDER BY max(`id`) DESC, min(`first`, `second`) ASC;"
,
context
:
QueryGenerator
},
{
title
:
'functions can take functions as arguments'
,
arguments
:
[
'myTable'
,
function
(
sequelize
)
{
return
{
order
:
[[
sequelize
.
fn
(
'f1'
,
sequelize
.
fn
(
'f2'
,
sequelize
.
col
(
'id'
))),
'DESC'
]]
}
}],
expectation
:
"SELECT * FROM `myTable` ORDER BY f1(f2(`id`)) DESC;"
,
context
:
QueryGenerator
,
needsSequelize
:
true
},
{
title
:
'functions can take all types as arguments'
,
arguments
:
[
'myTable'
,
function
(
sequelize
)
{
return
{
order
:
[
[
sequelize
.
fn
(
'f1'
,
sequelize
.
col
(
'myTable.id'
)),
'DESC'
],
[
sequelize
.
fn
(
'f2'
,
12
,
'lalala'
,
new
Date
(
Date
.
UTC
(
2011
,
2
,
27
,
10
,
1
,
55
))),
'ASC'
]
]
}
}],
expectation
:
"SELECT * FROM `myTable` ORDER BY f1(`myTable`.`id`) DESC, f2(12, 'lalala', '2011-03-27 10:01:55') ASC;"
,
context
:
QueryGenerator
,
needsSequelize
:
true
},
{
title
:
'single string argument is not quoted'
,
arguments
:
[
'myTable'
,
{
group
:
"name"
}],
expectation
:
"SELECT * FROM `myTable` GROUP BY name;"
,
context
:
QueryGenerator
...
...
@@ -174,9 +191,25 @@ if (dialect === 'sqlite') {
expectation
:
"SELECT * FROM `myTable` GROUP BY `name`;"
,
context
:
QueryGenerator
},
{
arguments
:
[
'myTable'
,
{
group
:
[{
fn
:
'max'
,
cols
:
[
'id'
]}]}],
expectation
:
"SELECT * FROM `myTable` GROUP BY max(`id`);"
,
context
:
QueryGenerator
title
:
'functions work for group by'
,
arguments
:
[
'myTable'
,
function
(
sequelize
)
{
return
{
group
:
[
sequelize
.
fn
(
'YEAR'
,
sequelize
.
col
(
'createdAt'
))]
}
}],
expectation
:
"SELECT * FROM `myTable` GROUP BY YEAR(`createdAt`);"
,
context
:
QueryGenerator
,
needsSequelize
:
true
},
{
title
:
'It is possible to mix sequelize.fn and string arguments to group by'
,
arguments
:
[
'myTable'
,
function
(
sequelize
)
{
return
{
group
:
[
sequelize
.
fn
(
'YEAR'
,
sequelize
.
col
(
'createdAt'
)),
'title'
]
}
}],
expectation
:
"SELECT * FROM `myTable` GROUP BY YEAR(`createdAt`), `title`;"
,
context
:
QueryGenerator
,
needsSequelize
:
true
},
{
arguments
:
[
'myTable'
,
{
group
:
[
"name"
,
"title"
]}],
expectation
:
"SELECT * FROM `myTable` GROUP BY `name`, `title`;"
,
...
...
@@ -374,6 +407,9 @@ if (dialect === 'sqlite') {
it
(
title
,
function
(
done
)
{
// Options would normally be set by the query interface that instantiates the query-generator, but here we specify it explicitly
var
context
=
test
.
context
||
{
options
:
{}};
if
(
test
.
needsSequelize
)
{
test
.
arguments
[
1
]
=
test
.
arguments
[
1
](
this
.
sequelize
)
}
QueryGenerator
.
options
=
context
.
options
var
conditions
=
QueryGenerator
[
suiteTitle
].
apply
(
QueryGenerator
,
test
.
arguments
)
expect
(
conditions
).
to
.
deep
.
equal
(
test
.
expectation
)
...
...
Write
Preview
Markdown
is supported
Attach a file
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to post a comment