Implemented the rest of the methods except for GetKillSwitchStatus

Change-Id: Ia5b1a1c44c2e52653b9845ecc9557f525e6d41b1
diff --git a/internal/db/features.go b/internal/db/features.go
index 4a263b3..5b68228 100644
--- a/internal/db/features.go
+++ b/internal/db/features.go
@@ -8,6 +8,18 @@
 	pb "gomodules.avm99963.com/twpt-server/api_proto"
 )
 
+func GetFeatureById(db *sql.DB, ctx context.Context, id int32) (*pb.Feature, error) {
+	query := db.QueryRowContext(ctx, "SELECT feat_id, codename, feat_type FROM Feature WHERE feat_id = ?", id)
+	var f pb.Feature
+	if err := query.Scan(&f.Id, &f.Codename, &f.Type); err != nil {
+		if err == sql.ErrNoRows {
+			return nil, nil
+		}
+		return nil, fmt.Errorf("Error while querying feature by codename: %v.", err)
+	}
+	return &f, nil
+}
+
 func GetFeatureByCodename(db *sql.DB, ctx context.Context, codename string) (*pb.Feature, error) {
 	query := db.QueryRowContext(ctx, "SELECT feat_id, codename, feat_type FROM Feature WHERE codename = ?", codename)
 	var f pb.Feature
@@ -29,7 +41,7 @@
     rows, err = db.QueryContext(ctx, "SELECT feat_id, codename, feat_type FROM Feature WHERE feat_type <> ?", pb.Feature_TYPE_DEPRECATED)
 	}
 	if err != nil {
-		return nil, fmt.Errorf("ListFeatures: ", err)
+		return nil, fmt.Errorf("ListFeatures: %v", err)
 	}
 	defer rows.Close()
 
@@ -37,12 +49,12 @@
 	for rows.Next() {
 		var f pb.Feature
 		if err := rows.Scan(&f.Id, &f.Codename, &f.Type); err != nil {
-			return nil, fmt.Errorf("ListFeatures: ", err)
+			return nil, fmt.Errorf("ListFeatures: %v", err)
 		}
 		features = append(features, &f)
 	}
 	if err := rows.Err(); err != nil {
-		return nil, fmt.Errorf("ListFeatures: ", err)
+		return nil, fmt.Errorf("ListFeatures: %v", err)
 	}
 	return features, nil
 }