Skip to content

Commit

Permalink
hacked bson for command support, find_and_modify implemented, sequences
Browse files Browse the repository at this point in the history
  • Loading branch information
Joshua Kifer committed Nov 4, 2010
1 parent b035b91 commit 42c3dd1
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 26 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Planned
-------

* support for more first class array operations
* sub-document loading/updating
* sub-document loading/updating (lazy loading)
* full support for the Mongo query api returning hydrated objects
* support for all Mongo data types

Expand Down
49 changes: 49 additions & 0 deletions lib/congo.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,54 @@ class ArrayType
@__defineGetter__ index, =>
@__get__ index

# class ObjectType
# constructor: (@__type__) ->
# @__values__ = {}

# __set__: (key, val, next) ->
# log '[ Setting ] ' + @__key__ + '.' + key if process.env.DEBUG?
# @__values__[key] = val
# @__relate__ key, val
# @__parent__.__ascend_set__ @__key__ + '.' + key, val, next

# __ascend_set__: (key, val, next) ->
# log '[ Ascending ] ' + @__key__ + '.' + key if process.env.DEBUG?
# @__parent__.__ascend_set__ @__key__ + '.' + key, val, next

# __get__: (key) ->
# @__values__[key]

# __relate__: (key, val) ->
# if val instanceof Model
# log '[ Relating ] ' + @__key__ + '.' + key if process.env.DEBUG?
# val.__parent__ = @
# val.__key__ = key

# __dehydrate__: ->
# document = {}
# for key, val of @__values__
# if val instanceof Model
# document[key] = val.__dehydrate__()
# else
# document[key] = val
# document

# __hydrate__: (document) ->
# log '[ Hydrating ] ' + @__key__ if process.env.DEBUG?
# for key, val of document
# if @__type__ instanceof Function and @__type__.prototype instanceof Model
# new @__type__ (object) =>
# @__relate__ key, object
# @__values__[key] = object
# object.__hydrate__ val
# else
# @__values__[key] = val
# @__defineSetter__ key, (val) =>
# @__set__ key, val
# @__defineGetter__ key, =>
# @__get__ key
# @

class DateType extends Type
initialize: (val) ->
return val if val?
Expand All @@ -108,6 +156,7 @@ class DateType extends Type

__type__ =
Identity: (args...) -> new Type args...
# Object: (args...) -> new ObjectType args...
Integer: (args...) -> new Type args...
Double: (args...) -> new Type args...
String: (args...) -> new Type args...
Expand Down
94 changes: 69 additions & 25 deletions lib/mongo.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ class Database
@connections = []

connection: (next) ->
for i in [0...@connections.length]
connection = @connections[i]
for connection, i in @connections
if connection.available
log 'Connection: ' + i if process.env.DEBUG?
next connection
Expand All @@ -39,50 +38,97 @@ class Database
@connection (connection) =>
connection.retain()
connection.send (@compose collection, 2002, 0, document)
connection.send (@compose '$cmd', 2004, 0, 0, 1, { getLastError: 1 }), (data) =>
@last_error connection, (error) ->
connection.release()
errors = @decompose data
log 'Mongo error: ' + errors[0].err if errors[0].err?
log 'Mongo error: ' + error.err if error.err?
next(document._id) if next?

update: (collection, selector, update, next) ->
update: (collection, query, update, next) ->
@connection (connection) =>
connection.retain()
connection.send (@compose collection, 2001, 0, 0, selector, update)
connection.send (@compose '$cmd', 2004, 0, 0, 1, { getLastError: 1 }), (data) =>
connection.send (@compose collection, 2001, 0, 0, query, update)
@last_error connection, (error) ->
connection.release()
errors = @decompose data
log 'Mongo error: ' + errors[0].err if errors[0].err?
next(errors[0].n) if next?
log 'Mongo error: ' + error.err if error.err?
next() if next?

