perkeep/lib/go/camli/mysqlindexer/search.go

200 lines
4.1 KiB
Go

/*
Copyright 2011 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
nYou may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package mysqlindexer
import (
"camli/blobref"
"camli/search"
"log"
"os"
"strings"
"time"
)
type permaNodeRow struct {
blobref string
signer string
lastmod string // "2011-03-13T23:30:19.03946Z"
}
func (mi *Indexer) GetRecentPermanodes(dest chan *search.Result, owner []*blobref.BlobRef, limit int) os.Error {
defer close(dest)
if len(owner) == 0 {
return nil
}
// TODO: support multiple
user := owner[0]
client, err := mi.getConnection()
if err != nil {
return err
}
defer mi.releaseConnection(client)
stmt, err := client.Prepare("SELECT blobref, signer, lastmod FROM permanodes WHERE signer = ? AND lastmod <> '' ORDER BY lastmod DESC LIMIT ?")
if err != nil {
return err
}
err = stmt.BindParams(user.String(), limit) // TODO: more than one owner, verification
if err != nil {
return err
}
err = stmt.Execute()
if err != nil {
return err
}
var row permaNodeRow
stmt.BindResult(&row.blobref, &row.signer, &row.lastmod)
for {
done, err := stmt.Fetch()
if err != nil {
return err
}
if done {
break
}
br := blobref.Parse(row.blobref)
if br == nil {
continue
}
signer := blobref.Parse(row.signer)
if signer == nil {
continue
}
row.lastmod = trimRFC3339Subseconds(row.lastmod)
t, err := time.Parse(time.RFC3339, row.lastmod)
if err != nil {
log.Printf("Skipping; error parsing time %q: %v", row.lastmod, err)
continue
}
dest <- &search.Result{
BlobRef: br,
Signer: signer,
LastModTime: t.Seconds(),
}
}
return nil
}
func trimRFC3339Subseconds(s string) string {
if !strings.HasSuffix(s, "Z") || len(s) < 20 || s[19] != '.' {
return s
}
return s[:19] + "Z"
}
type claimsRow struct {
blobref, signer, date, claim, unverified, permanode, attr, value string
}
func (mi *Indexer) GetOwnerClaims(permanode, owner *blobref.BlobRef) (claims search.ClaimList, reterr os.Error) {
claims = make(search.ClaimList, 0)
client, err := mi.getConnection()
if err != nil {
reterr = err
return
}
defer mi.releaseConnection(client)
// TODO: ignore rows where unverified = 'N'
stmt, err := client.Prepare("SELECT blobref, date, claim, attr, value FROM claims WHERE permanode = ? AND signer = ?")
if err != nil {
reterr = err
return
}
err = stmt.BindParams(permanode.String(), owner.String())
if err != nil {
reterr = err
return
}
err = stmt.Execute()
if err != nil {
reterr = err
return
}
var row claimsRow
stmt.BindResult(&row.blobref, &row.date, &row.claim, &row.attr, &row.value)
for {
done, err := stmt.Fetch()
if err != nil {
reterr = err
return
}
if done {
break
}
t, err := time.Parse(time.RFC3339, trimRFC3339Subseconds(row.date))
if err != nil {
log.Printf("Skipping; error parsing time %q: %v", row.date, err)
continue
}
claims = append(claims, &search.Claim{
BlobRef: blobref.Parse(row.blobref),
Signer: owner,
Permanode: permanode,
Type: row.claim,
Date: t,
Attr: row.attr,
Value: row.value,
})
}
return
}
func (mi *Indexer) GetBlobMimeType(blob *blobref.BlobRef) (mime string, ok bool, reterr os.Error) {
client, err := mi.getConnection()
if err != nil {
reterr = err
return
}
defer mi.releaseConnection(client)
stmt, err := client.Prepare("SELECT type FROM blobs WHERE blobref=?")
if err != nil {
reterr = err
return
}
err = stmt.BindParams(blob.String())
if err != nil {
reterr = err
return
}
err = stmt.Execute()
if err != nil {
reterr = err
return
}
stmt.BindResult(&mime)
for {
done, err := stmt.Fetch()
if err != nil {
reterr = err
return
}
if done {
break
}
}
ok = mime != ""
return
}