func (proj *project) Collaborators() []*lcmUser { if proj.collaborators != nil { return proj.collaborators } proj.collaborators = make([]*lcmUser, 0) rows := csql.Query(db, ` SELECT userid FROM collaborator WHERE project_name = $1 AND project_owner = $2 `, proj.Name, proj.Owner.Id) csql.ForRow(rows, func(s csql.RowScanner) { var userid string csql.Scan(rows, &userid) if user := findUserByNo(userid); user == nil { log.Printf("Could not find collaborator %s for "+ "project '%s' owned by '%s'.", userid, proj.Name, proj.Owner.Id) } else { proj.collaborators = append(proj.collaborators, user) } }) sort.Sort(usersAlphabetical(proj.collaborators)) return proj.collaborators }
// Tables returns the names of all tables in the database sorted // alphabetically in ascending order. func (db *DB) Tables() (tables []string, err error) { defer csql.Safe(&err) var q string switch db.Driver { case "postgres": q = ` SELECT tablename FROM pg_tables WHERE schemaname NOT IN ('pg_catalog', 'information_schema') ORDER BY tablename ASC ` case "sqlite3": q = ` SELECT tbl_name FROM sqlite_master WHERE type = 'table' ORDER BY tbl_name ASC ` default: return nil, ef("Unrecognized database driver: %s", db.Driver) } rows := csql.Query(db, q) csql.ForRow(rows, func(rs csql.RowScanner) { var table string csql.Scan(rs, &table) if table != "migration_version" { tables = append(tables, table) } }) return }
// newAtomizer returns an atomizer that can be used to access or create new // atom identifiers. Note that if tx is nil, then the atomizer returned is // read-only (attempting to write will cause a panic). // // A read-only atomizer may be accessed from multiple goroutines // simultaneously, but a read/write atomizer may NOT. // // If a read/write atomizer is created, then the caller is responsible for // closing the transaction (which should be done immediately after a call to // atomizer.Close). // // Note that this function loads the entire set of atoms from the database // into memory, so it is costly. func newAtomizer(db *imdb.DB, tx *sql.Tx) (az *atomizer, err error) { defer csql.Safe(&err) az = &atomizer{db, make(atomMap, 1000000), 0, nil} if tx != nil { var err error az.ins, err = csql.NewInserter( tx, db.Driver, "atom", "id", "hash") csql.Panic(err) } rs := csql.Query(db, "SELECT id, hash FROM atom ORDER BY id ASC") csql.ForRow(rs, az.readRow) az.nextId++ return }
// attrs uses reflection to automatically construct a list of simple attribute // rows from the database based on information in the attribute's struct. // This includes building the SELECT query and the slice itself. // // zero MUST be a pointer to a simple struct. A simple struct MUST ONLY contain // fields that can be encoded/decoded as declared by the 'database/sql' // package. Column names are the lowercase version of their struct field name // unless the 'imdb_name' struct tag is set, in which case, that name is used. // // extra is passed to the end of the query executed. Useful for specifying // ORDER BY or LIMIT clauses. func attrs( zero interface{}, db csql.Queryer, e Entity, tableName string, idColumn string, extra string, ) (v interface{}, err error) { defer csql.Safe(&err) rz := reflect.ValueOf(zero).Elem() tz := rz.Type() nfields := tz.NumField() columns := make([]string, nfields) for i := 0; i < nfields; i++ { f := tz.Field(i) column := f.Tag.Get("imdb_name") if len(column) == 0 { column = strings.ToLower(f.Name) } columns[i] = column } tattrs := reflect.SliceOf(tz) vattrs := reflect.MakeSlice(tattrs, 0, 10) v = vattrs.Interface() q := sf("SELECT %s FROM %s WHERE %s = $1 %s", strings.Join(columns, ", "), tableName, idColumn, extra) rs := csql.Query(db, q, e.Ident()) csql.ForRow(rs, func(s csql.RowScanner) { loadCols := make([]interface{}, nfields) for i := 0; i < nfields; i++ { loadCols[i] = reflect.New(tz.Field(i).Type).Interface() } csql.Scan(s, loadCols...) row := reflect.New(tz).Elem() for i := 0; i < nfields; i++ { row.Field(i).Set(reflect.ValueOf(loadCols[i]).Elem()) } vattrs = reflect.Append(vattrs, row) }) v = vattrs.Interface() // not sure if this is necessary. return }
// Results executes the parameters of the search and returns the results. func (s *Searcher) Results() (rs []Result, err error) { defer csql.Safe(&err) // Set the similarity threshold first. if s.db.IsFuzzyEnabled() { csql.Exec(s.db, "SELECT set_limit($1)", s.similarThreshold) } if s.subTvshow != nil { if err := s.subTvshow.choose(s, s.chooser); err != nil { return nil, err } } if s.subCredits != nil { if err := s.subCredits.choose(s, s.chooser); err != nil { return nil, err } } if s.subCast != nil { if err := s.subCast.choose(s, s.chooser); err != nil { return nil, err } } var rows *sql.Rows if len(s.name) == 0 { rows = csql.Query(s.db, s.sql()) } else { rows = csql.Query(s.db, s.sql(), strings.Join(s.name, " ")) } csql.ForRow(rows, func(scanner csql.RowScanner) { var r Result var ent string csql.Scan(scanner, &ent, &r.Id, &r.Name, &r.Year, &r.Similarity, &r.Attrs, &r.Rank.Votes, &r.Rank.Rank, &r.Credit.ActorId, &r.Credit.MediaId, &r.Credit.Character, &r.Credit.Position, &r.Credit.Attrs) r.Entity = imdb.Entities[ent] rs = append(rs, r) }) return }
func (user *lcmUser) projects() []*project { projs := make([]*project, 0) rows := csql.Query(db, ` SELECT name, created FROM project WHERE owner = $1 ORDER BY name ASC `, user.Id) csql.ForRow(rows, func(s csql.RowScanner) { proj := &project{Owner: user} csql.Scan(rows, &proj.Name, &proj.Added) proj.Display = nameToDisplay(proj.Name) projs = append(projs, proj) }) return projs }