コード例 #1
0
func (self *BundleManager) bundleFileValidateNolock(conn *sqlite.Conn, user string, bundle_id int, file_id int) error {
	if conn == nil {
		conn = self.conn
	}
	//FIXME better way to encode username and column?
	s, err := conn.Prepare("select 1 from files, bundles where bundles.user = ? and bundles.id = ? and bundles.id = files.bundle_id and files.id = ?;")
	if err != nil {
		log.Printf("%v\n", err)
		return err
	}
	defer s.Finalize()
	err = s.Exec(user, bundle_id, file_id)
	if err != nil {
		log.Printf("%v\n", err)
		return err
	}
	for {
		if !s.Next() {
			break
		}
		var value int
		err = s.Scan(&value)
		if err != nil {
			log.Printf("%v\n", err)
			return err
		}
		if value == 1 {
			return nil
		}
	}
	return errors.New("The specified file is not owned by the user and bundle specified.")
}
コード例 #2
0
func (self *BundleManager) BundleFileGroupsSet(conn *sqlite.Conn, user string, bundle_id int, file_id int, groups [][2]string) error {
	self.mutex.Lock()
	if self.shutdown {
		return errors.New("BundleManager is shutdown.")
	}
	defer self.mutex.Unlock()
	state, err := self.bundleStateGetNoLock(conn, user, bundle_id)
	if err != nil {
		return err
	}
	if state != BundleState_Unsubmitted {
		return errors.New("The bundle specified is not editable.")
	}
	err = self.bundleFileValidateNolock(conn, user, bundle_id, file_id)
	if err != nil {
		return nil
	}
	err = conn.Exec("delete from groups where file_id = ?;", file_id)
	if err != nil {
		log.Printf("%v\n", err)
		return err
	}
	for _, item := range groups {
		err = conn.Exec("insert into groups(file_id, type, name) values(?, ?, ?);", file_id, item[0], item[1])
		if err != nil {
			log.Printf("%v\n", err)
			return err
		}
	}
	return nil
}
コード例 #3
0
ファイル: murmurdb.go プロジェクト: pcgod/grumble
// Link a Server's channels together
func populateChannelLinkInfo(server *Server, db *sqlite.Conn) (err os.Error) {
	stmt, err := db.Prepare("SELECT channel_id, link_id FROM channel_links WHERE server_id=?")
	if err != nil {
		return err
	}

	if err := stmt.Exec(server.Id); err != nil {
		return err
	}

	for stmt.Next() {
		var (
			ChannelId int
			LinkId    int
		)
		if err := stmt.Scan(&ChannelId, &LinkId); err != nil {
			return err
		}

		channel, exists := server.Channels[ChannelId]
		if !exists {
			return os.NewError("Attempt to perform link operation on non-existant channel.")
		}

		other, exists := server.Channels[LinkId]
		if !exists {
			return os.NewError("Attempt to perform link operation on non-existant channel.")
		}

		server.LinkChannels(channel, other)
	}

	return nil
}
コード例 #4
0
func (self *BundleManager) BundleFileBoolSet(conn *sqlite.Conn, user string, bundle_id int, file_id int, column string, value bool) error {
	self.mutex.Lock()
	if conn == nil {
		conn = self.conn
	}
	if self.shutdown {
		return errors.New("BundleManager is shutdown.")
	}
	defer self.mutex.Unlock()
	if column != "disable_on_error" {
		old_state, err := self.bundleStateGetNoLock(conn, user, bundle_id)
		if err != nil {
			log.Printf("%v\n", err)
			return err
		}
		if old_state != BundleState_Unsubmitted {
			return errors.New("Can't set string on submitted bundle.")
		}
	}
	//FIXME check for bundle->file.
	err := conn.Exec("update files set "+column+" = ? where id = ?;", value, file_id)
	if err != nil {
		log.Printf("%v\n", err)
		return err
	}
	return nil
}
コード例 #5
0
func (self *BundleManager) bundleStateGetNoLock(conn *sqlite.Conn, user string, bundle_id int) (BundleState, error) {
	if conn == nil {
		conn = self.conn
	}
	s, err := conn.Prepare("select state from bundles where bundles.user = ? and bundles.id = ?;")
	if err != nil {
		log.Printf("%v\n", err)
		return BundleState_Error, err
	}
	defer s.Finalize()
	err = s.Exec(user, bundle_id)
	if err != nil {
		log.Printf("%v\n", err)
		return BundleState_Error, err
	}
	for {
		if !s.Next() {
			break
		}
		var value int
		err = s.Scan(&value)
		if err != nil {
			log.Printf("%v\n", err)
			return BundleState_Error, err
		}
		return BundleState(value), nil
	}
	return BundleState_Error, errors.New("Unknown error.")
}
コード例 #6
0
ファイル: table.go プロジェクト: timob/gemini
func StoreTableToSqlite(conn *sqlite.Conn, name string, tinfo *Table) error {
	queryStr := fmt.Sprintf("create table %s (", name)
	for i := 0; i < len(tinfo.ColumnNames); i++ {
		if i != 0 {
			queryStr += ","
		}
		queryStr +=
			tinfo.ColumnNames[i] +
				" " +
				mapDatatypeToSqlite[tinfo.ColumnTypes[i]]
	}
	queryStr += ");"

	err := conn.Exec(queryStr)
	if err != nil {
		return fmt.Errorf("StoreTableToSqlite(): %s , %s,", err.Error(), queryStr)
	}

	row := make([]*interface{}, len(tinfo.ColumnTypes))
	for i := 0; i < len(row); i++ {
		row[i] = new(interface{})
	}
	for i := 0; i < tinfo.rowCount(); i++ {
		queryStr = fmt.Sprintf("insert into %s values (", name)
		err := tinfo.readRow(i, row)
		if err != nil {
			return err
		}
		for j := 0; j < len(row); j++ {
			if j != 0 {
				queryStr += ","
			}
			value := *(row[j])
			if value == nil {
				queryStr += "null"
				continue
			}
			switch tinfo.ColumnTypes[j] {
			case IntegerDatatype:
				queryStr += fmt.Sprintf("%d", value)
			case StringDatatype:
				re, err := regexp.Compile("'")
				if err != nil {
					return err
				}
				escaped := re.ReplaceAllString(value.(string), "''")
				queryStr += fmt.Sprintf("'%s'", escaped)
			case FloatDatatype:
				queryStr += fmt.Sprintf("%f", value)
			}
		}
		queryStr += ");"
		err = conn.Exec(queryStr)
		if err != nil {
			return fmt.Errorf("StoreTableToSqlite(): %s , %s,", err.Error(), queryStr)
		}
	}

	return nil
}
コード例 #7
0
ファイル: murmurdb.go プロジェクト: pcgod/grumble
// Populate channel with its ACLs by reading the SQLite databse.
func populateChannelACLFromDatabase(server *Server, c *Channel, db *sqlite.Conn) os.Error {
	stmt, err := db.Prepare("SELECT user_id, group_name, apply_here, apply_sub, grantpriv, revokepriv FROM acl WHERE server_id=? AND channel_id=? ORDER BY priority")
	if err != nil {
		return err
	}

	if err := stmt.Exec(server.Id, c.Id); err != nil {
		return err
	}

	for stmt.Next() {
		var (
			UserId    string
			Group     string
			ApplyHere bool
			ApplySub  bool
			Allow     int64
			Deny      int64
		)
		if err := stmt.Scan(&UserId, &Group, &ApplyHere, &ApplySub, &Allow, &Deny); err != nil {
			return err
		}

		acl := NewChannelACL(c)
		acl.ApplyHere = ApplyHere
		acl.ApplySubs = ApplySub
		if len(UserId) > 0 {
			acl.UserId, err = strconv.Atoi(UserId)
			if err != nil {
				return err
			}
		} else if len(Group) > 0 {
			acl.Group = Group
		} else {
			return os.NewError("Invalid ACL: Neither Group or UserId specified")
		}

		acl.Deny = Permission(Deny)
		acl.Allow = Permission(Allow)
		c.ACL = append(c.ACL, acl)
	}

	return nil
}
コード例 #8
0
ファイル: murmurdb.go プロジェクト: pcgod/grumble
// Add channel metadata (channel_info table from SQLite) by reading the SQLite database.
func populateChannelInfoFromDatabase(server *Server, c *Channel, db *sqlite.Conn) os.Error {
	stmt, err := db.Prepare("SELECT value FROM channel_info WHERE server_id=? AND channel_id=? AND key=?")
	if err != nil {
		return err
	}

	// Fetch description
	if err := stmt.Exec(server.Id, c.Id, ChannelInfoDescription); err != nil {
		return err
	}
	for stmt.Next() {
		var description string
		err = stmt.Scan(&description)
		if err != nil {
			return err
		}

		key, err := globalBlobstore.Put([]byte(description))
		if err != nil {
			return err
		}
		c.DescriptionBlob = key
	}

	if err := stmt.Reset(); err != nil {
		return err
	}

	// Fetch position
	if err := stmt.Exec(server.Id, c.Id, ChannelInfoPosition); err != nil {
		return err
	}
	for stmt.Next() {
		var pos int
		if err := stmt.Scan(&pos); err != nil {
			return err
		}

		c.Position = pos
	}

	return nil
}
コード例 #9
0
ファイル: denormalize.go プロジェクト: timob/gemini
func getRowCount(name string, conn *sqlite.Conn) (int, error) {

	stmt, err := conn.Prepare(fmt.Sprintf("select count(1) from %s;", name))
	if err != nil {
		return -1, err
	}
	err = stmt.Exec()
	if err != nil {
		return -1, err
	}
	stmt.Next()
	var count int
	err = stmt.Scan(&count)
	if err != nil {
		return -1, err
	}
	stmt.Finalize()
	return count, nil
}
コード例 #10
0
func (self *BundleManager) bundleFileGet(conn *sqlite.Conn, bundle *BundleMD, user string, bundle_id int, file_id int) (*BundleFileMD, error) {
	self.mutex.Lock()
	if self.shutdown {
		return nil, errors.New("BundleManager is shutdown.")
	}
	defer self.mutex.Unlock()
	if bundle != nil {
		bundle_id = bundle.id
		user = bundle.user
	} else {
		bundle = &BundleMD{id: bundle_id, user: user, bm: self}
	}
	s, err := conn.Prepare("select 1 from files, bundles where bundles.user = ? and bundles.id = ? and files.bundle_id = bundles.id and files.id = ?;")
	if err != nil {
		log.Printf("%v\n", err)
		return nil, err
	}
	defer s.Finalize()
	err = s.Exec(user, bundle_id, file_id)
	if err != nil {
		log.Printf("%v\n", err)
		return nil, err
	}
	for {
		if !s.Next() {
			break
		}
		var value int
		err = s.Scan(&value)
		if err != nil {
			log.Printf("%v\n", err)
			return nil, err
		}
		if value == 1 {
			if conn == self.conn {
				conn = nil
			}
			return &BundleFileMD{id: file_id, bundle: bundle, conn: conn}, nil
		}
	}
	return nil, errors.New("File Id " + strconv.Itoa(file_id) + " not found.")
}
コード例 #11
0
func (self *BundleMD) FileAdd(pacifica_filename string, local_filename string, commit bool) (*BundleFileMD, error) {
	var conn *sqlite.Conn
	if commit == false {
		var err error
		conn, err = self.bm.connGet()
		if err != nil {
			return nil, err
		}
		err = conn.Exec("begin transaction")
		if err != nil {
			return nil, err
		}
	} else {
		conn = self.bm.conn
	}
	id, err := self.bm.bundleFileIdAdd(conn, self.user, self.id, pacifica_filename, local_filename)
	if err != nil {
		if commit == false {
			conn.Close()
		}
		return nil, err
	}
	return self.bm.bundleFileGet(conn, self, "", -1, id)
}
コード例 #12
0
ファイル: denormalize.go プロジェクト: timob/gemini
// Create fact table by joing source table to dimension tables
// Three cases for source data column:
// 1. Matches dimension column, fact row value is id in matching dimesnion table row
// 2. Is null, and dimension table for column has > 0 rows, fact row value is -1
// 3. Is null, and dimension table for column has 0 rows, fact row value is -1
func (d *Datamart) CreateFactTable(dimDefs map[string]*DimensionDefinition,
	conn *sqlite.Conn) error {

	rowCountCache := make(map[string]int)

	// make list of non-zero dim tables
	nzDim := make(map[string]*DimensionDefinition)
	for name, dim := range dimDefs {
		count, err := getRowCount(name, conn)
		if err != nil {
			return err
		}
		rowCountCache[name] = count
		if count > 0 {
			nzDim[name] = dim
		}
	}

	// make fact table
	query := "create table fact as select"
	i := 0
	for name, dim := range dimDefs {
		if i != 0 {
			query += ","
		}
		if rowCountCache[name] == 0 {
			query += " -1 " + dim.IndexColumn
		} else {
			// dim.IndexColumn value - 1 because want ids to start at 0
			query += " case when source." + dim.UniqueColumn +
				" is null then -1 else " + dim.IndexColumn + " - 1 end " +
				dim.IndexColumn
		}
		i++
	}

	query += "\nfrom source"
	for name, dim := range nzDim {
		query += " left outer join " + name + " on "
		query += "source." + dim.UniqueColumn + " = " +
			name + "." + dim.UniqueColumn
	}

	// if all dimension tables a empty return emtpy fact table
	if i == 0 {
		query += "\nwhere "
		query += "1 = 0"
	}

	query += ";"

	err := conn.Exec(query)
	if err != nil {
		return fmt.Errorf(
			"CreateFactTable() error, sqlite error: %s\nquery:\n%s\n",
			err.Error(),
			query,
		)
	}

	return nil
}
コード例 #13
0
ファイル: murmurdb.go プロジェクト: pcgod/grumble
// Populate the Server with Channels from the database.
func populateChannelsFromDatabase(server *Server, db *sqlite.Conn, parentId int) os.Error {
	parent, exists := server.Channels[parentId]
	if !exists {
		return os.NewError("Non-existant parent")
	}

	stmt, err := db.Prepare("SELECT channel_id, name, inheritacl FROM channels WHERE server_id=? AND parent_id=?")
	if err != nil {
		return err
	}

	err = stmt.Exec(server.Id, parentId)
	if err != nil {
		return err
	}

	for stmt.Next() {
		var (
			name    string
			chanid  int
			inherit bool
		)
		err = stmt.Scan(&chanid, &name, &inherit)
		if err != nil {
			return err
		}

		c := server.NewChannel(chanid, name)
		c.InheritACL = inherit
		parent.AddChild(c)
	}

	// Add channel_info
	for _, c := range parent.children {
		err = populateChannelInfoFromDatabase(server, c, db)
		if err != nil {
			return err
		}
	}

	// Add ACLs
	for _, c := range parent.children {
		err = populateChannelACLFromDatabase(server, c, db)
		if err != nil {
			return err
		}
	}

	// Add groups
	for _, c := range parent.children {
		err = populateChannelGroupsFromDatabase(server, c, db)
		if err != nil {
			return err
		}
	}

	// Add subchannels
	for id, _ := range parent.children {
		err = populateChannelsFromDatabase(server, db, id)
		if err != nil {
			return err
		}
	}

	return nil
}
コード例 #14
0
func (self *BundleManager) bundleFileIdAdd(conn *sqlite.Conn, user string, bundle_id int, pacifica_filename string, local_filename string) (int, error) {
	self.mutex.Lock()
	if self.shutdown {
		return -1, errors.New("BundleManager is shutdown.")
	}
	defer self.mutex.Unlock()
	sql := `
insert into files(bundle_id, local_filename, myemsl_filename) values(
	(select case when (state == ?) then ? else null end from bundles where user = ? and id = ?),
	?,
	?
);`
	err := conn.Exec(sql, int(BundleState_Unsubmitted), bundle_id, user, bundle_id, local_filename, pacifica_filename)
	if err != nil {
		old_state, terr := self.bundleStateGetNoLock(conn, user, bundle_id)
		if terr != nil {
			log.Printf("%v\n", terr)
			return -1, err
		}
		if old_state != BundleState_Unsubmitted {
			return -1, errors.New("Can't add files to submitted bundle.")
		}
		s, terr := conn.Prepare("select id, local_filename from files where bundle_id = ? and myemsl_filename = ?;")
		if terr != nil {
			log.Printf("%v\n", terr)
			return -1, err
		}
		defer s.Finalize()
		terr = s.Exec(bundle_id, pacifica_filename)
		if terr != nil {
			log.Printf("%v\n", terr)
			return -1, err
		}
		for {
			if !s.Next() {
				break
			}
			var tid int
			var tlocal_filename string
			terr = s.Scan(&tid, &tlocal_filename)
			if terr != nil {
				log.Printf("%v\n", terr)
				return -1, err
			}
			if tlocal_filename == local_filename {
				return -1, errors.New(fmt.Sprintf("The file with the specified Server filename (%s) already exists in the bundle (%d)!", pacifica_filename, bundle_id))
			} else {
				return -1, errors.New(fmt.Sprintf("The file with the specified Server filename (%s) already exists in the bundle (%d) but with a different local filename (%s != %s)!", pacifica_filename, bundle_id, local_filename, tlocal_filename))
			}
		}
		log.Printf("%v\n", err)
		log.Printf("SQL: %s, %d, %d, %s, %d, %s, %s\n", sql, int(BundleState_Unsubmitted), bundle_id, user, bundle_id, local_filename, pacifica_filename)
		return -1, err
	}
	s, err := conn.Prepare("select last_insert_rowid();")
	if err != nil {
		log.Printf("%v\n", err)
		return -1, err
	}
	defer s.Finalize()
	for {
		if !s.Next() {
			break
		}
		var value int
		err = s.Scan(&value)
		if err != nil {
			log.Printf("%v\n", err)
			return -1, err
		}
		return value, nil
	}
	return -1, errors.New("Unknown error.")
}
コード例 #15
0
ファイル: murmurdb.go プロジェクト: pcgod/grumble
func populateUsers(server *Server, db *sqlite.Conn) (err os.Error) {
	// Populate the server with regular user data
	stmt, err := db.Prepare("SELECT user_id, name, pw, lastchannel, texture, strftime('%s', last_active) FROM users WHERE server_id=?")
	if err != nil {
		return
	}

	err = stmt.Exec(server.Id)
	if err != nil {
		return
	}

	for stmt.Next() {
		var (
			UserId       int64
			UserName     string
			SHA1Password string
			LastChannel  int
			Texture      []byte
			LastActive   int64
		)

		err = stmt.Scan(&UserId, &UserName, &SHA1Password, &LastChannel, &Texture, &LastActive)
		if err != nil {
			continue
		}

		user, err := NewUser(uint32(UserId), UserName)
		if err != nil {
			return err
		}

		user.Password = "******" + SHA1Password

		key, err := globalBlobstore.Put(Texture)
		if err != nil {
			return err
		}
		user.TextureBlob = key

		user.LastActive = uint64(LastActive)
		user.LastChannelId = LastChannel

		server.Users[user.Id] = user
	}

	stmt, err = db.Prepare("SELECT key, value FROM user_info WHERE server_id=? AND user_id=?")
	if err != nil {
		return
	}

	// Populate users with any new-style UserInfo records
	for uid, user := range server.Users {
		err = stmt.Reset()
		if err != nil {
			return err
		}

		err = stmt.Exec(server.Id, uid)
		if err != nil {
			return err
		}

		for stmt.Next() {
			var (
				Key   int
				Value string
			)

			err = stmt.Scan(&Key, &Value)
			if err != nil {
				return err
			}

			switch Key {
			case UserInfoEmail:
				user.Email = Value
			case UserInfoComment:
				key, err := globalBlobstore.Put([]byte(Value))
				if err != nil {
					return err
				}
				user.CommentBlob = key
			case UserInfoHash:
				user.CertHash = Value
			case UserInfoLastActive:
				// not a kv-pair (trigger)
			case UserInfoPassword:
				// not a kv-pair
			case UserInfoName:
				// not a kv-pair
			}
		}
	}

	return
}
コード例 #16
0
ファイル: denormalize.go プロジェクト: timob/gemini
func (d *Datamart) CreateDimensionTables(dimDefs map[string]*DimensionDefinition,
	conn *sqlite.Conn) error {
	var queryStr string
	var err error
	for name, dim := range dimDefs {
		// "integer primary key" creates as auto incrementing column
		queryStr = fmt.Sprintf(
			"create table %s (%s integer primary key, %s %s",
			name,
			dim.IndexColumn,
			dim.UniqueColumn,
			d.findDatatype(dim.UniqueColumn),
		)
		extraStr := ""
		for _, extra := range dim.ExtraColumns {
			queryStr += fmt.Sprintf(", %s %s", extra, d.findDatatype(extra))
			extraStr += "," + extra
		}
		queryStr += "); "

		err = conn.Exec(queryStr)
		if err != nil {
			goto Error
		}

		queryStr = fmt.Sprintf(
			`insert into %s 
             select null, %s %s
             from (select %s, %s sort %s
                   from source
                   where %s is not null
                   group by %s, sort %s) a
             order by sort %s;`,
			name,
			dim.UniqueColumn,
			extraStr,
			dim.UniqueColumn,
			dim.SortExpr,
			extraStr,
			dim.UniqueColumn,
			dim.UniqueColumn,
			extraStr,
			dim.SortDirection,
		)

		err = conn.Exec(queryStr)
		if err != nil {
			goto Error
		}

		queryStr = fmt.Sprintf(
			"create index %s_idx on %s (%s);",
			dim.UniqueColumn,
			name,
			dim.UniqueColumn,
		)

		err = conn.Exec(queryStr)
		if err != nil {
			goto Error
		}
	}

	return nil

Error:
	return fmt.Errorf(
		"CreateDimensionTables() error, sqlite error: %s\nquery:\n%s\n",
		err.Error(),
		queryStr,
	)
}
コード例 #17
0
ファイル: murmurdb.go プロジェクト: pcgod/grumble
// Populate channel with groups by reading the SQLite database.
func populateChannelGroupsFromDatabase(server *Server, c *Channel, db *sqlite.Conn) os.Error {
	stmt, err := db.Prepare("SELECT group_id, name, inherit, inheritable FROM groups WHERE server_id=? AND channel_id=?")
	if err != nil {
		return err
	}

	if err := stmt.Exec(server.Id, c.Id); err != nil {
		return err
	}

	groups := make(map[int64]*Group)

	for stmt.Next() {
		var (
			GroupId     int64
			Name        string
			Inherit     bool
			Inheritable bool
		)

		if err := stmt.Scan(&GroupId, &Name, &Inherit, &Inheritable); err != nil {
			return err
		}

		g := NewGroup(c, Name)
		g.Inherit = Inherit
		g.Inheritable = Inheritable
		c.Groups[g.Name] = g
		groups[GroupId] = g
	}

	stmt, err = db.Prepare("SELECT user_id, addit FROM group_members WHERE server_id=? AND group_id=?")
	if err != nil {
		return err
	}

	for gid, grp := range groups {
		if err = stmt.Exec(server.Id, gid); err != nil {
			return err
		}

		for stmt.Next() {
			var (
				UserId int64
				Add    bool
			)

			if err := stmt.Scan(&UserId, &Add); err != nil {
				return err
			}

			if Add {
				grp.Add[int(UserId)] = true
			} else {
				grp.Remove[int(UserId)] = true
			}
		}
	}

	return nil
}