query: (collection, selector, next) ->
find: (collection, query, args..., next) ->
path = if args.length > 0 then { (args[0]): 1 } else {}
@connection (connection) =>
connection.retain()
connection.send (@compose collection, 2004, 0, 0, 0, selector), (data) =>
connection.send (@compose collection, 2004, 0, 0, 0, query, path), (data) =>
documents = @decompose data
connection.send (@compose '$cmd', 2004, 0, 0, 1, { getLastError: 1 }), (data) =>
@last_error connection, (error) ->
connection.release()
errors = @decompose data
log 'Mongo error: ' + errors[0].err if errors[0].err?
log 'Mongo error: ' + error.err if error.err?
next(documents) if next?

remove: (collection, selector, next) ->
find_one: (collection, query, args..., next) ->
@find collection, query, args..., (documents) ->
if documents.length > 0 then next documents[0] else next null

exists: (collection, id, path, next) ->
@find collection, { _id: id, (path): { $exists: true } }, '_id', (documents) ->
if documents.length > 0 then next true else next false

remove: (collection, query, next) ->
@connection (connection) =>
connection.retain()
connection.send (@compose collection, 2006, 0, 0, selector)
connection.send (@compose collection, 2006, 0, 0, query)
connection.send (@compose '$cmd', 2004, 0, 0, 1, { getLastError: 1 }), (data) =>
connection.release()
errors = @decompose data
log 'Mongo error: ' + errors[0].err if errors[0].err?
next() if next?

clear: (collection, next) ->
@remove collection, {}, next

last_error: (connection, next) ->
connection.send (@compose '$cmd', 2004, 0, 0, 1, { getLastError: 1 }), (data) =>
next (@decompose data)[0] if next?

command: (command, options, next) ->
options.__command__ = 'findandmodify'
@connection (connection) =>
connection.retain()
connection.send (@compose '$cmd', 2004, 0, 0, 1, options), (data) =>
connection.release()
document = (@decompose data)[0]
if document['bad cmd']?
log 'Mongo error: ' + document.errmsg
inspect document['bad cmd']
next null if next?
else if document['$err']?
log 'Mongo error: ' + document['$err']
next null if next?
else
next document if next?

modify: (collection, options, next) ->
options.findandmodify = collection
options.query ?= {}
options.sort ?= {}
options.remove ?= false
options.update ?= {}
options.new ?= false
options.fields ?= {}
options.upsert ?= false
@command 'findandmodify', options, (document) ->
next document.value

sequence: (collection, id, args..., next) ->
key = if args.length > 0 then args[0] else '_root'
@modify collection, { new: true, query: { _id: id }, update: { $inc: { ('_sequence.' + key): 1 }}, fields: { ('_sequence.' + key): 1 }}, (result) ->
next result._sequence[key]

compose: (collection, code, flags, items...) ->
data = binary.fromInt(flags) + binary.encode_cstring(@name + '.' + collection)
for i in [0...items.length]
if typeof items[i] == 'object'
data += bson.serialize items[i]
for item in items
if typeof item == 'object'
data += bson.serialize item
else
data += binary.fromInt items[i]
data += binary.fromInt item
binary.fromInt(data.length + 4 * 4) + binary.fromInt(0) + binary.fromInt(0) + binary.fromInt(code) + data

decompose: (data) ->
Expand All @@ -99,7 +145,7 @@ class Database
count = binary.toInt(data.substr i)
i += 4
documents = []
for c in [0...count]
while count--
documents.push bson.deserialize(data.substr i)
i += binary.toInt(data.substr i)
else
Expand Down Expand Up @@ -131,8 +177,6 @@ class Connection
log 'closed'
@stream.addListener 'end', =>
log 'end'
@stream.addListener 'end', =>
log 'end'
@stream.addListener 'close', =>
log 'close'
@stream.addListener 'timeout', =>
Expand Down
5 changes: 5 additions & 0 deletions lib/vendor/bson.js
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,11 @@ BSON.encodeArray = function(array, checkKeys) {

BSON.encodeObject = function(object, checkKeys) {
var encoded_string = '';
if (object['__command__']) {
encoded_string += BSON.encodeValue('', object['__command__'], object[object['__command__']], false, checkKeys);
delete object[object['__command__']]
delete object['__command__']
}
// Let's fetch all the variables for the object and encode each
for(var variable in object) {
if(object[variable] == null || (object[variable] != null && object[variable].constructor != Function)) {
Expand Down

0 comments on commit 42c3dd1

Please sign in to comment.