diff --git a/api.go b/api.go index 9373377..e91441d 100644 --- a/api.go +++ b/api.go @@ -1,6 +1,6 @@ package gorqlite -/* +/* this file has low level stuff: rqliteApiGet() @@ -33,69 +33,69 @@ import "time" func (conn *Connection) rqliteApiGet(apiOp apiOperation) ([]byte, error) { var responseBody []byte - trace("%s: rqliteApiGet() called",conn.ID) + trace("%s: rqliteApiGet() called", conn.ID) // only api_STATUS now - maybe someday BACKUP - if ( apiOp != api_STATUS ) { + if apiOp != api_STATUS { return responseBody, errors.New("rqliteApiGet() called for invalid api operation") } // just to be safe, check this peersToTry := conn.cluster.makePeerList() - if ( len(peersToTry) < 1 ) { + if len(peersToTry) < 1 { return responseBody, errors.New("I don't have any cluster info") } - trace("%s: I have a peer list %d peers long",conn.ID,len(peersToTry)) + trace("%s: I have a peer list %d peers long", conn.ID, len(peersToTry)) // failure log is used so that if all peers fail, we can say something // about why each failed - failureLog := make([]string,0) + failureLog := make([]string, 0) PeerLoop: - for peerNum, peerToTry := range peersToTry { - trace("%s: attemping to contact peer %d",conn.ID,peerNum) - // docs say default GET policy is up to 10 follows automatically - url := conn.assembleURL(api_STATUS,peerToTry) - req, err := http.NewRequest("GET",url,nil) - if ( err != nil ) { - trace("%s: got error '%s' doing http.NewRequest", conn.ID,err.Error()) - failureLog = append(failureLog,fmt.Sprintf("%s failed due to %s",url,err.Error())) + for peerNum, peerToTry := range peersToTry { + trace("%s: attemping to contact peer %d", conn.ID, peerNum) + // docs say default GET policy is up to 10 follows automatically + url := conn.assembleURL(api_STATUS, peerToTry) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + trace("%s: got error '%s' doing http.NewRequest", conn.ID, err.Error()) + failureLog = append(failureLog, fmt.Sprintf("%s failed due to %s", url, err.Error())) continue PeerLoop } - trace("%s: http.NewRequest() OK") - req.Header.Set("Content-Type","application/json") + trace("%s: http.NewRequest() OK") + req.Header.Set("Content-Type", "application/json") client := &http.Client{} client.Timeout = time.Duration(conn.timeout) * time.Second response, err := client.Do(req) - if ( err != nil ) { - trace("%s: got error '%s' doing client.Do", conn.ID,err.Error()) - failureLog = append(failureLog,fmt.Sprintf("%s failed due to %s",url,err.Error())) + if err != nil { + trace("%s: got error '%s' doing client.Do", conn.ID, err.Error()) + failureLog = append(failureLog, fmt.Sprintf("%s failed due to %s", url, err.Error())) continue PeerLoop } defer response.Body.Close() - trace("%s: client.Do() OK") + trace("%s: client.Do() OK") responseBody, err := ioutil.ReadAll(response.Body) - if ( err != nil ) { - trace("%s: got error '%s' doing ioutil.ReadAll", conn.ID,err.Error()) - failureLog = append(failureLog,fmt.Sprintf("%s failed due to %s",url,err.Error())) + if err != nil { + trace("%s: got error '%s' doing ioutil.ReadAll", conn.ID, err.Error()) + failureLog = append(failureLog, fmt.Sprintf("%s failed due to %s", url, err.Error())) continue PeerLoop } - trace("%s: ioutil.ReadAll() OK") - if ( response.Status != "200 OK" ) { - trace("%s: got code %s",conn.ID,response.Status) - failureLog = append(failureLog,fmt.Sprintf("%s failed, got: %s",url,response.Status)) + trace("%s: ioutil.ReadAll() OK") + if response.Status != "200 OK" { + trace("%s: got code %s", conn.ID, response.Status) + failureLog = append(failureLog, fmt.Sprintf("%s failed, got: %s", url, response.Status)) continue PeerLoop } // if we got here, we succeeded - trace("%s: api call OK, returning",conn.ID) + trace("%s: api call OK, returning", conn.ID) return responseBody, nil - } + } // if we got here, all peers failed. Let's build a verbose error message var stringBuffer bytes.Buffer stringBuffer.WriteString("tried all peers unsuccessfully. here are the results:\n") for n, v := range failureLog { - stringBuffer.WriteString(fmt.Sprintf(" peer #%d: %s\n",n,v)) + stringBuffer.WriteString(fmt.Sprintf(" peer #%d: %s\n", n, v)) } return responseBody, errors.New(stringBuffer.String()) } @@ -114,78 +114,80 @@ PeerLoop: * *****************************************************************/ -func (conn *Connection) rqliteApiPost (apiOp apiOperation, sqlStatements []string) ([]byte, error) { +func (conn *Connection) rqliteApiPost(apiOp apiOperation, sqlStatements []string) ([]byte, error) { var responseBody []byte - switch (apiOp) { - case api_QUERY: - trace("%s: rqliteApiGet() post called for a QUERY of %d statements",conn.ID,len(sqlStatements)) - case api_WRITE: - trace("%s: rqliteApiGet() post called for a QUERY of %d statements",conn.ID,len(sqlStatements)) - default: - return responseBody, errors.New("weird! called for an invalid apiOperation in rqliteApiPost()") + switch apiOp { + case api_QUERY: + trace("%s: rqliteApiGet() post called for a QUERY of %d statements", conn.ID, len(sqlStatements)) + case api_WRITE: + trace("%s: rqliteApiGet() post called for a QUERY of %d statements", conn.ID, len(sqlStatements)) + default: + return responseBody, errors.New("weird! called for an invalid apiOperation in rqliteApiPost()") } // jsonify the statements. not really needed in the - // case of api_STATUS but doesn't hurt + // case of api_STATUS but doesn't hurt - jStatements , err := json.Marshal(sqlStatements) - if ( err != nil ) { return nil, err } + jStatements, err := json.Marshal(sqlStatements) + if err != nil { + return nil, err + } // just to be safe, check this peersToTry := conn.cluster.makePeerList() - if ( len(peersToTry) < 1 ) { + if len(peersToTry) < 1 { return responseBody, errors.New("I don't have any cluster info") } // failure log is used so that if all peers fail, we can say something // about why each failed - failureLog := make([]string,0) + failureLog := make([]string, 0) PeerLoop: for peerNum, peer := range peersToTry { - trace("%s: trying peer #%d",conn.ID,peerNum) + trace("%s: trying peer #%d", conn.ID, peerNum) // we're doing a post, and the RFCs say that if you get a 301, it's not // automatically followed, so we have to do that ourselves responseStatus := "Haven't Tried Yet" var url string - for ( responseStatus == "Haven't Tried Yet" || responseStatus == "301 Moved Permanently" ) { - url = conn.assembleURL(apiOp,peer) - req, err := http.NewRequest("POST",url,bytes.NewBuffer(jStatements)) - if ( err != nil ) { - trace("%s: got error '%s' doing http.NewRequest", conn.ID,err.Error()) - failureLog = append(failureLog,fmt.Sprintf("%s failed due to %s",url,err.Error())) + for responseStatus == "Haven't Tried Yet" || responseStatus == "301 Moved Permanently" { + url = conn.assembleURL(apiOp, peer) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(jStatements)) + if err != nil { + trace("%s: got error '%s' doing http.NewRequest", conn.ID, err.Error()) + failureLog = append(failureLog, fmt.Sprintf("%s failed due to %s", url, err.Error())) continue PeerLoop } - req.Header.Set("Content-Type","application/json") + req.Header.Set("Content-Type", "application/json") client := &http.Client{} response, err := client.Do(req) - if ( err != nil ) { - trace("%s: got error '%s' doing client.Do", conn.ID,err.Error()) - failureLog = append(failureLog,fmt.Sprintf("%s failed due to %s",url,err.Error())) + if err != nil { + trace("%s: got error '%s' doing client.Do", conn.ID, err.Error()) + failureLog = append(failureLog, fmt.Sprintf("%s failed due to %s", url, err.Error())) continue PeerLoop } defer response.Body.Close() responseBody, err = ioutil.ReadAll(response.Body) - if ( err != nil ) { - trace("%s: got error '%s' doing ioutil.ReadAll", conn.ID,err.Error()) - failureLog = append(failureLog,fmt.Sprintf("%s failed due to %s",url,err.Error())) + if err != nil { + trace("%s: got error '%s' doing ioutil.ReadAll", conn.ID, err.Error()) + failureLog = append(failureLog, fmt.Sprintf("%s failed due to %s", url, err.Error())) continue PeerLoop } responseStatus = response.Status - if ( responseStatus == "301 Moved Permanently" ) { + if responseStatus == "301 Moved Permanently" { v := response.Header["Location"] - failureLog = append(failureLog,fmt.Sprintf("%s redirected me to %s",url,v[0])) + failureLog = append(failureLog, fmt.Sprintf("%s redirected me to %s", url, v[0])) url = v[0] continue PeerLoop - } else if ( responseStatus == "200 OK" ) { - trace("%s: api call OK, returning",conn.ID) + } else if responseStatus == "200 OK" { + trace("%s: api call OK, returning", conn.ID) return responseBody, nil } else { trace("%s: got error in responseStatus: %s", conn.ID, responseStatus) - failureLog = append(failureLog,fmt.Sprintf("%s failed, got: %s",url,response.Status)) + failureLog = append(failureLog, fmt.Sprintf("%s failed, got: %s", url, response.Status)) continue PeerLoop } } @@ -195,8 +197,7 @@ PeerLoop: var stringBuffer bytes.Buffer stringBuffer.WriteString("tried all peers unsuccessfully. here are the results:\n") for n, v := range failureLog { - stringBuffer.WriteString(fmt.Sprintf(" peer #%d: %s\n",n,v)) + stringBuffer.WriteString(fmt.Sprintf(" peer #%d: %s\n", n, v)) } return responseBody, errors.New(stringBuffer.String()) } - diff --git a/cluster.go b/cluster.go index b3928d2..d5df7d5 100644 --- a/cluster.go +++ b/cluster.go @@ -5,7 +5,7 @@ package gorqlite types: peer - rqliteCluster + rqliteCluster Connection methods: assembleURL (from a peer) updateClusterInfo (does the full cluster discovery via status) @@ -32,19 +32,18 @@ import "strings" this is an internal type to abstact peer info. - note that hostname is sometimes used for "has this struct been + note that hostname is sometimes used for "has this struct been inialized" checks. * *****************************************************************/ - type peer struct { - hostname string // hostname or "localhost" - port string // "4001" or port, only ever used as a string + hostname string // hostname or "localhost" + port string // "4001" or port, only ever used as a string } func (p *peer) String() string { - return fmt.Sprintf("%s:%s",p.hostname,p.port) + return fmt.Sprintf("%s:%s", p.hostname, p.port) } /* ***************************************************************** @@ -56,9 +55,9 @@ func (p *peer) String() string { * *****************************************************************/ type rqliteCluster struct { - leader peer + leader peer otherPeers []peer - conn *Connection + conn *Connection } /* ***************************************************************** @@ -72,16 +71,16 @@ type rqliteCluster struct { * *****************************************************************/ func (rc *rqliteCluster) makePeerList() []peer { - trace("%s: makePeerList() called",rc.conn.ID) + trace("%s: makePeerList() called", rc.conn.ID) var peerList []peer - peerList = append(peerList,rc.leader) + peerList = append(peerList, rc.leader) for _, p := range rc.otherPeers { - peerList = append(peerList,p) + peerList = append(peerList, p) } - trace("%s: makePeerList() returning this list:",rc.conn.ID) + trace("%s: makePeerList() returning this list:", rc.conn.ID) for n, v := range peerList { - trace("%s: makePeerList() peer %d -> %s",rc.conn.ID,n,v.hostname + ":" + v.port) + trace("%s: makePeerList() peer %d -> %s", rc.conn.ID, n, v.hostname+":"+v.port) } return peerList @@ -105,13 +104,13 @@ func (rc *rqliteCluster) makePeerList() []peer { func (conn *Connection) assembleURL(apiOp apiOperation, p peer) string { var stringBuffer bytes.Buffer - if ( conn.wantsHTTPS == true ) { + if conn.wantsHTTPS == true { stringBuffer.WriteString("https") } else { stringBuffer.WriteString("http") } stringBuffer.WriteString("://") - if ( conn.username != "" && conn.password != "" ) { + if conn.username != "" && conn.password != "" { stringBuffer.WriteString(conn.username) stringBuffer.WriteString(":") stringBuffer.WriteString(conn.password) @@ -122,26 +121,26 @@ func (conn *Connection) assembleURL(apiOp apiOperation, p peer) string { stringBuffer.WriteString(p.port) switch apiOp { - case api_STATUS: - stringBuffer.WriteString("/status") - case api_QUERY: - stringBuffer.WriteString("/db/query") - case api_WRITE: - stringBuffer.WriteString("/db/execute") + case api_STATUS: + stringBuffer.WriteString("/status") + case api_QUERY: + stringBuffer.WriteString("/db/query") + case api_WRITE: + stringBuffer.WriteString("/db/execute") } - if ( apiOp == api_QUERY || apiOp == api_WRITE ) { + if apiOp == api_QUERY || apiOp == api_WRITE { stringBuffer.WriteString("?timings&transaction&level=") stringBuffer.WriteString(consistencyLevelNames[conn.consistencyLevel]) } switch apiOp { - case api_QUERY: - trace("%s: assembled URL for an api_QUERY: %s",conn.ID,stringBuffer.String()) - case api_STATUS: - trace("%s: assembled URL for an api_STATUS: %s",conn.ID,stringBuffer.String()) - case api_WRITE: - trace("%s: assembled URL for an api_WRITE: %s",conn.ID,stringBuffer.String()) + case api_QUERY: + trace("%s: assembled URL for an api_QUERY: %s", conn.ID, stringBuffer.String()) + case api_STATUS: + trace("%s: assembled URL for an api_STATUS: %s", conn.ID, stringBuffer.String()) + case api_WRITE: + trace("%s: assembled URL for an api_WRITE: %s", conn.ID, stringBuffer.String()) } return stringBuffer.String() @@ -160,22 +159,26 @@ func (conn *Connection) assembleURL(apiOp apiOperation, p peer) string { * *****************************************************************/ func (conn *Connection) updateClusterInfo() error { - trace("%s: updateClusterInfo() called",conn.ID) + trace("%s: updateClusterInfo() called", conn.ID) // start with a fresh new cluster var rc rqliteCluster rc.conn = conn responseBody, err := conn.rqliteApiGet(api_STATUS) - if ( err != nil ) { return err } - trace("%s: updateClusterInfo() back from api call OK",conn.ID) - + if err != nil { + return err + } + trace("%s: updateClusterInfo() back from api call OK", conn.ID) + sections := make(map[string]interface{}) - err = json.Unmarshal(responseBody,§ions) - if ( err != nil ) { return err } + err = json.Unmarshal(responseBody, §ions) + if err != nil { + return err + } sMap := sections["store"].(map[string]interface{}) leaderRaftAddr := sMap["leader"].(string) - trace("%s: leader from store section is %s",conn.ID,leaderRaftAddr) + trace("%s: leader from store section is %s", conn.ID, leaderRaftAddr) // leader in this case is the RAFT address // we want the HTTP address, so we'll use this as @@ -185,37 +188,36 @@ func (conn *Connection) updateClusterInfo() error { apiPeers := meta["APIPeers"].(map[string]interface{}) for raftAddr, httpAddr := range apiPeers { - trace("%s: examining httpAddr %s",conn.ID,httpAddr) + trace("%s: examining httpAddr %s", conn.ID, httpAddr) /* httpAddr are usually hostname:port */ var p peer - parts := strings.Split(httpAddr.(string),":") + parts := strings.Split(httpAddr.(string), ":") p.hostname = parts[0] p.port = parts[1] // so is this the leader? - if ( leaderRaftAddr == raftAddr ) { - trace ("%s: found leader at %s",conn.ID,httpAddr) + if leaderRaftAddr == raftAddr { + trace("%s: found leader at %s", conn.ID, httpAddr) rc.leader = p } else { rc.otherPeers = append(rc.otherPeers, p) } } - if ( rc.leader.hostname == "" ) { + if rc.leader.hostname == "" { return errors.New("could not determine leader from API status call") } // dump to trace - trace("%s: here is my cluster config:",conn.ID) - trace("%s: leader : %s",conn.ID,rc.leader.String()) + trace("%s: here is my cluster config:", conn.ID) + trace("%s: leader : %s", conn.ID, rc.leader.String()) for n, v := range rc.otherPeers { - trace("%s: otherPeer #%d: %s",conn.ID,n,v.String()) - } + trace("%s: otherPeer #%d: %s", conn.ID, n, v.String()) + } // now make it official conn.cluster = rc return nil } - diff --git a/cluster_test.go b/cluster_test.go index 53f54d9..903dd1e 100644 --- a/cluster_test.go +++ b/cluster_test.go @@ -6,34 +6,33 @@ import "os" func TestInitCluster(t *testing.T) { -TraceOn(os.Stderr) + TraceOn(os.Stderr) t.Logf("trying Open") conn, err := Open(testUrl()) - if ( err != nil ) { + if err != nil { t.Logf("--> FAILED") - t.Fatal(err) + t.Fatal(err) } l, err := conn.Leader() - if ( err != nil ) { + if err != nil { t.Logf("--> FAILED") t.Fail() } - if ( len(l) < 1 ) { + if len(l) < 1 { t.Logf("--> FAILED") t.Fail() } p, err := conn.Peers() - if ( err != nil ) { + if err != nil { t.Logf("--> FAILED") t.Fail() } - if ( len(p) < 1 ) { + if len(p) < 1 { t.Logf("--> FAILED") t.Fail() } } - diff --git a/conn.go b/conn.go index bde7819..2673064 100644 --- a/conn.go +++ b/conn.go @@ -35,13 +35,13 @@ var wantsTrace bool /* The connection abstraction. Note that since rqlite is stateless, there really is no "connection". However, this type holds - information such as the current leader, peers, connection + information such as the current leader, peers, connection string to build URLs, etc. Connections are assigned a "connection ID" which is a pseudo-UUID for connection identification in trace output only. This helps sort out what's going on if you have multiple connections going - at once. It's generated using a non-standards-or-anything-else-compliant + at once. It's generated using a non-standards-or-anything-else-compliant function that uses crypto/rand to generate 16 random bytes. Note that the Connection objection holds info on all peers, gathered @@ -49,23 +49,22 @@ var wantsTrace bool */ type Connection struct { - cluster rqliteCluster /* - name type default - */ + name type default + */ - username string // username or "" - password string // username or "" - consistencyLevel consistencyLevel // WEAK - wantsHTTPS bool // false unless connection URL is https + username string // username or "" + password string // username or "" + consistencyLevel consistencyLevel // WEAK + wantsHTTPS bool // false unless connection URL is https // variables below this line need to be initialized in Open() - timeout int // 10 - hasBeenClosed bool // false - ID string // generated in init() + timeout int // 10 + hasBeenClosed bool // false + ID string // generated in init() } /* ***************************************************************** @@ -76,7 +75,7 @@ type Connection struct { func (conn *Connection) Close() { conn.hasBeenClosed = true - trace("%s: %s",conn.ID,"closing connection") + trace("%s: %s", conn.ID, "closing connection") } /* ***************************************************************** @@ -86,8 +85,8 @@ func (conn *Connection) Close() { * *****************************************************************/ func (conn *Connection) ConsistencyLevel() (string, error) { - if ( conn.hasBeenClosed) { - return "", errClosed + if conn.hasBeenClosed { + return "", errClosed } return consistencyLevelNames[conn.consistencyLevel], nil } @@ -99,16 +98,16 @@ func (conn *Connection) ConsistencyLevel() (string, error) { * *****************************************************************/ func (conn *Connection) Leader() (string, error) { - if ( conn.hasBeenClosed) { - return "", errClosed + if conn.hasBeenClosed { + return "", errClosed } - trace("%s: Leader(), calling updateClusterInfo()",conn.ID) + trace("%s: Leader(), calling updateClusterInfo()", conn.ID) err := conn.updateClusterInfo() - if ( err != nil ) { - trace("%s: Leader() got error from updateClusterInfo(): %s",conn.ID,err.Error()) + if err != nil { + trace("%s: Leader() got error from updateClusterInfo(): %s", conn.ID, err.Error()) return "", err } else { - trace("%s: Leader(), updateClusterInfo() OK",conn.ID) + trace("%s: Leader(), updateClusterInfo() OK", conn.ID) } return conn.cluster.leader.String(), nil } @@ -120,23 +119,23 @@ func (conn *Connection) Leader() (string, error) { * *****************************************************************/ func (conn *Connection) Peers() ([]string, error) { - if ( conn.hasBeenClosed) { + if conn.hasBeenClosed { var ans []string - return ans, errClosed + return ans, errClosed } - plist := make ([]string,0) + plist := make([]string, 0) - trace("%s: Peers(), calling updateClusterInfo()",conn.ID) + trace("%s: Peers(), calling updateClusterInfo()", conn.ID) err := conn.updateClusterInfo() - if ( err != nil ) { - trace("%s: Peers() got error from updateClusterInfo(): %s",conn.ID,err.Error()) + if err != nil { + trace("%s: Peers() got error from updateClusterInfo(): %s", conn.ID, err.Error()) return plist, err } else { - trace("%s: Peers(), updateClusterInfo() OK",conn.ID) + trace("%s: Peers(), updateClusterInfo() OK", conn.ID) } - plist = append(plist,conn.cluster.leader.String()) + plist = append(plist, conn.cluster.leader.String()) for _, p := range conn.cluster.otherPeers { - plist = append(plist,p.String()) + plist = append(plist, p.String()) } return plist, nil } @@ -148,15 +147,15 @@ func (conn *Connection) Peers() ([]string, error) { * *****************************************************************/ func (conn *Connection) SetConsistencyLevel(levelDesired string) error { - if ( conn.hasBeenClosed) { - return errClosed + if conn.hasBeenClosed { + return errClosed } _, ok := consistencyLevels[levelDesired] - if ( ok ) { + if ok { conn.consistencyLevel = consistencyLevels[levelDesired] return nil } - return errors.New(fmt.Sprintf("unknown consistency level: %s",levelDesired)) + return errors.New(fmt.Sprintf("unknown consistency level: %s", levelDesired)) } /* ***************************************************************** @@ -171,7 +170,7 @@ func (conn *Connection) SetConsistencyLevel(levelDesired string) error { be the leader. The next thing Open() does is updateClusterInfo() so the truth will be revealed soon enough. - initConnection() does not talk to rqlite. It only parses the + initConnection() does not talk to rqlite. It only parses the connection URL and prepares the new connection for work. URL format: @@ -204,21 +203,21 @@ func (conn *Connection) initConnection(url string) error { // do some sanity checks. You know users. - if ( len(url) < 7 ) { + if len(url) < 7 { return errors.New("url specified is impossibly short") } - if ( strings.HasPrefix(url,"http") == false ) { + if strings.HasPrefix(url, "http") == false { return errors.New("url does not start with 'http'") } u, err := nurl.Parse(url) - if ( err != nil ) { + if err != nil { return err } - trace("%s: net.url.Parse() OK",conn.ID) + trace("%s: net.url.Parse() OK", conn.ID) - if ( u.Scheme == "https" ) { + if u.Scheme == "https" { conn.wantsHTTPS = true } @@ -233,27 +232,27 @@ func (conn *Connection) initConnection(url string) error { // not guaranteed, so test if set pass, isset := u.User.Password() - if ( isset ) { + if isset { conn.password = pass } else { conn.password = "" } } - if ( u.Host == "" ) { + if u.Host == "" { conn.cluster.leader.hostname = "localhost" } else { conn.cluster.leader.hostname = u.Host } - if ( u.Host == "" ) { + if u.Host == "" { conn.cluster.leader.hostname = "localhost" conn.cluster.leader.port = "4001" } else { // SplitHostPort() should only return an error if there is no host port. // I think. h, p, err := net.SplitHostPort(u.Host) - if ( err != nil ) { + if err != nil { conn.cluster.leader.hostname = u.Host } else { conn.cluster.leader.hostname = h @@ -263,41 +262,39 @@ func (conn *Connection) initConnection(url string) error { /* - at the moment, the only allowed query is "level=" with - the desired consistency level + at the moment, the only allowed query is "level=" with + the desired consistency level */ // default conn.consistencyLevel = cl_WEAK - if ( u.RawQuery != "" ) { - if ( u.RawQuery == "level=weak") { + if u.RawQuery != "" { + if u.RawQuery == "level=weak" { // that's ok but nothing to do - } else if ( u.RawQuery == "level=strong" ) { + } else if u.RawQuery == "level=strong" { conn.consistencyLevel = cl_STRONG - } else if ( u.RawQuery == "level=none" ) { // the fools! + } else if u.RawQuery == "level=none" { // the fools! conn.consistencyLevel = cl_NONE } else { return errors.New("don't know what to do with this query: " + u.RawQuery) } } - trace("%s: parseDefaultPeer() is done:",conn.ID) - if ( conn.wantsHTTPS == true ) { - trace("%s: %s -> %s",conn.ID,"wants https?","yes") + trace("%s: parseDefaultPeer() is done:", conn.ID) + if conn.wantsHTTPS == true { + trace("%s: %s -> %s", conn.ID, "wants https?", "yes") } else { - trace("%s: %s -> %s",conn.ID,"wants https?","no") + trace("%s: %s -> %s", conn.ID, "wants https?", "no") } - trace("%s: %s -> %s",conn.ID,"username",conn.username) - trace("%s: %s -> %s",conn.ID,"password",conn.password) - trace("%s: %s -> %s",conn.ID,"hostname",conn.cluster.leader.hostname) - trace("%s: %s -> %s",conn.ID,"port",conn.cluster.leader.port) - trace("%s: %s -> %s",conn.ID,"consistencyLevel",consistencyLevelNames[conn.consistencyLevel]) + trace("%s: %s -> %s", conn.ID, "username", conn.username) + trace("%s: %s -> %s", conn.ID, "password", conn.password) + trace("%s: %s -> %s", conn.ID, "hostname", conn.cluster.leader.hostname) + trace("%s: %s -> %s", conn.ID, "port", conn.cluster.leader.port) + trace("%s: %s -> %s", conn.ID, "consistencyLevel", consistencyLevelNames[conn.consistencyLevel]) conn.cluster.conn = conn return nil } - - diff --git a/gorqlite.go b/gorqlite.go index 9752053..6ba7660 100644 --- a/gorqlite.go +++ b/gorqlite.go @@ -10,11 +10,11 @@ Learn more about rqlite at: https://github.com/rqlite/rqlite - */ +*/ package gorqlite /* - this file contains package-level stuff: + this file contains package-level stuff: consts init() Open, TraceOn(), TraceOff() @@ -33,16 +33,19 @@ import "strings" * *****************************************************************/ type consistencyLevel int + const ( cl_NONE consistencyLevel = iota cl_WEAK cl_STRONG ) + // used in several places, actually var consistencyLevelNames map[consistencyLevel]string var consistencyLevels map[string]consistencyLevel type apiOperation int + const ( api_QUERY apiOperation = iota api_STATUS @@ -56,7 +59,7 @@ const ( * *****************************************************************/ func init() { - traceOut = ioutil.Discard + traceOut = ioutil.Discard consistencyLevelNames = make(map[consistencyLevel]string) consistencyLevelNames[cl_NONE] = "none" @@ -70,7 +73,6 @@ func init() { } - /* ***************************************************************** Open() creates and returns a "connection" to rqlite. @@ -99,7 +101,7 @@ func Open(connURL string) (Connection, error) { return conn, err } conn.ID = fmt.Sprintf("%X-%X-%X-%X-%X", b[0:4], b[4:6], b[6:8], b[8:10], b[10:]) - trace("%s: Open() called for url: %s",conn.ID,connURL) + trace("%s: Open() called for url: %s", conn.ID, connURL) // set defaults conn.timeout = 10 @@ -107,7 +109,7 @@ func Open(connURL string) (Connection, error) { // parse the URL given err = conn.initConnection(connURL) - if ( err != nil ) { + if err != nil { return conn, err } @@ -124,7 +126,7 @@ func Open(connURL string) (Connection, error) { func: trace() - adds a message to the trace output + adds a message to the trace output not a public function. we (inside) can add - outside they can only see. @@ -132,7 +134,7 @@ func Open(connURL string) (Connection, error) { Call trace as: Sprintf pattern , args... This is done so that the more expensive Sprintf() stuff is - done only if truly needed. When tracing is off, calls to + done only if truly needed. When tracing is off, calls to trace() just hit a bool check and return. If tracing is on, then the Sprintfing is done at a leisurely pace because, well, we're tracing. @@ -146,7 +148,7 @@ func Open(connURL string) (Connection, error) { func trace(pattern string, args ...interface{}) { // don't do the probably expensive Sprintf() if not needed - if ( wantsTrace == false ) { + if wantsTrace == false { return } @@ -156,8 +158,8 @@ func trace(pattern string, args ...interface{}) { // make sure there is one and only one newline nlPattern := strings.TrimSpace(pattern) + "\n" - msg := fmt.Sprintf(nlPattern,args...) - traceOut.Write( []byte( msg ) ) + msg := fmt.Sprintf(nlPattern, args...) + traceOut.Write([]byte(msg)) } /* diff --git a/query.go b/query.go index a9a82b6..d093e1a 100644 --- a/query.go +++ b/query.go @@ -91,51 +91,51 @@ QueryOne() is a convenience method that wraps Query() into a single-statement method. */ func (conn *Connection) QueryOne(sqlStatement string) (qr QueryResult, err error) { - if ( conn.hasBeenClosed) { + if conn.hasBeenClosed { qr.Err = errClosed return qr, errClosed - } - sqlStatements := make([]string,0) - sqlStatements = append(sqlStatements,sqlStatement) + } + sqlStatements := make([]string, 0) + sqlStatements = append(sqlStatements, sqlStatement) qra, err := conn.Query(sqlStatements) return qra[0], err -} +} /* Query() is used to perform SELECT operations in the database. It takes an array of SQL statements and executes them in a single transaction, returning an array of QueryResult vars. -*/ +*/ func (conn *Connection) Query(sqlStatements []string) (results []QueryResult, err error) { - results = make([]QueryResult,0) + results = make([]QueryResult, 0) - if ( conn.hasBeenClosed) { + if conn.hasBeenClosed { var errResult QueryResult errResult.Err = errClosed - results = append(results,errResult) - return results, errClosed - } - trace("%s: Query() for %d statements",conn.ID,len(sqlStatements)) + results = append(results, errResult) + return results, errClosed + } + trace("%s: Query() for %d statements", conn.ID, len(sqlStatements)) // if we get an error POSTing, that's a showstopper - response, err := conn.rqliteApiPost(api_QUERY,sqlStatements) - if ( err != nil ) { - trace("%s: rqliteApiCall() ERROR: %s",conn.ID,err.Error()) + response, err := conn.rqliteApiPost(api_QUERY, sqlStatements) + if err != nil { + trace("%s: rqliteApiCall() ERROR: %s", conn.ID, err.Error()) var errResult QueryResult errResult.Err = err - results = append(results,errResult) + results = append(results, errResult) return results, err } - trace("%s: rqliteApiCall() OK",conn.ID) + trace("%s: rqliteApiCall() OK", conn.ID) // if we get an error Unmarshaling, that's a showstopper var sections map[string]interface{} - err = json.Unmarshal(response,§ions) - if ( err != nil ) { - trace("%s: json.Unmarshal() ERROR: %s",conn.ID,err.Error()) + err = json.Unmarshal(response, §ions) + if err != nil { + trace("%s: json.Unmarshal() ERROR: %s", conn.ID, err.Error()) var errResult QueryResult errResult.Err = err - results = append(results,errResult) + results = append(results, errResult) return results, err } @@ -145,13 +145,13 @@ func (conn *Connection) Query(sqlStatements []string) (results []QueryResult, er */ resultsArray := sections["results"].([]interface{}) - trace("%s: I have %d result(s) to parse",conn.ID,len(resultsArray)) + trace("%s: I have %d result(s) to parse", conn.ID, len(resultsArray)) numStatementErrors := 0 for n, r := range resultsArray { - trace("%s: parsing result %d",conn.ID,n) + trace("%s: parsing result %d", conn.ID, n) var thisQR QueryResult - thisQR.conn = conn + thisQR.conn = conn // r is a hash with columns, types, values, and time thisResult := r.(map[string]interface{}) @@ -159,9 +159,9 @@ func (conn *Connection) Query(sqlStatements []string) (results []QueryResult, er // did we get an error? _, ok := thisResult["error"] if ok { - trace("%s: have an error on this result: %s",conn.ID,thisResult["error"].(string)) + trace("%s: have an error on this result: %s", conn.ID, thisResult["error"].(string)) thisQR.Err = errors.New(thisResult["error"].(string)) - results = append(results,thisQR) + results = append(results, thisQR) numStatementErrors++ continue } @@ -172,28 +172,28 @@ func (conn *Connection) Query(sqlStatements []string) (results []QueryResult, er // column & type are an array of strings c := thisResult["columns"].([]interface{}) t := thisResult["types"].([]interface{}) - for i := 0; i < len(c) ; i++ { - thisQR.columns = append(thisQR.columns,c[i].(string)) - thisQR.types = append(thisQR.types,t[i].(string)) + for i := 0; i < len(c); i++ { + thisQR.columns = append(thisQR.columns, c[i].(string)) + thisQR.types = append(thisQR.types, t[i].(string)) } // and values are an array of arrays - if ( thisResult["values"] != nil ) { + if thisResult["values"] != nil { thisQR.values = thisResult["values"].([]interface{}) } else { - trace("%s: fyi, no values this query",conn.ID) + trace("%s: fyi, no values this query", conn.ID) } thisQR.rowNumber = -1 - trace("%s: this result (#col,time) %d %f",conn.ID,len(thisQR.columns),thisQR.Timing) - results = append(results,thisQR) + trace("%s: this result (#col,time) %d %f", conn.ID, len(thisQR.columns), thisQR.Timing) + results = append(results, thisQR) } - trace("%s: finished parsing, returning %d results",conn.ID,len(results)) + trace("%s: finished parsing, returning %d results", conn.ID, len(results)) - if ( numStatementErrors > 0 ) { - return results, errors.New(fmt.Sprintf("there were %d statement errors",numStatementErrors)) + if numStatementErrors > 0 { + return results, errors.New(fmt.Sprintf("there were %d statement errors", numStatementErrors)) } else { return results, nil } @@ -217,12 +217,12 @@ then a QueryResult would hold any errors from that query, a list of columns and Query() returns an array of QueryResult vars, while QueryOne() returns a single variable. */ type QueryResult struct { - conn *Connection - Err error - columns []string - types []string - Timing float64 - values []interface{} + conn *Connection + Err error + columns []string + types []string + Timing float64 + values []interface{} rowNumber int64 } @@ -232,7 +232,7 @@ type QueryResult struct { /* ***************************************************************** - method: QueryResult.Columns() + method: QueryResult.Columns() * *****************************************************************/ @@ -252,7 +252,7 @@ func (qr *QueryResult) Columns() []string { /* Map() returns the current row (as advanced by Next()) as a map[string]interface{} -The key is a string corresponding to a column name. +The key is a string corresponding to a column name. The value is the corresponding column. Note that only json values are supported, so you will need to type the interface{} accordingly. @@ -260,13 +260,13 @@ Note that only json values are supported, so you will need to type the interface func (qr *QueryResult) Map() (map[string]interface{}, error) { trace("%s: Map() called for row %d", qr.conn.ID, qr.rowNumber) ans := make(map[string]interface{}) - - if ( qr.rowNumber == -1 ) { + + if qr.rowNumber == -1 { return ans, errors.New("you need to Next() before you Map(), sorry, it's complicated") } - thisRowValues := qr.values[qr.rowNumber].([]interface {}) - for i := 0; i= int64(len(qr.values) - 1 )) { + if qr.rowNumber >= int64(len(qr.values)-1) { return false } qr.rowNumber += 1 - return true + return true } /* ***************************************************************** @@ -346,31 +346,31 @@ are a subset of the types JSON uses: booleans, JSON arrays, and JSON objects are not supported, since sqlite does not support them. */ -func (qr *QueryResult) Scan(dest... interface{}) error { - trace("%s: Scan() called for %d vars", qr.conn.ID,len(dest)) +func (qr *QueryResult) Scan(dest ...interface{}) error { + trace("%s: Scan() called for %d vars", qr.conn.ID, len(dest)) - if ( qr.rowNumber == -1 ) { + if qr.rowNumber == -1 { return errors.New("you need to Next() before you Scan(), sorry, it's complicated") } - if ( len(dest) != len(qr.columns) ) { + if len(dest) != len(qr.columns) { return errors.New(fmt.Sprintf("expected %d columns but got %d vars\n", len(qr.columns), len(dest))) } - thisRowValues := qr.values[qr.rowNumber].([]interface {}) + thisRowValues := qr.values[qr.rowNumber].([]interface{}) for n, d := range dest { switch d.(type) { - case *int64: - f := int64(thisRowValues[n].(float64)) - *d.(*int64) = f - case *float64: - f := float64(thisRowValues[n].(float64)) - *d.(*float64) = f - case *string: - s := string(thisRowValues[n].(string)) - *d.(*string) = s - default: - return errors.New(fmt.Sprintf("unknown destination type to scan into in variable #%d",n)) + case *int64: + f := int64(thisRowValues[n].(float64)) + *d.(*int64) = f + case *float64: + f := float64(thisRowValues[n].(float64)) + *d.(*float64) = f + case *string: + s := string(thisRowValues[n].(string)) + *d.(*string) = s + default: + return errors.New(fmt.Sprintf("unknown destination type to scan into in variable #%d", n)) } } @@ -393,4 +393,3 @@ This info may additionally conflict with the reality that your data is being JSO func (qr *QueryResult) Types() []string { return qr.types } - diff --git a/query_test.go b/query_test.go index 941f8e7..b670585 100644 --- a/query_test.go +++ b/query_test.go @@ -2,7 +2,7 @@ package gorqlite import "testing" -func TestQueryOne (t *testing.T) { +func TestQueryOne(t *testing.T) { var wr WriteResult var qr QueryResult var wResults []WriteResult @@ -11,59 +11,59 @@ func TestQueryOne (t *testing.T) { t.Logf("trying Open") conn, err := Open(testUrl()) - if ( err != nil ) { + if err != nil { t.Logf("--> FATAL") t.Fatal() } t.Logf("trying WriteOne DROP") wr, err = conn.WriteOne("DROP TABLE IF EXISTS " + testTableName()) - if ( err != nil ) { + if err != nil { t.Logf("--> FATAL") t.Fatal() } t.Logf("trying WriteOne CREATE") wr, err = conn.WriteOne("CREATE TABLE " + testTableName() + " (id integer, name text)") - if ( err != nil ) { + if err != nil { t.Logf("--> FATAL") t.Fatal() } t.Logf("trying Write INSERT") - s := make([]string,0) - s = append(s,"INSERT INTO " + testTableName() + " (id, name) VALUES ( 1, 'Romulan' )") - s = append(s,"INSERT INTO " + testTableName() + " (id, name) VALUES ( 2, 'Vulcan' )") - s = append(s,"INSERT INTO " + testTableName() + " (id, name) VALUES ( 3, 'Klingon' )") - s = append(s,"INSERT INTO " + testTableName() + " (id, name) VALUES ( 4, 'Ferengi' )") - s = append(s,"INSERT INTO " + testTableName() + " (id, name) VALUES ( 5, 'Cardassian' )") + s := make([]string, 0) + s = append(s, "INSERT INTO "+testTableName()+" (id, name) VALUES ( 1, 'Romulan' )") + s = append(s, "INSERT INTO "+testTableName()+" (id, name) VALUES ( 2, 'Vulcan' )") + s = append(s, "INSERT INTO "+testTableName()+" (id, name) VALUES ( 3, 'Klingon' )") + s = append(s, "INSERT INTO "+testTableName()+" (id, name) VALUES ( 4, 'Ferengi' )") + s = append(s, "INSERT INTO "+testTableName()+" (id, name) VALUES ( 5, 'Cardassian' )") wResults, err = conn.Write(s) - if ( err != nil ) { + if err != nil { t.Logf("--> FATAL") t.Fatal() } t.Logf("trying QueryOne") qr, err = conn.QueryOne("SELECT name FROM " + testTableName() + " WHERE id > 3") - if ( err != nil ) { + if err != nil { t.Logf("--> FAILED") t.Fail() } t.Logf("trying Next()") na := qr.Next() - if ( na != true ) { + if na != true { t.Logf("--> FAILED") t.Fail() } - + t.Logf("trying Map()") r, err := qr.Map() - if ( err != nil ) { + if err != nil { t.Logf("--> FAILED") t.Fail() } - if ( r["name"].(string) != "Ferengi" ) { + if r["name"].(string) != "Ferengi" { t.Logf("--> FAILED") t.Fail() } @@ -71,51 +71,51 @@ func TestQueryOne (t *testing.T) { t.Logf("trying Scan(), also float64->int64 in Scan()") var id int64 var name string - err = qr.Scan(&id,&name) - if ( err == nil ) { - t.Logf("--> FAILED (%s)",err.Error()) + err = qr.Scan(&id, &name) + if err == nil { + t.Logf("--> FAILED (%s)", err.Error()) t.Fail() } err = qr.Scan(&name) - if ( err != nil ) { - t.Logf("--> FAILED (%s)",err.Error()) + if err != nil { + t.Logf("--> FAILED (%s)", err.Error()) t.Fail() } - if ( name != "Ferengi" ) { - t.Logf("--> FAILED, name should be 'Ferengi' but it's '%s'",name) + if name != "Ferengi" { + t.Logf("--> FAILED, name should be 'Ferengi' but it's '%s'", name) t.Fail() } qr.Next() err = qr.Scan(&name) - if ( name != "Cardassian" ) { + if name != "Cardassian" { t.Logf("--> FAILED") t.Fail() } t.Logf("trying WriteOne DROP") wr, err = conn.WriteOne("DROP TABLE IF EXISTS " + testTableName() + "") - if ( err != nil ) { + if err != nil { t.Logf("--> FAILED") t.Fail() } - + t.Logf("trying Close") conn.Close() t.Logf("trying WriteOne after Close") wr, err = conn.WriteOne("DROP TABLE IF EXISTS " + testTableName() + "") - if ( err == nil ) { + if err == nil { t.Logf("--> FAILED") t.Fail() } _ = wr t.Logf("trying Write after Close") - t1 := make([]string,0) - t1 = append(t1,"DROP TABLE IF EXISTS " + testTableName() + "") - t1 = append(t1,"DROP TABLE IF EXISTS " + testTableName() + "") + t1 := make([]string, 0) + t1 = append(t1, "DROP TABLE IF EXISTS "+testTableName()+"") + t1 = append(t1, "DROP TABLE IF EXISTS "+testTableName()+"") wResults, err = conn.Write(t1) - if ( err == nil ) { + if err == nil { t.Logf("--> FAILED") t.Fail() } @@ -123,24 +123,22 @@ func TestQueryOne (t *testing.T) { t.Logf("trying QueryOne after Close") qr, err = conn.QueryOne("SELECT id FROM " + testTableName() + "") - if ( err == nil ) { + if err == nil { t.Logf("--> FAILED") t.Fail() } _ = qr t.Logf("trying Query after Close") - t2 := make([]string,0) - t2 = append(t2,"SELECT id FROM " + testTableName() + "") - t2 = append(t2,"SELECT name FROM " + testTableName() + "") - t2 = append(t2,"SELECT id,name FROM " + testTableName() + "") + t2 := make([]string, 0) + t2 = append(t2, "SELECT id FROM "+testTableName()+"") + t2 = append(t2, "SELECT name FROM "+testTableName()+"") + t2 = append(t2, "SELECT id,name FROM "+testTableName()+"") qResults, err = conn.Query(t2) - if ( err == nil ) { + if err == nil { t.Logf("--> FAILED") t.Fail() } _ = qResults - } - diff --git a/util_test.go b/util_test.go index f28caba..2cdfbb6 100644 --- a/util_test.go +++ b/util_test.go @@ -8,7 +8,7 @@ import "os" func testUrl() string { url := os.Getenv("GORQLITE_TEST_URL") - if ( url == "" ) { + if url == "" { url = "http://" } return url @@ -16,10 +16,8 @@ func testUrl() string { func testTableName() string { tableName := os.Getenv("GORQLITE_TEST_TABLE") - if ( tableName == "" ) { + if tableName == "" { tableName = "gorqlite_test" } return tableName } - - diff --git a/write.go b/write.go index 724a25e..0d7800b 100644 --- a/write.go +++ b/write.go @@ -1,7 +1,7 @@ package gorqlite /* - this file has + this file has Write() WriteResult and its methods */ @@ -58,15 +58,15 @@ method. */ func (conn *Connection) WriteOne(sqlStatement string) (wr WriteResult, err error) { - if ( conn.hasBeenClosed) { + if conn.hasBeenClosed { wr.Err = errClosed return wr, errClosed - } - sqlStatements := make([]string,0) - sqlStatements = append(sqlStatements,sqlStatement) - wra , err := conn.Write(sqlStatements) + } + sqlStatements := make([]string, 0) + sqlStatements = append(sqlStatements, sqlStatement) + wra, err := conn.Write(sqlStatements) return wra[0], err -} +} /* Write() is used to perform DDL/DML in the database. ALTER, CREATE, DELETE, DROP, INSERT, UPDATE, etc. all go through Write(). @@ -78,34 +78,34 @@ All statements are executed as a single transaction. Write() returns an error if one is encountered during its operation. If it's something like a call to the rqlite API, then it'll return that error. If one statement out of several has an error, it will return a generic "there were %d statement errors" and you'll have to look at the individual statement's Err for more info. */ func (conn *Connection) Write(sqlStatements []string) (results []WriteResult, err error) { - results = make([]WriteResult,0) + results = make([]WriteResult, 0) - if ( conn.hasBeenClosed) { + if conn.hasBeenClosed { var errResult WriteResult errResult.Err = errClosed - results = append(results,errResult) + results = append(results, errResult) return results, errClosed - } + } - trace("%s: Write() for %d statements",conn.ID,len(sqlStatements)) + trace("%s: Write() for %d statements", conn.ID, len(sqlStatements)) - response, err := conn.rqliteApiPost(api_WRITE,sqlStatements) - if ( err != nil ) { - trace("%s: rqliteApiCall() ERROR: %s",conn.ID,err.Error()) + response, err := conn.rqliteApiPost(api_WRITE, sqlStatements) + if err != nil { + trace("%s: rqliteApiCall() ERROR: %s", conn.ID, err.Error()) var errResult WriteResult errResult.Err = err - results = append(results,errResult) + results = append(results, errResult) return results, err } - trace("%s: rqliteApiCall() OK",conn.ID) + trace("%s: rqliteApiCall() OK", conn.ID) var sections map[string]interface{} - err = json.Unmarshal(response,§ions) - if ( err != nil ) { - trace("%s: json.Unmarshal() ERROR: %s",conn.ID,err.Error()) + err = json.Unmarshal(response, §ions) + if err != nil { + trace("%s: json.Unmarshal() ERROR: %s", conn.ID, err.Error()) var errResult WriteResult errResult.Err = err - results = append(results,errResult) + results = append(results, errResult) return results, err } @@ -115,44 +115,44 @@ func (conn *Connection) Write(sqlStatements []string) (results []WriteResult, er */ resultsArray := sections["results"].([]interface{}) - trace("%s: I have %d result(s) to parse",conn.ID,len(resultsArray)) + trace("%s: I have %d result(s) to parse", conn.ID, len(resultsArray)) numStatementErrors := 0 for n, k := range resultsArray { - trace("%s: starting on result %d",conn.ID,n) + trace("%s: starting on result %d", conn.ID, n) thisResult := k.(map[string]interface{}) var thisWR WriteResult - thisWR.conn = conn + thisWR.conn = conn // did we get an error? _, ok := thisResult["error"] if ok { - trace("%s: have an error on this result: %s",conn.ID,thisResult["error"].(string)) + trace("%s: have an error on this result: %s", conn.ID, thisResult["error"].(string)) thisWR.Err = errors.New(thisResult["error"].(string)) - results = append(results,thisWR) + results = append(results, thisWR) numStatementErrors += 1 continue } _, ok = thisResult["last_insert_id"] - if ok { + if ok { thisWR.LastInsertID = int64(thisResult["last_insert_id"].(float64)) } _, ok = thisResult["rows_affected"] // could be zero for a CREATE - if ok { + if ok { thisWR.RowsAffected = int64(thisResult["rows_affected"].(float64)) } thisWR.Timing = thisResult["time"].(float64) - trace("%s: this result (LII,RA,T): %d %d %f",conn.ID,thisWR.LastInsertID,thisWR.RowsAffected,thisWR.Timing) - results = append(results,thisWR) + trace("%s: this result (LII,RA,T): %d %d %f", conn.ID, thisWR.LastInsertID, thisWR.RowsAffected, thisWR.Timing) + results = append(results, thisWR) } - trace("%s: finished parsing, returning %d results",conn.ID,len(results)) + trace("%s: finished parsing, returning %d results", conn.ID, len(results)) - if ( numStatementErrors > 0 ) { - return results, errors.New(fmt.Sprintf("there were %d statement errors",numStatementErrors)) + if numStatementErrors > 0 { + return results, errors.New(fmt.Sprintf("there were %d statement errors", numStatementErrors)) } else { return results, nil } @@ -170,10 +170,9 @@ A WriteResult holds the result of a single statement sent to Write(). Write() returns an array of WriteResult vars, while WriteOne() returns a single WriteResult. */ type WriteResult struct { - Err error // don't trust the rest if this isn't nil - Timing float64 + Err error // don't trust the rest if this isn't nil + Timing float64 RowsAffected int64 // affected by the change LastInsertID int64 // if relevant, otherwise zero value - conn *Connection + conn *Connection } - diff --git a/write_test.go b/write_test.go index 6f611d1..1adb63d 100644 --- a/write_test.go +++ b/write_test.go @@ -1,108 +1,108 @@ package gorqlite import "testing" + // import "os" -func TestWriteOne (t *testing.T) { +func TestWriteOne(t *testing.T) { var wr WriteResult var err error t.Logf("trying Open") conn, err := Open(testUrl()) - if ( err != nil ) { + if err != nil { t.Logf("--> FATAL") - t.Fatal(err) + t.Fatal(err) } t.Logf("trying WriteOne DROP") wr, err = conn.WriteOne("DROP TABLE IF EXISTS " + testTableName() + "") - if ( err != nil ) { + if err != nil { t.Logf("--> FAILED") t.Fail() } t.Logf("trying WriteOne CTHULHU (should fail, bad SQL)") wr, err = conn.WriteOne("CTHULHU") - if ( err == nil ) { + if err == nil { t.Logf("--> FAILED") t.Fail() } t.Logf("trying WriteOne CREATE") wr, err = conn.WriteOne("CREATE TABLE " + testTableName() + " (id integer, name text)") - if ( err != nil ) { + if err != nil { t.Logf("--> FAILED") t.Fail() } t.Logf("trying WriteOne INSERT") wr, err = conn.WriteOne("INSERT INTO " + testTableName() + " (id, name) VALUES ( 1, 'aaa bbb ccc' )") - if ( err != nil ) { + if err != nil { t.Logf("--> FAILED") t.Fail() } t.Logf("checking WriteOne RowsAffected") - if ( wr.RowsAffected != 1 ) { + if wr.RowsAffected != 1 { t.Logf("--> FAILED") t.Fail() } t.Logf("trying WriteOne DROP") wr, err = conn.WriteOne("DROP TABLE IF EXISTS " + testTableName() + "") - if ( err != nil ) { + if err != nil { t.Logf("--> FAILED") t.Fail() } - + } -func TestWrite (t *testing.T) { +func TestWrite(t *testing.T) { var results []WriteResult var err error var s []string t.Logf("trying Open") conn, err := Open(testUrl()) - if ( err != nil ) { + if err != nil { t.Logf("--> FATAL") - t.Fatal(err) + t.Fatal(err) } t.Logf("trying Write DROP & CREATE") - s = make([]string,0) - s = append(s, "DROP TABLE IF EXISTS " + testTableName() + "") - s = append(s, "CREATE TABLE " + testTableName() + " (id integer, name text)") + s = make([]string, 0) + s = append(s, "DROP TABLE IF EXISTS "+testTableName()+"") + s = append(s, "CREATE TABLE "+testTableName()+" (id integer, name text)") results, err = conn.Write(s) - if ( err != nil ) { + if err != nil { t.Logf("--> FAILED") t.Fail() } t.Logf("trying Write INSERT") - s = make([]string,0) - s = append (s, "INSERT INTO " + testTableName() + " (id, name) VALUES ( 1, 'aaa bbb ccc' )") - s = append (s, "INSERT INTO " + testTableName() + " (id, name) VALUES ( 2, 'ddd eee fff' )") - s = append (s, "INSERT INTO " + testTableName() + " (id, name) VALUES ( 3, 'ggg hhh iii' )") - s = append (s, "INSERT INTO " + testTableName() + " (id, name) VALUES ( 4, 'jjj kkk lll' )") + s = make([]string, 0) + s = append(s, "INSERT INTO "+testTableName()+" (id, name) VALUES ( 1, 'aaa bbb ccc' )") + s = append(s, "INSERT INTO "+testTableName()+" (id, name) VALUES ( 2, 'ddd eee fff' )") + s = append(s, "INSERT INTO "+testTableName()+" (id, name) VALUES ( 3, 'ggg hhh iii' )") + s = append(s, "INSERT INTO "+testTableName()+" (id, name) VALUES ( 4, 'jjj kkk lll' )") results, err = conn.Write(s) - if ( err != nil ) { + if err != nil { t.Logf("--> FAILED") t.Fail() } - if ( len(results) != 4 ) { + if len(results) != 4 { t.Logf("--> FAILED") t.Fail() } - - t.Logf("trying Write DROP") - s = make([]string,0) - s = append(s, "DROP TABLE IF EXISTS " + testTableName() + "") - results, err = conn.Write(s) - if ( err != nil ) { - t.Logf("--> FAILED") - t.Fail() - } - -} + t.Logf("trying Write DROP") + s = make([]string, 0) + s = append(s, "DROP TABLE IF EXISTS "+testTableName()+"") + results, err = conn.Write(s) + if err != nil { + t.Logf("--> FAILED") + t.Fail() + } + +}