mirror of
https://github.com/goharbor/harbor.git
synced 2024-12-20 23:57:42 +01:00
Merge branch 'master' into fix_issues_for_jobservice
This commit is contained in:
commit
8e734407c0
15
src/Gopkg.lock
generated
15
src/Gopkg.lock
generated
@ -365,14 +365,6 @@
|
|||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "b2004221932bd6b13167ef654c81cffac36f7537"
|
revision = "b2004221932bd6b13167ef654c81cffac36f7537"
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
digest = "1:ee0845ea64262e3d1a6e2eab768fcb2008a0c8e571b7a3bebea554a1c031aeeb"
|
|
||||||
name = "github.com/mattn/go-sqlite3"
|
|
||||||
packages = ["."]
|
|
||||||
pruneopts = "UT"
|
|
||||||
revision = "6c771bb9887719704b210e87e934f08be014bdb1"
|
|
||||||
version = "v1.6.0"
|
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:5113b1edf6e2f370f9ce6101e7b5a86c3e8decd108067e34b762ae91e42964ee"
|
digest = "1:5113b1edf6e2f370f9ce6101e7b5a86c3e8decd108067e34b762ae91e42964ee"
|
||||||
name = "github.com/miekg/pkcs11"
|
name = "github.com/miekg/pkcs11"
|
||||||
@ -405,12 +397,12 @@
|
|||||||
version = "v1.0.0-rc0"
|
version = "v1.0.0-rc0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:40e195917a951a8bf867cd05de2a46aaf1806c50cf92eebf4c16f78cd196f747"
|
digest = "1:cf31692c14422fa27c83a05292eb5cbe0fb2775972e8f1f8446a71549bd8980b"
|
||||||
name = "github.com/pkg/errors"
|
name = "github.com/pkg/errors"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "645ef00459ed84a119197bfb8d8205042c6df63d"
|
revision = "ba968bfe8b2f7e042a574c888954fccecfa385b4"
|
||||||
version = "v0.8.0"
|
version = "v0.8.1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:0028cb19b2e4c3112225cd871870f2d9cf49b9b4276531f03438a88e94be86fe"
|
digest = "1:0028cb19b2e4c3112225cd871870f2d9cf49b9b4276531f03438a88e94be86fe"
|
||||||
@ -753,7 +745,6 @@
|
|||||||
"github.com/gorilla/handlers",
|
"github.com/gorilla/handlers",
|
||||||
"github.com/gorilla/mux",
|
"github.com/gorilla/mux",
|
||||||
"github.com/lib/pq",
|
"github.com/lib/pq",
|
||||||
"github.com/mattn/go-sqlite3",
|
|
||||||
"github.com/opencontainers/go-digest",
|
"github.com/opencontainers/go-digest",
|
||||||
"github.com/pkg/errors",
|
"github.com/pkg/errors",
|
||||||
"github.com/robfig/cron",
|
"github.com/robfig/cron",
|
||||||
|
@ -127,3 +127,7 @@ ignored = ["github.com/goharbor/harbor/tests*"]
|
|||||||
[[constraint]]
|
[[constraint]]
|
||||||
name = "github.com/bmatcuk/doublestar"
|
name = "github.com/bmatcuk/doublestar"
|
||||||
version = "1.1.1"
|
version = "1.1.1"
|
||||||
|
|
||||||
|
[[constraint]]
|
||||||
|
name = "github.com/pkg/errors"
|
||||||
|
version = "=0.8.1"
|
||||||
|
@ -43,19 +43,9 @@ type Session struct {
|
|||||||
ldapConn *goldap.Conn
|
ldapConn *goldap.Conn
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadSystemLdapConfig - load LDAP configure from adminserver
|
// LoadSystemLdapConfig - load LDAP configure
|
||||||
func LoadSystemLdapConfig() (*Session, error) {
|
func LoadSystemLdapConfig() (*Session, error) {
|
||||||
|
|
||||||
authMode, err := config.AuthMode()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("can't load auth mode from system, error: %v", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if authMode != "ldap_auth" {
|
|
||||||
return nil, fmt.Errorf("system auth_mode isn't ldap_auth, please check configuration")
|
|
||||||
}
|
|
||||||
|
|
||||||
ldapConf, err := config.LDAPConf()
|
ldapConf, err := config.LDAPConf()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -158,14 +148,8 @@ func ConnectionTestWithConfig(ldapConfig models.LdapConf) error {
|
|||||||
// ConnectionTestWithAllConfig - test ldap session connection, out of the scope of normal session create/close
|
// ConnectionTestWithAllConfig - test ldap session connection, out of the scope of normal session create/close
|
||||||
func ConnectionTestWithAllConfig(ldapConfig models.LdapConf, ldapGroupConfig models.LdapGroupConf) error {
|
func ConnectionTestWithAllConfig(ldapConfig models.LdapConf, ldapGroupConfig models.LdapGroupConf) error {
|
||||||
|
|
||||||
authMode, err := config.AuthMode()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Connection test failed %v", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// If no password present, use the system default password
|
// If no password present, use the system default password
|
||||||
if ldapConfig.LdapSearchPassword == "" && authMode == "ldap_auth" {
|
if ldapConfig.LdapSearchPassword == "" {
|
||||||
|
|
||||||
session, err := LoadSystemLdapConfig()
|
session, err := LoadSystemLdapConfig()
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ var insecureTransport = &http.Transport{
|
|||||||
|
|
||||||
// Token wraps the attributes of a oauth2 token plus the attribute of ID token
|
// Token wraps the attributes of a oauth2 token plus the attribute of ID token
|
||||||
type Token struct {
|
type Token struct {
|
||||||
*oauth2.Token
|
oauth2.Token
|
||||||
IDToken string `json:"id_token"`
|
IDToken string `json:"id_token"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,7 +167,7 @@ func ExchangeToken(ctx context.Context, code string) (*Token, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &Token{Token: oauthToken, IDToken: oauthToken.Extra("id_token").(string)}, nil
|
return &Token{Token: *oauthToken, IDToken: oauthToken.Extra("id_token").(string)}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// VerifyToken verifies the ID token based on the OIDC settings
|
// VerifyToken verifies the ID token based on the OIDC settings
|
||||||
@ -203,10 +203,10 @@ func RefreshToken(ctx context.Context, token *Token) (*Token, error) {
|
|||||||
}
|
}
|
||||||
setting := provider.setting.Load().(models.OIDCSetting)
|
setting := provider.setting.Load().(models.OIDCSetting)
|
||||||
ctx = clientCtx(ctx, setting.VerifyCert)
|
ctx = clientCtx(ctx, setting.VerifyCert)
|
||||||
ts := oauth.TokenSource(ctx, token.Token)
|
ts := oauth.TokenSource(ctx, &token.Token)
|
||||||
t, err := ts.Token()
|
t, err := ts.Token()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &Token{Token: t, IDToken: t.Extra("id_token").(string)}, nil
|
return &Token{Token: *t, IDToken: t.Extra("id_token").(string)}, nil
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/goharbor/harbor/src/common/dao"
|
"github.com/goharbor/harbor/src/common/dao"
|
||||||
|
"github.com/goharbor/harbor/src/common/models"
|
||||||
"github.com/goharbor/harbor/src/common/utils"
|
"github.com/goharbor/harbor/src/common/utils"
|
||||||
"github.com/goharbor/harbor/src/common/utils/log"
|
"github.com/goharbor/harbor/src/common/utils/log"
|
||||||
"github.com/goharbor/harbor/src/core/config"
|
"github.com/goharbor/harbor/src/core/config"
|
||||||
@ -28,12 +29,12 @@ func verifyError(err error) error {
|
|||||||
|
|
||||||
// SecretManager is the interface for store and verify the secret
|
// SecretManager is the interface for store and verify the secret
|
||||||
type SecretManager interface {
|
type SecretManager interface {
|
||||||
// SetSecret sets the secret and token based on the ID of the user, when setting the secret the user has to be
|
|
||||||
// onboarded to Harbor DB.
|
|
||||||
SetSecret(userID int, secret string, token *Token) error
|
|
||||||
// VerifySecret verifies the secret and the token associated with it, it refreshes the token in the DB if it's
|
// VerifySecret verifies the secret and the token associated with it, it refreshes the token in the DB if it's
|
||||||
// refreshed during the verification
|
// refreshed during the verification
|
||||||
VerifySecret(ctx context.Context, userID int, secret string) error
|
VerifySecret(ctx context.Context, userID int, secret string) error
|
||||||
|
// VerifyToken verifies the token in the model from parm,
|
||||||
|
// and refreshes the token in the DB if it's refreshed during the verification.
|
||||||
|
VerifyToken(ctx context.Context, user *models.OIDCUser) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type defaultManager struct {
|
type defaultManager struct {
|
||||||
@ -58,25 +59,6 @@ func (dm *defaultManager) getEncryptKey() (string, error) {
|
|||||||
return dm.key, nil
|
return dm.key, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetSecret sets the secret and token based on the ID of the user, when setting the secret the user has to be
|
|
||||||
// onboarded to Harbor DB.
|
|
||||||
func (dm *defaultManager) SetSecret(userID int, secret string, token *Token) error {
|
|
||||||
key, err := dm.getEncryptKey()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to load the key for encryption/decryption: %v", err)
|
|
||||||
}
|
|
||||||
oidcUser, err := dao.GetOIDCUserByUserID(userID)
|
|
||||||
if oidcUser == nil {
|
|
||||||
return fmt.Errorf("failed to get oidc user info, error: %v", err)
|
|
||||||
}
|
|
||||||
encSecret, _ := utils.ReversibleEncrypt(secret, key)
|
|
||||||
tb, _ := json.Marshal(token)
|
|
||||||
encToken, _ := utils.ReversibleEncrypt(string(tb), key)
|
|
||||||
oidcUser.Secret = encSecret
|
|
||||||
oidcUser.Token = encToken
|
|
||||||
return dao.UpdateOIDCUser(oidcUser)
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifySecret verifies the secret and the token associated with it, it tries to update the token in the DB if it's
|
// VerifySecret verifies the secret and the token associated with it, it tries to update the token in the DB if it's
|
||||||
// refreshed during the verification
|
// refreshed during the verification
|
||||||
func (dm *defaultManager) VerifySecret(ctx context.Context, userID int, secret string) error {
|
func (dm *defaultManager) VerifySecret(ctx context.Context, userID int, secret string) error {
|
||||||
@ -98,7 +80,20 @@ func (dm *defaultManager) VerifySecret(ctx context.Context, userID int, secret s
|
|||||||
if secret != plainSecret {
|
if secret != plainSecret {
|
||||||
return verifyError(errors.New("secret mismatch"))
|
return verifyError(errors.New("secret mismatch"))
|
||||||
}
|
}
|
||||||
tokenStr, err := utils.ReversibleDecrypt(oidcUser.Token, key)
|
return dm.VerifyToken(ctx, oidcUser)
|
||||||
|
}
|
||||||
|
|
||||||
|
// VerifyToken verifies the token in the model from parm in this implementation it will try to refresh the token
|
||||||
|
// if it's expired, if the refresh is successful it will persist the token and consider the verification successful.
|
||||||
|
func (dm *defaultManager) VerifyToken(ctx context.Context, user *models.OIDCUser) error {
|
||||||
|
if user == nil {
|
||||||
|
return verifyError(fmt.Errorf("input user is nil"))
|
||||||
|
}
|
||||||
|
key, err := dm.getEncryptKey()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to load the key for encryption/decryption: %v", err)
|
||||||
|
}
|
||||||
|
tokenStr, err := utils.ReversibleDecrypt(user.Token, key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return verifyError(err)
|
return verifyError(err)
|
||||||
}
|
}
|
||||||
@ -116,15 +111,25 @@ func (dm *defaultManager) VerifySecret(ctx context.Context, userID int, secret s
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return verifyError(err)
|
return verifyError(err)
|
||||||
}
|
}
|
||||||
err = dm.SetSecret(oidcUser.UserID, secret, t)
|
tb, err := json.Marshal(t)
|
||||||
|
if err != nil {
|
||||||
|
log.Warningf("Failed to encode the refreshed token, error: %v", err)
|
||||||
|
}
|
||||||
|
encToken, _ := utils.ReversibleEncrypt(string(tb), key)
|
||||||
|
user.Token = encToken
|
||||||
|
err = dao.UpdateOIDCUser(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warningf("Failed to update the token in DB: %v, ignore this error.", err)
|
log.Warningf("Failed to update the token in DB: %v, ignore this error.", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// VerifySecret verifies the secret and the token associated with it, it tries to update the token in the DB if it's
|
// VerifySecret calls the manager to verify the secret.
|
||||||
// refreshed during the verification
|
|
||||||
func VerifySecret(ctx context.Context, userID int, secret string) error {
|
func VerifySecret(ctx context.Context, userID int, secret string) error {
|
||||||
return m.VerifySecret(ctx, userID, secret)
|
return m.VerifySecret(ctx, userID, secret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VerifyAndPersistToken calls the manager to verify token and persist it if it's refreshed.
|
||||||
|
func VerifyAndPersistToken(ctx context.Context, user *models.OIDCUser) error {
|
||||||
|
return m.VerifyToken(ctx, user)
|
||||||
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
package oidc
|
package oidc
|
||||||
|
|
||||||
import "context"
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/goharbor/harbor/src/common/models"
|
||||||
|
)
|
||||||
import "errors"
|
import "errors"
|
||||||
|
|
||||||
// This is for testing only
|
// This is for testing only
|
||||||
@ -8,10 +11,6 @@ type fakeVerifier struct {
|
|||||||
secret string
|
secret string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fv *fakeVerifier) SetSecret(uid int, s string, t *Token) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (fv *fakeVerifier) VerifySecret(ctx context.Context, userID int, secret string) error {
|
func (fv *fakeVerifier) VerifySecret(ctx context.Context, userID int, secret string) error {
|
||||||
if secret != fv.secret {
|
if secret != fv.secret {
|
||||||
return verifyError(errors.New("mismatch"))
|
return verifyError(errors.New("mismatch"))
|
||||||
@ -19,6 +18,10 @@ func (fv *fakeVerifier) VerifySecret(ctx context.Context, userID int, secret str
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (fv *fakeVerifier) VerifyToken(ctx context.Context, u *models.OIDCUser) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// SetHardcodeVerifierForTest overwrite the default secret manager for testing.
|
// SetHardcodeVerifierForTest overwrite the default secret manager for testing.
|
||||||
// Be reminded this is for testing only.
|
// Be reminded this is for testing only.
|
||||||
func SetHardcodeVerifierForTest(s string) {
|
func SetHardcodeVerifierForTest(s string) {
|
||||||
|
@ -23,6 +23,9 @@ import (
|
|||||||
"github.com/goharbor/harbor/src/core/auth"
|
"github.com/goharbor/harbor/src/core/auth"
|
||||||
|
|
||||||
"errors"
|
"errors"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/goharbor/harbor/src/core/config"
|
||||||
goldap "gopkg.in/ldap.v2"
|
goldap "gopkg.in/ldap.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -52,6 +55,19 @@ func (l *LdapAPI) Prepare() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check the auth_mode except ping
|
||||||
|
if strings.EqualFold(l.Ctx.Request.RequestURI, "/api/ldap/ping") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
authMode, err := config.AuthMode()
|
||||||
|
if err != nil {
|
||||||
|
l.SendInternalServerError(fmt.Errorf("Can't load system configuration, error: %v", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if authMode != "ldap_auth" {
|
||||||
|
l.SendInternalServerError(fmt.Errorf("Can't load system configuration, error: %v", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
ldapCfg, err := ldapUtils.LoadSystemLdapConfig()
|
ldapCfg, err := ldapUtils.LoadSystemLdapConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.SendInternalServerError(fmt.Errorf("Can't load system configuration, error: %v", err))
|
l.SendInternalServerError(fmt.Errorf("Can't load system configuration, error: %v", err))
|
||||||
|
@ -147,14 +147,22 @@ func (t *RegistryAPI) Get() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Hide access secret
|
// Hide access secret
|
||||||
if r.Credential != nil && len(r.Credential.AccessSecret) != 0 {
|
hideAccessSecret(r.Credential)
|
||||||
r.Credential.AccessSecret = "*****"
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Data["json"] = r
|
t.Data["json"] = r
|
||||||
t.ServeJSON()
|
t.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hideAccessSecret(credential *model.Credential) {
|
||||||
|
if credential == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(credential.AccessSecret) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
credential.AccessSecret = "*****"
|
||||||
|
}
|
||||||
|
|
||||||
// List lists all registries that match a given registry name.
|
// List lists all registries that match a given registry name.
|
||||||
func (t *RegistryAPI) List() {
|
func (t *RegistryAPI) List() {
|
||||||
name := t.GetString("name")
|
name := t.GetString("name")
|
||||||
@ -170,9 +178,7 @@ func (t *RegistryAPI) List() {
|
|||||||
|
|
||||||
// Hide passwords
|
// Hide passwords
|
||||||
for _, r := range registries {
|
for _, r := range registries {
|
||||||
if r.Credential != nil && len(r.Credential.AccessSecret) != 0 {
|
hideAccessSecret(r.Credential)
|
||||||
r.Credential.AccessSecret = "*****"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Data["json"] = registries
|
t.Data["json"] = registries
|
||||||
|
@ -248,10 +248,10 @@ func populateRegistries(registryMgr registry.Manager, policy *model.Policy) erro
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if policy.SrcRegistry != nil {
|
if policy.SrcRegistry != nil {
|
||||||
policy.SrcRegistry.Credential = nil
|
hideAccessSecret(policy.SrcRegistry.Credential)
|
||||||
}
|
}
|
||||||
if policy.DestRegistry != nil {
|
if policy.DestRegistry != nil {
|
||||||
policy.DestRegistry.Credential = nil
|
hideAccessSecret(policy.DestRegistry.Credential)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -66,6 +66,8 @@ const (
|
|||||||
|
|
||||||
// PmKey is context value key for the project manager
|
// PmKey is context value key for the project manager
|
||||||
PmKey ContextValueKey = "harbor_project_manager"
|
PmKey ContextValueKey = "harbor_project_manager"
|
||||||
|
// AuthModeKey is context key for auth mode
|
||||||
|
AuthModeKey ContextValueKey = "harbor_auth_mode"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -110,6 +112,7 @@ func Init() {
|
|||||||
|
|
||||||
// standalone
|
// standalone
|
||||||
reqCtxModifiers = []ReqCtxModifier{
|
reqCtxModifiers = []ReqCtxModifier{
|
||||||
|
&configCtxModifier{},
|
||||||
&secretReqCtxModifier{config.SecretStore},
|
&secretReqCtxModifier{config.SecretStore},
|
||||||
&oidcCliReqCtxModifier{},
|
&oidcCliReqCtxModifier{},
|
||||||
&authProxyReqCtxModifier{},
|
&authProxyReqCtxModifier{},
|
||||||
@ -144,6 +147,20 @@ type ReqCtxModifier interface {
|
|||||||
Modify(*beegoctx.Context) bool
|
Modify(*beegoctx.Context) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// configCtxModifier populates to the configuration values to context, which are to be read by subsequent
|
||||||
|
// filters.
|
||||||
|
type configCtxModifier struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *configCtxModifier) Modify(ctx *beegoctx.Context) bool {
|
||||||
|
m, err := config.AuthMode()
|
||||||
|
if err != nil {
|
||||||
|
log.Warningf("Failed to get auth mode, err: %v", err)
|
||||||
|
}
|
||||||
|
addToReqContext(ctx.Request, AuthModeKey, m)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
type secretReqCtxModifier struct {
|
type secretReqCtxModifier struct {
|
||||||
store *secstore.Store
|
store *secstore.Store
|
||||||
}
|
}
|
||||||
@ -215,12 +232,7 @@ func (oc *oidcCliReqCtxModifier) Modify(ctx *beegoctx.Context) bool {
|
|||||||
log.Debug("OIDC CLI modifer only handles request by docker CLI or helm CLI")
|
log.Debug("OIDC CLI modifer only handles request by docker CLI or helm CLI")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
authMode, err := config.AuthMode()
|
if ctx.Request.Context().Value(AuthModeKey).(string) != common.OIDCAuth {
|
||||||
if err != nil {
|
|
||||||
log.Errorf("fail to get auth mode, %v", err)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if authMode != common.OIDCAuth {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
username, secret, ok := ctx.Request.BasicAuth()
|
username, secret, ok := ctx.Request.BasicAuth()
|
||||||
@ -251,12 +263,7 @@ func (oc *oidcCliReqCtxModifier) Modify(ctx *beegoctx.Context) bool {
|
|||||||
type authProxyReqCtxModifier struct{}
|
type authProxyReqCtxModifier struct{}
|
||||||
|
|
||||||
func (ap *authProxyReqCtxModifier) Modify(ctx *beegoctx.Context) bool {
|
func (ap *authProxyReqCtxModifier) Modify(ctx *beegoctx.Context) bool {
|
||||||
authMode, err := config.AuthMode()
|
if ctx.Request.Context().Value(AuthModeKey).(string) != common.HTTPAuth {
|
||||||
if err != nil {
|
|
||||||
log.Errorf("fail to get auth mode, %v", err)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if authMode != common.HTTPAuth {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -443,20 +450,31 @@ func (b *basicAuthReqCtxModifier) Modify(ctx *beegoctx.Context) bool {
|
|||||||
type sessionReqCtxModifier struct{}
|
type sessionReqCtxModifier struct{}
|
||||||
|
|
||||||
func (s *sessionReqCtxModifier) Modify(ctx *beegoctx.Context) bool {
|
func (s *sessionReqCtxModifier) Modify(ctx *beegoctx.Context) bool {
|
||||||
var user models.User
|
|
||||||
userInterface := ctx.Input.Session("user")
|
userInterface := ctx.Input.Session("user")
|
||||||
|
|
||||||
if userInterface == nil {
|
if userInterface == nil {
|
||||||
log.Debug("can not get user information from session")
|
log.Debug("can not get user information from session")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debug("got user information from session")
|
log.Debug("got user information from session")
|
||||||
user, ok := userInterface.(models.User)
|
user, ok := userInterface.(models.User)
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Info("can not get user information from session")
|
log.Info("can not get user information from session")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if ctx.Request.Context().Value(AuthModeKey).(string) == common.OIDCAuth {
|
||||||
|
ou, err := dao.GetOIDCUserByUserID(user.UserID)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Failed to get OIDC user info, error: %v", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if ou != nil { // If user does not have OIDC metadata, it means he is not onboarded via OIDC authn,
|
||||||
|
// so we can skip checking the token.
|
||||||
|
if err := oidc.VerifyAndPersistToken(ctx.Request.Context(), ou); err != nil {
|
||||||
|
log.Errorf("Failed to verify secret, error: %v", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
log.Debug("using local database project manager")
|
log.Debug("using local database project manager")
|
||||||
pm := config.GlobalProjectMgr
|
pm := config.GlobalProjectMgr
|
||||||
log.Debug("creating local database security context...")
|
log.Debug("creating local database security context...")
|
||||||
|
@ -101,6 +101,28 @@ func TestSecurityFilter(t *testing.T) {
|
|||||||
assert.NotNil(t, projectManager(ctx))
|
assert.NotNil(t, projectManager(ctx))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestConfigCtxModifier(t *testing.T) {
|
||||||
|
req, err := http.NewRequest(http.MethodGet,
|
||||||
|
"http://127.0.0.1/api/projects/", nil)
|
||||||
|
require.Nil(t, err)
|
||||||
|
conf := map[string]interface{}{
|
||||||
|
common.AUTHMode: common.OIDCAuth,
|
||||||
|
common.OIDCName: "test",
|
||||||
|
common.OIDCEndpoint: "https://accounts.google.com",
|
||||||
|
common.OIDCVerifyCert: "true",
|
||||||
|
common.OIDCScope: "openid, profile, offline_access",
|
||||||
|
common.OIDCCLientID: "client",
|
||||||
|
common.OIDCClientSecret: "secret",
|
||||||
|
common.ExtEndpoint: "https://harbor.test",
|
||||||
|
}
|
||||||
|
config.InitWithSettings(conf)
|
||||||
|
ctx, err := newContext(req)
|
||||||
|
m := &configCtxModifier{}
|
||||||
|
f := m.Modify(ctx)
|
||||||
|
assert.False(t, f)
|
||||||
|
assert.Equal(t, common.OIDCAuth, req.Context().Value(AuthModeKey).(string))
|
||||||
|
}
|
||||||
|
|
||||||
func TestSecretReqCtxModifier(t *testing.T) {
|
func TestSecretReqCtxModifier(t *testing.T) {
|
||||||
req, err := http.NewRequest(http.MethodGet,
|
req, err := http.NewRequest(http.MethodGet,
|
||||||
"http://127.0.0.1/api/projects/", nil)
|
"http://127.0.0.1/api/projects/", nil)
|
||||||
@ -145,6 +167,7 @@ func TestOIDCCliReqCtxModifier(t *testing.T) {
|
|||||||
assert.False(t, modifier.Modify(ctx1))
|
assert.False(t, modifier.Modify(ctx1))
|
||||||
req2, err := http.NewRequest(http.MethodGet, "http://127.0.0.1/service/token", nil)
|
req2, err := http.NewRequest(http.MethodGet, "http://127.0.0.1/service/token", nil)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
addToReqContext(req2, AuthModeKey, common.OIDCAuth)
|
||||||
ctx2, err := newContext(req2)
|
ctx2, err := newContext(req2)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
assert.False(t, modifier.Modify(ctx2))
|
assert.False(t, modifier.Modify(ctx2))
|
||||||
@ -161,6 +184,7 @@ func TestOIDCCliReqCtxModifier(t *testing.T) {
|
|||||||
req3, err := http.NewRequest(http.MethodGet, "http://127.0.0.1/service/token", nil)
|
req3, err := http.NewRequest(http.MethodGet, "http://127.0.0.1/service/token", nil)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
req3.SetBasicAuth(username, password)
|
req3.SetBasicAuth(username, password)
|
||||||
|
addToReqContext(req3, AuthModeKey, common.OIDCAuth)
|
||||||
ctx3, err := newContext(req3)
|
ctx3, err := newContext(req3)
|
||||||
assert.True(t, modifier.Modify(ctx3))
|
assert.True(t, modifier.Modify(ctx3))
|
||||||
o := dao.GetOrmer()
|
o := dao.GetOrmer()
|
||||||
@ -216,6 +240,7 @@ func TestAuthProxyReqCtxModifier(t *testing.T) {
|
|||||||
t.Fatalf("failed to create request: %v", req)
|
t.Fatalf("failed to create request: %v", req)
|
||||||
}
|
}
|
||||||
req.SetBasicAuth("tokenreview$administrator@vsphere.local", "reviEwt0k3n")
|
req.SetBasicAuth("tokenreview$administrator@vsphere.local", "reviEwt0k3n")
|
||||||
|
addToReqContext(req, AuthModeKey, common.HTTPAuth)
|
||||||
ctx, err := newContext(req)
|
ctx, err := newContext(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to crate context: %v", err)
|
t.Fatalf("failed to crate context: %v", err)
|
||||||
@ -236,6 +261,7 @@ func TestAuthProxyReqCtxModifier(t *testing.T) {
|
|||||||
t.Fatalf("failed to create request: %v", req)
|
t.Fatalf("failed to create request: %v", req)
|
||||||
}
|
}
|
||||||
req.SetBasicAuth("tokenreview$administrator@vsphere.local", "reviEwt0k3n")
|
req.SetBasicAuth("tokenreview$administrator@vsphere.local", "reviEwt0k3n")
|
||||||
|
addToReqContext(req, AuthModeKey, common.HTTPAuth)
|
||||||
ctx, err = newContext(req)
|
ctx, err = newContext(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to crate context: %v", err)
|
t.Fatalf("failed to crate context: %v", err)
|
||||||
@ -290,13 +316,8 @@ func TestSessionReqCtxModifier(t *testing.T) {
|
|||||||
t.Fatalf("failed to set session: %v", err)
|
t.Fatalf("failed to set session: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
req, err = http.NewRequest(http.MethodGet,
|
|
||||||
"http://127.0.0.1/api/projects/", nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to create request: %v", req)
|
|
||||||
}
|
|
||||||
addSessionIDToCookie(req, store.SessionID())
|
addSessionIDToCookie(req, store.SessionID())
|
||||||
|
addToReqContext(req, AuthModeKey, common.DBAuth)
|
||||||
ctx, err := newContext(req)
|
ctx, err := newContext(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to crate context: %v", err)
|
t.Fatalf("failed to crate context: %v", err)
|
||||||
@ -336,12 +357,11 @@ func TestSessionReqCtxModifierFailed(t *testing.T) {
|
|||||||
t.Fatalf("failed to create request: %v", req)
|
t.Fatalf("failed to create request: %v", req)
|
||||||
}
|
}
|
||||||
addSessionIDToCookie(req, store.SessionID())
|
addSessionIDToCookie(req, store.SessionID())
|
||||||
|
addToReqContext(req, AuthModeKey, common.DBAuth)
|
||||||
ctx, err := newContext(req)
|
ctx, err := newContext(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to crate context: %v", err)
|
t.Fatalf("failed to crate context: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
modifier := &sessionReqCtxModifier{}
|
modifier := &sessionReqCtxModifier{}
|
||||||
modified := modifier.Modify(ctx)
|
modified := modifier.Modify(ctx)
|
||||||
|
|
||||||
|
@ -32,6 +32,8 @@ import (
|
|||||||
// register the Native adapter
|
// register the Native adapter
|
||||||
"github.com/goharbor/harbor/src/jobservice/job"
|
"github.com/goharbor/harbor/src/jobservice/job"
|
||||||
_ "github.com/goharbor/harbor/src/replication/adapter/native"
|
_ "github.com/goharbor/harbor/src/replication/adapter/native"
|
||||||
|
// register the Huawei adapter
|
||||||
|
_ "github.com/goharbor/harbor/src/replication/adapter/huawei"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Replication implements the job interface
|
// Replication implements the job interface
|
||||||
|
@ -121,13 +121,13 @@
|
|||||||
<label for="ruleDeletion" class="clr-control-label">{{'REPLICATION.DELETE_REMOTE_IMAGES' | translate}}</label>
|
<label for="ruleDeletion" class="clr-control-label">{{'REPLICATION.DELETE_REMOTE_IMAGES' | translate}}</label>
|
||||||
</clr-checkbox-wrapper>
|
</clr-checkbox-wrapper>
|
||||||
</div>
|
</div>
|
||||||
<div class="rule-width">
|
<div class="clr-form-control rule-width">
|
||||||
<clr-checkbox-wrapper>
|
<clr-checkbox-wrapper>
|
||||||
<input type="checkbox" clrCheckbox [checked]="true" id="enablePolicy" formControlName="enabled" class="clr-checkbox">
|
<input type="checkbox" clrCheckbox [checked]="true" id="enablePolicy" formControlName="enabled" class="clr-checkbox">
|
||||||
<label for="enablePolicy" class="clr-control-label">{{'REPLICATION.ENABLED' | translate}}</label>
|
<label for="enablePolicy" class="clr-control-label">{{'REPLICATION.ENABLED' | translate}}</label>
|
||||||
</clr-checkbox-wrapper>
|
</clr-checkbox-wrapper>
|
||||||
</div>
|
</div>
|
||||||
<div class="rule-width">
|
<div class="clr-form-control rule-width">
|
||||||
<clr-checkbox-wrapper>
|
<clr-checkbox-wrapper>
|
||||||
<input type="checkbox" clrCheckbox [checked]="true" id="overridePolicy" formControlName="override" class="clr-checkbox">
|
<input type="checkbox" clrCheckbox [checked]="true" id="overridePolicy" formControlName="override" class="clr-checkbox">
|
||||||
<label for="overridePolicy" class="clr-control-label">{{'REPLICATION.OVERRIDE' | translate}}</label>
|
<label for="overridePolicy" class="clr-control-label">{{'REPLICATION.OVERRIDE' | translate}}</label>
|
||||||
|
@ -46,7 +46,7 @@ import { ErrorHandler } from "../error-handler/error-handler";
|
|||||||
import { CustomComparator } from "../utils";
|
import { CustomComparator } from "../utils";
|
||||||
import { operateChanges, OperateInfo, OperationState } from "../operation/operate";
|
import { operateChanges, OperateInfo, OperationState } from "../operation/operate";
|
||||||
import { OperationService } from "../operation/operation.service";
|
import { OperationService } from "../operation/operation.service";
|
||||||
|
const jobstatus = "InProgress";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "hbr-list-replication-rule",
|
selector: "hbr-list-replication-rule",
|
||||||
@ -204,9 +204,7 @@ export class ListReplicationRuleComponent implements OnInit, OnChanges {
|
|||||||
if (ruleData.length) {
|
if (ruleData.length) {
|
||||||
ruleData.forEach(job => {
|
ruleData.forEach(job => {
|
||||||
if (
|
if (
|
||||||
job.status === "pending" ||
|
job.status === jobstatus
|
||||||
job.status === "running" ||
|
|
||||||
job.status === "retrying"
|
|
||||||
) {
|
) {
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
@ -91,26 +91,19 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<clr-datagrid (clrDgRefresh)="clrLoadTasks($event)" [(clrDgSelected)]="selectedRow" [clrDgLoading]="loading">
|
<clr-datagrid [(clrDgSelected)]="selectedRow" [clrDgLoading]="loading">
|
||||||
<clr-dg-column>{{'REPLICATION.TASK_ID'| translate}}</clr-dg-column>
|
<clr-dg-column>{{'REPLICATION.TASK_ID'| translate}}</clr-dg-column>
|
||||||
<clr-dg-column [clrDgField]="'resource_type'">{{'REPLICATION.RESOURCE_TYPE'
|
<clr-dg-column [clrDgField]="'resource_type'" class="resource-width">{{'REPLICATION.RESOURCE_TYPE' | translate}}</clr-dg-column>
|
||||||
| translate}}</clr-dg-column>
|
<clr-dg-column [clrDgField]="'src_resource'">{{'REPLICATION.SOURCE' | translate}}</clr-dg-column>
|
||||||
<clr-dg-column [clrDgField]="'src_resource'">{{'REPLICATION.SOURCE' |
|
<clr-dg-column [clrDgField]="'dst_resource'">{{'REPLICATION.DESTINATION' | translate}}</clr-dg-column>
|
||||||
translate}}</clr-dg-column>
|
<clr-dg-column [clrDgField]="'operation'">{{'REPLICATION.OPERATION' | translate}}</clr-dg-column>
|
||||||
<clr-dg-column [clrDgField]="'dst_resource'">{{'REPLICATION.DESTINATION' |
|
<clr-dg-column [clrDgField]="'status'">{{'REPLICATION.STATUS' | translate}}</clr-dg-column>
|
||||||
translate}}</clr-dg-column>
|
<clr-dg-column [clrDgSortBy]="startTimeComparator">{{'REPLICATION.CREATION_TIME' | translate}}</clr-dg-column>
|
||||||
<clr-dg-column [clrDgField]="'operation'">{{'REPLICATION.OPERATION' |
|
<clr-dg-column [clrDgSortBy]="endTimeComparator">{{'REPLICATION.END_TIME' | translate}}</clr-dg-column>
|
||||||
translate}}</clr-dg-column>
|
|
||||||
<clr-dg-column [clrDgField]="'status'">{{'REPLICATION.STATUS' |
|
|
||||||
translate}}</clr-dg-column>
|
|
||||||
<clr-dg-column [clrDgSortBy]="startTimeComparator">{{'REPLICATION.CREATION_TIME'
|
|
||||||
| translate}}</clr-dg-column>
|
|
||||||
<clr-dg-column [clrDgSortBy]="endTimeComparator">{{'REPLICATION.END_TIME'
|
|
||||||
| translate}}</clr-dg-column>
|
|
||||||
<clr-dg-column>{{'REPLICATION.LOGS' | translate}}</clr-dg-column>
|
<clr-dg-column>{{'REPLICATION.LOGS' | translate}}</clr-dg-column>
|
||||||
<clr-dg-row *clrDgItems="let t of tasks">
|
<clr-dg-row *clrDgItems="let t of tasks">
|
||||||
<clr-dg-cell>{{t.id}}</clr-dg-cell>
|
<clr-dg-cell>{{t.id}}</clr-dg-cell>
|
||||||
<clr-dg-cell>{{t.resource_type}}</clr-dg-cell>
|
<clr-dg-cell class="resource-width">{{t.resource_type}}</clr-dg-cell>
|
||||||
<clr-dg-cell>{{t.src_resource}}</clr-dg-cell>
|
<clr-dg-cell>{{t.src_resource}}</clr-dg-cell>
|
||||||
<clr-dg-cell>{{t.dst_resource}}</clr-dg-cell>
|
<clr-dg-cell>{{t.dst_resource}}</clr-dg-cell>
|
||||||
<clr-dg-cell>{{t.operation}}</clr-dg-cell>
|
<clr-dg-cell>{{t.operation}}</clr-dg-cell>
|
||||||
@ -128,12 +121,8 @@
|
|||||||
</clr-dg-cell>
|
</clr-dg-cell>
|
||||||
</clr-dg-row>
|
</clr-dg-row>
|
||||||
<clr-dg-footer>
|
<clr-dg-footer>
|
||||||
<span *ngIf="pagination.totalItems">{{pagination.firstItem + 1}}
|
<span *ngIf="pagination.totalItems">{{pagination.firstItem + 1}} - {{pagination.lastItem +1 }} {{'REPLICATION.OF' | translate}} </span>{{pagination.totalItems }} {{'REPLICATION.ITEMS' | translate}}
|
||||||
-
|
<clr-dg-pagination #pagination [(clrDgPage)]="currentPage" [clrDgPageSize]="pageSize"></clr-dg-pagination>
|
||||||
{{pagination.lastItem +1 }} {{'ROBOT_ACCOUNT.OF' |
|
|
||||||
translate}} </span>
|
|
||||||
{{pagination.totalItems }} {{'ROBOT_ACCOUNT.ITEMS' | translate}}
|
|
||||||
<clr-dg-pagination #pagination [clrDgPageSize]="pageSize" [(clrDgPage)]="currentPage" [clrDgTotalItems]="totalCount"></clr-dg-pagination>
|
|
||||||
</clr-dg-footer>
|
</clr-dg-footer>
|
||||||
</clr-datagrid>
|
</clr-datagrid>
|
||||||
</div>
|
</div>
|
||||||
|
@ -105,6 +105,9 @@
|
|||||||
}
|
}
|
||||||
clr-datagrid {
|
clr-datagrid {
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
|
.resource-width {
|
||||||
|
width: 150px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,12 +20,9 @@ const taskStatus: any = {
|
|||||||
})
|
})
|
||||||
export class ReplicationTasksComponent implements OnInit, OnDestroy {
|
export class ReplicationTasksComponent implements OnInit, OnDestroy {
|
||||||
isOpenFilterTag: boolean;
|
isOpenFilterTag: boolean;
|
||||||
selectedRow: [];
|
|
||||||
currentPage: number = 1;
|
currentPage: number = 1;
|
||||||
currentPagePvt: number = 0;
|
selectedRow: [];
|
||||||
totalCount: number = 0;
|
|
||||||
pageSize: number = DEFAULT_PAGE_SIZE;
|
pageSize: number = DEFAULT_PAGE_SIZE;
|
||||||
currentState: State;
|
|
||||||
loading = true;
|
loading = true;
|
||||||
searchTask: string;
|
searchTask: string;
|
||||||
defaultFilter = "resource_type";
|
defaultFilter = "resource_type";
|
||||||
@ -53,6 +50,7 @@ export class ReplicationTasksComponent implements OnInit, OnDestroy {
|
|||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.searchTask = '';
|
this.searchTask = '';
|
||||||
this.getExecutionDetail();
|
this.getExecutionDetail();
|
||||||
|
this.clrLoadTasks();
|
||||||
}
|
}
|
||||||
|
|
||||||
getExecutionDetail(): void {
|
getExecutionDetail(): void {
|
||||||
@ -120,30 +118,16 @@ export class ReplicationTasksComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clrLoadTasks(state: State): void {
|
clrLoadTasks(): void {
|
||||||
if (!state || !state.page) {
|
this.loading = true;
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Keep it for future filter
|
|
||||||
this.currentState = state;
|
|
||||||
|
|
||||||
let pageNumber: number = calculatePage(state);
|
|
||||||
if (pageNumber !== this.currentPagePvt) {
|
|
||||||
// load data
|
|
||||||
let params: RequestQueryParams = new RequestQueryParams();
|
let params: RequestQueryParams = new RequestQueryParams();
|
||||||
params.set("page", '' + pageNumber);
|
|
||||||
params.set("page_size", '' + this.pageSize);
|
|
||||||
if (this.searchTask && this.searchTask !== "") {
|
if (this.searchTask && this.searchTask !== "") {
|
||||||
params.set(this.defaultFilter, this.searchTask);
|
params.set(this.defaultFilter, this.searchTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.loading = true;
|
|
||||||
this.replicationService.getReplicationTasks(this.executionId, params)
|
this.replicationService.getReplicationTasks(this.executionId, params)
|
||||||
.pipe(finalize(() => (this.loading = false)))
|
.pipe(finalize(() => (this.loading = false)))
|
||||||
.subscribe(res => {
|
.subscribe(res => {
|
||||||
this.totalCount = res.length;
|
|
||||||
this.tasks = res; // Keep the data
|
this.tasks = res; // Keep the data
|
||||||
this.taskItem = this.tasks.filter(tasks => tasks.resource_type !== "");
|
|
||||||
if (!this.timerDelay) {
|
if (!this.timerDelay) {
|
||||||
this.timerDelay = timer(10000, 10000).subscribe(() => {
|
this.timerDelay = timer(10000, 10000).subscribe(() => {
|
||||||
let count: number = 0;
|
let count: number = 0;
|
||||||
@ -157,31 +141,17 @@ export class ReplicationTasksComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
this.clrLoadTasks(this.currentState);
|
this.clrLoadTasks();
|
||||||
} else {
|
} else {
|
||||||
this.timerDelay.unsubscribe();
|
this.timerDelay.unsubscribe();
|
||||||
this.timerDelay = null;
|
this.timerDelay = null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.taskItem = doFiltering<ReplicationTasks>(this.taskItem, state);
|
|
||||||
|
|
||||||
this.taskItem = doSorting<ReplicationTasks>(this.taskItem, state);
|
|
||||||
|
|
||||||
this.currentPagePvt = pageNumber;
|
|
||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
this.errorHandler.error(error);
|
this.errorHandler.error(error);
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
|
|
||||||
this.taskItem = this.tasks.filter(tasks => tasks.resource_type !== "");
|
|
||||||
// Do customized filter
|
|
||||||
this.taskItem = doFiltering<ReplicationTasks>(this.taskItem, state);
|
|
||||||
|
|
||||||
// Do customized sorting
|
|
||||||
this.taskItem = doSorting<ReplicationTasks>(this.taskItem, state);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
onBack(): void {
|
onBack(): void {
|
||||||
this.router.navigate(["harbor", "replications"]);
|
this.router.navigate(["harbor", "replications"]);
|
||||||
@ -194,8 +164,8 @@ export class ReplicationTasksComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
// refresh icon
|
// refresh icon
|
||||||
refreshTasks(): void {
|
refreshTasks(): void {
|
||||||
this.searchTask = '';
|
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
|
this.currentPage = 1;
|
||||||
this.replicationService.getReplicationTasks(this.executionId)
|
this.replicationService.getReplicationTasks(this.executionId)
|
||||||
.subscribe(res => {
|
.subscribe(res => {
|
||||||
this.tasks = res;
|
this.tasks = res;
|
||||||
@ -213,23 +183,7 @@ export class ReplicationTasksComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
this.searchTask = value.trim();
|
this.searchTask = value.trim();
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
this.currentPage = 1;
|
this.clrLoadTasks();
|
||||||
if (this.currentPagePvt === 1) {
|
|
||||||
// Force reloading
|
|
||||||
let st: State = this.currentState;
|
|
||||||
if (!st) {
|
|
||||||
st = {
|
|
||||||
page: {}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
st.page.from = 0;
|
|
||||||
st.page.to = this.pageSize - 1;
|
|
||||||
st.page.size = this.pageSize;
|
|
||||||
|
|
||||||
this.currentPagePvt = 0;
|
|
||||||
|
|
||||||
this.clrLoadTasks(st);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
openFilter(isOpen: boolean): void {
|
openFilter(isOpen: boolean): void {
|
||||||
|
@ -94,14 +94,8 @@ func (a *adapter) PrepareForPush(resources []*model.Resource) error {
|
|||||||
if len(resource.Metadata.Repository.Name) == 0 {
|
if len(resource.Metadata.Repository.Name) == 0 {
|
||||||
return errors.New("the name of the namespace cannot be null")
|
return errors.New("the name of the namespace cannot be null")
|
||||||
}
|
}
|
||||||
namespace, _ := util.ParseRepository(resource.Metadata.Repository.Name)
|
paths := strings.Split(resource.Metadata.Repository.Name, "/")
|
||||||
// Docker Hub doesn't support the repository contains no "/"
|
namespace := paths[0]
|
||||||
// just skip here and the following task will fail
|
|
||||||
if len(namespace) == 0 {
|
|
||||||
log.Debug("the namespace is empty, skip")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
namespaces[namespace] = struct{}{}
|
namespaces[namespace] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,6 +106,7 @@ func (a *adapter) PrepareForPush(resources []*model.Resource) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("create namespace '%s' in DockerHub error: %v", namespace, err)
|
return fmt.Errorf("create namespace '%s' in DockerHub error: %v", namespace, err)
|
||||||
}
|
}
|
||||||
|
log.Debugf("namespace %s created", namespace)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -198,7 +193,6 @@ func (a *adapter) CreateNamespace(namespace *model.Namespace) error {
|
|||||||
// getNamespace get namespace from DockerHub, if the namespace not found, two nil would be returned.
|
// getNamespace get namespace from DockerHub, if the namespace not found, two nil would be returned.
|
||||||
func (a *adapter) getNamespace(namespace string) (*model.Namespace, error) {
|
func (a *adapter) getNamespace(namespace string) (*model.Namespace, error) {
|
||||||
resp, err := a.client.Do(http.MethodGet, getNamespacePath(namespace), nil)
|
resp, err := a.client.Do(http.MethodGet, getNamespacePath(namespace), nil)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -214,7 +208,7 @@ func (a *adapter) getNamespace(namespace string) (*model.Namespace, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if resp.StatusCode/100 != 2 {
|
if resp.StatusCode/100 != 2 {
|
||||||
log.Errorf("create namespace error: %d -- %s", resp.StatusCode, string(body))
|
log.Errorf("get namespace error: %d -- %s", resp.StatusCode, string(body))
|
||||||
return nil, fmt.Errorf("%d -- %s", resp.StatusCode, body)
|
return nil, fmt.Errorf("%d -- %s", resp.StatusCode, body)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -321,6 +315,32 @@ func (a *adapter) FetchImages(filters []*model.Filter) ([]*model.Resource, error
|
|||||||
return resources, nil
|
return resources, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteManifest ...
|
||||||
|
// Note: DockerHub only supports delete by tag
|
||||||
|
func (a *adapter) DeleteManifest(repository, reference string) error {
|
||||||
|
parts := strings.Split(repository, "/")
|
||||||
|
if len(parts) != 2 {
|
||||||
|
return fmt.Errorf("dockerhub only support repo in format <namespace>/<name>, but got: %s", repository)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := a.client.Do(http.MethodDelete, deleteTagPath(parts[0], parts[1], reference), nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.StatusCode/100 != 2 {
|
||||||
|
log.Errorf("Delete tag error: %d -- %s", resp.StatusCode, string(body))
|
||||||
|
return fmt.Errorf("%d -- %s", resp.StatusCode, string(body))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// getRepos gets a page of repos from DockerHub
|
// getRepos gets a page of repos from DockerHub
|
||||||
func (a *adapter) getRepos(namespace, name string, page, pageSize int) (*ReposResp, error) {
|
func (a *adapter) getRepos(namespace, name string, page, pageSize int) (*ReposResp, error) {
|
||||||
resp, err := a.client.Do(http.MethodGet, listReposPath(namespace, name, page, pageSize), nil)
|
resp, err := a.client.Do(http.MethodGet, listReposPath(namespace, name, page, pageSize), nil)
|
||||||
@ -336,7 +356,7 @@ func (a *adapter) getRepos(namespace, name string, page, pageSize int) (*ReposRe
|
|||||||
|
|
||||||
if resp.StatusCode/100 != 2 {
|
if resp.StatusCode/100 != 2 {
|
||||||
log.Errorf("list repos error: %d -- %s", resp.StatusCode, string(body))
|
log.Errorf("list repos error: %d -- %s", resp.StatusCode, string(body))
|
||||||
return nil, fmt.Errorf("%d -- %s", resp.StatusCode, body)
|
return nil, fmt.Errorf("%d -- %s", resp.StatusCode, string(body))
|
||||||
}
|
}
|
||||||
|
|
||||||
repos := &ReposResp{}
|
repos := &ReposResp{}
|
||||||
|
@ -97,20 +97,5 @@ func (c *Client) Do(method, path string, body io.Reader) (*http.Response, error)
|
|||||||
}
|
}
|
||||||
req.Header.Set("Authorization", fmt.Sprintf("JWT %s", c.token))
|
req.Header.Set("Authorization", fmt.Sprintf("JWT %s", c.token))
|
||||||
|
|
||||||
resp, err := c.client.Do(req)
|
return c.client.Do(req)
|
||||||
if err != nil {
|
|
||||||
log.Errorf("unexpected error: %v", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.StatusCode/100 != 2 {
|
|
||||||
b, err := ioutil.ReadAll(resp.Body)
|
|
||||||
defer resp.Body.Close()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("unexpected %d error from dockerhub: %s", resp.StatusCode, string(b))
|
|
||||||
}
|
|
||||||
return resp, nil
|
|
||||||
}
|
}
|
||||||
|
@ -28,3 +28,7 @@ func listReposPath(namespace, name string, page, pageSize int) string {
|
|||||||
func listTagsPath(namespace, repo string, page, pageSize int) string {
|
func listTagsPath(namespace, repo string, page, pageSize int) string {
|
||||||
return fmt.Sprintf("/v2/repositories/%s/%s/tags/?page=%d&page_size=%d", namespace, repo, page, pageSize)
|
return fmt.Sprintf("/v2/repositories/%s/%s/tags/?page=%d&page_size=%d", namespace, repo, page, pageSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func deleteTagPath(namespace, repo, tag string) string {
|
||||||
|
return fmt.Sprintf("/v2/repositories/%s/%s/tags/%s/", namespace, repo, tag)
|
||||||
|
}
|
||||||
|
@ -18,6 +18,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
common_http "github.com/goharbor/harbor/src/common/http"
|
common_http "github.com/goharbor/harbor/src/common/http"
|
||||||
"github.com/goharbor/harbor/src/common/http/modifier"
|
"github.com/goharbor/harbor/src/common/http/modifier"
|
||||||
@ -143,13 +144,8 @@ func (a *adapter) PrepareForPush(resources []*model.Resource) error {
|
|||||||
if len(resource.Metadata.Repository.Name) == 0 {
|
if len(resource.Metadata.Repository.Name) == 0 {
|
||||||
return errors.New("the name of the repository cannot be null")
|
return errors.New("the name of the repository cannot be null")
|
||||||
}
|
}
|
||||||
projectName, _ := util.ParseRepository(resource.Metadata.Repository.Name)
|
paths := strings.Split(resource.Metadata.Repository.Name, "/")
|
||||||
// harbor doesn't support the repository contains no "/"
|
projectName := paths[0]
|
||||||
// just skip here and the following task will fail
|
|
||||||
if len(projectName) == 0 {
|
|
||||||
log.Debug("the project name is empty, skip")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// TODO handle the public
|
// TODO handle the public
|
||||||
projects[projectName] = &project{
|
projects[projectName] = &project{
|
||||||
Name: projectName,
|
Name: projectName,
|
||||||
@ -164,12 +160,15 @@ func (a *adapter) PrepareForPush(resources []*model.Resource) error {
|
|||||||
Metadata: project.Metadata,
|
Metadata: project.Metadata,
|
||||||
}
|
}
|
||||||
err := a.client.Post(a.coreServiceURL+"/api/projects", pro)
|
err := a.client.Post(a.coreServiceURL+"/api/projects", pro)
|
||||||
|
if err != nil {
|
||||||
if httpErr, ok := err.(*common_http.Error); ok && httpErr.Code == http.StatusConflict {
|
if httpErr, ok := err.(*common_http.Error); ok && httpErr.Code == http.StatusConflict {
|
||||||
log.Debugf("got 409 when trying to create project %s", project.Name)
|
log.Debugf("got 409 when trying to create project %s", project.Name)
|
||||||
return nil
|
continue
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
log.Debugf("project %s created", project.Name)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
|
@ -10,11 +10,10 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/goharbor/harbor/src/replication/util"
|
|
||||||
|
|
||||||
"github.com/goharbor/harbor/src/common/utils/log"
|
"github.com/goharbor/harbor/src/common/utils/log"
|
||||||
"github.com/goharbor/harbor/src/replication/adapter"
|
adp "github.com/goharbor/harbor/src/replication/adapter"
|
||||||
"github.com/goharbor/harbor/src/replication/model"
|
"github.com/goharbor/harbor/src/replication/model"
|
||||||
|
"github.com/goharbor/harbor/src/replication/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -22,7 +21,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
err := adapter.RegisterFactory(huawei, AdapterFactory)
|
err := adp.RegisterFactory(model.RegistryTypeHuawei, AdapterFactory)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("failed to register factory for Huawei: %v", err)
|
log.Errorf("failed to register factory for Huawei: %v", err)
|
||||||
return
|
return
|
||||||
@ -31,12 +30,13 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Adapter is for images replications between harbor and Huawei image repository(SWR)
|
// Adapter is for images replications between harbor and Huawei image repository(SWR)
|
||||||
type Adapter struct {
|
type adapter struct {
|
||||||
Registry *model.Registry
|
*adp.DefaultImageRegistry
|
||||||
|
registry *model.Registry
|
||||||
}
|
}
|
||||||
|
|
||||||
// Info gets info about Huawei SWR
|
// Info gets info about Huawei SWR
|
||||||
func (adapter Adapter) Info() (*model.RegistryInfo, error) {
|
func (a *adapter) Info() (*model.RegistryInfo, error) {
|
||||||
registryInfo := model.RegistryInfo{
|
registryInfo := model.RegistryInfo{
|
||||||
Type: huawei,
|
Type: huawei,
|
||||||
Description: "Adapter for SWR -- The image registry of Huawei Cloud",
|
Description: "Adapter for SWR -- The image registry of Huawei Cloud",
|
||||||
@ -48,10 +48,10 @@ func (adapter Adapter) Info() (*model.RegistryInfo, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ListNamespaces lists namespaces from Huawei SWR with the provided query conditions.
|
// ListNamespaces lists namespaces from Huawei SWR with the provided query conditions.
|
||||||
func (adapter Adapter) ListNamespaces(query *model.NamespaceQuery) ([]*model.Namespace, error) {
|
func (a *adapter) ListNamespaces(query *model.NamespaceQuery) ([]*model.Namespace, error) {
|
||||||
var namespaces []*model.Namespace
|
var namespaces []*model.Namespace
|
||||||
|
|
||||||
urls := fmt.Sprintf("%s/dockyard/v2/visible/namespaces", adapter.Registry.URL)
|
urls := fmt.Sprintf("%s/dockyard/v2/visible/namespaces", a.registry.URL)
|
||||||
|
|
||||||
r, err := http.NewRequest("GET", urls, nil)
|
r, err := http.NewRequest("GET", urls, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -59,11 +59,11 @@ func (adapter Adapter) ListNamespaces(query *model.NamespaceQuery) ([]*model.Nam
|
|||||||
}
|
}
|
||||||
|
|
||||||
r.Header.Add("content-type", "application/json; charset=utf-8")
|
r.Header.Add("content-type", "application/json; charset=utf-8")
|
||||||
encodeAuth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", adapter.Registry.Credential.AccessKey, adapter.Registry.Credential.AccessSecret)))
|
encodeAuth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", a.registry.Credential.AccessKey, a.registry.Credential.AccessSecret)))
|
||||||
r.Header.Add("Authorization", "Basic "+encodeAuth)
|
r.Header.Add("Authorization", "Basic "+encodeAuth)
|
||||||
|
|
||||||
client := &http.Client{}
|
client := &http.Client{}
|
||||||
if adapter.Registry.Insecure == true {
|
if a.registry.Insecure == true {
|
||||||
client = &http.Client{
|
client = &http.Client{
|
||||||
Transport: &http.Transport{
|
Transport: &http.Transport{
|
||||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
@ -110,7 +110,7 @@ func (adapter Adapter) ListNamespaces(query *model.NamespaceQuery) ([]*model.Nam
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ConvertResourceMetadata convert resource metadata for Huawei SWR
|
// ConvertResourceMetadata convert resource metadata for Huawei SWR
|
||||||
func (adapter Adapter) ConvertResourceMetadata(resourceMetadata *model.ResourceMetadata, namespace *model.Namespace) (*model.ResourceMetadata, error) {
|
func (a *adapter) ConvertResourceMetadata(resourceMetadata *model.ResourceMetadata, namespace *model.Namespace) (*model.ResourceMetadata, error) {
|
||||||
metadata := &model.ResourceMetadata{
|
metadata := &model.ResourceMetadata{
|
||||||
Repository: resourceMetadata.Repository,
|
Repository: resourceMetadata.Repository,
|
||||||
Vtags: resourceMetadata.Vtags,
|
Vtags: resourceMetadata.Vtags,
|
||||||
@ -120,23 +120,31 @@ func (adapter Adapter) ConvertResourceMetadata(resourceMetadata *model.ResourceM
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PrepareForPush prepare for push to Huawei SWR
|
// PrepareForPush prepare for push to Huawei SWR
|
||||||
func (adapter Adapter) PrepareForPush(resources []*model.Resource) error {
|
func (a *adapter) PrepareForPush(resources []*model.Resource) error {
|
||||||
// TODO optimize the logic by merging the same namesapces
|
namespaces := map[string]struct{}{}
|
||||||
for _, resource := range resources {
|
for _, resource := range resources {
|
||||||
namespace, _ := util.ParseRepository(resource.Metadata.Repository.Name)
|
paths := strings.Split(resource.Metadata.Repository.Name, "/")
|
||||||
ns, err := adapter.GetNamespace(namespace)
|
namespace := paths[0]
|
||||||
|
ns, err := a.GetNamespace(namespace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
//
|
return err
|
||||||
} else {
|
|
||||||
if ns.Name == namespace {
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
if ns != nil && ns.Name == namespace {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
namespaces[namespace] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := fmt.Sprintf("%s/dockyard/v2/namespaces", adapter.Registry.URL)
|
url := fmt.Sprintf("%s/dockyard/v2/namespaces", a.registry.URL)
|
||||||
|
client := &http.Client{
|
||||||
|
Transport: util.GetHTTPTransport(a.registry.Insecure),
|
||||||
|
}
|
||||||
|
for namespace := range namespaces {
|
||||||
namespacebyte, err := json.Marshal(struct {
|
namespacebyte, err := json.Marshal(struct {
|
||||||
Namespace string `json:"namespace"`
|
Namespace string `json:"namespace"`
|
||||||
}{Namespace: namespace})
|
}{
|
||||||
|
Namespace: namespace,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -147,51 +155,44 @@ func (adapter Adapter) PrepareForPush(resources []*model.Resource) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
r.Header.Add("content-type", "application/json; charset=utf-8")
|
r.Header.Add("content-type", "application/json; charset=utf-8")
|
||||||
encodeAuth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", adapter.Registry.Credential.AccessKey, adapter.Registry.Credential.AccessSecret)))
|
encodeAuth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", a.registry.Credential.AccessKey, a.registry.Credential.AccessSecret)))
|
||||||
r.Header.Add("Authorization", "Basic "+encodeAuth)
|
r.Header.Add("Authorization", "Basic "+encodeAuth)
|
||||||
|
|
||||||
client := &http.Client{}
|
|
||||||
if adapter.Registry.Insecure == true {
|
|
||||||
client = &http.Client{
|
|
||||||
Transport: &http.Transport{
|
|
||||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
resp, err := client.Do(r)
|
resp, err := client.Do(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
code := resp.StatusCode
|
code := resp.StatusCode
|
||||||
if code >= 300 || code < 200 {
|
if code >= 300 || code < 200 {
|
||||||
body, _ := ioutil.ReadAll(resp.Body)
|
body, _ := ioutil.ReadAll(resp.Body)
|
||||||
return fmt.Errorf("[%d][%s]", code, string(body))
|
return fmt.Errorf("[%d][%s]", code, string(body))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Debugf("namespace %s created", namespace)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNamespace gets a namespace from Huawei SWR
|
// GetNamespace gets a namespace from Huawei SWR
|
||||||
func (adapter Adapter) GetNamespace(namespaceStr string) (*model.Namespace, error) {
|
func (a *adapter) GetNamespace(namespaceStr string) (*model.Namespace, error) {
|
||||||
var namespace = &model.Namespace{
|
var namespace = &model.Namespace{
|
||||||
Name: "",
|
Name: "",
|
||||||
Metadata: make(map[string]interface{}),
|
Metadata: make(map[string]interface{}),
|
||||||
}
|
}
|
||||||
|
|
||||||
urls := fmt.Sprintf("%s/dockyard/v2/namespaces/%s", adapter.Registry.URL, namespaceStr)
|
urls := fmt.Sprintf("%s/dockyard/v2/namespaces/%s", a.registry.URL, namespaceStr)
|
||||||
r, err := http.NewRequest("GET", urls, nil)
|
r, err := http.NewRequest("GET", urls, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return namespace, err
|
return namespace, err
|
||||||
}
|
}
|
||||||
|
|
||||||
r.Header.Add("content-type", "application/json; charset=utf-8")
|
r.Header.Add("content-type", "application/json; charset=utf-8")
|
||||||
encodeAuth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", adapter.Registry.Credential.AccessKey, adapter.Registry.Credential.AccessSecret)))
|
encodeAuth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", a.registry.Credential.AccessKey, a.registry.Credential.AccessSecret)))
|
||||||
r.Header.Add("Authorization", "Basic "+encodeAuth)
|
r.Header.Add("Authorization", "Basic "+encodeAuth)
|
||||||
|
|
||||||
var client *http.Client
|
var client *http.Client
|
||||||
if adapter.Registry.Insecure == true {
|
if a.registry.Insecure == true {
|
||||||
client = &http.Client{
|
client = &http.Client{
|
||||||
Transport: &http.Transport{
|
Transport: &http.Transport{
|
||||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
@ -229,17 +230,20 @@ func (adapter Adapter) GetNamespace(namespaceStr string) (*model.Namespace, erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HealthCheck check health for huawei SWR
|
// HealthCheck check health for huawei SWR
|
||||||
func (adapter Adapter) HealthCheck() (model.HealthStatus, error) {
|
func (a *adapter) HealthCheck() (model.HealthStatus, error) {
|
||||||
return model.Healthy, nil
|
return model.Healthy, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AdapterFactory is the factory for huawei adapter
|
// AdapterFactory is the factory for huawei adapter
|
||||||
func AdapterFactory(registry *model.Registry) (adapter.Adapter, error) {
|
func AdapterFactory(registry *model.Registry) (adp.Adapter, error) {
|
||||||
var adapter Adapter
|
reg, err := adp.NewDefaultImageRegistry(registry)
|
||||||
|
if err != nil {
|
||||||
adapter.Registry = registry
|
return nil, err
|
||||||
|
}
|
||||||
return adapter, nil
|
return &adapter{
|
||||||
|
registry: registry,
|
||||||
|
DefaultImageRegistry: reg,
|
||||||
|
}, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,11 +5,11 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/goharbor/harbor/src/replication/adapter"
|
adp "github.com/goharbor/harbor/src/replication/adapter"
|
||||||
"github.com/goharbor/harbor/src/replication/model"
|
"github.com/goharbor/harbor/src/replication/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
var hwAdapter adapter.Adapter
|
var hwAdapter adp.Adapter
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
var err error
|
var err error
|
||||||
@ -17,7 +17,7 @@ func init() {
|
|||||||
ID: 1,
|
ID: 1,
|
||||||
Name: "Huawei",
|
Name: "Huawei",
|
||||||
Description: "Adapter for SWR -- The image registry of Huawei Cloud",
|
Description: "Adapter for SWR -- The image registry of Huawei Cloud",
|
||||||
Type: "huawei",
|
Type: model.RegistryTypeHuawei,
|
||||||
URL: "https://swr.cn-north-1.myhuaweicloud.com",
|
URL: "https://swr.cn-north-1.myhuaweicloud.com",
|
||||||
Credential: &model.Credential{AccessKey: "cn-north-1@AQR6NF5G2MQ1V7U4FCD", AccessSecret: "2f7ec95070592fd4838a3aa4fd09338c047fd1cd654b3422197318f97281cd9"},
|
Credential: &model.Credential{AccessKey: "cn-north-1@AQR6NF5G2MQ1V7U4FCD", AccessSecret: "2f7ec95070592fd4838a3aa4fd09338c047fd1cd654b3422197318f97281cd9"},
|
||||||
Insecure: false,
|
Insecure: false,
|
||||||
@ -60,3 +60,11 @@ func TestAdapter_PrepareForPush(t *testing.T) {
|
|||||||
t.Log("success prepare for push")
|
t.Log("success prepare for push")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAdapter_HealthCheck(t *testing.T) {
|
||||||
|
health, err := hwAdapter.HealthCheck()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
t.Log(health)
|
||||||
|
}
|
||||||
|
@ -13,11 +13,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// FetchImages gets resources from Huawei SWR
|
// FetchImages gets resources from Huawei SWR
|
||||||
func (adapter *Adapter) FetchImages(namespaces []string, filters []*model.Filter) ([]*model.Resource, error) {
|
func (a *adapter) FetchImages(filters []*model.Filter) ([]*model.Resource, error) {
|
||||||
|
|
||||||
resources := []*model.Resource{}
|
resources := []*model.Resource{}
|
||||||
|
|
||||||
urls := fmt.Sprintf("%s/dockyard/v2/repositories?filter=center::self", adapter.Registry.URL)
|
urls := fmt.Sprintf("%s/dockyard/v2/repositories?filter=center::self", a.registry.URL)
|
||||||
|
|
||||||
r, err := http.NewRequest("GET", urls, nil)
|
r, err := http.NewRequest("GET", urls, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -25,11 +25,11 @@ func (adapter *Adapter) FetchImages(namespaces []string, filters []*model.Filter
|
|||||||
}
|
}
|
||||||
|
|
||||||
r.Header.Add("content-type", "application/json; charset=utf-8")
|
r.Header.Add("content-type", "application/json; charset=utf-8")
|
||||||
encodeAuth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", adapter.Registry.Credential.AccessKey, adapter.Registry.Credential.AccessSecret)))
|
encodeAuth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", a.registry.Credential.AccessKey, a.registry.Credential.AccessSecret)))
|
||||||
r.Header.Add("Authorization", "Basic "+encodeAuth)
|
r.Header.Add("Authorization", "Basic "+encodeAuth)
|
||||||
|
|
||||||
client := &http.Client{}
|
client := &http.Client{}
|
||||||
if adapter.Registry.Insecure == true {
|
if a.registry.Insecure == true {
|
||||||
client = &http.Client{
|
client = &http.Client{
|
||||||
Transport: &http.Transport{
|
Transport: &http.Transport{
|
||||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
@ -57,18 +57,102 @@ func (adapter *Adapter) FetchImages(namespaces []string, filters []*model.Filter
|
|||||||
return resources, err
|
return resources, err
|
||||||
}
|
}
|
||||||
for _, repo := range repos {
|
for _, repo := range repos {
|
||||||
for _, namespace := range namespaces {
|
|
||||||
if repo.NamespaceName == namespace {
|
|
||||||
resource := parseRepoQueryResultToResource(repo)
|
resource := parseRepoQueryResultToResource(repo)
|
||||||
resource.Registry = adapter.Registry
|
resource.Registry = a.registry
|
||||||
resources = append(resources, resource)
|
resources = append(resources, resource)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
return resources, nil
|
return resources, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ManifestExist check the manifest of Huawei SWR
|
||||||
|
func (a *adapter) ManifestExist(repository, reference string) (exist bool, digest string, err error) {
|
||||||
|
token, err := getJwtToken(a, repository)
|
||||||
|
if err != nil {
|
||||||
|
return exist, digest, err
|
||||||
|
}
|
||||||
|
|
||||||
|
urls := fmt.Sprintf("%s/v2/%s/manifests/%s", a.registry.URL, repository, reference)
|
||||||
|
|
||||||
|
r, err := http.NewRequest("GET", urls, nil)
|
||||||
|
if err != nil {
|
||||||
|
return exist, digest, err
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Header.Add("content-type", "application/json; charset=utf-8")
|
||||||
|
r.Header.Add("Authorization", "Bearer "+token.Token)
|
||||||
|
|
||||||
|
client := &http.Client{}
|
||||||
|
if a.registry.Insecure == true {
|
||||||
|
client = &http.Client{
|
||||||
|
Transport: &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resp, err := client.Do(r)
|
||||||
|
if err != nil {
|
||||||
|
return exist, digest, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer resp.Body.Close()
|
||||||
|
code := resp.StatusCode
|
||||||
|
if code >= 300 || code < 200 {
|
||||||
|
body, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
return exist, digest, fmt.Errorf("[%d][%s]", code, string(body))
|
||||||
|
}
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return exist, digest, err
|
||||||
|
}
|
||||||
|
exist = true
|
||||||
|
manifest := hwManifest{}
|
||||||
|
err = json.Unmarshal(body, &manifest)
|
||||||
|
if err != nil {
|
||||||
|
return exist, digest, err
|
||||||
|
}
|
||||||
|
return exist, manifest.Config.Digest, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteManifest delete the manifest of Huawei SWR
|
||||||
|
func (a *adapter) DeleteManifest(repository, reference string) error {
|
||||||
|
token, err := getJwtToken(a, repository)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
urls := fmt.Sprintf("%s/v2/%s/manifests/%s", a.registry.URL, repository, reference)
|
||||||
|
|
||||||
|
r, err := http.NewRequest("DELETE", urls, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
r.Header.Add("content-type", "application/json; charset=utf-8")
|
||||||
|
r.Header.Add("Authorization", "Bearer "+token.Token)
|
||||||
|
|
||||||
|
client := &http.Client{}
|
||||||
|
if a.registry.Insecure == true {
|
||||||
|
client = &http.Client{
|
||||||
|
Transport: &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resp, err := client.Do(r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer resp.Body.Close()
|
||||||
|
code := resp.StatusCode
|
||||||
|
if code >= 300 || code < 200 {
|
||||||
|
body, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
return fmt.Errorf("[%d][%s]", code, string(body))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func parseRepoQueryResultToResource(repo hwRepoQueryResult) *model.Resource {
|
func parseRepoQueryResultToResource(repo hwRepoQueryResult) *model.Resource {
|
||||||
var resource model.Resource
|
var resource model.Resource
|
||||||
info := make(map[string]interface{})
|
info := make(map[string]interface{})
|
||||||
@ -85,7 +169,7 @@ func parseRepoQueryResultToResource(repo hwRepoQueryResult) *model.Resource {
|
|||||||
info["total_range"] = repo.TotalRange
|
info["total_range"] = repo.TotalRange
|
||||||
|
|
||||||
repository := &model.Repository{
|
repository := &model.Repository{
|
||||||
Name: repo.Name,
|
Name: fmt.Sprintf("%s/%s", repo.NamespaceName, repo.Name),
|
||||||
Metadata: info,
|
Metadata: info,
|
||||||
}
|
}
|
||||||
resource.ExtendedInfo = info
|
resource.ExtendedInfo = info
|
||||||
@ -123,3 +207,94 @@ type hwRepoQueryResult struct {
|
|||||||
Status bool `json:"status"`
|
Status bool `json:"status"`
|
||||||
TotalRange int64 `json:"total_range"`
|
TotalRange int64 `json:"total_range"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getJwtToken(a *adapter, repository string) (token jwtToken, err error) {
|
||||||
|
urls := fmt.Sprintf("%s/swr/auth/v2/registry/auth?scope=repository:%s:push,pull", a.registry.URL, repository)
|
||||||
|
|
||||||
|
r, err := http.NewRequest("GET", urls, nil)
|
||||||
|
if err != nil {
|
||||||
|
return token, err
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Header.Add("content-type", "application/json; charset=utf-8")
|
||||||
|
encodeAuth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", a.registry.Credential.AccessKey, a.registry.Credential.AccessSecret)))
|
||||||
|
r.Header.Add("Authorization", "Basic "+encodeAuth)
|
||||||
|
|
||||||
|
client := &http.Client{}
|
||||||
|
if a.registry.Insecure == true {
|
||||||
|
client = &http.Client{
|
||||||
|
Transport: &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resp, err := client.Do(r)
|
||||||
|
if err != nil {
|
||||||
|
return token, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer resp.Body.Close()
|
||||||
|
code := resp.StatusCode
|
||||||
|
if code >= 300 || code < 200 {
|
||||||
|
body, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
return token, fmt.Errorf("[%d][%s]", code, string(body))
|
||||||
|
}
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return token, err
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(body, &token)
|
||||||
|
if err != nil {
|
||||||
|
return token, err
|
||||||
|
}
|
||||||
|
return token, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type jwtToken struct {
|
||||||
|
Token string `json:"token" description:"token return to user"`
|
||||||
|
ExpiresIn int `json:"expires_in" description:"describes token will expires in how many seconds later"`
|
||||||
|
IssuedAt time.Time `json:"issued_at" description:"token issued time"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type hwManifest struct {
|
||||||
|
// SchemaVersion is the image manifest schema that this image follows
|
||||||
|
SchemaVersion int `json:"schemaVersion"`
|
||||||
|
|
||||||
|
// MediaType is the media type of this schema.
|
||||||
|
MediaType string `json:"mediaType,omitempty"`
|
||||||
|
|
||||||
|
// Config references the image configuration as a blob.
|
||||||
|
Config hwDescriptor `json:"config"`
|
||||||
|
|
||||||
|
// Layers lists descriptors for the layers referenced by the
|
||||||
|
// configuration.
|
||||||
|
Layers []hwDescriptor `json:"layers"`
|
||||||
|
|
||||||
|
// summary keeps the summary infos
|
||||||
|
Summary hwManifestSummary `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type hwDescriptor struct {
|
||||||
|
// MediaType describe the type of the content. All text based formats are
|
||||||
|
// encoded as utf-8.
|
||||||
|
MediaType string `json:"mediaType,omitempty"`
|
||||||
|
|
||||||
|
// Size in bytes of content.
|
||||||
|
Size int64 `json:"size,omitempty"`
|
||||||
|
|
||||||
|
// Digest uniquely identifies the content. A byte stream can be verified
|
||||||
|
// against this digest.
|
||||||
|
Digest string `json:"digest,omitempty"`
|
||||||
|
|
||||||
|
// URLs contains the source URLs of this content.
|
||||||
|
URLs []string `json:"urls,omitempty"`
|
||||||
|
|
||||||
|
// depandence
|
||||||
|
Dependence string `json:"dependence,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type hwManifestSummary struct {
|
||||||
|
Config string
|
||||||
|
RepoTags []string
|
||||||
|
Layers []string
|
||||||
|
}
|
||||||
|
@ -7,24 +7,24 @@ import (
|
|||||||
"github.com/goharbor/harbor/src/replication/model"
|
"github.com/goharbor/harbor/src/replication/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
var HWAdapter Adapter
|
var HWAdapter adapter
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
hwRegistry := &model.Registry{
|
hwRegistry := &model.Registry{
|
||||||
ID: 1,
|
ID: 1,
|
||||||
Name: "Huawei",
|
Name: "Huawei",
|
||||||
Description: "Adapter for SWR -- The image registry of Huawei Cloud",
|
Description: "Adapter for SWR -- The image registry of Huawei Cloud",
|
||||||
Type: "huawei",
|
Type: model.RegistryTypeHuawei,
|
||||||
URL: "https://swr.cn-north-1.myhuaweicloud.com",
|
URL: "https://swr.cn-north-1.myhuaweicloud.com",
|
||||||
Credential: &model.Credential{AccessKey: "cn-north-1@AQR6NF5G2MQ1V7U4FCD", AccessSecret: "2f7ec95070592fd4838a3aa4fd09338c047fd1cd654b3422197318f97281cd9"},
|
Credential: &model.Credential{AccessKey: "cn-north-1@IJYZLFBKBFN8LOUITAH", AccessSecret: "f31e8e2b948265afdae32e83722a7705fd43e154585ff69e64108247750e5d"},
|
||||||
Insecure: false,
|
Insecure: false,
|
||||||
Status: "",
|
Status: "",
|
||||||
}
|
}
|
||||||
HWAdapter.Registry = hwRegistry
|
HWAdapter.registry = hwRegistry
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAdapter_FetchImages(t *testing.T) {
|
func TestAdapter_FetchImages(t *testing.T) {
|
||||||
resources, err := HWAdapter.FetchImages([]string{"swr_namespace2", "sunday0615"}, nil)
|
resources, err := HWAdapter.FetchImages(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if strings.HasPrefix(err.Error(), "[401]") {
|
if strings.HasPrefix(err.Error(), "[401]") {
|
||||||
t.Log("huawei ak/sk is not available", err.Error())
|
t.Log("huawei ak/sk is not available", err.Error())
|
||||||
@ -37,3 +37,31 @@ func TestAdapter_FetchImages(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAdapter_ManifestExist(t *testing.T) {
|
||||||
|
exist, digest, err := HWAdapter.ManifestExist("", "")
|
||||||
|
if err != nil {
|
||||||
|
if strings.HasPrefix(err.Error(), "[401]") {
|
||||||
|
t.Log("huawei ak/sk is not available", err.Error())
|
||||||
|
} else {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if exist {
|
||||||
|
t.Log(digest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAdapter_DeleteManifest(t *testing.T) {
|
||||||
|
err := HWAdapter.DeleteManifest("sundaymango_mango/hello-world", "latest")
|
||||||
|
if err != nil {
|
||||||
|
if strings.HasPrefix(err.Error(), "[401]") {
|
||||||
|
t.Log("huawei ak/sk is not available", err.Error())
|
||||||
|
} else {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
t.Error("the manifest is deleted")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -96,6 +96,11 @@ func (h *handler) getRelatedPolicies(resource *model.Resource) ([]*model.Policy,
|
|||||||
if !policy.Enabled {
|
if !policy.Enabled {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
// currently, the events are produced only by local Harbor,
|
||||||
|
// so they should only apply to the policies whose source registry is local Harbor
|
||||||
|
if !(policy.SrcRegistry == nil || policy.SrcRegistry.ID == 0) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
// has no trigger
|
// has no trigger
|
||||||
if policy.Trigger == nil {
|
if policy.Trigger == nil {
|
||||||
continue
|
continue
|
||||||
|
@ -71,6 +71,9 @@ func (f *fakedPolicyController) List(...*model.PolicyQuery) (int64, []*model.Pol
|
|||||||
Value: "test/*",
|
Value: "test/*",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
DestRegistry: &model.Registry{
|
||||||
|
ID: 1,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
// nil trigger
|
// nil trigger
|
||||||
{
|
{
|
||||||
@ -84,6 +87,9 @@ func (f *fakedPolicyController) List(...*model.PolicyQuery) (int64, []*model.Pol
|
|||||||
Value: "library/*",
|
Value: "library/*",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
DestRegistry: &model.Registry{
|
||||||
|
ID: 1,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
// doesn't replicate deletion
|
// doesn't replicate deletion
|
||||||
{
|
{
|
||||||
@ -99,6 +105,9 @@ func (f *fakedPolicyController) List(...*model.PolicyQuery) (int64, []*model.Pol
|
|||||||
Value: "library/*",
|
Value: "library/*",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
DestRegistry: &model.Registry{
|
||||||
|
ID: 1,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
// replicate deletion
|
// replicate deletion
|
||||||
{
|
{
|
||||||
@ -114,6 +123,9 @@ func (f *fakedPolicyController) List(...*model.PolicyQuery) (int64, []*model.Pol
|
|||||||
Value: "library/*",
|
Value: "library/*",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
DestRegistry: &model.Registry{
|
||||||
|
ID: 1,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
// disabled
|
// disabled
|
||||||
{
|
{
|
||||||
@ -129,6 +141,27 @@ func (f *fakedPolicyController) List(...*model.PolicyQuery) (int64, []*model.Pol
|
|||||||
Value: "library/*",
|
Value: "library/*",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
DestRegistry: &model.Registry{
|
||||||
|
ID: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// the source registry is not local Harbor
|
||||||
|
{
|
||||||
|
ID: 6,
|
||||||
|
Enabled: true,
|
||||||
|
Deletion: true,
|
||||||
|
Trigger: &model.Trigger{
|
||||||
|
Type: model.TriggerTypeEventBased,
|
||||||
|
},
|
||||||
|
Filters: []*model.Filter{
|
||||||
|
{
|
||||||
|
Type: model.FilterTypeName,
|
||||||
|
Value: "library/*",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
SrcRegistry: &model.Registry{
|
||||||
|
ID: 1,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return int64(len(polices)), polices, nil
|
return int64(len(polices)), polices, nil
|
||||||
|
@ -25,6 +25,7 @@ const (
|
|||||||
// RegistryTypeHarbor indicates registry type harbor
|
// RegistryTypeHarbor indicates registry type harbor
|
||||||
RegistryTypeHarbor RegistryType = "harbor"
|
RegistryTypeHarbor RegistryType = "harbor"
|
||||||
RegistryTypeDockerHub RegistryType = "dockerHub"
|
RegistryTypeDockerHub RegistryType = "dockerHub"
|
||||||
|
RegistryTypeHuawei RegistryType = "Huawei"
|
||||||
|
|
||||||
FilterStyleTypeText = "input"
|
FilterStyleTypeText = "input"
|
||||||
FilterStyleTypeRadio = "radio"
|
FilterStyleTypeRadio = "radio"
|
||||||
|
@ -33,6 +33,8 @@ import (
|
|||||||
_ "github.com/goharbor/harbor/src/replication/adapter/dockerhub"
|
_ "github.com/goharbor/harbor/src/replication/adapter/dockerhub"
|
||||||
// register the Native adapter
|
// register the Native adapter
|
||||||
_ "github.com/goharbor/harbor/src/replication/adapter/native"
|
_ "github.com/goharbor/harbor/src/replication/adapter/native"
|
||||||
|
// register the huawei adapter
|
||||||
|
_ "github.com/goharbor/harbor/src/replication/adapter/huawei"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
4
src/vendor/github.com/mattn/go-sqlite3/.gitignore
generated
vendored
4
src/vendor/github.com/mattn/go-sqlite3/.gitignore
generated
vendored
@ -1,4 +0,0 @@
|
|||||||
*.db
|
|
||||||
*.exe
|
|
||||||
*.dll
|
|
||||||
*.o
|
|
19
src/vendor/github.com/mattn/go-sqlite3/.travis.yml
generated
vendored
19
src/vendor/github.com/mattn/go-sqlite3/.travis.yml
generated
vendored
@ -1,19 +0,0 @@
|
|||||||
language: go
|
|
||||||
sudo: required
|
|
||||||
dist: trusty
|
|
||||||
env:
|
|
||||||
- GOTAGS=
|
|
||||||
- GOTAGS=libsqlite3
|
|
||||||
- GOTAGS=trace
|
|
||||||
- GOTAGS=vtable
|
|
||||||
go:
|
|
||||||
- 1.7.x
|
|
||||||
- 1.8.x
|
|
||||||
- 1.9.x
|
|
||||||
- master
|
|
||||||
before_install:
|
|
||||||
- go get github.com/mattn/goveralls
|
|
||||||
- go get golang.org/x/tools/cmd/cover
|
|
||||||
script:
|
|
||||||
- $HOME/gopath/bin/goveralls -repotoken 3qJVUE0iQwqnCbmNcDsjYu1nh4J4KIFXx
|
|
||||||
- go test -race -v . -tags "$GOTAGS"
|
|
21
src/vendor/github.com/mattn/go-sqlite3/LICENSE
generated
vendored
21
src/vendor/github.com/mattn/go-sqlite3/LICENSE
generated
vendored
@ -1,21 +0,0 @@
|
|||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2014 Yasuhiro Matsumoto
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
97
src/vendor/github.com/mattn/go-sqlite3/README.md
generated
vendored
97
src/vendor/github.com/mattn/go-sqlite3/README.md
generated
vendored
@ -1,97 +0,0 @@
|
|||||||
go-sqlite3
|
|
||||||
==========
|
|
||||||
|
|
||||||
[![GoDoc Reference](https://godoc.org/github.com/mattn/go-sqlite3?status.svg)](http://godoc.org/github.com/mattn/go-sqlite3)
|
|
||||||
[![Build Status](https://travis-ci.org/mattn/go-sqlite3.svg?branch=master)](https://travis-ci.org/mattn/go-sqlite3)
|
|
||||||
[![Coverage Status](https://coveralls.io/repos/mattn/go-sqlite3/badge.svg?branch=master)](https://coveralls.io/r/mattn/go-sqlite3?branch=master)
|
|
||||||
[![Go Report Card](https://goreportcard.com/badge/github.com/mattn/go-sqlite3)](https://goreportcard.com/report/github.com/mattn/go-sqlite3)
|
|
||||||
|
|
||||||
Description
|
|
||||||
-----------
|
|
||||||
|
|
||||||
sqlite3 driver conforming to the built-in database/sql interface
|
|
||||||
|
|
||||||
Installation
|
|
||||||
------------
|
|
||||||
|
|
||||||
This package can be installed with the go get command:
|
|
||||||
|
|
||||||
go get github.com/mattn/go-sqlite3
|
|
||||||
|
|
||||||
_go-sqlite3_ is *cgo* package.
|
|
||||||
If you want to build your app using go-sqlite3, you need gcc.
|
|
||||||
However, if you install _go-sqlite3_ with `go install github.com/mattn/go-sqlite3`, you don't need gcc to build your app anymore.
|
|
||||||
|
|
||||||
Documentation
|
|
||||||
-------------
|
|
||||||
|
|
||||||
API documentation can be found here: http://godoc.org/github.com/mattn/go-sqlite3
|
|
||||||
|
|
||||||
Examples can be found under the `./_example` directory
|
|
||||||
|
|
||||||
FAQ
|
|
||||||
---
|
|
||||||
|
|
||||||
* Want to build go-sqlite3 with libsqlite3 on my linux.
|
|
||||||
|
|
||||||
Use `go build --tags "libsqlite3 linux"`
|
|
||||||
|
|
||||||
* Want to build go-sqlite3 with libsqlite3 on OS X.
|
|
||||||
|
|
||||||
Install sqlite3 from homebrew: `brew install sqlite3`
|
|
||||||
|
|
||||||
Use `go build --tags "libsqlite3 darwin"`
|
|
||||||
|
|
||||||
* Want to build go-sqlite3 with icu extension.
|
|
||||||
|
|
||||||
Use `go build --tags "icu"`
|
|
||||||
|
|
||||||
Available extensions: `json1`, `fts5`, `icu`
|
|
||||||
|
|
||||||
* Can't build go-sqlite3 on windows 64bit.
|
|
||||||
|
|
||||||
> Probably, you are using go 1.0, go1.0 has a problem when it comes to compiling/linking on windows 64bit.
|
|
||||||
> See: [#27](https://github.com/mattn/go-sqlite3/issues/27)
|
|
||||||
|
|
||||||
* Getting insert error while query is opened.
|
|
||||||
|
|
||||||
> You can pass some arguments into the connection string, for example, a URI.
|
|
||||||
> See: [#39](https://github.com/mattn/go-sqlite3/issues/39)
|
|
||||||
|
|
||||||
* Do you want to cross compile? mingw on Linux or Mac?
|
|
||||||
|
|
||||||
> See: [#106](https://github.com/mattn/go-sqlite3/issues/106)
|
|
||||||
> See also: http://www.limitlessfx.com/cross-compile-golang-app-for-windows-from-linux.html
|
|
||||||
|
|
||||||
* Want to get time.Time with current locale
|
|
||||||
|
|
||||||
Use `_loc=auto` in SQLite3 filename schema like `file:foo.db?_loc=auto`.
|
|
||||||
|
|
||||||
* Can I use this in multiple routines concurrently?
|
|
||||||
|
|
||||||
Yes for readonly. But, No for writable. See [#50](https://github.com/mattn/go-sqlite3/issues/50), [#51](https://github.com/mattn/go-sqlite3/issues/51), [#209](https://github.com/mattn/go-sqlite3/issues/209).
|
|
||||||
|
|
||||||
* Why is it racy if I use a `sql.Open("sqlite3", ":memory:")` database?
|
|
||||||
|
|
||||||
Each connection to :memory: opens a brand new in-memory sql database, so if
|
|
||||||
the stdlib's sql engine happens to open another connection and you've only
|
|
||||||
specified ":memory:", that connection will see a brand new database. A
|
|
||||||
workaround is to use "file::memory:?mode=memory&cache=shared". Every
|
|
||||||
connection to this string will point to the same in-memory database. See
|
|
||||||
[#204](https://github.com/mattn/go-sqlite3/issues/204) for more info.
|
|
||||||
|
|
||||||
License
|
|
||||||
-------
|
|
||||||
|
|
||||||
MIT: http://mattn.mit-license.org/2012
|
|
||||||
|
|
||||||
sqlite3-binding.c, sqlite3-binding.h, sqlite3ext.h
|
|
||||||
|
|
||||||
The -binding suffix was added to avoid build failures under gccgo.
|
|
||||||
|
|
||||||
In this repository, those files are an amalgamation of code that was copied from SQLite3. The license of that code is the same as the license of SQLite3.
|
|
||||||
|
|
||||||
Author
|
|
||||||
------
|
|
||||||
|
|
||||||
Yasuhiro Matsumoto (a.k.a mattn)
|
|
85
src/vendor/github.com/mattn/go-sqlite3/backup.go
generated
vendored
85
src/vendor/github.com/mattn/go-sqlite3/backup.go
generated
vendored
@ -1,85 +0,0 @@
|
|||||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
|
|
||||||
//
|
|
||||||
// Use of this source code is governed by an MIT-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package sqlite3
|
|
||||||
|
|
||||||
/*
|
|
||||||
#ifndef USE_LIBSQLITE3
|
|
||||||
#include <sqlite3-binding.h>
|
|
||||||
#else
|
|
||||||
#include <sqlite3.h>
|
|
||||||
#endif
|
|
||||||
#include <stdlib.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
import (
|
|
||||||
"runtime"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
// SQLiteBackup implement interface of Backup.
|
|
||||||
type SQLiteBackup struct {
|
|
||||||
b *C.sqlite3_backup
|
|
||||||
}
|
|
||||||
|
|
||||||
// Backup make backup from src to dest.
|
|
||||||
func (c *SQLiteConn) Backup(dest string, conn *SQLiteConn, src string) (*SQLiteBackup, error) {
|
|
||||||
destptr := C.CString(dest)
|
|
||||||
defer C.free(unsafe.Pointer(destptr))
|
|
||||||
srcptr := C.CString(src)
|
|
||||||
defer C.free(unsafe.Pointer(srcptr))
|
|
||||||
|
|
||||||
if b := C.sqlite3_backup_init(c.db, destptr, conn.db, srcptr); b != nil {
|
|
||||||
bb := &SQLiteBackup{b: b}
|
|
||||||
runtime.SetFinalizer(bb, (*SQLiteBackup).Finish)
|
|
||||||
return bb, nil
|
|
||||||
}
|
|
||||||
return nil, c.lastError()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step to backs up for one step. Calls the underlying `sqlite3_backup_step`
|
|
||||||
// function. This function returns a boolean indicating if the backup is done
|
|
||||||
// and an error signalling any other error. Done is returned if the underlying
|
|
||||||
// C function returns SQLITE_DONE (Code 101)
|
|
||||||
func (b *SQLiteBackup) Step(p int) (bool, error) {
|
|
||||||
ret := C.sqlite3_backup_step(b.b, C.int(p))
|
|
||||||
if ret == C.SQLITE_DONE {
|
|
||||||
return true, nil
|
|
||||||
} else if ret != 0 && ret != C.SQLITE_LOCKED && ret != C.SQLITE_BUSY {
|
|
||||||
return false, Error{Code: ErrNo(ret)}
|
|
||||||
}
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remaining return whether have the rest for backup.
|
|
||||||
func (b *SQLiteBackup) Remaining() int {
|
|
||||||
return int(C.sqlite3_backup_remaining(b.b))
|
|
||||||
}
|
|
||||||
|
|
||||||
// PageCount return count of pages.
|
|
||||||
func (b *SQLiteBackup) PageCount() int {
|
|
||||||
return int(C.sqlite3_backup_pagecount(b.b))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finish close backup.
|
|
||||||
func (b *SQLiteBackup) Finish() error {
|
|
||||||
return b.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close close backup.
|
|
||||||
func (b *SQLiteBackup) Close() error {
|
|
||||||
ret := C.sqlite3_backup_finish(b.b)
|
|
||||||
|
|
||||||
// sqlite3_backup_finish() never fails, it just returns the
|
|
||||||
// error code from previous operations, so clean up before
|
|
||||||
// checking and returning an error
|
|
||||||
b.b = nil
|
|
||||||
runtime.SetFinalizer(b, nil)
|
|
||||||
|
|
||||||
if ret != 0 {
|
|
||||||
return Error{Code: ErrNo(ret)}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
364
src/vendor/github.com/mattn/go-sqlite3/callback.go
generated
vendored
364
src/vendor/github.com/mattn/go-sqlite3/callback.go
generated
vendored
@ -1,364 +0,0 @@
|
|||||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
|
|
||||||
//
|
|
||||||
// Use of this source code is governed by an MIT-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package sqlite3
|
|
||||||
|
|
||||||
// You can't export a Go function to C and have definitions in the C
|
|
||||||
// preamble in the same file, so we have to have callbackTrampoline in
|
|
||||||
// its own file. Because we need a separate file anyway, the support
|
|
||||||
// code for SQLite custom functions is in here.
|
|
||||||
|
|
||||||
/*
|
|
||||||
#ifndef USE_LIBSQLITE3
|
|
||||||
#include <sqlite3-binding.h>
|
|
||||||
#else
|
|
||||||
#include <sqlite3.h>
|
|
||||||
#endif
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
void _sqlite3_result_text(sqlite3_context* ctx, const char* s);
|
|
||||||
void _sqlite3_result_blob(sqlite3_context* ctx, const void* b, int l);
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"math"
|
|
||||||
"reflect"
|
|
||||||
"sync"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
//export callbackTrampoline
|
|
||||||
func callbackTrampoline(ctx *C.sqlite3_context, argc int, argv **C.sqlite3_value) {
|
|
||||||
args := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.sqlite3_value)(nil))]*C.sqlite3_value)(unsafe.Pointer(argv))[:argc:argc]
|
|
||||||
fi := lookupHandle(uintptr(C.sqlite3_user_data(ctx))).(*functionInfo)
|
|
||||||
fi.Call(ctx, args)
|
|
||||||
}
|
|
||||||
|
|
||||||
//export stepTrampoline
|
|
||||||
func stepTrampoline(ctx *C.sqlite3_context, argc C.int, argv **C.sqlite3_value) {
|
|
||||||
args := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.sqlite3_value)(nil))]*C.sqlite3_value)(unsafe.Pointer(argv))[:int(argc):int(argc)]
|
|
||||||
ai := lookupHandle(uintptr(C.sqlite3_user_data(ctx))).(*aggInfo)
|
|
||||||
ai.Step(ctx, args)
|
|
||||||
}
|
|
||||||
|
|
||||||
//export doneTrampoline
|
|
||||||
func doneTrampoline(ctx *C.sqlite3_context) {
|
|
||||||
handle := uintptr(C.sqlite3_user_data(ctx))
|
|
||||||
ai := lookupHandle(handle).(*aggInfo)
|
|
||||||
ai.Done(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
//export compareTrampoline
|
|
||||||
func compareTrampoline(handlePtr uintptr, la C.int, a *C.char, lb C.int, b *C.char) C.int {
|
|
||||||
cmp := lookupHandle(handlePtr).(func(string, string) int)
|
|
||||||
return C.int(cmp(C.GoStringN(a, la), C.GoStringN(b, lb)))
|
|
||||||
}
|
|
||||||
|
|
||||||
//export commitHookTrampoline
|
|
||||||
func commitHookTrampoline(handle uintptr) int {
|
|
||||||
callback := lookupHandle(handle).(func() int)
|
|
||||||
return callback()
|
|
||||||
}
|
|
||||||
|
|
||||||
//export rollbackHookTrampoline
|
|
||||||
func rollbackHookTrampoline(handle uintptr) {
|
|
||||||
callback := lookupHandle(handle).(func())
|
|
||||||
callback()
|
|
||||||
}
|
|
||||||
|
|
||||||
//export updateHookTrampoline
|
|
||||||
func updateHookTrampoline(handle uintptr, op int, db *C.char, table *C.char, rowid int64) {
|
|
||||||
callback := lookupHandle(handle).(func(int, string, string, int64))
|
|
||||||
callback(op, C.GoString(db), C.GoString(table), rowid)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use handles to avoid passing Go pointers to C.
|
|
||||||
|
|
||||||
type handleVal struct {
|
|
||||||
db *SQLiteConn
|
|
||||||
val interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
var handleLock sync.Mutex
|
|
||||||
var handleVals = make(map[uintptr]handleVal)
|
|
||||||
var handleIndex uintptr = 100
|
|
||||||
|
|
||||||
func newHandle(db *SQLiteConn, v interface{}) uintptr {
|
|
||||||
handleLock.Lock()
|
|
||||||
defer handleLock.Unlock()
|
|
||||||
i := handleIndex
|
|
||||||
handleIndex++
|
|
||||||
handleVals[i] = handleVal{db, v}
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
|
|
||||||
func lookupHandle(handle uintptr) interface{} {
|
|
||||||
handleLock.Lock()
|
|
||||||
defer handleLock.Unlock()
|
|
||||||
r, ok := handleVals[handle]
|
|
||||||
if !ok {
|
|
||||||
if handle >= 100 && handle < handleIndex {
|
|
||||||
panic("deleted handle")
|
|
||||||
} else {
|
|
||||||
panic("invalid handle")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r.val
|
|
||||||
}
|
|
||||||
|
|
||||||
func deleteHandles(db *SQLiteConn) {
|
|
||||||
handleLock.Lock()
|
|
||||||
defer handleLock.Unlock()
|
|
||||||
for handle, val := range handleVals {
|
|
||||||
if val.db == db {
|
|
||||||
delete(handleVals, handle)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is only here so that tests can refer to it.
|
|
||||||
type callbackArgRaw C.sqlite3_value
|
|
||||||
|
|
||||||
type callbackArgConverter func(*C.sqlite3_value) (reflect.Value, error)
|
|
||||||
|
|
||||||
type callbackArgCast struct {
|
|
||||||
f callbackArgConverter
|
|
||||||
typ reflect.Type
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c callbackArgCast) Run(v *C.sqlite3_value) (reflect.Value, error) {
|
|
||||||
val, err := c.f(v)
|
|
||||||
if err != nil {
|
|
||||||
return reflect.Value{}, err
|
|
||||||
}
|
|
||||||
if !val.Type().ConvertibleTo(c.typ) {
|
|
||||||
return reflect.Value{}, fmt.Errorf("cannot convert %s to %s", val.Type(), c.typ)
|
|
||||||
}
|
|
||||||
return val.Convert(c.typ), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func callbackArgInt64(v *C.sqlite3_value) (reflect.Value, error) {
|
|
||||||
if C.sqlite3_value_type(v) != C.SQLITE_INTEGER {
|
|
||||||
return reflect.Value{}, fmt.Errorf("argument must be an INTEGER")
|
|
||||||
}
|
|
||||||
return reflect.ValueOf(int64(C.sqlite3_value_int64(v))), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func callbackArgBool(v *C.sqlite3_value) (reflect.Value, error) {
|
|
||||||
if C.sqlite3_value_type(v) != C.SQLITE_INTEGER {
|
|
||||||
return reflect.Value{}, fmt.Errorf("argument must be an INTEGER")
|
|
||||||
}
|
|
||||||
i := int64(C.sqlite3_value_int64(v))
|
|
||||||
val := false
|
|
||||||
if i != 0 {
|
|
||||||
val = true
|
|
||||||
}
|
|
||||||
return reflect.ValueOf(val), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func callbackArgFloat64(v *C.sqlite3_value) (reflect.Value, error) {
|
|
||||||
if C.sqlite3_value_type(v) != C.SQLITE_FLOAT {
|
|
||||||
return reflect.Value{}, fmt.Errorf("argument must be a FLOAT")
|
|
||||||
}
|
|
||||||
return reflect.ValueOf(float64(C.sqlite3_value_double(v))), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func callbackArgBytes(v *C.sqlite3_value) (reflect.Value, error) {
|
|
||||||
switch C.sqlite3_value_type(v) {
|
|
||||||
case C.SQLITE_BLOB:
|
|
||||||
l := C.sqlite3_value_bytes(v)
|
|
||||||
p := C.sqlite3_value_blob(v)
|
|
||||||
return reflect.ValueOf(C.GoBytes(p, l)), nil
|
|
||||||
case C.SQLITE_TEXT:
|
|
||||||
l := C.sqlite3_value_bytes(v)
|
|
||||||
c := unsafe.Pointer(C.sqlite3_value_text(v))
|
|
||||||
return reflect.ValueOf(C.GoBytes(c, l)), nil
|
|
||||||
default:
|
|
||||||
return reflect.Value{}, fmt.Errorf("argument must be BLOB or TEXT")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func callbackArgString(v *C.sqlite3_value) (reflect.Value, error) {
|
|
||||||
switch C.sqlite3_value_type(v) {
|
|
||||||
case C.SQLITE_BLOB:
|
|
||||||
l := C.sqlite3_value_bytes(v)
|
|
||||||
p := (*C.char)(C.sqlite3_value_blob(v))
|
|
||||||
return reflect.ValueOf(C.GoStringN(p, l)), nil
|
|
||||||
case C.SQLITE_TEXT:
|
|
||||||
c := (*C.char)(unsafe.Pointer(C.sqlite3_value_text(v)))
|
|
||||||
return reflect.ValueOf(C.GoString(c)), nil
|
|
||||||
default:
|
|
||||||
return reflect.Value{}, fmt.Errorf("argument must be BLOB or TEXT")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func callbackArgGeneric(v *C.sqlite3_value) (reflect.Value, error) {
|
|
||||||
switch C.sqlite3_value_type(v) {
|
|
||||||
case C.SQLITE_INTEGER:
|
|
||||||
return callbackArgInt64(v)
|
|
||||||
case C.SQLITE_FLOAT:
|
|
||||||
return callbackArgFloat64(v)
|
|
||||||
case C.SQLITE_TEXT:
|
|
||||||
return callbackArgString(v)
|
|
||||||
case C.SQLITE_BLOB:
|
|
||||||
return callbackArgBytes(v)
|
|
||||||
case C.SQLITE_NULL:
|
|
||||||
// Interpret NULL as a nil byte slice.
|
|
||||||
var ret []byte
|
|
||||||
return reflect.ValueOf(ret), nil
|
|
||||||
default:
|
|
||||||
panic("unreachable")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func callbackArg(typ reflect.Type) (callbackArgConverter, error) {
|
|
||||||
switch typ.Kind() {
|
|
||||||
case reflect.Interface:
|
|
||||||
if typ.NumMethod() != 0 {
|
|
||||||
return nil, errors.New("the only supported interface type is interface{}")
|
|
||||||
}
|
|
||||||
return callbackArgGeneric, nil
|
|
||||||
case reflect.Slice:
|
|
||||||
if typ.Elem().Kind() != reflect.Uint8 {
|
|
||||||
return nil, errors.New("the only supported slice type is []byte")
|
|
||||||
}
|
|
||||||
return callbackArgBytes, nil
|
|
||||||
case reflect.String:
|
|
||||||
return callbackArgString, nil
|
|
||||||
case reflect.Bool:
|
|
||||||
return callbackArgBool, nil
|
|
||||||
case reflect.Int64:
|
|
||||||
return callbackArgInt64, nil
|
|
||||||
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int, reflect.Uint:
|
|
||||||
c := callbackArgCast{callbackArgInt64, typ}
|
|
||||||
return c.Run, nil
|
|
||||||
case reflect.Float64:
|
|
||||||
return callbackArgFloat64, nil
|
|
||||||
case reflect.Float32:
|
|
||||||
c := callbackArgCast{callbackArgFloat64, typ}
|
|
||||||
return c.Run, nil
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("don't know how to convert to %s", typ)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func callbackConvertArgs(argv []*C.sqlite3_value, converters []callbackArgConverter, variadic callbackArgConverter) ([]reflect.Value, error) {
|
|
||||||
var args []reflect.Value
|
|
||||||
|
|
||||||
if len(argv) < len(converters) {
|
|
||||||
return nil, fmt.Errorf("function requires at least %d arguments", len(converters))
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, arg := range argv[:len(converters)] {
|
|
||||||
v, err := converters[i](arg)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
args = append(args, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
if variadic != nil {
|
|
||||||
for _, arg := range argv[len(converters):] {
|
|
||||||
v, err := variadic(arg)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
args = append(args, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return args, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type callbackRetConverter func(*C.sqlite3_context, reflect.Value) error
|
|
||||||
|
|
||||||
func callbackRetInteger(ctx *C.sqlite3_context, v reflect.Value) error {
|
|
||||||
switch v.Type().Kind() {
|
|
||||||
case reflect.Int64:
|
|
||||||
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int, reflect.Uint:
|
|
||||||
v = v.Convert(reflect.TypeOf(int64(0)))
|
|
||||||
case reflect.Bool:
|
|
||||||
b := v.Interface().(bool)
|
|
||||||
if b {
|
|
||||||
v = reflect.ValueOf(int64(1))
|
|
||||||
} else {
|
|
||||||
v = reflect.ValueOf(int64(0))
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("cannot convert %s to INTEGER", v.Type())
|
|
||||||
}
|
|
||||||
|
|
||||||
C.sqlite3_result_int64(ctx, C.sqlite3_int64(v.Interface().(int64)))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func callbackRetFloat(ctx *C.sqlite3_context, v reflect.Value) error {
|
|
||||||
switch v.Type().Kind() {
|
|
||||||
case reflect.Float64:
|
|
||||||
case reflect.Float32:
|
|
||||||
v = v.Convert(reflect.TypeOf(float64(0)))
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("cannot convert %s to FLOAT", v.Type())
|
|
||||||
}
|
|
||||||
|
|
||||||
C.sqlite3_result_double(ctx, C.double(v.Interface().(float64)))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func callbackRetBlob(ctx *C.sqlite3_context, v reflect.Value) error {
|
|
||||||
if v.Type().Kind() != reflect.Slice || v.Type().Elem().Kind() != reflect.Uint8 {
|
|
||||||
return fmt.Errorf("cannot convert %s to BLOB", v.Type())
|
|
||||||
}
|
|
||||||
i := v.Interface()
|
|
||||||
if i == nil || len(i.([]byte)) == 0 {
|
|
||||||
C.sqlite3_result_null(ctx)
|
|
||||||
} else {
|
|
||||||
bs := i.([]byte)
|
|
||||||
C._sqlite3_result_blob(ctx, unsafe.Pointer(&bs[0]), C.int(len(bs)))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func callbackRetText(ctx *C.sqlite3_context, v reflect.Value) error {
|
|
||||||
if v.Type().Kind() != reflect.String {
|
|
||||||
return fmt.Errorf("cannot convert %s to TEXT", v.Type())
|
|
||||||
}
|
|
||||||
C._sqlite3_result_text(ctx, C.CString(v.Interface().(string)))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func callbackRet(typ reflect.Type) (callbackRetConverter, error) {
|
|
||||||
switch typ.Kind() {
|
|
||||||
case reflect.Slice:
|
|
||||||
if typ.Elem().Kind() != reflect.Uint8 {
|
|
||||||
return nil, errors.New("the only supported slice type is []byte")
|
|
||||||
}
|
|
||||||
return callbackRetBlob, nil
|
|
||||||
case reflect.String:
|
|
||||||
return callbackRetText, nil
|
|
||||||
case reflect.Bool, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int, reflect.Uint:
|
|
||||||
return callbackRetInteger, nil
|
|
||||||
case reflect.Float32, reflect.Float64:
|
|
||||||
return callbackRetFloat, nil
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("don't know how to convert to %s", typ)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func callbackError(ctx *C.sqlite3_context, err error) {
|
|
||||||
cstr := C.CString(err.Error())
|
|
||||||
defer C.free(unsafe.Pointer(cstr))
|
|
||||||
C.sqlite3_result_error(ctx, cstr, -1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test support code. Tests are not allowed to import "C", so we can't
|
|
||||||
// declare any functions that use C.sqlite3_value.
|
|
||||||
func callbackSyntheticForTests(v reflect.Value, err error) callbackArgConverter {
|
|
||||||
return func(*C.sqlite3_value) (reflect.Value, error) {
|
|
||||||
return v, err
|
|
||||||
}
|
|
||||||
}
|
|
112
src/vendor/github.com/mattn/go-sqlite3/doc.go
generated
vendored
112
src/vendor/github.com/mattn/go-sqlite3/doc.go
generated
vendored
@ -1,112 +0,0 @@
|
|||||||
/*
|
|
||||||
Package sqlite3 provides interface to SQLite3 databases.
|
|
||||||
|
|
||||||
This works as a driver for database/sql.
|
|
||||||
|
|
||||||
Installation
|
|
||||||
|
|
||||||
go get github.com/mattn/go-sqlite3
|
|
||||||
|
|
||||||
Supported Types
|
|
||||||
|
|
||||||
Currently, go-sqlite3 supports the following data types.
|
|
||||||
|
|
||||||
+------------------------------+
|
|
||||||
|go | sqlite3 |
|
|
||||||
|----------|-------------------|
|
|
||||||
|nil | null |
|
|
||||||
|int | integer |
|
|
||||||
|int64 | integer |
|
|
||||||
|float64 | float |
|
|
||||||
|bool | integer |
|
|
||||||
|[]byte | blob |
|
|
||||||
|string | text |
|
|
||||||
|time.Time | timestamp/datetime|
|
|
||||||
+------------------------------+
|
|
||||||
|
|
||||||
SQLite3 Extension
|
|
||||||
|
|
||||||
You can write your own extension module for sqlite3. For example, below is an
|
|
||||||
extension for a Regexp matcher operation.
|
|
||||||
|
|
||||||
#include <pcre.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <sqlite3ext.h>
|
|
||||||
|
|
||||||
SQLITE_EXTENSION_INIT1
|
|
||||||
static void regexp_func(sqlite3_context *context, int argc, sqlite3_value **argv) {
|
|
||||||
if (argc >= 2) {
|
|
||||||
const char *target = (const char *)sqlite3_value_text(argv[1]);
|
|
||||||
const char *pattern = (const char *)sqlite3_value_text(argv[0]);
|
|
||||||
const char* errstr = NULL;
|
|
||||||
int erroff = 0;
|
|
||||||
int vec[500];
|
|
||||||
int n, rc;
|
|
||||||
pcre* re = pcre_compile(pattern, 0, &errstr, &erroff, NULL);
|
|
||||||
rc = pcre_exec(re, NULL, target, strlen(target), 0, 0, vec, 500);
|
|
||||||
if (rc <= 0) {
|
|
||||||
sqlite3_result_error(context, errstr, 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sqlite3_result_int(context, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
__declspec(dllexport)
|
|
||||||
#endif
|
|
||||||
int sqlite3_extension_init(sqlite3 *db, char **errmsg,
|
|
||||||
const sqlite3_api_routines *api) {
|
|
||||||
SQLITE_EXTENSION_INIT2(api);
|
|
||||||
return sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8,
|
|
||||||
(void*)db, regexp_func, NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
It needs to be built as a so/dll shared library. And you need to register
|
|
||||||
the extension module like below.
|
|
||||||
|
|
||||||
sql.Register("sqlite3_with_extensions",
|
|
||||||
&sqlite3.SQLiteDriver{
|
|
||||||
Extensions: []string{
|
|
||||||
"sqlite3_mod_regexp",
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
Then, you can use this extension.
|
|
||||||
|
|
||||||
rows, err := db.Query("select text from mytable where name regexp '^golang'")
|
|
||||||
|
|
||||||
Connection Hook
|
|
||||||
|
|
||||||
You can hook and inject your code when the connection is established. database/sql
|
|
||||||
doesn't provide a way to get native go-sqlite3 interfaces. So if you want,
|
|
||||||
you need to set ConnectHook and get the SQLiteConn.
|
|
||||||
|
|
||||||
sql.Register("sqlite3_with_hook_example",
|
|
||||||
&sqlite3.SQLiteDriver{
|
|
||||||
ConnectHook: func(conn *sqlite3.SQLiteConn) error {
|
|
||||||
sqlite3conn = append(sqlite3conn, conn)
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
Go SQlite3 Extensions
|
|
||||||
|
|
||||||
If you want to register Go functions as SQLite extension functions,
|
|
||||||
call RegisterFunction from ConnectHook.
|
|
||||||
|
|
||||||
regex = func(re, s string) (bool, error) {
|
|
||||||
return regexp.MatchString(re, s)
|
|
||||||
}
|
|
||||||
sql.Register("sqlite3_with_go_func",
|
|
||||||
&sqlite3.SQLiteDriver{
|
|
||||||
ConnectHook: func(conn *sqlite3.SQLiteConn) error {
|
|
||||||
return conn.RegisterFunc("regexp", regex, true)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
See the documentation of RegisterFunc for more details.
|
|
||||||
|
|
||||||
*/
|
|
||||||
package sqlite3
|
|
135
src/vendor/github.com/mattn/go-sqlite3/error.go
generated
vendored
135
src/vendor/github.com/mattn/go-sqlite3/error.go
generated
vendored
@ -1,135 +0,0 @@
|
|||||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
|
|
||||||
//
|
|
||||||
// Use of this source code is governed by an MIT-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package sqlite3
|
|
||||||
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
// ErrNo inherit errno.
|
|
||||||
type ErrNo int
|
|
||||||
|
|
||||||
// ErrNoMask is mask code.
|
|
||||||
const ErrNoMask C.int = 0xff
|
|
||||||
|
|
||||||
// ErrNoExtended is extended errno.
|
|
||||||
type ErrNoExtended int
|
|
||||||
|
|
||||||
// Error implement sqlite error code.
|
|
||||||
type Error struct {
|
|
||||||
Code ErrNo /* The error code returned by SQLite */
|
|
||||||
ExtendedCode ErrNoExtended /* The extended error code returned by SQLite */
|
|
||||||
err string /* The error string returned by sqlite3_errmsg(),
|
|
||||||
this usually contains more specific details. */
|
|
||||||
}
|
|
||||||
|
|
||||||
// result codes from http://www.sqlite.org/c3ref/c_abort.html
|
|
||||||
var (
|
|
||||||
ErrError = ErrNo(1) /* SQL error or missing database */
|
|
||||||
ErrInternal = ErrNo(2) /* Internal logic error in SQLite */
|
|
||||||
ErrPerm = ErrNo(3) /* Access permission denied */
|
|
||||||
ErrAbort = ErrNo(4) /* Callback routine requested an abort */
|
|
||||||
ErrBusy = ErrNo(5) /* The database file is locked */
|
|
||||||
ErrLocked = ErrNo(6) /* A table in the database is locked */
|
|
||||||
ErrNomem = ErrNo(7) /* A malloc() failed */
|
|
||||||
ErrReadonly = ErrNo(8) /* Attempt to write a readonly database */
|
|
||||||
ErrInterrupt = ErrNo(9) /* Operation terminated by sqlite3_interrupt() */
|
|
||||||
ErrIoErr = ErrNo(10) /* Some kind of disk I/O error occurred */
|
|
||||||
ErrCorrupt = ErrNo(11) /* The database disk image is malformed */
|
|
||||||
ErrNotFound = ErrNo(12) /* Unknown opcode in sqlite3_file_control() */
|
|
||||||
ErrFull = ErrNo(13) /* Insertion failed because database is full */
|
|
||||||
ErrCantOpen = ErrNo(14) /* Unable to open the database file */
|
|
||||||
ErrProtocol = ErrNo(15) /* Database lock protocol error */
|
|
||||||
ErrEmpty = ErrNo(16) /* Database is empty */
|
|
||||||
ErrSchema = ErrNo(17) /* The database schema changed */
|
|
||||||
ErrTooBig = ErrNo(18) /* String or BLOB exceeds size limit */
|
|
||||||
ErrConstraint = ErrNo(19) /* Abort due to constraint violation */
|
|
||||||
ErrMismatch = ErrNo(20) /* Data type mismatch */
|
|
||||||
ErrMisuse = ErrNo(21) /* Library used incorrectly */
|
|
||||||
ErrNoLFS = ErrNo(22) /* Uses OS features not supported on host */
|
|
||||||
ErrAuth = ErrNo(23) /* Authorization denied */
|
|
||||||
ErrFormat = ErrNo(24) /* Auxiliary database format error */
|
|
||||||
ErrRange = ErrNo(25) /* 2nd parameter to sqlite3_bind out of range */
|
|
||||||
ErrNotADB = ErrNo(26) /* File opened that is not a database file */
|
|
||||||
ErrNotice = ErrNo(27) /* Notifications from sqlite3_log() */
|
|
||||||
ErrWarning = ErrNo(28) /* Warnings from sqlite3_log() */
|
|
||||||
)
|
|
||||||
|
|
||||||
// Error return error message from errno.
|
|
||||||
func (err ErrNo) Error() string {
|
|
||||||
return Error{Code: err}.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extend return extended errno.
|
|
||||||
func (err ErrNo) Extend(by int) ErrNoExtended {
|
|
||||||
return ErrNoExtended(int(err) | (by << 8))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error return error message that is extended code.
|
|
||||||
func (err ErrNoExtended) Error() string {
|
|
||||||
return Error{Code: ErrNo(C.int(err) & ErrNoMask), ExtendedCode: err}.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (err Error) Error() string {
|
|
||||||
if err.err != "" {
|
|
||||||
return err.err
|
|
||||||
}
|
|
||||||
return errorString(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// result codes from http://www.sqlite.org/c3ref/c_abort_rollback.html
|
|
||||||
var (
|
|
||||||
ErrIoErrRead = ErrIoErr.Extend(1)
|
|
||||||
ErrIoErrShortRead = ErrIoErr.Extend(2)
|
|
||||||
ErrIoErrWrite = ErrIoErr.Extend(3)
|
|
||||||
ErrIoErrFsync = ErrIoErr.Extend(4)
|
|
||||||
ErrIoErrDirFsync = ErrIoErr.Extend(5)
|
|
||||||
ErrIoErrTruncate = ErrIoErr.Extend(6)
|
|
||||||
ErrIoErrFstat = ErrIoErr.Extend(7)
|
|
||||||
ErrIoErrUnlock = ErrIoErr.Extend(8)
|
|
||||||
ErrIoErrRDlock = ErrIoErr.Extend(9)
|
|
||||||
ErrIoErrDelete = ErrIoErr.Extend(10)
|
|
||||||
ErrIoErrBlocked = ErrIoErr.Extend(11)
|
|
||||||
ErrIoErrNoMem = ErrIoErr.Extend(12)
|
|
||||||
ErrIoErrAccess = ErrIoErr.Extend(13)
|
|
||||||
ErrIoErrCheckReservedLock = ErrIoErr.Extend(14)
|
|
||||||
ErrIoErrLock = ErrIoErr.Extend(15)
|
|
||||||
ErrIoErrClose = ErrIoErr.Extend(16)
|
|
||||||
ErrIoErrDirClose = ErrIoErr.Extend(17)
|
|
||||||
ErrIoErrSHMOpen = ErrIoErr.Extend(18)
|
|
||||||
ErrIoErrSHMSize = ErrIoErr.Extend(19)
|
|
||||||
ErrIoErrSHMLock = ErrIoErr.Extend(20)
|
|
||||||
ErrIoErrSHMMap = ErrIoErr.Extend(21)
|
|
||||||
ErrIoErrSeek = ErrIoErr.Extend(22)
|
|
||||||
ErrIoErrDeleteNoent = ErrIoErr.Extend(23)
|
|
||||||
ErrIoErrMMap = ErrIoErr.Extend(24)
|
|
||||||
ErrIoErrGetTempPath = ErrIoErr.Extend(25)
|
|
||||||
ErrIoErrConvPath = ErrIoErr.Extend(26)
|
|
||||||
ErrLockedSharedCache = ErrLocked.Extend(1)
|
|
||||||
ErrBusyRecovery = ErrBusy.Extend(1)
|
|
||||||
ErrBusySnapshot = ErrBusy.Extend(2)
|
|
||||||
ErrCantOpenNoTempDir = ErrCantOpen.Extend(1)
|
|
||||||
ErrCantOpenIsDir = ErrCantOpen.Extend(2)
|
|
||||||
ErrCantOpenFullPath = ErrCantOpen.Extend(3)
|
|
||||||
ErrCantOpenConvPath = ErrCantOpen.Extend(4)
|
|
||||||
ErrCorruptVTab = ErrCorrupt.Extend(1)
|
|
||||||
ErrReadonlyRecovery = ErrReadonly.Extend(1)
|
|
||||||
ErrReadonlyCantLock = ErrReadonly.Extend(2)
|
|
||||||
ErrReadonlyRollback = ErrReadonly.Extend(3)
|
|
||||||
ErrReadonlyDbMoved = ErrReadonly.Extend(4)
|
|
||||||
ErrAbortRollback = ErrAbort.Extend(2)
|
|
||||||
ErrConstraintCheck = ErrConstraint.Extend(1)
|
|
||||||
ErrConstraintCommitHook = ErrConstraint.Extend(2)
|
|
||||||
ErrConstraintForeignKey = ErrConstraint.Extend(3)
|
|
||||||
ErrConstraintFunction = ErrConstraint.Extend(4)
|
|
||||||
ErrConstraintNotNull = ErrConstraint.Extend(5)
|
|
||||||
ErrConstraintPrimaryKey = ErrConstraint.Extend(6)
|
|
||||||
ErrConstraintTrigger = ErrConstraint.Extend(7)
|
|
||||||
ErrConstraintUnique = ErrConstraint.Extend(8)
|
|
||||||
ErrConstraintVTab = ErrConstraint.Extend(9)
|
|
||||||
ErrConstraintRowID = ErrConstraint.Extend(10)
|
|
||||||
ErrNoticeRecoverWAL = ErrNotice.Extend(1)
|
|
||||||
ErrNoticeRecoverRollback = ErrNotice.Extend(2)
|
|
||||||
ErrWarningAutoIndex = ErrWarning.Extend(1)
|
|
||||||
)
|
|
205357
src/vendor/github.com/mattn/go-sqlite3/sqlite3-binding.c
generated
vendored
205357
src/vendor/github.com/mattn/go-sqlite3/sqlite3-binding.c
generated
vendored
File diff suppressed because it is too large
Load Diff
10732
src/vendor/github.com/mattn/go-sqlite3/sqlite3-binding.h
generated
vendored
10732
src/vendor/github.com/mattn/go-sqlite3/sqlite3-binding.h
generated
vendored
File diff suppressed because it is too large
Load Diff
1346
src/vendor/github.com/mattn/go-sqlite3/sqlite3.go
generated
vendored
1346
src/vendor/github.com/mattn/go-sqlite3/sqlite3.go
generated
vendored
File diff suppressed because it is too large
Load Diff
103
src/vendor/github.com/mattn/go-sqlite3/sqlite3_context.go
generated
vendored
103
src/vendor/github.com/mattn/go-sqlite3/sqlite3_context.go
generated
vendored
@ -1,103 +0,0 @@
|
|||||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
|
|
||||||
//
|
|
||||||
// Use of this source code is governed by an MIT-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package sqlite3
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
#ifndef USE_LIBSQLITE3
|
|
||||||
#include <sqlite3-binding.h>
|
|
||||||
#else
|
|
||||||
#include <sqlite3.h>
|
|
||||||
#endif
|
|
||||||
#include <stdlib.h>
|
|
||||||
// These wrappers are necessary because SQLITE_TRANSIENT
|
|
||||||
// is a pointer constant, and cgo doesn't translate them correctly.
|
|
||||||
|
|
||||||
static inline void my_result_text(sqlite3_context *ctx, char *p, int np) {
|
|
||||||
sqlite3_result_text(ctx, p, np, SQLITE_TRANSIENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void my_result_blob(sqlite3_context *ctx, void *p, int np) {
|
|
||||||
sqlite3_result_blob(ctx, p, np, SQLITE_TRANSIENT);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math"
|
|
||||||
"reflect"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
const i64 = unsafe.Sizeof(int(0)) > 4
|
|
||||||
|
|
||||||
// SQLiteContext behave sqlite3_context
|
|
||||||
type SQLiteContext C.sqlite3_context
|
|
||||||
|
|
||||||
// ResultBool sets the result of an SQL function.
|
|
||||||
func (c *SQLiteContext) ResultBool(b bool) {
|
|
||||||
if b {
|
|
||||||
c.ResultInt(1)
|
|
||||||
} else {
|
|
||||||
c.ResultInt(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResultBlob sets the result of an SQL function.
|
|
||||||
// See: sqlite3_result_blob, http://sqlite.org/c3ref/result_blob.html
|
|
||||||
func (c *SQLiteContext) ResultBlob(b []byte) {
|
|
||||||
if i64 && len(b) > math.MaxInt32 {
|
|
||||||
C.sqlite3_result_error_toobig((*C.sqlite3_context)(c))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var p *byte
|
|
||||||
if len(b) > 0 {
|
|
||||||
p = &b[0]
|
|
||||||
}
|
|
||||||
C.my_result_blob((*C.sqlite3_context)(c), unsafe.Pointer(p), C.int(len(b)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResultDouble sets the result of an SQL function.
|
|
||||||
// See: sqlite3_result_double, http://sqlite.org/c3ref/result_blob.html
|
|
||||||
func (c *SQLiteContext) ResultDouble(d float64) {
|
|
||||||
C.sqlite3_result_double((*C.sqlite3_context)(c), C.double(d))
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResultInt sets the result of an SQL function.
|
|
||||||
// See: sqlite3_result_int, http://sqlite.org/c3ref/result_blob.html
|
|
||||||
func (c *SQLiteContext) ResultInt(i int) {
|
|
||||||
if i64 && (i > math.MaxInt32 || i < math.MinInt32) {
|
|
||||||
C.sqlite3_result_int64((*C.sqlite3_context)(c), C.sqlite3_int64(i))
|
|
||||||
} else {
|
|
||||||
C.sqlite3_result_int((*C.sqlite3_context)(c), C.int(i))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResultInt64 sets the result of an SQL function.
|
|
||||||
// See: sqlite3_result_int64, http://sqlite.org/c3ref/result_blob.html
|
|
||||||
func (c *SQLiteContext) ResultInt64(i int64) {
|
|
||||||
C.sqlite3_result_int64((*C.sqlite3_context)(c), C.sqlite3_int64(i))
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResultNull sets the result of an SQL function.
|
|
||||||
// See: sqlite3_result_null, http://sqlite.org/c3ref/result_blob.html
|
|
||||||
func (c *SQLiteContext) ResultNull() {
|
|
||||||
C.sqlite3_result_null((*C.sqlite3_context)(c))
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResultText sets the result of an SQL function.
|
|
||||||
// See: sqlite3_result_text, http://sqlite.org/c3ref/result_blob.html
|
|
||||||
func (c *SQLiteContext) ResultText(s string) {
|
|
||||||
h := (*reflect.StringHeader)(unsafe.Pointer(&s))
|
|
||||||
cs, l := (*C.char)(unsafe.Pointer(h.Data)), C.int(h.Len)
|
|
||||||
C.my_result_text((*C.sqlite3_context)(c), cs, l)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResultZeroblob sets the result of an SQL function.
|
|
||||||
// See: sqlite3_result_zeroblob, http://sqlite.org/c3ref/result_blob.html
|
|
||||||
func (c *SQLiteContext) ResultZeroblob(n int) {
|
|
||||||
C.sqlite3_result_zeroblob((*C.sqlite3_context)(c), C.int(n))
|
|
||||||
}
|
|
13
src/vendor/github.com/mattn/go-sqlite3/sqlite3_fts5.go
generated
vendored
13
src/vendor/github.com/mattn/go-sqlite3/sqlite3_fts5.go
generated
vendored
@ -1,13 +0,0 @@
|
|||||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
|
|
||||||
//
|
|
||||||
// Use of this source code is governed by an MIT-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
// +build fts5
|
|
||||||
|
|
||||||
package sqlite3
|
|
||||||
|
|
||||||
/*
|
|
||||||
#cgo CFLAGS: -DSQLITE_ENABLE_FTS5
|
|
||||||
#cgo LDFLAGS: -lm
|
|
||||||
*/
|
|
||||||
import "C"
|
|
69
src/vendor/github.com/mattn/go-sqlite3/sqlite3_go18.go
generated
vendored
69
src/vendor/github.com/mattn/go-sqlite3/sqlite3_go18.go
generated
vendored
@ -1,69 +0,0 @@
|
|||||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
|
|
||||||
//
|
|
||||||
// Use of this source code is governed by an MIT-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build go1.8
|
|
||||||
|
|
||||||
package sqlite3
|
|
||||||
|
|
||||||
import (
|
|
||||||
"database/sql/driver"
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
"context"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Ping implement Pinger.
|
|
||||||
func (c *SQLiteConn) Ping(ctx context.Context) error {
|
|
||||||
if c.db == nil {
|
|
||||||
return errors.New("Connection was closed")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// QueryContext implement QueryerContext.
|
|
||||||
func (c *SQLiteConn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) {
|
|
||||||
list := make([]namedValue, len(args))
|
|
||||||
for i, nv := range args {
|
|
||||||
list[i] = namedValue(nv)
|
|
||||||
}
|
|
||||||
return c.query(ctx, query, list)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExecContext implement ExecerContext.
|
|
||||||
func (c *SQLiteConn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) {
|
|
||||||
list := make([]namedValue, len(args))
|
|
||||||
for i, nv := range args {
|
|
||||||
list[i] = namedValue(nv)
|
|
||||||
}
|
|
||||||
return c.exec(ctx, query, list)
|
|
||||||
}
|
|
||||||
|
|
||||||
// PrepareContext implement ConnPrepareContext.
|
|
||||||
func (c *SQLiteConn) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) {
|
|
||||||
return c.prepare(ctx, query)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BeginTx implement ConnBeginTx.
|
|
||||||
func (c *SQLiteConn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) {
|
|
||||||
return c.begin(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
// QueryContext implement QueryerContext.
|
|
||||||
func (s *SQLiteStmt) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) {
|
|
||||||
list := make([]namedValue, len(args))
|
|
||||||
for i, nv := range args {
|
|
||||||
list[i] = namedValue(nv)
|
|
||||||
}
|
|
||||||
return s.query(ctx, list)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExecContext implement ExecerContext.
|
|
||||||
func (s *SQLiteStmt) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) {
|
|
||||||
list := make([]namedValue, len(args))
|
|
||||||
for i, nv := range args {
|
|
||||||
list[i] = namedValue(nv)
|
|
||||||
}
|
|
||||||
return s.exec(ctx, list)
|
|
||||||
}
|
|
13
src/vendor/github.com/mattn/go-sqlite3/sqlite3_icu.go
generated
vendored
13
src/vendor/github.com/mattn/go-sqlite3/sqlite3_icu.go
generated
vendored
@ -1,13 +0,0 @@
|
|||||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
|
|
||||||
//
|
|
||||||
// Use of this source code is governed by an MIT-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
// +build icu
|
|
||||||
|
|
||||||
package sqlite3
|
|
||||||
|
|
||||||
/*
|
|
||||||
#cgo LDFLAGS: -licuuc -licui18n
|
|
||||||
#cgo CFLAGS: -DSQLITE_ENABLE_ICU
|
|
||||||
*/
|
|
||||||
import "C"
|
|
12
src/vendor/github.com/mattn/go-sqlite3/sqlite3_json1.go
generated
vendored
12
src/vendor/github.com/mattn/go-sqlite3/sqlite3_json1.go
generated
vendored
@ -1,12 +0,0 @@
|
|||||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
|
|
||||||
//
|
|
||||||
// Use of this source code is governed by an MIT-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
// +build json1
|
|
||||||
|
|
||||||
package sqlite3
|
|
||||||
|
|
||||||
/*
|
|
||||||
#cgo CFLAGS: -DSQLITE_ENABLE_JSON1
|
|
||||||
*/
|
|
||||||
import "C"
|
|
15
src/vendor/github.com/mattn/go-sqlite3/sqlite3_libsqlite3.go
generated
vendored
15
src/vendor/github.com/mattn/go-sqlite3/sqlite3_libsqlite3.go
generated
vendored
@ -1,15 +0,0 @@
|
|||||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
|
|
||||||
//
|
|
||||||
// Use of this source code is governed by an MIT-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
// +build libsqlite3
|
|
||||||
|
|
||||||
package sqlite3
|
|
||||||
|
|
||||||
/*
|
|
||||||
#cgo CFLAGS: -DUSE_LIBSQLITE3
|
|
||||||
#cgo linux LDFLAGS: -lsqlite3
|
|
||||||
#cgo darwin LDFLAGS: -L/usr/local/opt/sqlite/lib -lsqlite3
|
|
||||||
#cgo solaris LDFLAGS: -lsqlite3
|
|
||||||
*/
|
|
||||||
import "C"
|
|
69
src/vendor/github.com/mattn/go-sqlite3/sqlite3_load_extension.go
generated
vendored
69
src/vendor/github.com/mattn/go-sqlite3/sqlite3_load_extension.go
generated
vendored
@ -1,69 +0,0 @@
|
|||||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
|
|
||||||
//
|
|
||||||
// Use of this source code is governed by an MIT-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
// +build !sqlite_omit_load_extension
|
|
||||||
|
|
||||||
package sqlite3
|
|
||||||
|
|
||||||
/*
|
|
||||||
#ifndef USE_LIBSQLITE3
|
|
||||||
#include <sqlite3-binding.h>
|
|
||||||
#else
|
|
||||||
#include <sqlite3.h>
|
|
||||||
#endif
|
|
||||||
#include <stdlib.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (c *SQLiteConn) loadExtensions(extensions []string) error {
|
|
||||||
rv := C.sqlite3_enable_load_extension(c.db, 1)
|
|
||||||
if rv != C.SQLITE_OK {
|
|
||||||
return errors.New(C.GoString(C.sqlite3_errmsg(c.db)))
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, extension := range extensions {
|
|
||||||
cext := C.CString(extension)
|
|
||||||
defer C.free(unsafe.Pointer(cext))
|
|
||||||
rv = C.sqlite3_load_extension(c.db, cext, nil, nil)
|
|
||||||
if rv != C.SQLITE_OK {
|
|
||||||
C.sqlite3_enable_load_extension(c.db, 0)
|
|
||||||
return errors.New(C.GoString(C.sqlite3_errmsg(c.db)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = C.sqlite3_enable_load_extension(c.db, 0)
|
|
||||||
if rv != C.SQLITE_OK {
|
|
||||||
return errors.New(C.GoString(C.sqlite3_errmsg(c.db)))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadExtension load the sqlite3 extension.
|
|
||||||
func (c *SQLiteConn) LoadExtension(lib string, entry string) error {
|
|
||||||
rv := C.sqlite3_enable_load_extension(c.db, 1)
|
|
||||||
if rv != C.SQLITE_OK {
|
|
||||||
return errors.New(C.GoString(C.sqlite3_errmsg(c.db)))
|
|
||||||
}
|
|
||||||
|
|
||||||
clib := C.CString(lib)
|
|
||||||
defer C.free(unsafe.Pointer(clib))
|
|
||||||
centry := C.CString(entry)
|
|
||||||
defer C.free(unsafe.Pointer(centry))
|
|
||||||
|
|
||||||
rv = C.sqlite3_load_extension(c.db, clib, centry, nil)
|
|
||||||
if rv != C.SQLITE_OK {
|
|
||||||
return errors.New(C.GoString(C.sqlite3_errmsg(c.db)))
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = C.sqlite3_enable_load_extension(c.db, 0)
|
|
||||||
if rv != C.SQLITE_OK {
|
|
||||||
return errors.New(C.GoString(C.sqlite3_errmsg(c.db)))
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
23
src/vendor/github.com/mattn/go-sqlite3/sqlite3_omit_load_extension.go
generated
vendored
23
src/vendor/github.com/mattn/go-sqlite3/sqlite3_omit_load_extension.go
generated
vendored
@ -1,23 +0,0 @@
|
|||||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
|
|
||||||
//
|
|
||||||
// Use of this source code is governed by an MIT-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
// +build sqlite_omit_load_extension
|
|
||||||
|
|
||||||
package sqlite3
|
|
||||||
|
|
||||||
/*
|
|
||||||
#cgo CFLAGS: -DSQLITE_OMIT_LOAD_EXTENSION
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (c *SQLiteConn) loadExtensions(extensions []string) error {
|
|
||||||
return errors.New("Extensions have been disabled for static builds")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *SQLiteConn) LoadExtension(lib string, entry string) error {
|
|
||||||
return errors.New("Extensions have been disabled for static builds")
|
|
||||||
}
|
|
14
src/vendor/github.com/mattn/go-sqlite3/sqlite3_other.go
generated
vendored
14
src/vendor/github.com/mattn/go-sqlite3/sqlite3_other.go
generated
vendored
@ -1,14 +0,0 @@
|
|||||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
|
|
||||||
//
|
|
||||||
// Use of this source code is governed by an MIT-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
// +build !windows
|
|
||||||
|
|
||||||
package sqlite3
|
|
||||||
|
|
||||||
/*
|
|
||||||
#cgo CFLAGS: -I.
|
|
||||||
#cgo linux LDFLAGS: -ldl
|
|
||||||
#cgo solaris LDFLAGS: -lc
|
|
||||||
*/
|
|
||||||
import "C"
|
|
285
src/vendor/github.com/mattn/go-sqlite3/sqlite3_trace.go
generated
vendored
285
src/vendor/github.com/mattn/go-sqlite3/sqlite3_trace.go
generated
vendored
@ -1,285 +0,0 @@
|
|||||||
// Copyright (C) 2016 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
|
|
||||||
//
|
|
||||||
// Use of this source code is governed by an MIT-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
// +build trace
|
|
||||||
|
|
||||||
package sqlite3
|
|
||||||
|
|
||||||
/*
|
|
||||||
#ifndef USE_LIBSQLITE3
|
|
||||||
#include <sqlite3-binding.h>
|
|
||||||
#else
|
|
||||||
#include <sqlite3.h>
|
|
||||||
#endif
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
int traceCallbackTrampoline(unsigned int traceEventCode, void *ctx, void *p, void *x);
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Trace... constants identify the possible events causing callback invocation.
|
|
||||||
// Values are same as the corresponding SQLite Trace Event Codes.
|
|
||||||
const (
|
|
||||||
TraceStmt = C.SQLITE_TRACE_STMT
|
|
||||||
TraceProfile = C.SQLITE_TRACE_PROFILE
|
|
||||||
TraceRow = C.SQLITE_TRACE_ROW
|
|
||||||
TraceClose = C.SQLITE_TRACE_CLOSE
|
|
||||||
)
|
|
||||||
|
|
||||||
type TraceInfo struct {
|
|
||||||
// Pack together the shorter fields, to keep the struct smaller.
|
|
||||||
// On a 64-bit machine there would be padding
|
|
||||||
// between EventCode and ConnHandle; having AutoCommit here is "free":
|
|
||||||
EventCode uint32
|
|
||||||
AutoCommit bool
|
|
||||||
ConnHandle uintptr
|
|
||||||
|
|
||||||
// Usually filled, unless EventCode = TraceClose = SQLITE_TRACE_CLOSE:
|
|
||||||
// identifier for a prepared statement:
|
|
||||||
StmtHandle uintptr
|
|
||||||
|
|
||||||
// Two strings filled when EventCode = TraceStmt = SQLITE_TRACE_STMT:
|
|
||||||
// (1) either the unexpanded SQL text of the prepared statement, or
|
|
||||||
// an SQL comment that indicates the invocation of a trigger;
|
|
||||||
// (2) expanded SQL, if requested and if (1) is not an SQL comment.
|
|
||||||
StmtOrTrigger string
|
|
||||||
ExpandedSQL string // only if requested (TraceConfig.WantExpandedSQL = true)
|
|
||||||
|
|
||||||
// filled when EventCode = TraceProfile = SQLITE_TRACE_PROFILE:
|
|
||||||
// estimated number of nanoseconds that the prepared statement took to run:
|
|
||||||
RunTimeNanosec int64
|
|
||||||
|
|
||||||
DBError Error
|
|
||||||
}
|
|
||||||
|
|
||||||
// TraceUserCallback gives the signature for a trace function
|
|
||||||
// provided by the user (Go application programmer).
|
|
||||||
// SQLite 3.14 documentation (as of September 2, 2016)
|
|
||||||
// for SQL Trace Hook = sqlite3_trace_v2():
|
|
||||||
// The integer return value from the callback is currently ignored,
|
|
||||||
// though this may change in future releases. Callback implementations
|
|
||||||
// should return zero to ensure future compatibility.
|
|
||||||
type TraceUserCallback func(TraceInfo) int
|
|
||||||
|
|
||||||
type TraceConfig struct {
|
|
||||||
Callback TraceUserCallback
|
|
||||||
EventMask C.uint
|
|
||||||
WantExpandedSQL bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func fillDBError(dbErr *Error, db *C.sqlite3) {
|
|
||||||
// See SQLiteConn.lastError(), in file 'sqlite3.go' at the time of writing (Sept 5, 2016)
|
|
||||||
dbErr.Code = ErrNo(C.sqlite3_errcode(db))
|
|
||||||
dbErr.ExtendedCode = ErrNoExtended(C.sqlite3_extended_errcode(db))
|
|
||||||
dbErr.err = C.GoString(C.sqlite3_errmsg(db))
|
|
||||||
}
|
|
||||||
|
|
||||||
func fillExpandedSQL(info *TraceInfo, db *C.sqlite3, pStmt unsafe.Pointer) {
|
|
||||||
if pStmt == nil {
|
|
||||||
panic("No SQLite statement pointer in P arg of trace_v2 callback")
|
|
||||||
}
|
|
||||||
|
|
||||||
expSQLiteCStr := C.sqlite3_expanded_sql((*C.sqlite3_stmt)(pStmt))
|
|
||||||
if expSQLiteCStr == nil {
|
|
||||||
fillDBError(&info.DBError, db)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
info.ExpandedSQL = C.GoString(expSQLiteCStr)
|
|
||||||
}
|
|
||||||
|
|
||||||
//export traceCallbackTrampoline
|
|
||||||
func traceCallbackTrampoline(
|
|
||||||
traceEventCode C.uint,
|
|
||||||
// Parameter named 'C' in SQLite docs = Context given at registration:
|
|
||||||
ctx unsafe.Pointer,
|
|
||||||
// Parameter named 'P' in SQLite docs (Primary event data?):
|
|
||||||
p unsafe.Pointer,
|
|
||||||
// Parameter named 'X' in SQLite docs (eXtra event data?):
|
|
||||||
xValue unsafe.Pointer) C.int {
|
|
||||||
|
|
||||||
if ctx == nil {
|
|
||||||
panic(fmt.Sprintf("No context (ev 0x%x)", traceEventCode))
|
|
||||||
}
|
|
||||||
|
|
||||||
contextDB := (*C.sqlite3)(ctx)
|
|
||||||
connHandle := uintptr(ctx)
|
|
||||||
|
|
||||||
var traceConf TraceConfig
|
|
||||||
var found bool
|
|
||||||
if traceEventCode == TraceClose {
|
|
||||||
// clean up traceMap: 'pop' means get and delete
|
|
||||||
traceConf, found = popTraceMapping(connHandle)
|
|
||||||
} else {
|
|
||||||
traceConf, found = lookupTraceMapping(connHandle)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !found {
|
|
||||||
panic(fmt.Sprintf("Mapping not found for handle 0x%x (ev 0x%x)",
|
|
||||||
connHandle, traceEventCode))
|
|
||||||
}
|
|
||||||
|
|
||||||
var info TraceInfo
|
|
||||||
|
|
||||||
info.EventCode = uint32(traceEventCode)
|
|
||||||
info.AutoCommit = (int(C.sqlite3_get_autocommit(contextDB)) != 0)
|
|
||||||
info.ConnHandle = connHandle
|
|
||||||
|
|
||||||
switch traceEventCode {
|
|
||||||
case TraceStmt:
|
|
||||||
info.StmtHandle = uintptr(p)
|
|
||||||
|
|
||||||
var xStr string
|
|
||||||
if xValue != nil {
|
|
||||||
xStr = C.GoString((*C.char)(xValue))
|
|
||||||
}
|
|
||||||
info.StmtOrTrigger = xStr
|
|
||||||
if !strings.HasPrefix(xStr, "--") {
|
|
||||||
// Not SQL comment, therefore the current event
|
|
||||||
// is not related to a trigger.
|
|
||||||
// The user might want to receive the expanded SQL;
|
|
||||||
// let's check:
|
|
||||||
if traceConf.WantExpandedSQL {
|
|
||||||
fillExpandedSQL(&info, contextDB, p)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case TraceProfile:
|
|
||||||
info.StmtHandle = uintptr(p)
|
|
||||||
|
|
||||||
if xValue == nil {
|
|
||||||
panic("NULL pointer in X arg of trace_v2 callback for SQLITE_TRACE_PROFILE event")
|
|
||||||
}
|
|
||||||
|
|
||||||
info.RunTimeNanosec = *(*int64)(xValue)
|
|
||||||
|
|
||||||
// sample the error //TODO: is it safe? is it useful?
|
|
||||||
fillDBError(&info.DBError, contextDB)
|
|
||||||
|
|
||||||
case TraceRow:
|
|
||||||
info.StmtHandle = uintptr(p)
|
|
||||||
|
|
||||||
case TraceClose:
|
|
||||||
handle := uintptr(p)
|
|
||||||
if handle != info.ConnHandle {
|
|
||||||
panic(fmt.Sprintf("Different conn handle 0x%x (expected 0x%x) in SQLITE_TRACE_CLOSE event.",
|
|
||||||
handle, info.ConnHandle))
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
// Pass unsupported events to the user callback (if configured);
|
|
||||||
// let the user callback decide whether to panic or ignore them.
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do not execute user callback when the event was not requested by user!
|
|
||||||
// Remember that the Close event is always selected when
|
|
||||||
// registering this callback trampoline with SQLite --- for cleanup.
|
|
||||||
// In the future there may be more events forced to "selected" in SQLite
|
|
||||||
// for the driver's needs.
|
|
||||||
if traceConf.EventMask&traceEventCode == 0 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
r := 0
|
|
||||||
if traceConf.Callback != nil {
|
|
||||||
r = traceConf.Callback(info)
|
|
||||||
}
|
|
||||||
return C.int(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
type traceMapEntry struct {
|
|
||||||
config TraceConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
var traceMapLock sync.Mutex
|
|
||||||
var traceMap = make(map[uintptr]traceMapEntry)
|
|
||||||
|
|
||||||
func addTraceMapping(connHandle uintptr, traceConf TraceConfig) {
|
|
||||||
traceMapLock.Lock()
|
|
||||||
defer traceMapLock.Unlock()
|
|
||||||
|
|
||||||
oldEntryCopy, found := traceMap[connHandle]
|
|
||||||
if found {
|
|
||||||
panic(fmt.Sprintf("Adding trace config %v: handle 0x%x already registered (%v).",
|
|
||||||
traceConf, connHandle, oldEntryCopy.config))
|
|
||||||
}
|
|
||||||
traceMap[connHandle] = traceMapEntry{config: traceConf}
|
|
||||||
fmt.Printf("Added trace config %v: handle 0x%x.\n", traceConf, connHandle)
|
|
||||||
}
|
|
||||||
|
|
||||||
func lookupTraceMapping(connHandle uintptr) (TraceConfig, bool) {
|
|
||||||
traceMapLock.Lock()
|
|
||||||
defer traceMapLock.Unlock()
|
|
||||||
|
|
||||||
entryCopy, found := traceMap[connHandle]
|
|
||||||
return entryCopy.config, found
|
|
||||||
}
|
|
||||||
|
|
||||||
// 'pop' = get and delete from map before returning the value to the caller
|
|
||||||
func popTraceMapping(connHandle uintptr) (TraceConfig, bool) {
|
|
||||||
traceMapLock.Lock()
|
|
||||||
defer traceMapLock.Unlock()
|
|
||||||
|
|
||||||
entryCopy, found := traceMap[connHandle]
|
|
||||||
if found {
|
|
||||||
delete(traceMap, connHandle)
|
|
||||||
fmt.Printf("Pop handle 0x%x: deleted trace config %v.\n", connHandle, entryCopy.config)
|
|
||||||
}
|
|
||||||
return entryCopy.config, found
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetTrace installs or removes the trace callback for the given database connection.
|
|
||||||
// It's not named 'RegisterTrace' because only one callback can be kept and called.
|
|
||||||
// Calling SetTrace a second time on same database connection
|
|
||||||
// overrides (cancels) any prior callback and all its settings:
|
|
||||||
// event mask, etc.
|
|
||||||
func (c *SQLiteConn) SetTrace(requested *TraceConfig) error {
|
|
||||||
connHandle := uintptr(unsafe.Pointer(c.db))
|
|
||||||
|
|
||||||
_, _ = popTraceMapping(connHandle)
|
|
||||||
|
|
||||||
if requested == nil {
|
|
||||||
// The traceMap entry was deleted already by popTraceMapping():
|
|
||||||
// can disable all events now, no need to watch for TraceClose.
|
|
||||||
err := c.setSQLiteTrace(0)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
reqCopy := *requested
|
|
||||||
|
|
||||||
// Disable potentially expensive operations
|
|
||||||
// if their result will not be used. We are doing this
|
|
||||||
// just in case the caller provided nonsensical input.
|
|
||||||
if reqCopy.EventMask&TraceStmt == 0 {
|
|
||||||
reqCopy.WantExpandedSQL = false
|
|
||||||
}
|
|
||||||
|
|
||||||
addTraceMapping(connHandle, reqCopy)
|
|
||||||
|
|
||||||
// The callback trampoline function does cleanup on Close event,
|
|
||||||
// regardless of the presence or absence of the user callback.
|
|
||||||
// Therefore it needs the Close event to be selected:
|
|
||||||
actualEventMask := uint(reqCopy.EventMask | TraceClose)
|
|
||||||
err := c.setSQLiteTrace(actualEventMask)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *SQLiteConn) setSQLiteTrace(sqliteEventMask uint) error {
|
|
||||||
rv := C.sqlite3_trace_v2(c.db,
|
|
||||||
C.uint(sqliteEventMask),
|
|
||||||
(*[0]byte)(unsafe.Pointer(C.traceCallbackTrampoline)),
|
|
||||||
unsafe.Pointer(c.db)) // Fourth arg is same as first: we are
|
|
||||||
// passing the database connection handle as callback context.
|
|
||||||
|
|
||||||
if rv != C.SQLITE_OK {
|
|
||||||
return c.lastError()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
57
src/vendor/github.com/mattn/go-sqlite3/sqlite3_type.go
generated
vendored
57
src/vendor/github.com/mattn/go-sqlite3/sqlite3_type.go
generated
vendored
@ -1,57 +0,0 @@
|
|||||||
package sqlite3
|
|
||||||
|
|
||||||
/*
|
|
||||||
#ifndef USE_LIBSQLITE3
|
|
||||||
#include <sqlite3-binding.h>
|
|
||||||
#else
|
|
||||||
#include <sqlite3.h>
|
|
||||||
#endif
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ColumnTypeDatabaseTypeName implement RowsColumnTypeDatabaseTypeName.
|
|
||||||
func (rc *SQLiteRows) ColumnTypeDatabaseTypeName(i int) string {
|
|
||||||
return C.GoString(C.sqlite3_column_decltype(rc.s.s, C.int(i)))
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
func (rc *SQLiteRows) ColumnTypeLength(index int) (length int64, ok bool) {
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rc *SQLiteRows) ColumnTypePrecisionScale(index int) (precision, scale int64, ok bool) {
|
|
||||||
return 0, 0, false
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// ColumnTypeNullable implement RowsColumnTypeNullable.
|
|
||||||
func (rc *SQLiteRows) ColumnTypeNullable(i int) (nullable, ok bool) {
|
|
||||||
return true, true
|
|
||||||
}
|
|
||||||
|
|
||||||
// ColumnTypeScanType implement RowsColumnTypeScanType.
|
|
||||||
func (rc *SQLiteRows) ColumnTypeScanType(i int) reflect.Type {
|
|
||||||
switch C.sqlite3_column_type(rc.s.s, C.int(i)) {
|
|
||||||
case C.SQLITE_INTEGER:
|
|
||||||
switch C.GoString(C.sqlite3_column_decltype(rc.s.s, C.int(i))) {
|
|
||||||
case "timestamp", "datetime", "date":
|
|
||||||
return reflect.TypeOf(time.Time{})
|
|
||||||
case "boolean":
|
|
||||||
return reflect.TypeOf(false)
|
|
||||||
}
|
|
||||||
return reflect.TypeOf(int64(0))
|
|
||||||
case C.SQLITE_FLOAT:
|
|
||||||
return reflect.TypeOf(float64(0))
|
|
||||||
case C.SQLITE_BLOB:
|
|
||||||
return reflect.SliceOf(reflect.TypeOf(byte(0)))
|
|
||||||
case C.SQLITE_NULL:
|
|
||||||
return reflect.TypeOf(nil)
|
|
||||||
case C.SQLITE_TEXT:
|
|
||||||
return reflect.TypeOf("")
|
|
||||||
}
|
|
||||||
return reflect.SliceOf(reflect.TypeOf(byte(0)))
|
|
||||||
}
|
|
646
src/vendor/github.com/mattn/go-sqlite3/sqlite3_vtable.go
generated
vendored
646
src/vendor/github.com/mattn/go-sqlite3/sqlite3_vtable.go
generated
vendored
@ -1,646 +0,0 @@
|
|||||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
|
|
||||||
//
|
|
||||||
// Use of this source code is governed by an MIT-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
// +build vtable
|
|
||||||
|
|
||||||
package sqlite3
|
|
||||||
|
|
||||||
/*
|
|
||||||
#cgo CFLAGS: -std=gnu99
|
|
||||||
#cgo CFLAGS: -DSQLITE_ENABLE_RTREE -DSQLITE_THREADSAFE
|
|
||||||
#cgo CFLAGS: -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_FTS4_UNICODE61
|
|
||||||
#cgo CFLAGS: -DSQLITE_TRACE_SIZE_LIMIT=15
|
|
||||||
#cgo CFLAGS: -DSQLITE_ENABLE_COLUMN_METADATA=1
|
|
||||||
#cgo CFLAGS: -Wno-deprecated-declarations
|
|
||||||
|
|
||||||
#ifndef USE_LIBSQLITE3
|
|
||||||
#include <sqlite3-binding.h>
|
|
||||||
#else
|
|
||||||
#include <sqlite3.h>
|
|
||||||
#endif
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <memory.h>
|
|
||||||
|
|
||||||
static inline char *_sqlite3_mprintf(char *zFormat, char *arg) {
|
|
||||||
return sqlite3_mprintf(zFormat, arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct goVTab goVTab;
|
|
||||||
|
|
||||||
struct goVTab {
|
|
||||||
sqlite3_vtab base;
|
|
||||||
void *vTab;
|
|
||||||
};
|
|
||||||
|
|
||||||
uintptr_t goMInit(void *db, void *pAux, int argc, char **argv, char **pzErr, int isCreate);
|
|
||||||
|
|
||||||
static int cXInit(sqlite3 *db, void *pAux, int argc, const char *const*argv, sqlite3_vtab **ppVTab, char **pzErr, int isCreate) {
|
|
||||||
void *vTab = (void *)goMInit(db, pAux, argc, (char**)argv, pzErr, isCreate);
|
|
||||||
if (!vTab || *pzErr) {
|
|
||||||
return SQLITE_ERROR;
|
|
||||||
}
|
|
||||||
goVTab *pvTab = (goVTab *)sqlite3_malloc(sizeof(goVTab));
|
|
||||||
if (!pvTab) {
|
|
||||||
*pzErr = sqlite3_mprintf("%s", "Out of memory");
|
|
||||||
return SQLITE_NOMEM;
|
|
||||||
}
|
|
||||||
memset(pvTab, 0, sizeof(goVTab));
|
|
||||||
pvTab->vTab = vTab;
|
|
||||||
|
|
||||||
*ppVTab = (sqlite3_vtab *)pvTab;
|
|
||||||
*pzErr = 0;
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int cXCreate(sqlite3 *db, void *pAux, int argc, const char *const*argv, sqlite3_vtab **ppVTab, char **pzErr) {
|
|
||||||
return cXInit(db, pAux, argc, argv, ppVTab, pzErr, 1);
|
|
||||||
}
|
|
||||||
static inline int cXConnect(sqlite3 *db, void *pAux, int argc, const char *const*argv, sqlite3_vtab **ppVTab, char **pzErr) {
|
|
||||||
return cXInit(db, pAux, argc, argv, ppVTab, pzErr, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
char* goVBestIndex(void *pVTab, void *icp);
|
|
||||||
|
|
||||||
static inline int cXBestIndex(sqlite3_vtab *pVTab, sqlite3_index_info *info) {
|
|
||||||
char *pzErr = goVBestIndex(((goVTab*)pVTab)->vTab, info);
|
|
||||||
if (pzErr) {
|
|
||||||
if (pVTab->zErrMsg)
|
|
||||||
sqlite3_free(pVTab->zErrMsg);
|
|
||||||
pVTab->zErrMsg = pzErr;
|
|
||||||
return SQLITE_ERROR;
|
|
||||||
}
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* goVRelease(void *pVTab, int isDestroy);
|
|
||||||
|
|
||||||
static int cXRelease(sqlite3_vtab *pVTab, int isDestroy) {
|
|
||||||
char *pzErr = goVRelease(((goVTab*)pVTab)->vTab, isDestroy);
|
|
||||||
if (pzErr) {
|
|
||||||
if (pVTab->zErrMsg)
|
|
||||||
sqlite3_free(pVTab->zErrMsg);
|
|
||||||
pVTab->zErrMsg = pzErr;
|
|
||||||
return SQLITE_ERROR;
|
|
||||||
}
|
|
||||||
if (pVTab->zErrMsg)
|
|
||||||
sqlite3_free(pVTab->zErrMsg);
|
|
||||||
sqlite3_free(pVTab);
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int cXDisconnect(sqlite3_vtab *pVTab) {
|
|
||||||
return cXRelease(pVTab, 0);
|
|
||||||
}
|
|
||||||
static inline int cXDestroy(sqlite3_vtab *pVTab) {
|
|
||||||
return cXRelease(pVTab, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct goVTabCursor goVTabCursor;
|
|
||||||
|
|
||||||
struct goVTabCursor {
|
|
||||||
sqlite3_vtab_cursor base;
|
|
||||||
void *vTabCursor;
|
|
||||||
};
|
|
||||||
|
|
||||||
uintptr_t goVOpen(void *pVTab, char **pzErr);
|
|
||||||
|
|
||||||
static int cXOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor) {
|
|
||||||
void *vTabCursor = (void *)goVOpen(((goVTab*)pVTab)->vTab, &(pVTab->zErrMsg));
|
|
||||||
goVTabCursor *pCursor = (goVTabCursor *)sqlite3_malloc(sizeof(goVTabCursor));
|
|
||||||
if (!pCursor) {
|
|
||||||
return SQLITE_NOMEM;
|
|
||||||
}
|
|
||||||
memset(pCursor, 0, sizeof(goVTabCursor));
|
|
||||||
pCursor->vTabCursor = vTabCursor;
|
|
||||||
*ppCursor = (sqlite3_vtab_cursor *)pCursor;
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int setErrMsg(sqlite3_vtab_cursor *pCursor, char *pzErr) {
|
|
||||||
if (pCursor->pVtab->zErrMsg)
|
|
||||||
sqlite3_free(pCursor->pVtab->zErrMsg);
|
|
||||||
pCursor->pVtab->zErrMsg = pzErr;
|
|
||||||
return SQLITE_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* goVClose(void *pCursor);
|
|
||||||
|
|
||||||
static int cXClose(sqlite3_vtab_cursor *pCursor) {
|
|
||||||
char *pzErr = goVClose(((goVTabCursor*)pCursor)->vTabCursor);
|
|
||||||
if (pzErr) {
|
|
||||||
return setErrMsg(pCursor, pzErr);
|
|
||||||
}
|
|
||||||
sqlite3_free(pCursor);
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* goVFilter(void *pCursor, int idxNum, char* idxName, int argc, sqlite3_value **argv);
|
|
||||||
|
|
||||||
static int cXFilter(sqlite3_vtab_cursor *pCursor, int idxNum, const char *idxStr, int argc, sqlite3_value **argv) {
|
|
||||||
char *pzErr = goVFilter(((goVTabCursor*)pCursor)->vTabCursor, idxNum, (char*)idxStr, argc, argv);
|
|
||||||
if (pzErr) {
|
|
||||||
return setErrMsg(pCursor, pzErr);
|
|
||||||
}
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* goVNext(void *pCursor);
|
|
||||||
|
|
||||||
static int cXNext(sqlite3_vtab_cursor *pCursor) {
|
|
||||||
char *pzErr = goVNext(((goVTabCursor*)pCursor)->vTabCursor);
|
|
||||||
if (pzErr) {
|
|
||||||
return setErrMsg(pCursor, pzErr);
|
|
||||||
}
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int goVEof(void *pCursor);
|
|
||||||
|
|
||||||
static inline int cXEof(sqlite3_vtab_cursor *pCursor) {
|
|
||||||
return goVEof(((goVTabCursor*)pCursor)->vTabCursor);
|
|
||||||
}
|
|
||||||
|
|
||||||
char* goVColumn(void *pCursor, void *cp, int col);
|
|
||||||
|
|
||||||
static int cXColumn(sqlite3_vtab_cursor *pCursor, sqlite3_context *ctx, int i) {
|
|
||||||
char *pzErr = goVColumn(((goVTabCursor*)pCursor)->vTabCursor, ctx, i);
|
|
||||||
if (pzErr) {
|
|
||||||
return setErrMsg(pCursor, pzErr);
|
|
||||||
}
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* goVRowid(void *pCursor, sqlite3_int64 *pRowid);
|
|
||||||
|
|
||||||
static int cXRowid(sqlite3_vtab_cursor *pCursor, sqlite3_int64 *pRowid) {
|
|
||||||
char *pzErr = goVRowid(((goVTabCursor*)pCursor)->vTabCursor, pRowid);
|
|
||||||
if (pzErr) {
|
|
||||||
return setErrMsg(pCursor, pzErr);
|
|
||||||
}
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* goVUpdate(void *pVTab, int argc, sqlite3_value **argv, sqlite3_int64 *pRowid);
|
|
||||||
|
|
||||||
static int cXUpdate(sqlite3_vtab *pVTab, int argc, sqlite3_value **argv, sqlite3_int64 *pRowid) {
|
|
||||||
char *pzErr = goVUpdate(((goVTab*)pVTab)->vTab, argc, argv, pRowid);
|
|
||||||
if (pzErr) {
|
|
||||||
if (pVTab->zErrMsg)
|
|
||||||
sqlite3_free(pVTab->zErrMsg);
|
|
||||||
pVTab->zErrMsg = pzErr;
|
|
||||||
return SQLITE_ERROR;
|
|
||||||
}
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static sqlite3_module goModule = {
|
|
||||||
0, // iVersion
|
|
||||||
cXCreate, // xCreate - create a table
|
|
||||||
cXConnect, // xConnect - connect to an existing table
|
|
||||||
cXBestIndex, // xBestIndex - Determine search strategy
|
|
||||||
cXDisconnect, // xDisconnect - Disconnect from a table
|
|
||||||
cXDestroy, // xDestroy - Drop a table
|
|
||||||
cXOpen, // xOpen - open a cursor
|
|
||||||
cXClose, // xClose - close a cursor
|
|
||||||
cXFilter, // xFilter - configure scan constraints
|
|
||||||
cXNext, // xNext - advance a cursor
|
|
||||||
cXEof, // xEof
|
|
||||||
cXColumn, // xColumn - read data
|
|
||||||
cXRowid, // xRowid - read data
|
|
||||||
cXUpdate, // xUpdate - write data
|
|
||||||
// Not implemented
|
|
||||||
0, // xBegin - begin transaction
|
|
||||||
0, // xSync - sync transaction
|
|
||||||
0, // xCommit - commit transaction
|
|
||||||
0, // xRollback - rollback transaction
|
|
||||||
0, // xFindFunction - function overloading
|
|
||||||
0, // xRename - rename the table
|
|
||||||
0, // xSavepoint
|
|
||||||
0, // xRelease
|
|
||||||
0 // xRollbackTo
|
|
||||||
};
|
|
||||||
|
|
||||||
void goMDestroy(void*);
|
|
||||||
|
|
||||||
static int _sqlite3_create_module(sqlite3 *db, const char *zName, uintptr_t pClientData) {
|
|
||||||
return sqlite3_create_module_v2(db, zName, &goModule, (void*) pClientData, goMDestroy);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"math"
|
|
||||||
"reflect"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
type sqliteModule struct {
|
|
||||||
c *SQLiteConn
|
|
||||||
name string
|
|
||||||
module Module
|
|
||||||
}
|
|
||||||
|
|
||||||
type sqliteVTab struct {
|
|
||||||
module *sqliteModule
|
|
||||||
vTab VTab
|
|
||||||
}
|
|
||||||
|
|
||||||
type sqliteVTabCursor struct {
|
|
||||||
vTab *sqliteVTab
|
|
||||||
vTabCursor VTabCursor
|
|
||||||
}
|
|
||||||
|
|
||||||
// Op is type of operations.
|
|
||||||
type Op uint8
|
|
||||||
|
|
||||||
// Op mean identity of operations.
|
|
||||||
const (
|
|
||||||
OpEQ Op = 2
|
|
||||||
OpGT = 4
|
|
||||||
OpLE = 8
|
|
||||||
OpLT = 16
|
|
||||||
OpGE = 32
|
|
||||||
OpMATCH = 64
|
|
||||||
OpLIKE = 65 /* 3.10.0 and later only */
|
|
||||||
OpGLOB = 66 /* 3.10.0 and later only */
|
|
||||||
OpREGEXP = 67 /* 3.10.0 and later only */
|
|
||||||
OpScanUnique = 1 /* Scan visits at most 1 row */
|
|
||||||
)
|
|
||||||
|
|
||||||
// InfoConstraint give information of constraint.
|
|
||||||
type InfoConstraint struct {
|
|
||||||
Column int
|
|
||||||
Op Op
|
|
||||||
Usable bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// InfoOrderBy give information of order-by.
|
|
||||||
type InfoOrderBy struct {
|
|
||||||
Column int
|
|
||||||
Desc bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func constraints(info *C.sqlite3_index_info) []InfoConstraint {
|
|
||||||
l := info.nConstraint
|
|
||||||
slice := (*[1 << 30]C.struct_sqlite3_index_constraint)(unsafe.Pointer(info.aConstraint))[:l:l]
|
|
||||||
|
|
||||||
cst := make([]InfoConstraint, 0, l)
|
|
||||||
for _, c := range slice {
|
|
||||||
var usable bool
|
|
||||||
if c.usable > 0 {
|
|
||||||
usable = true
|
|
||||||
}
|
|
||||||
cst = append(cst, InfoConstraint{
|
|
||||||
Column: int(c.iColumn),
|
|
||||||
Op: Op(c.op),
|
|
||||||
Usable: usable,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return cst
|
|
||||||
}
|
|
||||||
|
|
||||||
func orderBys(info *C.sqlite3_index_info) []InfoOrderBy {
|
|
||||||
l := info.nOrderBy
|
|
||||||
slice := (*[1 << 30]C.struct_sqlite3_index_orderby)(unsafe.Pointer(info.aOrderBy))[:l:l]
|
|
||||||
|
|
||||||
ob := make([]InfoOrderBy, 0, l)
|
|
||||||
for _, c := range slice {
|
|
||||||
var desc bool
|
|
||||||
if c.desc > 0 {
|
|
||||||
desc = true
|
|
||||||
}
|
|
||||||
ob = append(ob, InfoOrderBy{
|
|
||||||
Column: int(c.iColumn),
|
|
||||||
Desc: desc,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return ob
|
|
||||||
}
|
|
||||||
|
|
||||||
// IndexResult is a Go struct representation of what eventually ends up in the
|
|
||||||
// output fields for `sqlite3_index_info`
|
|
||||||
// See: https://www.sqlite.org/c3ref/index_info.html
|
|
||||||
type IndexResult struct {
|
|
||||||
Used []bool // aConstraintUsage
|
|
||||||
IdxNum int
|
|
||||||
IdxStr string
|
|
||||||
AlreadyOrdered bool // orderByConsumed
|
|
||||||
EstimatedCost float64
|
|
||||||
EstimatedRows float64
|
|
||||||
}
|
|
||||||
|
|
||||||
// mPrintf is a utility wrapper around sqlite3_mprintf
|
|
||||||
func mPrintf(format, arg string) *C.char {
|
|
||||||
cf := C.CString(format)
|
|
||||||
defer C.free(unsafe.Pointer(cf))
|
|
||||||
ca := C.CString(arg)
|
|
||||||
defer C.free(unsafe.Pointer(ca))
|
|
||||||
return C._sqlite3_mprintf(cf, ca)
|
|
||||||
}
|
|
||||||
|
|
||||||
//export goMInit
|
|
||||||
func goMInit(db, pClientData unsafe.Pointer, argc C.int, argv **C.char, pzErr **C.char, isCreate C.int) C.uintptr_t {
|
|
||||||
m := lookupHandle(uintptr(pClientData)).(*sqliteModule)
|
|
||||||
if m.c.db != (*C.sqlite3)(db) {
|
|
||||||
*pzErr = mPrintf("%s", "Inconsistent db handles")
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
args := make([]string, argc)
|
|
||||||
var A []*C.char
|
|
||||||
slice := reflect.SliceHeader{Data: uintptr(unsafe.Pointer(argv)), Len: int(argc), Cap: int(argc)}
|
|
||||||
a := reflect.NewAt(reflect.TypeOf(A), unsafe.Pointer(&slice)).Elem().Interface()
|
|
||||||
for i, s := range a.([]*C.char) {
|
|
||||||
args[i] = C.GoString(s)
|
|
||||||
}
|
|
||||||
var vTab VTab
|
|
||||||
var err error
|
|
||||||
if isCreate == 1 {
|
|
||||||
vTab, err = m.module.Create(m.c, args)
|
|
||||||
} else {
|
|
||||||
vTab, err = m.module.Connect(m.c, args)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
*pzErr = mPrintf("%s", err.Error())
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
vt := sqliteVTab{m, vTab}
|
|
||||||
*pzErr = nil
|
|
||||||
return C.uintptr_t(newHandle(m.c, &vt))
|
|
||||||
}
|
|
||||||
|
|
||||||
//export goVRelease
|
|
||||||
func goVRelease(pVTab unsafe.Pointer, isDestroy C.int) *C.char {
|
|
||||||
vt := lookupHandle(uintptr(pVTab)).(*sqliteVTab)
|
|
||||||
var err error
|
|
||||||
if isDestroy == 1 {
|
|
||||||
err = vt.vTab.Destroy()
|
|
||||||
} else {
|
|
||||||
err = vt.vTab.Disconnect()
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return mPrintf("%s", err.Error())
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
//export goVOpen
|
|
||||||
func goVOpen(pVTab unsafe.Pointer, pzErr **C.char) C.uintptr_t {
|
|
||||||
vt := lookupHandle(uintptr(pVTab)).(*sqliteVTab)
|
|
||||||
vTabCursor, err := vt.vTab.Open()
|
|
||||||
if err != nil {
|
|
||||||
*pzErr = mPrintf("%s", err.Error())
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
vtc := sqliteVTabCursor{vt, vTabCursor}
|
|
||||||
*pzErr = nil
|
|
||||||
return C.uintptr_t(newHandle(vt.module.c, &vtc))
|
|
||||||
}
|
|
||||||
|
|
||||||
//export goVBestIndex
|
|
||||||
func goVBestIndex(pVTab unsafe.Pointer, icp unsafe.Pointer) *C.char {
|
|
||||||
vt := lookupHandle(uintptr(pVTab)).(*sqliteVTab)
|
|
||||||
info := (*C.sqlite3_index_info)(icp)
|
|
||||||
csts := constraints(info)
|
|
||||||
res, err := vt.vTab.BestIndex(csts, orderBys(info))
|
|
||||||
if err != nil {
|
|
||||||
return mPrintf("%s", err.Error())
|
|
||||||
}
|
|
||||||
if len(res.Used) != len(csts) {
|
|
||||||
return mPrintf("Result.Used != expected value", "")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get a pointer to constraint_usage struct so we can update in place.
|
|
||||||
l := info.nConstraint
|
|
||||||
s := (*[1 << 30]C.struct_sqlite3_index_constraint_usage)(unsafe.Pointer(info.aConstraintUsage))[:l:l]
|
|
||||||
index := 1
|
|
||||||
for i := C.int(0); i < info.nConstraint; i++ {
|
|
||||||
if res.Used[i] {
|
|
||||||
s[i].argvIndex = C.int(index)
|
|
||||||
s[i].omit = C.uchar(1)
|
|
||||||
index++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
info.idxNum = C.int(res.IdxNum)
|
|
||||||
idxStr := C.CString(res.IdxStr)
|
|
||||||
defer C.free(unsafe.Pointer(idxStr))
|
|
||||||
info.idxStr = idxStr
|
|
||||||
info.needToFreeIdxStr = C.int(0)
|
|
||||||
if res.AlreadyOrdered {
|
|
||||||
info.orderByConsumed = C.int(1)
|
|
||||||
}
|
|
||||||
info.estimatedCost = C.double(res.EstimatedCost)
|
|
||||||
info.estimatedRows = C.sqlite3_int64(res.EstimatedRows)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
//export goVClose
|
|
||||||
func goVClose(pCursor unsafe.Pointer) *C.char {
|
|
||||||
vtc := lookupHandle(uintptr(pCursor)).(*sqliteVTabCursor)
|
|
||||||
err := vtc.vTabCursor.Close()
|
|
||||||
if err != nil {
|
|
||||||
return mPrintf("%s", err.Error())
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
//export goMDestroy
|
|
||||||
func goMDestroy(pClientData unsafe.Pointer) {
|
|
||||||
m := lookupHandle(uintptr(pClientData)).(*sqliteModule)
|
|
||||||
m.module.DestroyModule()
|
|
||||||
}
|
|
||||||
|
|
||||||
//export goVFilter
|
|
||||||
func goVFilter(pCursor unsafe.Pointer, idxNum C.int, idxName *C.char, argc C.int, argv **C.sqlite3_value) *C.char {
|
|
||||||
vtc := lookupHandle(uintptr(pCursor)).(*sqliteVTabCursor)
|
|
||||||
args := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.sqlite3_value)(nil))]*C.sqlite3_value)(unsafe.Pointer(argv))[:argc:argc]
|
|
||||||
vals := make([]interface{}, 0, argc)
|
|
||||||
for _, v := range args {
|
|
||||||
conv, err := callbackArgGeneric(v)
|
|
||||||
if err != nil {
|
|
||||||
return mPrintf("%s", err.Error())
|
|
||||||
}
|
|
||||||
vals = append(vals, conv.Interface())
|
|
||||||
}
|
|
||||||
err := vtc.vTabCursor.Filter(int(idxNum), C.GoString(idxName), vals)
|
|
||||||
if err != nil {
|
|
||||||
return mPrintf("%s", err.Error())
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
//export goVNext
|
|
||||||
func goVNext(pCursor unsafe.Pointer) *C.char {
|
|
||||||
vtc := lookupHandle(uintptr(pCursor)).(*sqliteVTabCursor)
|
|
||||||
err := vtc.vTabCursor.Next()
|
|
||||||
if err != nil {
|
|
||||||
return mPrintf("%s", err.Error())
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
//export goVEof
|
|
||||||
func goVEof(pCursor unsafe.Pointer) C.int {
|
|
||||||
vtc := lookupHandle(uintptr(pCursor)).(*sqliteVTabCursor)
|
|
||||||
err := vtc.vTabCursor.EOF()
|
|
||||||
if err {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
//export goVColumn
|
|
||||||
func goVColumn(pCursor, cp unsafe.Pointer, col C.int) *C.char {
|
|
||||||
vtc := lookupHandle(uintptr(pCursor)).(*sqliteVTabCursor)
|
|
||||||
c := (*SQLiteContext)(cp)
|
|
||||||
err := vtc.vTabCursor.Column(c, int(col))
|
|
||||||
if err != nil {
|
|
||||||
return mPrintf("%s", err.Error())
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
//export goVRowid
|
|
||||||
func goVRowid(pCursor unsafe.Pointer, pRowid *C.sqlite3_int64) *C.char {
|
|
||||||
vtc := lookupHandle(uintptr(pCursor)).(*sqliteVTabCursor)
|
|
||||||
rowid, err := vtc.vTabCursor.Rowid()
|
|
||||||
if err != nil {
|
|
||||||
return mPrintf("%s", err.Error())
|
|
||||||
}
|
|
||||||
*pRowid = C.sqlite3_int64(rowid)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
//export goVUpdate
|
|
||||||
func goVUpdate(pVTab unsafe.Pointer, argc C.int, argv **C.sqlite3_value, pRowid *C.sqlite3_int64) *C.char {
|
|
||||||
vt := lookupHandle(uintptr(pVTab)).(*sqliteVTab)
|
|
||||||
|
|
||||||
var tname string
|
|
||||||
if n, ok := vt.vTab.(interface {
|
|
||||||
TableName() string
|
|
||||||
}); ok {
|
|
||||||
tname = n.TableName() + " "
|
|
||||||
}
|
|
||||||
|
|
||||||
err := fmt.Errorf("virtual %s table %sis read-only", vt.module.name, tname)
|
|
||||||
if v, ok := vt.vTab.(VTabUpdater); ok {
|
|
||||||
// convert argv
|
|
||||||
args := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.sqlite3_value)(nil))]*C.sqlite3_value)(unsafe.Pointer(argv))[:argc:argc]
|
|
||||||
vals := make([]interface{}, 0, argc)
|
|
||||||
for _, v := range args {
|
|
||||||
conv, err := callbackArgGeneric(v)
|
|
||||||
if err != nil {
|
|
||||||
return mPrintf("%s", err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
// work around for SQLITE_NULL
|
|
||||||
x := conv.Interface()
|
|
||||||
if z, ok := x.([]byte); ok && z == nil {
|
|
||||||
x = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
vals = append(vals, x)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case argc == 1:
|
|
||||||
err = v.Delete(vals[0])
|
|
||||||
|
|
||||||
case argc > 1 && vals[0] == nil:
|
|
||||||
var id int64
|
|
||||||
id, err = v.Insert(vals[1], vals[2:])
|
|
||||||
if err == nil {
|
|
||||||
*pRowid = C.sqlite3_int64(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
case argc > 1:
|
|
||||||
err = v.Update(vals[1], vals[2:])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return mPrintf("%s", err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Module is a "virtual table module", it defines the implementation of a
|
|
||||||
// virtual tables. See: http://sqlite.org/c3ref/module.html
|
|
||||||
type Module interface {
|
|
||||||
// http://sqlite.org/vtab.html#xcreate
|
|
||||||
Create(c *SQLiteConn, args []string) (VTab, error)
|
|
||||||
// http://sqlite.org/vtab.html#xconnect
|
|
||||||
Connect(c *SQLiteConn, args []string) (VTab, error)
|
|
||||||
// http://sqlite.org/c3ref/create_module.html
|
|
||||||
DestroyModule()
|
|
||||||
}
|
|
||||||
|
|
||||||
// VTab describes a particular instance of the virtual table.
|
|
||||||
// See: http://sqlite.org/c3ref/vtab.html
|
|
||||||
type VTab interface {
|
|
||||||
// http://sqlite.org/vtab.html#xbestindex
|
|
||||||
BestIndex([]InfoConstraint, []InfoOrderBy) (*IndexResult, error)
|
|
||||||
// http://sqlite.org/vtab.html#xdisconnect
|
|
||||||
Disconnect() error
|
|
||||||
// http://sqlite.org/vtab.html#sqlite3_module.xDestroy
|
|
||||||
Destroy() error
|
|
||||||
// http://sqlite.org/vtab.html#xopen
|
|
||||||
Open() (VTabCursor, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// VTabUpdater is a type that allows a VTab to be inserted, updated, or
|
|
||||||
// deleted.
|
|
||||||
// See: https://sqlite.org/vtab.html#xupdate
|
|
||||||
type VTabUpdater interface {
|
|
||||||
Delete(interface{}) error
|
|
||||||
Insert(interface{}, []interface{}) (int64, error)
|
|
||||||
Update(interface{}, []interface{}) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// VTabCursor describes cursors that point into the virtual table and are used
|
|
||||||
// to loop through the virtual table. See: http://sqlite.org/c3ref/vtab_cursor.html
|
|
||||||
type VTabCursor interface {
|
|
||||||
// http://sqlite.org/vtab.html#xclose
|
|
||||||
Close() error
|
|
||||||
// http://sqlite.org/vtab.html#xfilter
|
|
||||||
Filter(idxNum int, idxStr string, vals []interface{}) error
|
|
||||||
// http://sqlite.org/vtab.html#xnext
|
|
||||||
Next() error
|
|
||||||
// http://sqlite.org/vtab.html#xeof
|
|
||||||
EOF() bool
|
|
||||||
// http://sqlite.org/vtab.html#xcolumn
|
|
||||||
Column(c *SQLiteContext, col int) error
|
|
||||||
// http://sqlite.org/vtab.html#xrowid
|
|
||||||
Rowid() (int64, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeclareVTab declares the Schema of a virtual table.
|
|
||||||
// See: http://sqlite.org/c3ref/declare_vtab.html
|
|
||||||
func (c *SQLiteConn) DeclareVTab(sql string) error {
|
|
||||||
zSQL := C.CString(sql)
|
|
||||||
defer C.free(unsafe.Pointer(zSQL))
|
|
||||||
rv := C.sqlite3_declare_vtab(c.db, zSQL)
|
|
||||||
if rv != C.SQLITE_OK {
|
|
||||||
return c.lastError()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateModule registers a virtual table implementation.
|
|
||||||
// See: http://sqlite.org/c3ref/create_module.html
|
|
||||||
func (c *SQLiteConn) CreateModule(moduleName string, module Module) error {
|
|
||||||
mname := C.CString(moduleName)
|
|
||||||
defer C.free(unsafe.Pointer(mname))
|
|
||||||
udm := sqliteModule{c, moduleName, module}
|
|
||||||
rv := C._sqlite3_create_module(c.db, mname, C.uintptr_t(newHandle(c, &udm)))
|
|
||||||
if rv != C.SQLITE_OK {
|
|
||||||
return c.lastError()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
14
src/vendor/github.com/mattn/go-sqlite3/sqlite3_windows.go
generated
vendored
14
src/vendor/github.com/mattn/go-sqlite3/sqlite3_windows.go
generated
vendored
@ -1,14 +0,0 @@
|
|||||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
|
|
||||||
//
|
|
||||||
// Use of this source code is governed by an MIT-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
// +build windows
|
|
||||||
|
|
||||||
package sqlite3
|
|
||||||
|
|
||||||
/*
|
|
||||||
#cgo CFLAGS: -I. -fno-stack-check -fno-stack-protector -mno-stack-arg-probe
|
|
||||||
#cgo windows,386 CFLAGS: -D_USE_32BIT_TIME_T
|
|
||||||
#cgo LDFLAGS: -lmingwex -lmingw32
|
|
||||||
*/
|
|
||||||
import "C"
|
|
583
src/vendor/github.com/mattn/go-sqlite3/sqlite3ext.h
generated
vendored
583
src/vendor/github.com/mattn/go-sqlite3/sqlite3ext.h
generated
vendored
@ -1,583 +0,0 @@
|
|||||||
#ifndef USE_LIBSQLITE3
|
|
||||||
/*
|
|
||||||
** 2006 June 7
|
|
||||||
**
|
|
||||||
** The author disclaims copyright to this source code. In place of
|
|
||||||
** a legal notice, here is a blessing:
|
|
||||||
**
|
|
||||||
** May you do good and not evil.
|
|
||||||
** May you find forgiveness for yourself and forgive others.
|
|
||||||
** May you share freely, never taking more than you give.
|
|
||||||
**
|
|
||||||
*************************************************************************
|
|
||||||
** This header file defines the SQLite interface for use by
|
|
||||||
** shared libraries that want to be imported as extensions into
|
|
||||||
** an SQLite instance. Shared libraries that intend to be loaded
|
|
||||||
** as extensions by SQLite should #include this file instead of
|
|
||||||
** sqlite3.h.
|
|
||||||
*/
|
|
||||||
#ifndef SQLITE3EXT_H
|
|
||||||
#define SQLITE3EXT_H
|
|
||||||
#include "sqlite3-binding.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
** The following structure holds pointers to all of the SQLite API
|
|
||||||
** routines.
|
|
||||||
**
|
|
||||||
** WARNING: In order to maintain backwards compatibility, add new
|
|
||||||
** interfaces to the end of this structure only. If you insert new
|
|
||||||
** interfaces in the middle of this structure, then older different
|
|
||||||
** versions of SQLite will not be able to load each other's shared
|
|
||||||
** libraries!
|
|
||||||
*/
|
|
||||||
struct sqlite3_api_routines {
|
|
||||||
void * (*aggregate_context)(sqlite3_context*,int nBytes);
|
|
||||||
int (*aggregate_count)(sqlite3_context*);
|
|
||||||
int (*bind_blob)(sqlite3_stmt*,int,const void*,int n,void(*)(void*));
|
|
||||||
int (*bind_double)(sqlite3_stmt*,int,double);
|
|
||||||
int (*bind_int)(sqlite3_stmt*,int,int);
|
|
||||||
int (*bind_int64)(sqlite3_stmt*,int,sqlite_int64);
|
|
||||||
int (*bind_null)(sqlite3_stmt*,int);
|
|
||||||
int (*bind_parameter_count)(sqlite3_stmt*);
|
|
||||||
int (*bind_parameter_index)(sqlite3_stmt*,const char*zName);
|
|
||||||
const char * (*bind_parameter_name)(sqlite3_stmt*,int);
|
|
||||||
int (*bind_text)(sqlite3_stmt*,int,const char*,int n,void(*)(void*));
|
|
||||||
int (*bind_text16)(sqlite3_stmt*,int,const void*,int,void(*)(void*));
|
|
||||||
int (*bind_value)(sqlite3_stmt*,int,const sqlite3_value*);
|
|
||||||
int (*busy_handler)(sqlite3*,int(*)(void*,int),void*);
|
|
||||||
int (*busy_timeout)(sqlite3*,int ms);
|
|
||||||
int (*changes)(sqlite3*);
|
|
||||||
int (*close)(sqlite3*);
|
|
||||||
int (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*,
|
|
||||||
int eTextRep,const char*));
|
|
||||||
int (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*,
|
|
||||||
int eTextRep,const void*));
|
|
||||||
const void * (*column_blob)(sqlite3_stmt*,int iCol);
|
|
||||||
int (*column_bytes)(sqlite3_stmt*,int iCol);
|
|
||||||
int (*column_bytes16)(sqlite3_stmt*,int iCol);
|
|
||||||
int (*column_count)(sqlite3_stmt*pStmt);
|
|
||||||
const char * (*column_database_name)(sqlite3_stmt*,int);
|
|
||||||
const void * (*column_database_name16)(sqlite3_stmt*,int);
|
|
||||||
const char * (*column_decltype)(sqlite3_stmt*,int i);
|
|
||||||
const void * (*column_decltype16)(sqlite3_stmt*,int);
|
|
||||||
double (*column_double)(sqlite3_stmt*,int iCol);
|
|
||||||
int (*column_int)(sqlite3_stmt*,int iCol);
|
|
||||||
sqlite_int64 (*column_int64)(sqlite3_stmt*,int iCol);
|
|
||||||
const char * (*column_name)(sqlite3_stmt*,int);
|
|
||||||
const void * (*column_name16)(sqlite3_stmt*,int);
|
|
||||||
const char * (*column_origin_name)(sqlite3_stmt*,int);
|
|
||||||
const void * (*column_origin_name16)(sqlite3_stmt*,int);
|
|
||||||
const char * (*column_table_name)(sqlite3_stmt*,int);
|
|
||||||
const void * (*column_table_name16)(sqlite3_stmt*,int);
|
|
||||||
const unsigned char * (*column_text)(sqlite3_stmt*,int iCol);
|
|
||||||
const void * (*column_text16)(sqlite3_stmt*,int iCol);
|
|
||||||
int (*column_type)(sqlite3_stmt*,int iCol);
|
|
||||||
sqlite3_value* (*column_value)(sqlite3_stmt*,int iCol);
|
|
||||||
void * (*commit_hook)(sqlite3*,int(*)(void*),void*);
|
|
||||||
int (*complete)(const char*sql);
|
|
||||||
int (*complete16)(const void*sql);
|
|
||||||
int (*create_collation)(sqlite3*,const char*,int,void*,
|
|
||||||
int(*)(void*,int,const void*,int,const void*));
|
|
||||||
int (*create_collation16)(sqlite3*,const void*,int,void*,
|
|
||||||
int(*)(void*,int,const void*,int,const void*));
|
|
||||||
int (*create_function)(sqlite3*,const char*,int,int,void*,
|
|
||||||
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
|
|
||||||
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
|
|
||||||
void (*xFinal)(sqlite3_context*));
|
|
||||||
int (*create_function16)(sqlite3*,const void*,int,int,void*,
|
|
||||||
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
|
|
||||||
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
|
|
||||||
void (*xFinal)(sqlite3_context*));
|
|
||||||
int (*create_module)(sqlite3*,const char*,const sqlite3_module*,void*);
|
|
||||||
int (*data_count)(sqlite3_stmt*pStmt);
|
|
||||||
sqlite3 * (*db_handle)(sqlite3_stmt*);
|
|
||||||
int (*declare_vtab)(sqlite3*,const char*);
|
|
||||||
int (*enable_shared_cache)(int);
|
|
||||||
int (*errcode)(sqlite3*db);
|
|
||||||
const char * (*errmsg)(sqlite3*);
|
|
||||||
const void * (*errmsg16)(sqlite3*);
|
|
||||||
int (*exec)(sqlite3*,const char*,sqlite3_callback,void*,char**);
|
|
||||||
int (*expired)(sqlite3_stmt*);
|
|
||||||
int (*finalize)(sqlite3_stmt*pStmt);
|
|
||||||
void (*free)(void*);
|
|
||||||
void (*free_table)(char**result);
|
|
||||||
int (*get_autocommit)(sqlite3*);
|
|
||||||
void * (*get_auxdata)(sqlite3_context*,int);
|
|
||||||
int (*get_table)(sqlite3*,const char*,char***,int*,int*,char**);
|
|
||||||
int (*global_recover)(void);
|
|
||||||
void (*interruptx)(sqlite3*);
|
|
||||||
sqlite_int64 (*last_insert_rowid)(sqlite3*);
|
|
||||||
const char * (*libversion)(void);
|
|
||||||
int (*libversion_number)(void);
|
|
||||||
void *(*malloc)(int);
|
|
||||||
char * (*mprintf)(const char*,...);
|
|
||||||
int (*open)(const char*,sqlite3**);
|
|
||||||
int (*open16)(const void*,sqlite3**);
|
|
||||||
int (*prepare)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
|
|
||||||
int (*prepare16)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
|
|
||||||
void * (*profile)(sqlite3*,void(*)(void*,const char*,sqlite_uint64),void*);
|
|
||||||
void (*progress_handler)(sqlite3*,int,int(*)(void*),void*);
|
|
||||||
void *(*realloc)(void*,int);
|
|
||||||
int (*reset)(sqlite3_stmt*pStmt);
|
|
||||||
void (*result_blob)(sqlite3_context*,const void*,int,void(*)(void*));
|
|
||||||
void (*result_double)(sqlite3_context*,double);
|
|
||||||
void (*result_error)(sqlite3_context*,const char*,int);
|
|
||||||
void (*result_error16)(sqlite3_context*,const void*,int);
|
|
||||||
void (*result_int)(sqlite3_context*,int);
|
|
||||||
void (*result_int64)(sqlite3_context*,sqlite_int64);
|
|
||||||
void (*result_null)(sqlite3_context*);
|
|
||||||
void (*result_text)(sqlite3_context*,const char*,int,void(*)(void*));
|
|
||||||
void (*result_text16)(sqlite3_context*,const void*,int,void(*)(void*));
|
|
||||||
void (*result_text16be)(sqlite3_context*,const void*,int,void(*)(void*));
|
|
||||||
void (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*));
|
|
||||||
void (*result_value)(sqlite3_context*,sqlite3_value*);
|
|
||||||
void * (*rollback_hook)(sqlite3*,void(*)(void*),void*);
|
|
||||||
int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,
|
|
||||||
const char*,const char*),void*);
|
|
||||||
void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*));
|
|
||||||
char * (*xsnprintf)(int,char*,const char*,...);
|
|
||||||
int (*step)(sqlite3_stmt*);
|
|
||||||
int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,
|
|
||||||
char const**,char const**,int*,int*,int*);
|
|
||||||
void (*thread_cleanup)(void);
|
|
||||||
int (*total_changes)(sqlite3*);
|
|
||||||
void * (*trace)(sqlite3*,void(*xTrace)(void*,const char*),void*);
|
|
||||||
int (*transfer_bindings)(sqlite3_stmt*,sqlite3_stmt*);
|
|
||||||
void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*,
|
|
||||||
sqlite_int64),void*);
|
|
||||||
void * (*user_data)(sqlite3_context*);
|
|
||||||
const void * (*value_blob)(sqlite3_value*);
|
|
||||||
int (*value_bytes)(sqlite3_value*);
|
|
||||||
int (*value_bytes16)(sqlite3_value*);
|
|
||||||
double (*value_double)(sqlite3_value*);
|
|
||||||
int (*value_int)(sqlite3_value*);
|
|
||||||
sqlite_int64 (*value_int64)(sqlite3_value*);
|
|
||||||
int (*value_numeric_type)(sqlite3_value*);
|
|
||||||
const unsigned char * (*value_text)(sqlite3_value*);
|
|
||||||
const void * (*value_text16)(sqlite3_value*);
|
|
||||||
const void * (*value_text16be)(sqlite3_value*);
|
|
||||||
const void * (*value_text16le)(sqlite3_value*);
|
|
||||||
int (*value_type)(sqlite3_value*);
|
|
||||||
char *(*vmprintf)(const char*,va_list);
|
|
||||||
/* Added ??? */
|
|
||||||
int (*overload_function)(sqlite3*, const char *zFuncName, int nArg);
|
|
||||||
/* Added by 3.3.13 */
|
|
||||||
int (*prepare_v2)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
|
|
||||||
int (*prepare16_v2)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
|
|
||||||
int (*clear_bindings)(sqlite3_stmt*);
|
|
||||||
/* Added by 3.4.1 */
|
|
||||||
int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*,
|
|
||||||
void (*xDestroy)(void *));
|
|
||||||
/* Added by 3.5.0 */
|
|
||||||
int (*bind_zeroblob)(sqlite3_stmt*,int,int);
|
|
||||||
int (*blob_bytes)(sqlite3_blob*);
|
|
||||||
int (*blob_close)(sqlite3_blob*);
|
|
||||||
int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64,
|
|
||||||
int,sqlite3_blob**);
|
|
||||||
int (*blob_read)(sqlite3_blob*,void*,int,int);
|
|
||||||
int (*blob_write)(sqlite3_blob*,const void*,int,int);
|
|
||||||
int (*create_collation_v2)(sqlite3*,const char*,int,void*,
|
|
||||||
int(*)(void*,int,const void*,int,const void*),
|
|
||||||
void(*)(void*));
|
|
||||||
int (*file_control)(sqlite3*,const char*,int,void*);
|
|
||||||
sqlite3_int64 (*memory_highwater)(int);
|
|
||||||
sqlite3_int64 (*memory_used)(void);
|
|
||||||
sqlite3_mutex *(*mutex_alloc)(int);
|
|
||||||
void (*mutex_enter)(sqlite3_mutex*);
|
|
||||||
void (*mutex_free)(sqlite3_mutex*);
|
|
||||||
void (*mutex_leave)(sqlite3_mutex*);
|
|
||||||
int (*mutex_try)(sqlite3_mutex*);
|
|
||||||
int (*open_v2)(const char*,sqlite3**,int,const char*);
|
|
||||||
int (*release_memory)(int);
|
|
||||||
void (*result_error_nomem)(sqlite3_context*);
|
|
||||||
void (*result_error_toobig)(sqlite3_context*);
|
|
||||||
int (*sleep)(int);
|
|
||||||
void (*soft_heap_limit)(int);
|
|
||||||
sqlite3_vfs *(*vfs_find)(const char*);
|
|
||||||
int (*vfs_register)(sqlite3_vfs*,int);
|
|
||||||
int (*vfs_unregister)(sqlite3_vfs*);
|
|
||||||
int (*xthreadsafe)(void);
|
|
||||||
void (*result_zeroblob)(sqlite3_context*,int);
|
|
||||||
void (*result_error_code)(sqlite3_context*,int);
|
|
||||||
int (*test_control)(int, ...);
|
|
||||||
void (*randomness)(int,void*);
|
|
||||||
sqlite3 *(*context_db_handle)(sqlite3_context*);
|
|
||||||
int (*extended_result_codes)(sqlite3*,int);
|
|
||||||
int (*limit)(sqlite3*,int,int);
|
|
||||||
sqlite3_stmt *(*next_stmt)(sqlite3*,sqlite3_stmt*);
|
|
||||||
const char *(*sql)(sqlite3_stmt*);
|
|
||||||
int (*status)(int,int*,int*,int);
|
|
||||||
int (*backup_finish)(sqlite3_backup*);
|
|
||||||
sqlite3_backup *(*backup_init)(sqlite3*,const char*,sqlite3*,const char*);
|
|
||||||
int (*backup_pagecount)(sqlite3_backup*);
|
|
||||||
int (*backup_remaining)(sqlite3_backup*);
|
|
||||||
int (*backup_step)(sqlite3_backup*,int);
|
|
||||||
const char *(*compileoption_get)(int);
|
|
||||||
int (*compileoption_used)(const char*);
|
|
||||||
int (*create_function_v2)(sqlite3*,const char*,int,int,void*,
|
|
||||||
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
|
|
||||||
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
|
|
||||||
void (*xFinal)(sqlite3_context*),
|
|
||||||
void(*xDestroy)(void*));
|
|
||||||
int (*db_config)(sqlite3*,int,...);
|
|
||||||
sqlite3_mutex *(*db_mutex)(sqlite3*);
|
|
||||||
int (*db_status)(sqlite3*,int,int*,int*,int);
|
|
||||||
int (*extended_errcode)(sqlite3*);
|
|
||||||
void (*log)(int,const char*,...);
|
|
||||||
sqlite3_int64 (*soft_heap_limit64)(sqlite3_int64);
|
|
||||||
const char *(*sourceid)(void);
|
|
||||||
int (*stmt_status)(sqlite3_stmt*,int,int);
|
|
||||||
int (*strnicmp)(const char*,const char*,int);
|
|
||||||
int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*);
|
|
||||||
int (*wal_autocheckpoint)(sqlite3*,int);
|
|
||||||
int (*wal_checkpoint)(sqlite3*,const char*);
|
|
||||||
void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*);
|
|
||||||
int (*blob_reopen)(sqlite3_blob*,sqlite3_int64);
|
|
||||||
int (*vtab_config)(sqlite3*,int op,...);
|
|
||||||
int (*vtab_on_conflict)(sqlite3*);
|
|
||||||
/* Version 3.7.16 and later */
|
|
||||||
int (*close_v2)(sqlite3*);
|
|
||||||
const char *(*db_filename)(sqlite3*,const char*);
|
|
||||||
int (*db_readonly)(sqlite3*,const char*);
|
|
||||||
int (*db_release_memory)(sqlite3*);
|
|
||||||
const char *(*errstr)(int);
|
|
||||||
int (*stmt_busy)(sqlite3_stmt*);
|
|
||||||
int (*stmt_readonly)(sqlite3_stmt*);
|
|
||||||
int (*stricmp)(const char*,const char*);
|
|
||||||
int (*uri_boolean)(const char*,const char*,int);
|
|
||||||
sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64);
|
|
||||||
const char *(*uri_parameter)(const char*,const char*);
|
|
||||||
char *(*xvsnprintf)(int,char*,const char*,va_list);
|
|
||||||
int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*);
|
|
||||||
/* Version 3.8.7 and later */
|
|
||||||
int (*auto_extension)(void(*)(void));
|
|
||||||
int (*bind_blob64)(sqlite3_stmt*,int,const void*,sqlite3_uint64,
|
|
||||||
void(*)(void*));
|
|
||||||
int (*bind_text64)(sqlite3_stmt*,int,const char*,sqlite3_uint64,
|
|
||||||
void(*)(void*),unsigned char);
|
|
||||||
int (*cancel_auto_extension)(void(*)(void));
|
|
||||||
int (*load_extension)(sqlite3*,const char*,const char*,char**);
|
|
||||||
void *(*malloc64)(sqlite3_uint64);
|
|
||||||
sqlite3_uint64 (*msize)(void*);
|
|
||||||
void *(*realloc64)(void*,sqlite3_uint64);
|
|
||||||
void (*reset_auto_extension)(void);
|
|
||||||
void (*result_blob64)(sqlite3_context*,const void*,sqlite3_uint64,
|
|
||||||
void(*)(void*));
|
|
||||||
void (*result_text64)(sqlite3_context*,const char*,sqlite3_uint64,
|
|
||||||
void(*)(void*), unsigned char);
|
|
||||||
int (*strglob)(const char*,const char*);
|
|
||||||
/* Version 3.8.11 and later */
|
|
||||||
sqlite3_value *(*value_dup)(const sqlite3_value*);
|
|
||||||
void (*value_free)(sqlite3_value*);
|
|
||||||
int (*result_zeroblob64)(sqlite3_context*,sqlite3_uint64);
|
|
||||||
int (*bind_zeroblob64)(sqlite3_stmt*, int, sqlite3_uint64);
|
|
||||||
/* Version 3.9.0 and later */
|
|
||||||
unsigned int (*value_subtype)(sqlite3_value*);
|
|
||||||
void (*result_subtype)(sqlite3_context*,unsigned int);
|
|
||||||
/* Version 3.10.0 and later */
|
|
||||||
int (*status64)(int,sqlite3_int64*,sqlite3_int64*,int);
|
|
||||||
int (*strlike)(const char*,const char*,unsigned int);
|
|
||||||
int (*db_cacheflush)(sqlite3*);
|
|
||||||
/* Version 3.12.0 and later */
|
|
||||||
int (*system_errno)(sqlite3*);
|
|
||||||
/* Version 3.14.0 and later */
|
|
||||||
int (*trace_v2)(sqlite3*,unsigned,int(*)(unsigned,void*,void*,void*),void*);
|
|
||||||
char *(*expanded_sql)(sqlite3_stmt*);
|
|
||||||
/* Version 3.18.0 and later */
|
|
||||||
void (*set_last_insert_rowid)(sqlite3*,sqlite3_int64);
|
|
||||||
/* Version 3.20.0 and later */
|
|
||||||
int (*prepare_v3)(sqlite3*,const char*,int,unsigned int,
|
|
||||||
sqlite3_stmt**,const char**);
|
|
||||||
int (*prepare16_v3)(sqlite3*,const void*,int,unsigned int,
|
|
||||||
sqlite3_stmt**,const void**);
|
|
||||||
int (*bind_pointer)(sqlite3_stmt*,int,void*,const char*,void(*)(void*));
|
|
||||||
void (*result_pointer)(sqlite3_context*,void*,const char*,void(*)(void*));
|
|
||||||
void *(*value_pointer)(sqlite3_value*,const char*);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
** This is the function signature used for all extension entry points. It
|
|
||||||
** is also defined in the file "loadext.c".
|
|
||||||
*/
|
|
||||||
typedef int (*sqlite3_loadext_entry)(
|
|
||||||
sqlite3 *db, /* Handle to the database. */
|
|
||||||
char **pzErrMsg, /* Used to set error string on failure. */
|
|
||||||
const sqlite3_api_routines *pThunk /* Extension API function pointers. */
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
** The following macros redefine the API routines so that they are
|
|
||||||
** redirected through the global sqlite3_api structure.
|
|
||||||
**
|
|
||||||
** This header file is also used by the loadext.c source file
|
|
||||||
** (part of the main SQLite library - not an extension) so that
|
|
||||||
** it can get access to the sqlite3_api_routines structure
|
|
||||||
** definition. But the main library does not want to redefine
|
|
||||||
** the API. So the redefinition macros are only valid if the
|
|
||||||
** SQLITE_CORE macros is undefined.
|
|
||||||
*/
|
|
||||||
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
|
||||||
#define sqlite3_aggregate_context sqlite3_api->aggregate_context
|
|
||||||
#ifndef SQLITE_OMIT_DEPRECATED
|
|
||||||
#define sqlite3_aggregate_count sqlite3_api->aggregate_count
|
|
||||||
#endif
|
|
||||||
#define sqlite3_bind_blob sqlite3_api->bind_blob
|
|
||||||
#define sqlite3_bind_double sqlite3_api->bind_double
|
|
||||||
#define sqlite3_bind_int sqlite3_api->bind_int
|
|
||||||
#define sqlite3_bind_int64 sqlite3_api->bind_int64
|
|
||||||
#define sqlite3_bind_null sqlite3_api->bind_null
|
|
||||||
#define sqlite3_bind_parameter_count sqlite3_api->bind_parameter_count
|
|
||||||
#define sqlite3_bind_parameter_index sqlite3_api->bind_parameter_index
|
|
||||||
#define sqlite3_bind_parameter_name sqlite3_api->bind_parameter_name
|
|
||||||
#define sqlite3_bind_text sqlite3_api->bind_text
|
|
||||||
#define sqlite3_bind_text16 sqlite3_api->bind_text16
|
|
||||||
#define sqlite3_bind_value sqlite3_api->bind_value
|
|
||||||
#define sqlite3_busy_handler sqlite3_api->busy_handler
|
|
||||||
#define sqlite3_busy_timeout sqlite3_api->busy_timeout
|
|
||||||
#define sqlite3_changes sqlite3_api->changes
|
|
||||||
#define sqlite3_close sqlite3_api->close
|
|
||||||
#define sqlite3_collation_needed sqlite3_api->collation_needed
|
|
||||||
#define sqlite3_collation_needed16 sqlite3_api->collation_needed16
|
|
||||||
#define sqlite3_column_blob sqlite3_api->column_blob
|
|
||||||
#define sqlite3_column_bytes sqlite3_api->column_bytes
|
|
||||||
#define sqlite3_column_bytes16 sqlite3_api->column_bytes16
|
|
||||||
#define sqlite3_column_count sqlite3_api->column_count
|
|
||||||
#define sqlite3_column_database_name sqlite3_api->column_database_name
|
|
||||||
#define sqlite3_column_database_name16 sqlite3_api->column_database_name16
|
|
||||||
#define sqlite3_column_decltype sqlite3_api->column_decltype
|
|
||||||
#define sqlite3_column_decltype16 sqlite3_api->column_decltype16
|
|
||||||
#define sqlite3_column_double sqlite3_api->column_double
|
|
||||||
#define sqlite3_column_int sqlite3_api->column_int
|
|
||||||
#define sqlite3_column_int64 sqlite3_api->column_int64
|
|
||||||
#define sqlite3_column_name sqlite3_api->column_name
|
|
||||||
#define sqlite3_column_name16 sqlite3_api->column_name16
|
|
||||||
#define sqlite3_column_origin_name sqlite3_api->column_origin_name
|
|
||||||
#define sqlite3_column_origin_name16 sqlite3_api->column_origin_name16
|
|
||||||
#define sqlite3_column_table_name sqlite3_api->column_table_name
|
|
||||||
#define sqlite3_column_table_name16 sqlite3_api->column_table_name16
|
|
||||||
#define sqlite3_column_text sqlite3_api->column_text
|
|
||||||
#define sqlite3_column_text16 sqlite3_api->column_text16
|
|
||||||
#define sqlite3_column_type sqlite3_api->column_type
|
|
||||||
#define sqlite3_column_value sqlite3_api->column_value
|
|
||||||
#define sqlite3_commit_hook sqlite3_api->commit_hook
|
|
||||||
#define sqlite3_complete sqlite3_api->complete
|
|
||||||
#define sqlite3_complete16 sqlite3_api->complete16
|
|
||||||
#define sqlite3_create_collation sqlite3_api->create_collation
|
|
||||||
#define sqlite3_create_collation16 sqlite3_api->create_collation16
|
|
||||||
#define sqlite3_create_function sqlite3_api->create_function
|
|
||||||
#define sqlite3_create_function16 sqlite3_api->create_function16
|
|
||||||
#define sqlite3_create_module sqlite3_api->create_module
|
|
||||||
#define sqlite3_create_module_v2 sqlite3_api->create_module_v2
|
|
||||||
#define sqlite3_data_count sqlite3_api->data_count
|
|
||||||
#define sqlite3_db_handle sqlite3_api->db_handle
|
|
||||||
#define sqlite3_declare_vtab sqlite3_api->declare_vtab
|
|
||||||
#define sqlite3_enable_shared_cache sqlite3_api->enable_shared_cache
|
|
||||||
#define sqlite3_errcode sqlite3_api->errcode
|
|
||||||
#define sqlite3_errmsg sqlite3_api->errmsg
|
|
||||||
#define sqlite3_errmsg16 sqlite3_api->errmsg16
|
|
||||||
#define sqlite3_exec sqlite3_api->exec
|
|
||||||
#ifndef SQLITE_OMIT_DEPRECATED
|
|
||||||
#define sqlite3_expired sqlite3_api->expired
|
|
||||||
#endif
|
|
||||||
#define sqlite3_finalize sqlite3_api->finalize
|
|
||||||
#define sqlite3_free sqlite3_api->free
|
|
||||||
#define sqlite3_free_table sqlite3_api->free_table
|
|
||||||
#define sqlite3_get_autocommit sqlite3_api->get_autocommit
|
|
||||||
#define sqlite3_get_auxdata sqlite3_api->get_auxdata
|
|
||||||
#define sqlite3_get_table sqlite3_api->get_table
|
|
||||||
#ifndef SQLITE_OMIT_DEPRECATED
|
|
||||||
#define sqlite3_global_recover sqlite3_api->global_recover
|
|
||||||
#endif
|
|
||||||
#define sqlite3_interrupt sqlite3_api->interruptx
|
|
||||||
#define sqlite3_last_insert_rowid sqlite3_api->last_insert_rowid
|
|
||||||
#define sqlite3_libversion sqlite3_api->libversion
|
|
||||||
#define sqlite3_libversion_number sqlite3_api->libversion_number
|
|
||||||
#define sqlite3_malloc sqlite3_api->malloc
|
|
||||||
#define sqlite3_mprintf sqlite3_api->mprintf
|
|
||||||
#define sqlite3_open sqlite3_api->open
|
|
||||||
#define sqlite3_open16 sqlite3_api->open16
|
|
||||||
#define sqlite3_prepare sqlite3_api->prepare
|
|
||||||
#define sqlite3_prepare16 sqlite3_api->prepare16
|
|
||||||
#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
|
|
||||||
#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
|
|
||||||
#define sqlite3_profile sqlite3_api->profile
|
|
||||||
#define sqlite3_progress_handler sqlite3_api->progress_handler
|
|
||||||
#define sqlite3_realloc sqlite3_api->realloc
|
|
||||||
#define sqlite3_reset sqlite3_api->reset
|
|
||||||
#define sqlite3_result_blob sqlite3_api->result_blob
|
|
||||||
#define sqlite3_result_double sqlite3_api->result_double
|
|
||||||
#define sqlite3_result_error sqlite3_api->result_error
|
|
||||||
#define sqlite3_result_error16 sqlite3_api->result_error16
|
|
||||||
#define sqlite3_result_int sqlite3_api->result_int
|
|
||||||
#define sqlite3_result_int64 sqlite3_api->result_int64
|
|
||||||
#define sqlite3_result_null sqlite3_api->result_null
|
|
||||||
#define sqlite3_result_text sqlite3_api->result_text
|
|
||||||
#define sqlite3_result_text16 sqlite3_api->result_text16
|
|
||||||
#define sqlite3_result_text16be sqlite3_api->result_text16be
|
|
||||||
#define sqlite3_result_text16le sqlite3_api->result_text16le
|
|
||||||
#define sqlite3_result_value sqlite3_api->result_value
|
|
||||||
#define sqlite3_rollback_hook sqlite3_api->rollback_hook
|
|
||||||
#define sqlite3_set_authorizer sqlite3_api->set_authorizer
|
|
||||||
#define sqlite3_set_auxdata sqlite3_api->set_auxdata
|
|
||||||
#define sqlite3_snprintf sqlite3_api->xsnprintf
|
|
||||||
#define sqlite3_step sqlite3_api->step
|
|
||||||
#define sqlite3_table_column_metadata sqlite3_api->table_column_metadata
|
|
||||||
#define sqlite3_thread_cleanup sqlite3_api->thread_cleanup
|
|
||||||
#define sqlite3_total_changes sqlite3_api->total_changes
|
|
||||||
#define sqlite3_trace sqlite3_api->trace
|
|
||||||
#ifndef SQLITE_OMIT_DEPRECATED
|
|
||||||
#define sqlite3_transfer_bindings sqlite3_api->transfer_bindings
|
|
||||||
#endif
|
|
||||||
#define sqlite3_update_hook sqlite3_api->update_hook
|
|
||||||
#define sqlite3_user_data sqlite3_api->user_data
|
|
||||||
#define sqlite3_value_blob sqlite3_api->value_blob
|
|
||||||
#define sqlite3_value_bytes sqlite3_api->value_bytes
|
|
||||||
#define sqlite3_value_bytes16 sqlite3_api->value_bytes16
|
|
||||||
#define sqlite3_value_double sqlite3_api->value_double
|
|
||||||
#define sqlite3_value_int sqlite3_api->value_int
|
|
||||||
#define sqlite3_value_int64 sqlite3_api->value_int64
|
|
||||||
#define sqlite3_value_numeric_type sqlite3_api->value_numeric_type
|
|
||||||
#define sqlite3_value_text sqlite3_api->value_text
|
|
||||||
#define sqlite3_value_text16 sqlite3_api->value_text16
|
|
||||||
#define sqlite3_value_text16be sqlite3_api->value_text16be
|
|
||||||
#define sqlite3_value_text16le sqlite3_api->value_text16le
|
|
||||||
#define sqlite3_value_type sqlite3_api->value_type
|
|
||||||
#define sqlite3_vmprintf sqlite3_api->vmprintf
|
|
||||||
#define sqlite3_vsnprintf sqlite3_api->xvsnprintf
|
|
||||||
#define sqlite3_overload_function sqlite3_api->overload_function
|
|
||||||
#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
|
|
||||||
#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
|
|
||||||
#define sqlite3_clear_bindings sqlite3_api->clear_bindings
|
|
||||||
#define sqlite3_bind_zeroblob sqlite3_api->bind_zeroblob
|
|
||||||
#define sqlite3_blob_bytes sqlite3_api->blob_bytes
|
|
||||||
#define sqlite3_blob_close sqlite3_api->blob_close
|
|
||||||
#define sqlite3_blob_open sqlite3_api->blob_open
|
|
||||||
#define sqlite3_blob_read sqlite3_api->blob_read
|
|
||||||
#define sqlite3_blob_write sqlite3_api->blob_write
|
|
||||||
#define sqlite3_create_collation_v2 sqlite3_api->create_collation_v2
|
|
||||||
#define sqlite3_file_control sqlite3_api->file_control
|
|
||||||
#define sqlite3_memory_highwater sqlite3_api->memory_highwater
|
|
||||||
#define sqlite3_memory_used sqlite3_api->memory_used
|
|
||||||
#define sqlite3_mutex_alloc sqlite3_api->mutex_alloc
|
|
||||||
#define sqlite3_mutex_enter sqlite3_api->mutex_enter
|
|
||||||
#define sqlite3_mutex_free sqlite3_api->mutex_free
|
|
||||||
#define sqlite3_mutex_leave sqlite3_api->mutex_leave
|
|
||||||
#define sqlite3_mutex_try sqlite3_api->mutex_try
|
|
||||||
#define sqlite3_open_v2 sqlite3_api->open_v2
|
|
||||||
#define sqlite3_release_memory sqlite3_api->release_memory
|
|
||||||
#define sqlite3_result_error_nomem sqlite3_api->result_error_nomem
|
|
||||||
#define sqlite3_result_error_toobig sqlite3_api->result_error_toobig
|
|
||||||
#define sqlite3_sleep sqlite3_api->sleep
|
|
||||||
#define sqlite3_soft_heap_limit sqlite3_api->soft_heap_limit
|
|
||||||
#define sqlite3_vfs_find sqlite3_api->vfs_find
|
|
||||||
#define sqlite3_vfs_register sqlite3_api->vfs_register
|
|
||||||
#define sqlite3_vfs_unregister sqlite3_api->vfs_unregister
|
|
||||||
#define sqlite3_threadsafe sqlite3_api->xthreadsafe
|
|
||||||
#define sqlite3_result_zeroblob sqlite3_api->result_zeroblob
|
|
||||||
#define sqlite3_result_error_code sqlite3_api->result_error_code
|
|
||||||
#define sqlite3_test_control sqlite3_api->test_control
|
|
||||||
#define sqlite3_randomness sqlite3_api->randomness
|
|
||||||
#define sqlite3_context_db_handle sqlite3_api->context_db_handle
|
|
||||||
#define sqlite3_extended_result_codes sqlite3_api->extended_result_codes
|
|
||||||
#define sqlite3_limit sqlite3_api->limit
|
|
||||||
#define sqlite3_next_stmt sqlite3_api->next_stmt
|
|
||||||
#define sqlite3_sql sqlite3_api->sql
|
|
||||||
#define sqlite3_status sqlite3_api->status
|
|
||||||
#define sqlite3_backup_finish sqlite3_api->backup_finish
|
|
||||||
#define sqlite3_backup_init sqlite3_api->backup_init
|
|
||||||
#define sqlite3_backup_pagecount sqlite3_api->backup_pagecount
|
|
||||||
#define sqlite3_backup_remaining sqlite3_api->backup_remaining
|
|
||||||
#define sqlite3_backup_step sqlite3_api->backup_step
|
|
||||||
#define sqlite3_compileoption_get sqlite3_api->compileoption_get
|
|
||||||
#define sqlite3_compileoption_used sqlite3_api->compileoption_used
|
|
||||||
#define sqlite3_create_function_v2 sqlite3_api->create_function_v2
|
|
||||||
#define sqlite3_db_config sqlite3_api->db_config
|
|
||||||
#define sqlite3_db_mutex sqlite3_api->db_mutex
|
|
||||||
#define sqlite3_db_status sqlite3_api->db_status
|
|
||||||
#define sqlite3_extended_errcode sqlite3_api->extended_errcode
|
|
||||||
#define sqlite3_log sqlite3_api->log
|
|
||||||
#define sqlite3_soft_heap_limit64 sqlite3_api->soft_heap_limit64
|
|
||||||
#define sqlite3_sourceid sqlite3_api->sourceid
|
|
||||||
#define sqlite3_stmt_status sqlite3_api->stmt_status
|
|
||||||
#define sqlite3_strnicmp sqlite3_api->strnicmp
|
|
||||||
#define sqlite3_unlock_notify sqlite3_api->unlock_notify
|
|
||||||
#define sqlite3_wal_autocheckpoint sqlite3_api->wal_autocheckpoint
|
|
||||||
#define sqlite3_wal_checkpoint sqlite3_api->wal_checkpoint
|
|
||||||
#define sqlite3_wal_hook sqlite3_api->wal_hook
|
|
||||||
#define sqlite3_blob_reopen sqlite3_api->blob_reopen
|
|
||||||
#define sqlite3_vtab_config sqlite3_api->vtab_config
|
|
||||||
#define sqlite3_vtab_on_conflict sqlite3_api->vtab_on_conflict
|
|
||||||
/* Version 3.7.16 and later */
|
|
||||||
#define sqlite3_close_v2 sqlite3_api->close_v2
|
|
||||||
#define sqlite3_db_filename sqlite3_api->db_filename
|
|
||||||
#define sqlite3_db_readonly sqlite3_api->db_readonly
|
|
||||||
#define sqlite3_db_release_memory sqlite3_api->db_release_memory
|
|
||||||
#define sqlite3_errstr sqlite3_api->errstr
|
|
||||||
#define sqlite3_stmt_busy sqlite3_api->stmt_busy
|
|
||||||
#define sqlite3_stmt_readonly sqlite3_api->stmt_readonly
|
|
||||||
#define sqlite3_stricmp sqlite3_api->stricmp
|
|
||||||
#define sqlite3_uri_boolean sqlite3_api->uri_boolean
|
|
||||||
#define sqlite3_uri_int64 sqlite3_api->uri_int64
|
|
||||||
#define sqlite3_uri_parameter sqlite3_api->uri_parameter
|
|
||||||
#define sqlite3_uri_vsnprintf sqlite3_api->xvsnprintf
|
|
||||||
#define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2
|
|
||||||
/* Version 3.8.7 and later */
|
|
||||||
#define sqlite3_auto_extension sqlite3_api->auto_extension
|
|
||||||
#define sqlite3_bind_blob64 sqlite3_api->bind_blob64
|
|
||||||
#define sqlite3_bind_text64 sqlite3_api->bind_text64
|
|
||||||
#define sqlite3_cancel_auto_extension sqlite3_api->cancel_auto_extension
|
|
||||||
#define sqlite3_load_extension sqlite3_api->load_extension
|
|
||||||
#define sqlite3_malloc64 sqlite3_api->malloc64
|
|
||||||
#define sqlite3_msize sqlite3_api->msize
|
|
||||||
#define sqlite3_realloc64 sqlite3_api->realloc64
|
|
||||||
#define sqlite3_reset_auto_extension sqlite3_api->reset_auto_extension
|
|
||||||
#define sqlite3_result_blob64 sqlite3_api->result_blob64
|
|
||||||
#define sqlite3_result_text64 sqlite3_api->result_text64
|
|
||||||
#define sqlite3_strglob sqlite3_api->strglob
|
|
||||||
/* Version 3.8.11 and later */
|
|
||||||
#define sqlite3_value_dup sqlite3_api->value_dup
|
|
||||||
#define sqlite3_value_free sqlite3_api->value_free
|
|
||||||
#define sqlite3_result_zeroblob64 sqlite3_api->result_zeroblob64
|
|
||||||
#define sqlite3_bind_zeroblob64 sqlite3_api->bind_zeroblob64
|
|
||||||
/* Version 3.9.0 and later */
|
|
||||||
#define sqlite3_value_subtype sqlite3_api->value_subtype
|
|
||||||
#define sqlite3_result_subtype sqlite3_api->result_subtype
|
|
||||||
/* Version 3.10.0 and later */
|
|
||||||
#define sqlite3_status64 sqlite3_api->status64
|
|
||||||
#define sqlite3_strlike sqlite3_api->strlike
|
|
||||||
#define sqlite3_db_cacheflush sqlite3_api->db_cacheflush
|
|
||||||
/* Version 3.12.0 and later */
|
|
||||||
#define sqlite3_system_errno sqlite3_api->system_errno
|
|
||||||
/* Version 3.14.0 and later */
|
|
||||||
#define sqlite3_trace_v2 sqlite3_api->trace_v2
|
|
||||||
#define sqlite3_expanded_sql sqlite3_api->expanded_sql
|
|
||||||
/* Version 3.18.0 and later */
|
|
||||||
#define sqlite3_set_last_insert_rowid sqlite3_api->set_last_insert_rowid
|
|
||||||
/* Version 3.20.0 and later */
|
|
||||||
#define sqlite3_prepare_v3 sqlite3_api->prepare_v3
|
|
||||||
#define sqlite3_prepare16_v3 sqlite3_api->prepare16_v3
|
|
||||||
#define sqlite3_bind_pointer sqlite3_api->bind_pointer
|
|
||||||
#define sqlite3_result_pointer sqlite3_api->result_pointer
|
|
||||||
#define sqlite3_value_pointer sqlite3_api->value_pointer
|
|
||||||
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
|
|
||||||
|
|
||||||
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
|
||||||
/* This case when the file really is being compiled as a loadable
|
|
||||||
** extension */
|
|
||||||
# define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0;
|
|
||||||
# define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v;
|
|
||||||
# define SQLITE_EXTENSION_INIT3 \
|
|
||||||
extern const sqlite3_api_routines *sqlite3_api;
|
|
||||||
#else
|
|
||||||
/* This case when the file is being statically linked into the
|
|
||||||
** application */
|
|
||||||
# define SQLITE_EXTENSION_INIT1 /*no-op*/
|
|
||||||
# define SQLITE_EXTENSION_INIT2(v) (void)v; /* unused parameter */
|
|
||||||
# define SQLITE_EXTENSION_INIT3 /*no-op*/
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* SQLITE3EXT_H */
|
|
||||||
#else // USE_LIBSQLITE3
|
|
||||||
// If users really want to link against the system sqlite3 we
|
|
||||||
// need to make this file a noop.
|
|
||||||
#endif
|
|
12
src/vendor/github.com/pkg/errors/.travis.yml
generated
vendored
12
src/vendor/github.com/pkg/errors/.travis.yml
generated
vendored
@ -1,10 +1,14 @@
|
|||||||
language: go
|
language: go
|
||||||
go_import_path: github.com/pkg/errors
|
go_import_path: github.com/pkg/errors
|
||||||
go:
|
go:
|
||||||
- 1.4.3
|
- 1.4.x
|
||||||
- 1.5.4
|
- 1.5.x
|
||||||
- 1.6.2
|
- 1.6.x
|
||||||
- 1.7.1
|
- 1.7.x
|
||||||
|
- 1.8.x
|
||||||
|
- 1.9.x
|
||||||
|
- 1.10.x
|
||||||
|
- 1.11.x
|
||||||
- tip
|
- tip
|
||||||
|
|
||||||
script:
|
script:
|
||||||
|
4
src/vendor/github.com/pkg/errors/README.md
generated
vendored
4
src/vendor/github.com/pkg/errors/README.md
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
# errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors)
|
# errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors) [![Sourcegraph](https://sourcegraph.com/github.com/pkg/errors/-/badge.svg)](https://sourcegraph.com/github.com/pkg/errors?badge)
|
||||||
|
|
||||||
Package errors provides simple error handling primitives.
|
Package errors provides simple error handling primitives.
|
||||||
|
|
||||||
@ -47,6 +47,6 @@ We welcome pull requests, bug fixes and issue reports. With that said, the bar f
|
|||||||
|
|
||||||
Before proposing a change, please discuss your change by raising an issue.
|
Before proposing a change, please discuss your change by raising an issue.
|
||||||
|
|
||||||
## Licence
|
## License
|
||||||
|
|
||||||
BSD-2-Clause
|
BSD-2-Clause
|
||||||
|
43
src/vendor/github.com/pkg/errors/errors.go
generated
vendored
43
src/vendor/github.com/pkg/errors/errors.go
generated
vendored
@ -6,7 +6,7 @@
|
|||||||
// return err
|
// return err
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// which applied recursively up the call stack results in error reports
|
// which when applied recursively up the call stack results in error reports
|
||||||
// without context or debugging information. The errors package allows
|
// without context or debugging information. The errors package allows
|
||||||
// programmers to add context to the failure path in their code in a way
|
// programmers to add context to the failure path in their code in a way
|
||||||
// that does not destroy the original value of the error.
|
// that does not destroy the original value of the error.
|
||||||
@ -15,16 +15,17 @@
|
|||||||
//
|
//
|
||||||
// The errors.Wrap function returns a new error that adds context to the
|
// The errors.Wrap function returns a new error that adds context to the
|
||||||
// original error by recording a stack trace at the point Wrap is called,
|
// original error by recording a stack trace at the point Wrap is called,
|
||||||
// and the supplied message. For example
|
// together with the supplied message. For example
|
||||||
//
|
//
|
||||||
// _, err := ioutil.ReadAll(r)
|
// _, err := ioutil.ReadAll(r)
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
// return errors.Wrap(err, "read failed")
|
// return errors.Wrap(err, "read failed")
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// If additional control is required the errors.WithStack and errors.WithMessage
|
// If additional control is required, the errors.WithStack and
|
||||||
// functions destructure errors.Wrap into its component operations of annotating
|
// errors.WithMessage functions destructure errors.Wrap into its component
|
||||||
// an error with a stack trace and an a message, respectively.
|
// operations: annotating an error with a stack trace and with a message,
|
||||||
|
// respectively.
|
||||||
//
|
//
|
||||||
// Retrieving the cause of an error
|
// Retrieving the cause of an error
|
||||||
//
|
//
|
||||||
@ -38,7 +39,7 @@
|
|||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// can be inspected by errors.Cause. errors.Cause will recursively retrieve
|
// can be inspected by errors.Cause. errors.Cause will recursively retrieve
|
||||||
// the topmost error which does not implement causer, which is assumed to be
|
// the topmost error that does not implement causer, which is assumed to be
|
||||||
// the original cause. For example:
|
// the original cause. For example:
|
||||||
//
|
//
|
||||||
// switch err := errors.Cause(err).(type) {
|
// switch err := errors.Cause(err).(type) {
|
||||||
@ -48,16 +49,16 @@
|
|||||||
// // unknown error
|
// // unknown error
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// causer interface is not exported by this package, but is considered a part
|
// Although the causer interface is not exported by this package, it is
|
||||||
// of stable public API.
|
// considered a part of its stable public interface.
|
||||||
//
|
//
|
||||||
// Formatted printing of errors
|
// Formatted printing of errors
|
||||||
//
|
//
|
||||||
// All error values returned from this package implement fmt.Formatter and can
|
// All error values returned from this package implement fmt.Formatter and can
|
||||||
// be formatted by the fmt package. The following verbs are supported
|
// be formatted by the fmt package. The following verbs are supported:
|
||||||
//
|
//
|
||||||
// %s print the error. If the error has a Cause it will be
|
// %s print the error. If the error has a Cause it will be
|
||||||
// printed recursively
|
// printed recursively.
|
||||||
// %v see %s
|
// %v see %s
|
||||||
// %+v extended format. Each Frame of the error's StackTrace will
|
// %+v extended format. Each Frame of the error's StackTrace will
|
||||||
// be printed in detail.
|
// be printed in detail.
|
||||||
@ -65,13 +66,13 @@
|
|||||||
// Retrieving the stack trace of an error or wrapper
|
// Retrieving the stack trace of an error or wrapper
|
||||||
//
|
//
|
||||||
// New, Errorf, Wrap, and Wrapf record a stack trace at the point they are
|
// New, Errorf, Wrap, and Wrapf record a stack trace at the point they are
|
||||||
// invoked. This information can be retrieved with the following interface.
|
// invoked. This information can be retrieved with the following interface:
|
||||||
//
|
//
|
||||||
// type stackTracer interface {
|
// type stackTracer interface {
|
||||||
// StackTrace() errors.StackTrace
|
// StackTrace() errors.StackTrace
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// Where errors.StackTrace is defined as
|
// The returned errors.StackTrace type is defined as
|
||||||
//
|
//
|
||||||
// type StackTrace []Frame
|
// type StackTrace []Frame
|
||||||
//
|
//
|
||||||
@ -85,8 +86,8 @@
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// stackTracer interface is not exported by this package, but is considered a part
|
// Although the stackTracer interface is not exported by this package, it is
|
||||||
// of stable public API.
|
// considered a part of its stable public interface.
|
||||||
//
|
//
|
||||||
// See the documentation for Frame.Format for more details.
|
// See the documentation for Frame.Format for more details.
|
||||||
package errors
|
package errors
|
||||||
@ -192,7 +193,7 @@ func Wrap(err error, message string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Wrapf returns an error annotating err with a stack trace
|
// Wrapf returns an error annotating err with a stack trace
|
||||||
// at the point Wrapf is call, and the format specifier.
|
// at the point Wrapf is called, and the format specifier.
|
||||||
// If err is nil, Wrapf returns nil.
|
// If err is nil, Wrapf returns nil.
|
||||||
func Wrapf(err error, format string, args ...interface{}) error {
|
func Wrapf(err error, format string, args ...interface{}) error {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@ -220,6 +221,18 @@ func WithMessage(err error, message string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithMessagef annotates err with the format specifier.
|
||||||
|
// If err is nil, WithMessagef returns nil.
|
||||||
|
func WithMessagef(err error, format string, args ...interface{}) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &withMessage{
|
||||||
|
cause: err,
|
||||||
|
msg: fmt.Sprintf(format, args...),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type withMessage struct {
|
type withMessage struct {
|
||||||
cause error
|
cause error
|
||||||
msg string
|
msg string
|
||||||
|
51
src/vendor/github.com/pkg/errors/stack.go
generated
vendored
51
src/vendor/github.com/pkg/errors/stack.go
generated
vendored
@ -46,7 +46,8 @@ func (f Frame) line() int {
|
|||||||
//
|
//
|
||||||
// Format accepts flags that alter the printing of some verbs, as follows:
|
// Format accepts flags that alter the printing of some verbs, as follows:
|
||||||
//
|
//
|
||||||
// %+s path of source file relative to the compile time GOPATH
|
// %+s function name and path of source file relative to the compile time
|
||||||
|
// GOPATH separated by \n\t (<funcname>\n\t<path>)
|
||||||
// %+v equivalent to %+s:%d
|
// %+v equivalent to %+s:%d
|
||||||
func (f Frame) Format(s fmt.State, verb rune) {
|
func (f Frame) Format(s fmt.State, verb rune) {
|
||||||
switch verb {
|
switch verb {
|
||||||
@ -79,6 +80,14 @@ func (f Frame) Format(s fmt.State, verb rune) {
|
|||||||
// StackTrace is stack of Frames from innermost (newest) to outermost (oldest).
|
// StackTrace is stack of Frames from innermost (newest) to outermost (oldest).
|
||||||
type StackTrace []Frame
|
type StackTrace []Frame
|
||||||
|
|
||||||
|
// Format formats the stack of Frames according to the fmt.Formatter interface.
|
||||||
|
//
|
||||||
|
// %s lists source files for each Frame in the stack
|
||||||
|
// %v lists the source file and line number for each Frame in the stack
|
||||||
|
//
|
||||||
|
// Format accepts flags that alter the printing of some verbs, as follows:
|
||||||
|
//
|
||||||
|
// %+v Prints filename, function, and line number for each Frame in the stack.
|
||||||
func (st StackTrace) Format(s fmt.State, verb rune) {
|
func (st StackTrace) Format(s fmt.State, verb rune) {
|
||||||
switch verb {
|
switch verb {
|
||||||
case 'v':
|
case 'v':
|
||||||
@ -136,43 +145,3 @@ func funcname(name string) string {
|
|||||||
i = strings.Index(name, ".")
|
i = strings.Index(name, ".")
|
||||||
return name[i+1:]
|
return name[i+1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
func trimGOPATH(name, file string) string {
|
|
||||||
// Here we want to get the source file path relative to the compile time
|
|
||||||
// GOPATH. As of Go 1.6.x there is no direct way to know the compiled
|
|
||||||
// GOPATH at runtime, but we can infer the number of path segments in the
|
|
||||||
// GOPATH. We note that fn.Name() returns the function name qualified by
|
|
||||||
// the import path, which does not include the GOPATH. Thus we can trim
|
|
||||||
// segments from the beginning of the file path until the number of path
|
|
||||||
// separators remaining is one more than the number of path separators in
|
|
||||||
// the function name. For example, given:
|
|
||||||
//
|
|
||||||
// GOPATH /home/user
|
|
||||||
// file /home/user/src/pkg/sub/file.go
|
|
||||||
// fn.Name() pkg/sub.Type.Method
|
|
||||||
//
|
|
||||||
// We want to produce:
|
|
||||||
//
|
|
||||||
// pkg/sub/file.go
|
|
||||||
//
|
|
||||||
// From this we can easily see that fn.Name() has one less path separator
|
|
||||||
// than our desired output. We count separators from the end of the file
|
|
||||||
// path until it finds two more than in the function name and then move
|
|
||||||
// one character forward to preserve the initial path segment without a
|
|
||||||
// leading separator.
|
|
||||||
const sep = "/"
|
|
||||||
goal := strings.Count(name, sep) + 2
|
|
||||||
i := len(file)
|
|
||||||
for n := 0; n < goal; n++ {
|
|
||||||
i = strings.LastIndex(file[:i], sep)
|
|
||||||
if i == -1 {
|
|
||||||
// not enough separators found, set i so that the slice expression
|
|
||||||
// below leaves file unmodified
|
|
||||||
i = -len(sep)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// get back to 0 or trim the leading separator
|
|
||||||
file = file[i+len(sep):]
|
|
||||||
return file
|
|
||||||
}
|
|
||||||
|
40
tests/apitests/python/test_ldap_ping.py
Normal file
40
tests/apitests/python/test_ldap_ping.py
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
# coding: utf-8
|
||||||
|
|
||||||
|
"""
|
||||||
|
Harbor API
|
||||||
|
These APIs provide services for manipulating Harbor project.
|
||||||
|
OpenAPI spec version: 1.4.0
|
||||||
|
Generated by: https://github.com/swagger-api/swagger-codegen.git
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
sys.path.append(os.environ["SWAGGER_CLIENT_PATH"])
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
import testutils
|
||||||
|
from swagger_client.models.ldap_conf import LdapConf
|
||||||
|
from pprint import pprint
|
||||||
|
|
||||||
|
#Testcase
|
||||||
|
# Define a LDAP group with harbor admin
|
||||||
|
class TestLdapPing(unittest.TestCase):
|
||||||
|
"""AccessLog unit test stubs"""
|
||||||
|
product_api = testutils.GetProductApi("admin", "Harbor12345")
|
||||||
|
project_id = 0
|
||||||
|
def setUp(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def testLdapPing(self):
|
||||||
|
"""Test LdapAdminRole"""
|
||||||
|
result = self.product_api.ldap_ping_post(ldapconf=LdapConf(ldap_url="10.161.127.236", ldap_search_dn="cn=admin,dc=example,dc=com", ldap_search_password="admin", ldap_scope=2))
|
||||||
|
pprint(result)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
Loading…
Reference in New Issue
Block a user