From fec324426fee7565a28e8038c7bea66df304f1b7 Mon Sep 17 00:00:00 2001 From: Evan Shaw Date: Tue, 15 Mar 2011 17:12:55 +1300 Subject: [PATCH] Development is discontinued --- LICENSE | 25 ------ Makefile | 16 ---- README.md | 54 +----------- collection.go | 224 -------------------------------------------------- conn.go | 115 -------------------------- cursor.go | 97 ---------------------- database.go | 69 ---------------- query.go | 78 ------------------ 8 files changed, 3 insertions(+), 675 deletions(-) delete mode 100644 LICENSE delete mode 100644 Makefile delete mode 100644 collection.go delete mode 100644 conn.go delete mode 100644 cursor.go delete mode 100644 database.go delete mode 100644 query.go diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 8c43dd4..0000000 --- a/LICENSE +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2010, Evan Shaw -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the copyright holder nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - diff --git a/Makefile b/Makefile deleted file mode 100644 index daef29b..0000000 --- a/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright 2010, Evan Shaw. All rights reserved. -# Use of this source code is governed by a BSD-style License -# that can be found in the LICENSE file. - -include $(GOROOT)/src/Make.inc - -TARG=github.com/edsrzf/mongogo -GOFILES=\ - collection.go\ - conn.go\ - cursor.go\ - database.go\ - query.go\ - -include $(GOROOT)/src/Make.pkg - diff --git a/README.md b/README.md index b0fd7b7..7a3475f 100644 --- a/README.md +++ b/README.md @@ -1,55 +1,7 @@ Mongogo ======= -Mongogo is a MongoDB driver for the [Go programming language](http://golang.org/). +Mongogo was a MongoDB driver for the [Go programming language](http://golang.org/). -This project is still in development. It's been tested on Arch and Ubuntu Linux for -the amd64 architecture, but there's no reason it shouldn't work on other architectures -as well. - -Dependencies ------------- - -Mongogo compiles with Go release 2010-10-27 or newer, barring any recent language or -library changes. - -Mongogo works with MongoDB version 2.6 or newer. It may partially work with older versions. - -Mongogo's only non-core Go dependency is [Go-BSON](go-bson). -You can install it with goinstall by running - goinstall github.com/edsrzf/go-bson - -Usage ------ - -Create a connection: - - conn := mongo.Dial("127.0.0.1:27017") - -Get a database: - - db := conn.Database("blog") - -Get a collection: - - col := db.Collection("posts") - -Insert a document into the collection: - - doc := map[string]interface{}{"title": "Hello", "body": "World!"} - col.Insert(doc) - -Query the database: - - q := mongo.Query{"title": "Hello"} - cursor := col.Find(q, 0, 0) - defer cursor.Close() - -See the documentation in the source for more information. - -Contributing ------------- - -Simply use GitHub as usual to create a fork, make your changes, and create a pull -request. Code is expected to be formatted with gofmt and to adhere to the usual Go -conventions -- that is, the conventions used by Go's core libraries. +Development has ceased in favor of [Gustavo Niemeyer's mgo](http://labix.org/mgo). +The history remains here intact for posterity. diff --git a/collection.go b/collection.go deleted file mode 100644 index eba5c71..0000000 --- a/collection.go +++ /dev/null @@ -1,224 +0,0 @@ -// Copyright 2010, Evan Shaw. All rights reserved. -// Use of this source code is governed by a BSD-style License -// that can be found in the LICENSE file. - -package mongo - -import ( - "bytes" - "encoding/binary" - "os" - "github.com/edsrzf/go-bson" -) - -// common message header size -// 16-byte header -const headerSize = 16 - -// A Collection represents a MongoDB collection. -type Collection struct { - db *Database - name string - fullName []byte -} - -// Drop deletes c from the database. -func (c *Collection) Drop() os.Error { - cmd := Query{"drop": string(c.fullName)} - _, err := c.db.Command(cmd) - return err -} - -// Update updates a single document selected by query, according to doc. -func (c *Collection) Update(query, doc bson.Doc) os.Error { - return c.update(query, doc, false, false) -} - -// Upsert updates or inserts a single document selected by query, -// according to doc. -func (c *Collection) Upsert(query, doc bson.Doc) os.Error { - return c.update(query, doc, true, false) -} - -// Update updates multiple documents selected by query, according to doc. -func (c *Collection) UpdateAll(query, doc bson.Doc) os.Error { - return c.update(query, doc, false, true) -} - -// UpsertAll updates or inserts multiple documents selected by query, -// according to doc. -func (c *Collection) UpsertAll(query, doc bson.Doc) os.Error { - return c.update(query, doc, true, true) -} - -func (c *Collection) update(query, doc bson.Doc, upsert, multi bool) os.Error { - selData, err := bson.Marshal(query) - if err != nil { - return err - } - docData, err := bson.Marshal(doc) - if err != nil { - return err - } - cap := headerSize + 4 + len(c.fullName) + 4 + len(selData) + len(docData) - payload := make([]byte, headerSize+4, cap) - buf := bytes.NewBuffer(payload) - buf.Write(c.fullName) - var flags int32 - if upsert { - flags |= 1 - } - if multi { - flags |= 2 - } - binary.Write(buf, order, flags) - buf.Write(selData) - buf.Write(docData) - payload = payload[:cap] - return c.db.conn.sendMessage(2001, 0, payload) -} - -// Insert creates a new document in c. -func (c *Collection) Insert(doc bson.Doc) os.Error { - data, err := bson.Marshal(doc) - if err != nil { - return err - } - cap := headerSize + 4 + len(c.fullName) + len(data) - payload := make([]byte, headerSize+4, cap) - buf := bytes.NewBuffer(payload) - buf.Write(c.fullName) - buf.Write(data) - payload = payload[:cap] - return c.db.conn.sendMessage(2002, 0, payload) -} - -// Find searches c for any documents matching a query. It skips the first skip -// documents and limits the search to limit. -func (c *Collection) Find(query Query, skip, limit int32) (*Cursor, os.Error) { - return c.FindFields(query, nil, skip, limit) -} - -// FindFields performs a query that returns only specified fields. It skips the -// first skip documents and limits the search to limit. -// The fields specified can be inclusive or exclusive, but not both. That is, -// the values in the fields parameter must be all true or all false with no -// mixing. Fields with true values will be returned, while fields with false -// values will be excluded. -func (c *Collection) FindFields(query Query, fields map[string]interface{}, skip, limit int32) (*Cursor, os.Error) { - conn := c.db.conn - data, err := bson.Marshal(bson.Doc(query)) - if err != nil { - return nil, err - } - var fieldData []byte - if fields != nil { - fieldData, err = bson.Marshal(bson.Doc(fields)) - if err != nil { - return nil, err - } - } - cap := headerSize + 4 + len(c.fullName) + 8 + len(data) + len(fieldData) - payload := make([]byte, headerSize, cap) - buf := bytes.NewBuffer(payload[headerSize:]) - // TODO(eds): Consider supporting flags - binary.Write(buf, order, int32(0)) - buf.Write(c.fullName) - binary.Write(buf, order, skip) - binary.Write(buf, order, limit) - buf.Write(data) - buf.Write(fieldData) - payload = payload[:cap] - if err := conn.sendMessage(2004, 0, payload); err != nil { - return nil, err - } - - reply, err := conn.readReply() - if err != nil { - return nil, err - } - - return &Cursor{c, reply.cursorID, 0, reply.docs}, nil -} - -// FindOneFields performs a query that returns only speciied fields from one -// document. -func (c *Collection) FindOneFields(query Query, fields map[string]interface{}) (bson.Doc, os.Error) { - cursor, err := c.FindFields(query, fields, 0, 1) - if err != nil { - return nil, err - } - defer cursor.Close() - return cursor.Next(), nil -} - -// FindAll returns all documents in c matching a query. -func (c *Collection) FindAll(query Query) (*Cursor, os.Error) { - return c.Find(query, 0, 0) -} - -// FindOne returns the first document in c that matches a query. -func (c *Collection) FindOne(query Query) (bson.Doc, os.Error) { - cursor, err := c.Find(query, 0, 1) - if err != nil { - return nil, err - } - defer cursor.Close() - return cursor.Next(), nil -} - -// Count returns the number of documents in c that match a query. -func (c *Collection) Count(query bson.Doc) (int64, os.Error) { - cmd := Query{"count": c.name, "query": query} - reply, err := c.db.Command(cmd) - if reply == nil || err != nil { - return -1, err - } - - // NOTE(eds): Mongo returns count as a double? Really? That seems silly. - return int64(reply["n"].(float64)), nil -} - -func (c *Collection) remove(query bson.Doc, singleRemove bool) os.Error { - data, err := bson.Marshal(query) - if err != nil { - return err - } - l := len(c.fullName) - payload := make([]byte, headerSize+4+l+4+len(data)) - copy(payload[headerSize+4:], c.fullName) - if singleRemove { - payload[headerSize+4+l] |= 1 - } - copy(payload[headerSize+4+l+4:], data) - return c.db.conn.sendMessage(2006, 0, payload) -} - -// Remove removes all documents in c that match a query. -func (c *Collection) Remove(query bson.Doc) os.Error { - return c.remove(query, false) -} - -// RemoveFirst removes the first document in c that matches a query. -func (c *Collection) RemoveFirst(query bson.Doc) os.Error { - return c.remove(query, true) -} - -// EnsureIndex ensures that an index exists on this collection. -func (c *Collection) EnsureIndex(name string, keys map[string]int32, unique bool) os.Error { - col := c.db.Collection("system.indexes") - id := bson.Doc{"name": name, "ns": string(c.fullName), "key": keys, "unique": unique} - return col.Insert(id) -} - -// DropIndexes deletes all indexes on c. -func (c *Collection) DropIndexes() os.Error { - return c.DropIndex("*") -} - -// DropIndex deletes a single index. -func (c *Collection) DropIndex(name string) os.Error { - cmd := Query{"deleteIndexes": string(c.fullName), "index": name} - _, err := c.db.Command(cmd) - return err -} diff --git a/conn.go b/conn.go deleted file mode 100644 index 109676e..0000000 --- a/conn.go +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2010, Evan Shaw. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// The mongo package provides a MongoDB driver implementation. -package mongo - -import ( - "bytes" - "encoding/binary" - "os" - "net" - "rand" - "github.com/edsrzf/go-bson" -) - -var order = binary.LittleEndian - -// ConnError is an error related to the connection to the MongoDB server. -type ConnError string - -func (e ConnError) String() string { return string(e) } - -// A Conn represents a connection to a MongoDB server. -type Conn struct { - conn net.Conn -} - -type reply struct { - requestID int32 - responseTo int32 - responseFlags int32 - cursorID int64 - startingFrom int32 - numberReturned int32 - docs []bson.Doc -} - -// Dial connects to a MongoDB server at the remote address addr. -func Dial(addr string) (*Conn, os.Error) { - c, err := net.Dial("tcp", "", addr) - if err != nil { - return nil, ConnError(err.String()) - } - return &Conn{c}, nil -} - -// Close closes the connection. -func (c *Conn) Close() os.Error { - err := c.conn.Close() - if err != nil { - return ConnError(err.String()) - } - return nil -} - -// Database returns the Database object for a name. -func (c *Conn) Database(name string) *Database { - return &Database{c, name} -} - -func (c *Conn) sendMessage(opCode, responseId int32, message []byte) os.Error { - messageLength := int32(len(message)) - message = message[:0] - buf := bytes.NewBuffer(message) - binary.Write(buf, order, messageLength) - // request ID - binary.Write(buf, order, rand.Int31()) - // response to - binary.Write(buf, order, responseId) - binary.Write(buf, order, opCode) - message = message[:messageLength] - _, err := c.conn.Write(message) - if err != nil { - return ConnError(err.String()) - } - return nil -} - -func (c *Conn) readReply() (*reply, os.Error) { - var size uint32 - err := binary.Read(c.conn, order, &size) - if err != nil { - return nil, ConnError(err.String()) - } - raw := make([]byte, size) - _, err = c.conn.Read(raw) - if err != nil { - return nil, ConnError(err.String()) - } - buf := bytes.NewBuffer(raw) - r := new(reply) - binary.Read(buf, order, &r.requestID) - binary.Read(buf, order, &r.responseTo) - var opCode int32 - binary.Read(buf, order, &opCode) - if opCode != 1 { - return nil, os.NewError("expected OP_REPLY opCode") - } - binary.Read(buf, order, &r.responseFlags) - binary.Read(buf, order, &r.cursorID) - binary.Read(buf, order, &r.startingFrom) - binary.Read(buf, order, &r.numberReturned) - r.docs = make([]bson.Doc, r.numberReturned) - for i := range r.docs { - raw := buf.Bytes() - size := order.Uint32(raw) - r.docs[i], err = bson.Unmarshal(raw) - if err != nil { - break - } - buf.Next(int(size)) - } - return r, err -} diff --git a/cursor.go b/cursor.go deleted file mode 100644 index 5948b60..0000000 --- a/cursor.go +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2010, Evan Shaw. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package mongo - -import ( - "bytes" - "encoding/binary" - "os" - "github.com/edsrzf/go-bson" -) - -// A Cursor is the result of a query. -type Cursor struct { - collection *Collection - id int64 - pos int - docs []bson.Doc -} - -// Peek returns the next document or nil if the Cursor is at the end. -func (c *Cursor) Peek() bson.Doc { - if !c.HasNext() { - return nil - } - return c.docs[c.pos] -} - -// Next is like Peek, but also iterates to the next document. -func (c *Cursor) Next() bson.Doc { - if !c.HasNext() { - return nil - } - doc := c.docs[c.pos] - c.pos++ - return doc -} - -// HasNext indicates whether the Cursor still has more documents to iterate through. -func (c *Cursor) HasNext() bool { - if c.pos < len(c.docs) { - return true - } - - if err := c.getMore(0); err != nil { - return false - } - - return c.pos < len(c.docs) -} - -func (c *Cursor) getMore(limit int32) os.Error { - if c.id == 0 { - return os.NewError("no cursorID") - } - - cap := headerSize + 4 + len(c.collection.fullName) + 4 + 8 - payload := make([]byte, headerSize+4, cap) - buf := bytes.NewBuffer(payload) - buf.Write(c.collection.fullName) - binary.Write(buf, order, limit) - binary.Write(buf, order, c.id) - payload = payload[:cap] - - conn := c.collection.db.conn - if err := conn.sendMessage(2005, 0, payload); err != nil { - return err - } - - reply, err := conn.readReply() - if err != nil { - return err - } - - c.pos = 0 - c.docs = reply.docs - - return nil -} - -// Close tells the server that c is no longer in use and makes c invalid. -func (c *Cursor) Close() os.Error { - if c.id == 0 { - // not open on server - return nil - } - - cap := headerSize + 16 - payload := make([]byte, headerSize+4, cap) - buf := bytes.NewBuffer(payload) - binary.Write(buf, order, int32(1)) - binary.Write(buf, order, c.id) - payload = payload[:cap] - c.id = 0 - return c.collection.db.conn.sendMessage(2007, 0, payload) -} diff --git a/database.go b/database.go deleted file mode 100644 index 5d57c5a..0000000 --- a/database.go +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2010, Evan Shaw. All rights reserved. -// Use of this source code is governed by a BSD-style License -// that can be found in the LICENSE file. - -package mongo - -import ( - "os" - "github.com/edsrzf/go-bson" -) - -// Database represents a MongoDB database. -type Database struct { - conn *Conn - name string -} - -// Collection returns a Collection specified by name. -func (db *Database) Collection(name string) *Collection { - return &Collection{db, name, []byte(db.name + "." + name + "\x00")} -} - -// Drop deletes db. -func (db *Database) Drop() os.Error { - cmd := Query{"dropDatabase": int32(1)} - _, err := db.Command(cmd) - return err -} - -// Eval evaluates a JavaScript expression or function on the MongoDB server. -func (db *Database) Eval(code *bson.JavaScript, args string) (bson.Doc, os.Error) { - cmd := Query{"$eval": code} - if args != "" { - cmd["args"] = args - } - return db.Command(cmd) -} - -// Stats returns database statistics for db. -func (db *Database) Stats() (bson.Doc, os.Error) { - cmd := Query{"dbstats": int32(1)} - return db.Command(cmd) -} - -// Repair checks for and repairs corruption in the database. -func (db *Database) Repair() os.Error { - cmd := Query{"repairDatabase": int32(1)} - _, err := db.Command(cmd) - return err -} - -// Command sends an arbitrary command to the database. -// It is equivalent to -// col := db.Collection("$cmd") -// doc := col.FindOne(cmd) -// If the $err key is not null in the reply, Command returns an error. -func (db *Database) Command(cmd Query) (bson.Doc, os.Error) { - col := db.Collection("$cmd") - reply, err := col.FindOne(cmd) - if reply["$err"] != nil { - msg, ok := reply["$err"].(string) - if !ok { - // this probably shouldn't ever happen - msg = "non-string error message" - } - return nil, os.NewError(msg) - } - return reply, err -} diff --git a/query.go b/query.go deleted file mode 100644 index 3352547..0000000 --- a/query.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2010, Evan Shaw. All rights reserved. -// Use of this source code is governed by a BSD-style License -// that can be found in the LICENSE file. - -package mongo - -// Query represents a MongoDB database query. -// Simple queries can be constructed just like regular maps. For example the query -// -// q := Query{"_id": 14} -// -// would search a collection for a document with an _id of 14. -// Query's methods allow construction of more advanced queries. -type Query map[string]interface{} - -// makeComplex makes query into a "complex" query, where the inner query is the -// value stored under the key "$query" and other options can be specified. -func (query *Query) makeComplex() { - q := *query - if _, ok := q["$query"]; !ok { - outer := make(Query) - outer["$query"] = q - *query = outer - } -} - -// Explain causes MongoDB to return information on how this query is performed -// instead of returning the actual results of the query. -// After calling this method on a Query, the Query should not be updated through -// index expressions. -func (q *Query) Explain() { - q.makeComplex() - (*q)["$explain"] = true -} - -// Hint forces MongoDB to use a particular index for this query. -// After calling this method on a Query, the Query should not be updated through -// index expressions. -func (q *Query) Hint(index string) { - q.makeComplex() - (*q)["$hint"] = index -} - -func (q *Query) MinKey(min map[string]int32) { - q.makeComplex() - (*q)["$min"] = min -} - -func (q *Query) MaxKey(max map[string]int32) { - q.makeComplex() - (*q)["$max"] = max -} - -func (q *Query) MaxScan(max int32) { - q.makeComplex() - (*q)["$maxScan"] = max -} - -// ShowDiskLocation will cause the returned documents to contain a key $diskLoc -// which shows the location of that document on disk. -// After calling this method on a Query, the Query should not be updated through -// index expressions. -func (q *Query) ShowDiskLocation() { - q.makeComplex() - (*q)["$showDiskLoc"] = true -} - -// After calling this method on a Query, the Query should not be updated through -// index expressions. -func (q *Query) Snapshot() { - q.makeComplex() - (*q)["$snapshot"] = true -} - -func (q *Query) Sort(keys map[string]int32) { - q.makeComplex() - (*q)["$orderby"] = keys -}