Merge branch 'master' into telegram_webhook
This commit is contained in:
commit
b6c7ce32a3
10
Gopkg.lock
generated
10
Gopkg.lock
generated
|
@ -288,17 +288,19 @@
|
|||
[[projects]]
|
||||
name = "github.com/go-xorm/builder"
|
||||
packages = ["."]
|
||||
revision = "488224409dd8aa2ce7a5baf8d10d55764a913738"
|
||||
revision = "dc8bf48f58fab2b4da338ffd25191905fd741b8f"
|
||||
version = "v0.3.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/go-xorm/core"
|
||||
packages = ["."]
|
||||
revision = "cb1d0ca71f42d3ee1bf4aba7daa16099bc31a7e9"
|
||||
revision = "c10e21e7e1cec20e09398f2dfae385e58c8df555"
|
||||
version = "v0.6.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/go-xorm/xorm"
|
||||
packages = ["."]
|
||||
revision = "d4149d1eee0c2c488a74a5863fd9caf13d60fd03"
|
||||
revision = "ad69f7d8f0861a29438154bb0a20b60501298480"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
|
@ -701,6 +703,6 @@
|
|||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "59451a3ad1d449f75c5e9035daf542a377c5c4a397e219bebec0aa0007ab9c39"
|
||||
inputs-digest = "5ae18d543bbb8186589c003422b333097d67bb5fed8b4c294be70c012ccffc94"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
|
|
@ -33,7 +33,7 @@ ignored = ["google.golang.org/appengine*"]
|
|||
[[override]]
|
||||
name = "github.com/go-xorm/xorm"
|
||||
#version = "0.6.5"
|
||||
revision = "d4149d1eee0c2c488a74a5863fd9caf13d60fd03"
|
||||
revision = "ad69f7d8f0861a29438154bb0a20b60501298480"
|
||||
|
||||
[[override]]
|
||||
name = "github.com/go-sql-driver/mysql"
|
||||
|
|
|
@ -316,6 +316,9 @@ DEFAULT_KEEP_EMAIL_PRIVATE = false
|
|||
; Default value for AllowCreateOrganization
|
||||
; Every new user will have rights set to create organizations depending on this setting
|
||||
DEFAULT_ALLOW_CREATE_ORGANIZATION = true
|
||||
; Default value for EnableDependencies
|
||||
; Repositories will use depencies by default depending on this setting
|
||||
DEFAULT_ENABLE_DEPENDENCIES = true
|
||||
; Enable Timetracking
|
||||
ENABLE_TIMETRACKING = true
|
||||
; Default value for EnableTimetracking
|
||||
|
|
|
@ -182,6 +182,7 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
|
|||
- `CAPTCHA_TYPE`: **image**: \[image, recaptcha\]
|
||||
- `RECAPTCHA_SECRET`: **""**: Go to https://www.google.com/recaptcha/admin to get a secret for recaptcha
|
||||
- `RECAPTCHA_SITEKEY`: **""**: Go to https://www.google.com/recaptcha/admin to get a sitekey for recaptcha
|
||||
- `DEFAULT_ENABLE_DEPENDENCIES`: **true** Enable this to have dependencies enabled by default.
|
||||
|
||||
## Webhook (`webhook`)
|
||||
|
||||
|
|
1
main.go
1
main.go
|
@ -14,6 +14,7 @@ import (
|
|||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
// register supported doc types
|
||||
_ "code.gitea.io/gitea/modules/markup/csv"
|
||||
_ "code.gitea.io/gitea/modules/markup/markdown"
|
||||
_ "code.gitea.io/gitea/modules/markup/orgmode"
|
||||
|
||||
|
|
|
@ -477,6 +477,10 @@ func UpdateIssuesCommit(doer *User, repo *Repository, commits []*PushCommit) err
|
|||
}
|
||||
|
||||
if err = issue.ChangeStatus(doer, repo, true); err != nil {
|
||||
// Don't return an error when dependencies are open as this would let the push fail
|
||||
if IsErrDependenciesLeft(err) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1259,3 +1259,88 @@ func IsErrU2FRegistrationNotExist(err error) bool {
|
|||
_, ok := err.(ErrU2FRegistrationNotExist)
|
||||
return ok
|
||||
}
|
||||
|
||||
// .___ ________ .___ .__
|
||||
// | | ______ ________ __ ____ \______ \ ____ ______ ____ ____ __| _/____ ____ ____ |__| ____ ______
|
||||
// | |/ ___// ___/ | \_/ __ \ | | \_/ __ \\____ \_/ __ \ / \ / __ |/ __ \ / \_/ ___\| |/ __ \ / ___/
|
||||
// | |\___ \ \___ \| | /\ ___/ | ` \ ___/| |_> > ___/| | \/ /_/ \ ___/| | \ \___| \ ___/ \___ \
|
||||
// |___/____ >____ >____/ \___ >_______ /\___ > __/ \___ >___| /\____ |\___ >___| /\___ >__|\___ >____ >
|
||||
// \/ \/ \/ \/ \/|__| \/ \/ \/ \/ \/ \/ \/ \/
|
||||
|
||||
// ErrDependencyExists represents a "DependencyAlreadyExists" kind of error.
|
||||
type ErrDependencyExists struct {
|
||||
IssueID int64
|
||||
DependencyID int64
|
||||
}
|
||||
|
||||
// IsErrDependencyExists checks if an error is a ErrDependencyExists.
|
||||
func IsErrDependencyExists(err error) bool {
|
||||
_, ok := err.(ErrDependencyExists)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrDependencyExists) Error() string {
|
||||
return fmt.Sprintf("issue dependency does already exist [issue id: %d, dependency id: %d]", err.IssueID, err.DependencyID)
|
||||
}
|
||||
|
||||
// ErrDependencyNotExists represents a "DependencyAlreadyExists" kind of error.
|
||||
type ErrDependencyNotExists struct {
|
||||
IssueID int64
|
||||
DependencyID int64
|
||||
}
|
||||
|
||||
// IsErrDependencyNotExists checks if an error is a ErrDependencyExists.
|
||||
func IsErrDependencyNotExists(err error) bool {
|
||||
_, ok := err.(ErrDependencyNotExists)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrDependencyNotExists) Error() string {
|
||||
return fmt.Sprintf("issue dependency does not exist [issue id: %d, dependency id: %d]", err.IssueID, err.DependencyID)
|
||||
}
|
||||
|
||||
// ErrCircularDependency represents a "DependencyCircular" kind of error.
|
||||
type ErrCircularDependency struct {
|
||||
IssueID int64
|
||||
DependencyID int64
|
||||
}
|
||||
|
||||
// IsErrCircularDependency checks if an error is a ErrCircularDependency.
|
||||
func IsErrCircularDependency(err error) bool {
|
||||
_, ok := err.(ErrCircularDependency)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrCircularDependency) Error() string {
|
||||
return fmt.Sprintf("circular dependencies exists (two issues blocking each other) [issue id: %d, dependency id: %d]", err.IssueID, err.DependencyID)
|
||||
}
|
||||
|
||||
// ErrDependenciesLeft represents an error where the issue you're trying to close still has dependencies left.
|
||||
type ErrDependenciesLeft struct {
|
||||
IssueID int64
|
||||
}
|
||||
|
||||
// IsErrDependenciesLeft checks if an error is a ErrDependenciesLeft.
|
||||
func IsErrDependenciesLeft(err error) bool {
|
||||
_, ok := err.(ErrDependenciesLeft)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrDependenciesLeft) Error() string {
|
||||
return fmt.Sprintf("issue has open dependencies [issue id: %d]", err.IssueID)
|
||||
}
|
||||
|
||||
// ErrUnknownDependencyType represents an error where an unknown dependency type was passed
|
||||
type ErrUnknownDependencyType struct {
|
||||
Type DependencyType
|
||||
}
|
||||
|
||||
// IsErrUnknownDependencyType checks if an error is ErrUnknownDependencyType
|
||||
func IsErrUnknownDependencyType(err error) bool {
|
||||
_, ok := err.(ErrUnknownDependencyType)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrUnknownDependencyType) Error() string {
|
||||
return fmt.Sprintf("unknown dependency type [type: %d]", err.Type)
|
||||
}
|
||||
|
|
|
@ -649,6 +649,20 @@ func (issue *Issue) changeStatus(e *xorm.Session, doer *User, repo *Repository,
|
|||
if issue.IsClosed == isClosed {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check for open dependencies
|
||||
if isClosed && issue.Repo.IsDependenciesEnabled() {
|
||||
// only check if dependencies are enabled and we're about to close an issue, otherwise reopening an issue would fail when there are unsatisfied dependencies
|
||||
noDeps, err := IssueNoDependenciesLeft(issue)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !noDeps {
|
||||
return ErrDependenciesLeft{issue.ID}
|
||||
}
|
||||
}
|
||||
|
||||
issue.IsClosed = isClosed
|
||||
if isClosed {
|
||||
issue.ClosedUnix = util.TimeStampNow()
|
||||
|
@ -1283,7 +1297,7 @@ func getParticipantsByIssueID(e Engine, issueID int64) ([]*User, error) {
|
|||
And("`comment`.type = ?", CommentTypeComment).
|
||||
And("`user`.is_active = ?", true).
|
||||
And("`user`.prohibit_login = ?", false).
|
||||
Join("INNER", "user", "`user`.id = `comment`.poster_id").
|
||||
Join("INNER", "`user`", "`user`.id = `comment`.poster_id").
|
||||
Distinct("poster_id").
|
||||
Find(&userIDs); err != nil {
|
||||
return nil, fmt.Errorf("get poster IDs: %v", err)
|
||||
|
@ -1598,3 +1612,33 @@ func UpdateIssueDeadline(issue *Issue, deadlineUnix util.TimeStamp, doer *User)
|
|||
|
||||
return sess.Commit()
|
||||
}
|
||||
|
||||
// Get Blocked By Dependencies, aka all issues this issue is blocked by.
|
||||
func (issue *Issue) getBlockedByDependencies(e Engine) (issueDeps []*Issue, err error) {
|
||||
return issueDeps, e.
|
||||
Table("issue_dependency").
|
||||
Select("issue.*").
|
||||
Join("INNER", "issue", "issue.id = issue_dependency.dependency_id").
|
||||
Where("issue_id = ?", issue.ID).
|
||||
Find(&issueDeps)
|
||||
}
|
||||
|
||||
// Get Blocking Dependencies, aka all issues this issue blocks.
|
||||
func (issue *Issue) getBlockingDependencies(e Engine) (issueDeps []*Issue, err error) {
|
||||
return issueDeps, e.
|
||||
Table("issue_dependency").
|
||||
Select("issue.*").
|
||||
Join("INNER", "issue", "issue.id = issue_dependency.issue_id").
|
||||
Where("dependency_id = ?", issue.ID).
|
||||
Find(&issueDeps)
|
||||
}
|
||||
|
||||
// BlockedByDependencies finds all Dependencies an issue is blocked by
|
||||
func (issue *Issue) BlockedByDependencies() ([]*Issue, error) {
|
||||
return issue.getBlockedByDependencies(x)
|
||||
}
|
||||
|
||||
// BlockingDependencies returns all blocking dependencies, aka all other issues a given issue blocks
|
||||
func (issue *Issue) BlockingDependencies() ([]*Issue, error) {
|
||||
return issue.getBlockingDependencies(x)
|
||||
}
|
||||
|
|
|
@ -66,6 +66,10 @@ const (
|
|||
CommentTypeModifiedDeadline
|
||||
// Removed a due date
|
||||
CommentTypeRemovedDeadline
|
||||
// Dependency added
|
||||
CommentTypeAddDependency
|
||||
//Dependency removed
|
||||
CommentTypeRemoveDependency
|
||||
)
|
||||
|
||||
// CommentTag defines comment tag type
|
||||
|
@ -81,23 +85,25 @@ const (
|
|||
|
||||
// Comment represents a comment in commit and issue page.
|
||||
type Comment struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
Type CommentType
|
||||
PosterID int64 `xorm:"INDEX"`
|
||||
Poster *User `xorm:"-"`
|
||||
IssueID int64 `xorm:"INDEX"`
|
||||
Issue *Issue `xorm:"-"`
|
||||
LabelID int64
|
||||
Label *Label `xorm:"-"`
|
||||
OldMilestoneID int64
|
||||
MilestoneID int64
|
||||
OldMilestone *Milestone `xorm:"-"`
|
||||
Milestone *Milestone `xorm:"-"`
|
||||
AssigneeID int64
|
||||
RemovedAssignee bool
|
||||
Assignee *User `xorm:"-"`
|
||||
OldTitle string
|
||||
NewTitle string
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
Type CommentType
|
||||
PosterID int64 `xorm:"INDEX"`
|
||||
Poster *User `xorm:"-"`
|
||||
IssueID int64 `xorm:"INDEX"`
|
||||
Issue *Issue `xorm:"-"`
|
||||
LabelID int64
|
||||
Label *Label `xorm:"-"`
|
||||
OldMilestoneID int64
|
||||
MilestoneID int64
|
||||
OldMilestone *Milestone `xorm:"-"`
|
||||
Milestone *Milestone `xorm:"-"`
|
||||
AssigneeID int64
|
||||
RemovedAssignee bool
|
||||
Assignee *User `xorm:"-"`
|
||||
OldTitle string
|
||||
NewTitle string
|
||||
DependentIssueID int64
|
||||
DependentIssue *Issue `xorm:"-"`
|
||||
|
||||
CommitID int64
|
||||
Line int64
|
||||
|
@ -281,6 +287,15 @@ func (c *Comment) LoadAssigneeUser() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// LoadDepIssueDetails loads Dependent Issue Details
|
||||
func (c *Comment) LoadDepIssueDetails() (err error) {
|
||||
if c.DependentIssueID <= 0 || c.DependentIssue != nil {
|
||||
return nil
|
||||
}
|
||||
c.DependentIssue, err = getIssueByID(x, c.DependentIssueID)
|
||||
return err
|
||||
}
|
||||
|
||||
// MailParticipants sends new comment emails to repository watchers
|
||||
// and mentioned people.
|
||||
func (c *Comment) MailParticipants(e Engine, opType ActionType, issue *Issue) (err error) {
|
||||
|
@ -332,22 +347,24 @@ func createComment(e *xorm.Session, opts *CreateCommentOptions) (_ *Comment, err
|
|||
if opts.Label != nil {
|
||||
LabelID = opts.Label.ID
|
||||
}
|
||||
|
||||
comment := &Comment{
|
||||
Type: opts.Type,
|
||||
PosterID: opts.Doer.ID,
|
||||
Poster: opts.Doer,
|
||||
IssueID: opts.Issue.ID,
|
||||
LabelID: LabelID,
|
||||
OldMilestoneID: opts.OldMilestoneID,
|
||||
MilestoneID: opts.MilestoneID,
|
||||
RemovedAssignee: opts.RemovedAssignee,
|
||||
AssigneeID: opts.AssigneeID,
|
||||
CommitID: opts.CommitID,
|
||||
CommitSHA: opts.CommitSHA,
|
||||
Line: opts.LineNum,
|
||||
Content: opts.Content,
|
||||
OldTitle: opts.OldTitle,
|
||||
NewTitle: opts.NewTitle,
|
||||
Type: opts.Type,
|
||||
PosterID: opts.Doer.ID,
|
||||
Poster: opts.Doer,
|
||||
IssueID: opts.Issue.ID,
|
||||
LabelID: LabelID,
|
||||
OldMilestoneID: opts.OldMilestoneID,
|
||||
MilestoneID: opts.MilestoneID,
|
||||
RemovedAssignee: opts.RemovedAssignee,
|
||||
AssigneeID: opts.AssigneeID,
|
||||
CommitID: opts.CommitID,
|
||||
CommitSHA: opts.CommitSHA,
|
||||
Line: opts.LineNum,
|
||||
Content: opts.Content,
|
||||
OldTitle: opts.OldTitle,
|
||||
NewTitle: opts.NewTitle,
|
||||
DependentIssueID: opts.DependentIssueID,
|
||||
}
|
||||
if _, err = e.Insert(comment); err != nil {
|
||||
return nil, err
|
||||
|
@ -549,6 +566,39 @@ func createDeleteBranchComment(e *xorm.Session, doer *User, repo *Repository, is
|
|||
})
|
||||
}
|
||||
|
||||
// Creates issue dependency comment
|
||||
func createIssueDependencyComment(e *xorm.Session, doer *User, issue *Issue, dependentIssue *Issue, add bool) (err error) {
|
||||
cType := CommentTypeAddDependency
|
||||
if !add {
|
||||
cType = CommentTypeRemoveDependency
|
||||
}
|
||||
|
||||
// Make two comments, one in each issue
|
||||
_, err = createComment(e, &CreateCommentOptions{
|
||||
Type: cType,
|
||||
Doer: doer,
|
||||
Repo: issue.Repo,
|
||||
Issue: issue,
|
||||
DependentIssueID: dependentIssue.ID,
|
||||
})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
_, err = createComment(e, &CreateCommentOptions{
|
||||
Type: cType,
|
||||
Doer: doer,
|
||||
Repo: issue.Repo,
|
||||
Issue: dependentIssue,
|
||||
DependentIssueID: issue.ID,
|
||||
})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// CreateCommentOptions defines options for creating comment
|
||||
type CreateCommentOptions struct {
|
||||
Type CommentType
|
||||
|
@ -557,17 +607,18 @@ type CreateCommentOptions struct {
|
|||
Issue *Issue
|
||||
Label *Label
|
||||
|
||||
OldMilestoneID int64
|
||||
MilestoneID int64
|
||||
AssigneeID int64
|
||||
RemovedAssignee bool
|
||||
OldTitle string
|
||||
NewTitle string
|
||||
CommitID int64
|
||||
CommitSHA string
|
||||
LineNum int64
|
||||
Content string
|
||||
Attachments []string // UUIDs of attachments
|
||||
DependentIssueID int64
|
||||
OldMilestoneID int64
|
||||
MilestoneID int64
|
||||
AssigneeID int64
|
||||
RemovedAssignee bool
|
||||
OldTitle string
|
||||
NewTitle string
|
||||
CommitID int64
|
||||
CommitSHA string
|
||||
LineNum int64
|
||||
Content string
|
||||
Attachments []string // UUIDs of attachments
|
||||
}
|
||||
|
||||
// CreateComment creates comment of issue or commit.
|
||||
|
|
137
models/issue_dependency.go
Normal file
137
models/issue_dependency.go
Normal file
|
@ -0,0 +1,137 @@
|
|||
// Copyright 2018 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
// IssueDependency represents an issue dependency
|
||||
type IssueDependency struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
UserID int64 `xorm:"NOT NULL"`
|
||||
IssueID int64 `xorm:"UNIQUE(issue_dependency) NOT NULL"`
|
||||
DependencyID int64 `xorm:"UNIQUE(issue_dependency) NOT NULL"`
|
||||
CreatedUnix util.TimeStamp `xorm:"created"`
|
||||
UpdatedUnix util.TimeStamp `xorm:"updated"`
|
||||
}
|
||||
|
||||
// DependencyType Defines Dependency Type Constants
|
||||
type DependencyType int
|
||||
|
||||
// Define Dependency Types
|
||||
const (
|
||||
DependencyTypeBlockedBy DependencyType = iota
|
||||
DependencyTypeBlocking
|
||||
)
|
||||
|
||||
// CreateIssueDependency creates a new dependency for an issue
|
||||
func CreateIssueDependency(user *User, issue, dep *Issue) error {
|
||||
sess := x.NewSession()
|
||||
defer sess.Close()
|
||||
if err := sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check if it aleready exists
|
||||
exists, err := issueDepExists(sess, issue.ID, dep.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if exists {
|
||||
return ErrDependencyExists{issue.ID, dep.ID}
|
||||
}
|
||||
// And if it would be circular
|
||||
circular, err := issueDepExists(sess, dep.ID, issue.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if circular {
|
||||
return ErrCircularDependency{issue.ID, dep.ID}
|
||||
}
|
||||
|
||||
if _, err := sess.Insert(&IssueDependency{
|
||||
UserID: user.ID,
|
||||
IssueID: issue.ID,
|
||||
DependencyID: dep.ID,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Add comment referencing the new dependency
|
||||
if err = createIssueDependencyComment(sess, user, issue, dep, true); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return sess.Commit()
|
||||
}
|
||||
|
||||
// RemoveIssueDependency removes a dependency from an issue
|
||||
func RemoveIssueDependency(user *User, issue *Issue, dep *Issue, depType DependencyType) (err error) {
|
||||
sess := x.NewSession()
|
||||
defer sess.Close()
|
||||
if err = sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var issueDepToDelete IssueDependency
|
||||
|
||||
switch depType {
|
||||
case DependencyTypeBlockedBy:
|
||||
issueDepToDelete = IssueDependency{IssueID: issue.ID, DependencyID: dep.ID}
|
||||
case DependencyTypeBlocking:
|
||||
issueDepToDelete = IssueDependency{IssueID: dep.ID, DependencyID: issue.ID}
|
||||
default:
|
||||
return ErrUnknownDependencyType{depType}
|
||||
}
|
||||
|
||||
affected, err := sess.Delete(&issueDepToDelete)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If we deleted nothing, the dependency did not exist
|
||||
if affected <= 0 {
|
||||
return ErrDependencyNotExists{issue.ID, dep.ID}
|
||||
}
|
||||
|
||||
// Add comment referencing the removed dependency
|
||||
if err = createIssueDependencyComment(sess, user, issue, dep, false); err != nil {
|
||||
return err
|
||||
}
|
||||
return sess.Commit()
|
||||
}
|
||||
|
||||
// Check if the dependency already exists
|
||||
func issueDepExists(e Engine, issueID int64, depID int64) (bool, error) {
|
||||
return e.Where("(issue_id = ? AND dependency_id = ?)", issueID, depID).Exist(&IssueDependency{})
|
||||
}
|
||||
|
||||
// IssueNoDependenciesLeft checks if issue can be closed
|
||||
func IssueNoDependenciesLeft(issue *Issue) (bool, error) {
|
||||
|
||||
exists, err := x.
|
||||
Table("issue_dependency").
|
||||
Select("issue.*").
|
||||
Join("INNER", "issue", "issue.id = issue_dependency.dependency_id").
|
||||
Where("issue_dependency.issue_id = ?", issue.ID).
|
||||
And("issue.is_closed = ?", "0").
|
||||
Exist(&Issue{})
|
||||
|
||||
return !exists, err
|
||||
}
|
||||
|
||||
// IsDependenciesEnabled returns if dependecies are enabled and returns the default setting if not set.
|
||||
func (repo *Repository) IsDependenciesEnabled() bool {
|
||||
var u *RepoUnit
|
||||
var err error
|
||||
if u, err = repo.GetUnit(UnitTypeIssues); err != nil {
|
||||
log.Trace("%s", err)
|
||||
return setting.Service.DefaultEnableDependencies
|
||||
}
|
||||
return u.IssuesConfig().EnableDependencies
|
||||
}
|
57
models/issue_dependency_test.go
Normal file
57
models/issue_dependency_test.go
Normal file
|
@ -0,0 +1,57 @@
|
|||
// Copyright 2018 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCreateIssueDependency(t *testing.T) {
|
||||
// Prepare
|
||||
assert.NoError(t, PrepareTestDatabase())
|
||||
|
||||
user1, err := GetUserByID(1)
|
||||
assert.NoError(t, err)
|
||||
|
||||
issue1, err := GetIssueByID(1)
|
||||
assert.NoError(t, err)
|
||||
issue2, err := GetIssueByID(2)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Create a dependency and check if it was successful
|
||||
err = CreateIssueDependency(user1, issue1, issue2)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Do it again to see if it will check if the dependency already exists
|
||||
err = CreateIssueDependency(user1, issue1, issue2)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrDependencyExists(err))
|
||||
|
||||
// Check for circular dependencies
|
||||
err = CreateIssueDependency(user1, issue2, issue1)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrCircularDependency(err))
|
||||
|
||||
_ = AssertExistsAndLoadBean(t, &Comment{Type: CommentTypeAddDependency, PosterID: user1.ID, IssueID: issue1.ID})
|
||||
|
||||
// Check if dependencies left is correct
|
||||
left, err := IssueNoDependenciesLeft(issue1)
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, left)
|
||||
|
||||
// Close #2 and check again
|
||||
err = issue2.ChangeStatus(user1, issue2.Repo, true)
|
||||
assert.NoError(t, err)
|
||||
|
||||
left, err = IssueNoDependenciesLeft(issue1)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, left)
|
||||
|
||||
// Test removing the dependency
|
||||
err = RemoveIssueDependency(user1, issue1, issue2, DependencyTypeBlockedBy)
|
||||
assert.NoError(t, err)
|
||||
}
|
|
@ -166,7 +166,7 @@ func (issues IssueList) loadAssignees(e Engine) error {
|
|||
|
||||
var assignees = make(map[int64][]*User, len(issues))
|
||||
rows, err := e.Table("issue_assignees").
|
||||
Join("INNER", "user", "`user`.id = `issue_assignees`.assignee_id").
|
||||
Join("INNER", "`user`", "`user`.id = `issue_assignees`.assignee_id").
|
||||
In("`issue_assignees`.issue_id", issues.getIssueIDs()).
|
||||
Rows(new(AssigneeIssue))
|
||||
if err != nil {
|
||||
|
|
|
@ -67,7 +67,7 @@ func getIssueWatchers(e Engine, issueID int64) (watches []*IssueWatch, err error
|
|||
Where("`issue_watch`.issue_id = ?", issueID).
|
||||
And("`user`.is_active = ?", true).
|
||||
And("`user`.prohibit_login = ?", false).
|
||||
Join("INNER", "user", "`user`.id = `issue_watch`.user_id").
|
||||
Join("INNER", "`user`", "`user`.id = `issue_watch`.user_id").
|
||||
Find(&watches)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -192,6 +192,8 @@ var migrations = []Migration{
|
|||
NewMigration("Reformat and remove incorrect topics", reformatAndRemoveIncorrectTopics),
|
||||
// v69 -> v70
|
||||
NewMigration("move team units to team_unit table", moveTeamUnitsToTeamUnitTable),
|
||||
// v70 -> v71
|
||||
NewMigration("add issue_dependencies", addIssueDependencies),
|
||||
}
|
||||
|
||||
// Migrate database to current version
|
||||
|
|
100
models/migrations/v70.go
Normal file
100
models/migrations/v70.go
Normal file
|
@ -0,0 +1,100 @@
|
|||
// Copyright 2018 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/go-xorm/xorm"
|
||||
)
|
||||
|
||||
func addIssueDependencies(x *xorm.Engine) (err error) {
|
||||
|
||||
type IssueDependency struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
UserID int64 `xorm:"NOT NULL"`
|
||||
IssueID int64 `xorm:"NOT NULL"`
|
||||
DependencyID int64 `xorm:"NOT NULL"`
|
||||
Created time.Time `xorm:"-"`
|
||||
CreatedUnix int64 `xorm:"created"`
|
||||
Updated time.Time `xorm:"-"`
|
||||
UpdatedUnix int64 `xorm:"updated"`
|
||||
}
|
||||
|
||||
if err = x.Sync(new(IssueDependency)); err != nil {
|
||||
return fmt.Errorf("Error creating issue_dependency_table column definition: %v", err)
|
||||
}
|
||||
|
||||
// Update Comment definition
|
||||
// This (copied) struct does only contain fields used by xorm as the only use here is to update the database
|
||||
|
||||
// CommentType defines the comment type
|
||||
type CommentType int
|
||||
|
||||
// TimeStamp defines a timestamp
|
||||
type TimeStamp int64
|
||||
|
||||
type Comment struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
Type CommentType
|
||||
PosterID int64 `xorm:"INDEX"`
|
||||
IssueID int64 `xorm:"INDEX"`
|
||||
LabelID int64
|
||||
OldMilestoneID int64
|
||||
MilestoneID int64
|
||||
OldAssigneeID int64
|
||||
AssigneeID int64
|
||||
OldTitle string
|
||||
NewTitle string
|
||||
DependentIssueID int64
|
||||
|
||||
CommitID int64
|
||||
Line int64
|
||||
Content string `xorm:"TEXT"`
|
||||
|
||||
CreatedUnix TimeStamp `xorm:"INDEX created"`
|
||||
UpdatedUnix TimeStamp `xorm:"INDEX updated"`
|
||||
|
||||
// Reference issue in commit message
|
||||
CommitSHA string `xorm:"VARCHAR(40)"`
|
||||
}
|
||||
|
||||
if err = x.Sync(new(Comment)); err != nil {
|
||||
return fmt.Errorf("Error updating issue_comment table column definition: %v", err)
|
||||
}
|
||||
|
||||
// RepoUnit describes all units of a repository
|
||||
type RepoUnit struct {
|
||||
ID int64
|
||||
RepoID int64 `xorm:"INDEX(s)"`
|
||||
Type int `xorm:"INDEX(s)"`
|
||||
Config map[string]interface{} `xorm:"JSON"`
|
||||
CreatedUnix int64 `xorm:"INDEX CREATED"`
|
||||
Created time.Time `xorm:"-"`
|
||||
}
|
||||
|
||||
//Updating existing issue units
|
||||
units := make([]*RepoUnit, 0, 100)
|
||||
err = x.Where("`type` = ?", V16UnitTypeIssues).Find(&units)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Query repo units: %v", err)
|
||||
}
|
||||
for _, unit := range units {
|
||||
if unit.Config == nil {
|
||||
unit.Config = make(map[string]interface{})
|
||||
}
|
||||
if _, ok := unit.Config["EnableDependencies"]; !ok {
|
||||
unit.Config["EnableDependencies"] = setting.Service.DefaultEnableDependencies
|
||||
}
|
||||
if _, err := x.ID(unit.ID).Cols("config").Update(unit); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
|
@ -118,6 +118,7 @@ func init() {
|
|||
new(TrackedTime),
|
||||
new(DeletedBranch),
|
||||
new(RepoIndexerStatus),
|
||||
new(IssueDependency),
|
||||
new(LFSLock),
|
||||
new(Reaction),
|
||||
new(IssueAssignees),
|
||||
|
|
|
@ -383,7 +383,7 @@ func GetOwnedOrgsByUserIDDesc(userID int64, desc string) ([]*User, error) {
|
|||
func GetOrgUsersByUserID(uid int64, all bool) ([]*OrgUser, error) {
|
||||
ous := make([]*OrgUser, 0, 10)
|
||||
sess := x.
|
||||
Join("LEFT", "user", "`org_user`.org_id=`user`.id").
|
||||
Join("LEFT", "`user`", "`org_user`.org_id=`user`.id").
|
||||
Where("`org_user`.uid=?", uid)
|
||||
if !all {
|
||||
// Only show public organizations
|
||||
|
@ -575,7 +575,7 @@ func (org *User) getUserTeams(e Engine, userID int64, cols ...string) ([]*Team,
|
|||
return teams, e.
|
||||
Where("`team_user`.org_id = ?", org.ID).
|
||||
Join("INNER", "team_user", "`team_user`.team_id = team.id").
|
||||
Join("INNER", "user", "`user`.id=team_user.uid").
|
||||
Join("INNER", "`user`", "`user`.id=team_user.uid").
|
||||
And("`team_user`.uid = ?", userID).
|
||||
Asc("`user`.name").
|
||||
Cols(cols...).
|
||||
|
|
|
@ -1345,7 +1345,11 @@ func createRepository(e *xorm.Session, doer, u *User, repo *Repository) (err err
|
|||
units = append(units, RepoUnit{
|
||||
RepoID: repo.ID,
|
||||
Type: tp,
|
||||
Config: &IssuesConfig{EnableTimetracker: setting.Service.DefaultEnableTimetracking, AllowOnlyContributorsToTrackTime: setting.Service.DefaultAllowOnlyContributorsToTrackTime},
|
||||
Config: &IssuesConfig{
|
||||
EnableTimetracker: setting.Service.DefaultEnableTimetracking,
|
||||
AllowOnlyContributorsToTrackTime: setting.Service.DefaultAllowOnlyContributorsToTrackTime,
|
||||
EnableDependencies: setting.Service.DefaultEnableDependencies,
|
||||
},
|
||||
})
|
||||
} else if tp == UnitTypePullRequests {
|
||||
units = append(units, RepoUnit{
|
||||
|
@ -1954,7 +1958,7 @@ func DeleteRepository(doer *User, uid, repoID int64) error {
|
|||
func GetRepositoryByOwnerAndName(ownerName, repoName string) (*Repository, error) {
|
||||
var repo Repository
|
||||
has, err := x.Select("repository.*").
|
||||
Join("INNER", "user", "`user`.id = repository.owner_id").
|
||||
Join("INNER", "`user`", "`user`.id = repository.owner_id").
|
||||
Where("repository.lower_name = ?", strings.ToLower(repoName)).
|
||||
And("`user`.lower_name = ?", strings.ToLower(ownerName)).
|
||||
Get(&repo)
|
||||
|
|
|
@ -73,6 +73,7 @@ func (cfg *ExternalTrackerConfig) ToDB() ([]byte, error) {
|
|||
type IssuesConfig struct {
|
||||
EnableTimetracker bool
|
||||
AllowOnlyContributorsToTrackTime bool
|
||||
EnableDependencies bool
|
||||
}
|
||||
|
||||
// FromDB fills up a IssuesConfig from serialized format.
|
||||
|
@ -165,7 +166,6 @@ func (r *RepoUnit) IssuesConfig() *IssuesConfig {
|
|||
func (r *RepoUnit) ExternalTrackerConfig() *ExternalTrackerConfig {
|
||||
return r.Config.(*ExternalTrackerConfig)
|
||||
}
|
||||
|
||||
func getUnitsByRepoID(e Engine, repoID int64) (units []*RepoUnit, err error) {
|
||||
return units, e.Where("repo_id = ?", repoID).Find(&units)
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ func getWatchers(e Engine, repoID int64) ([]*Watch, error) {
|
|||
return watches, e.Where("`watch`.repo_id=?", repoID).
|
||||
And("`user`.is_active=?", true).
|
||||
And("`user`.prohibit_login=?", false).
|
||||
Join("INNER", "user", "`user`.id = `watch`.user_id").
|
||||
Join("INNER", "`user`", "`user`.id = `watch`.user_id").
|
||||
Find(&watches)
|
||||
}
|
||||
|
||||
|
|
|
@ -374,9 +374,9 @@ func (u *User) GetFollowers(page int) ([]*User, error) {
|
|||
Limit(ItemsPerPage, (page-1)*ItemsPerPage).
|
||||
Where("follow.follow_id=?", u.ID)
|
||||
if setting.UsePostgreSQL {
|
||||
sess = sess.Join("LEFT", "follow", `"user".id=follow.user_id`)
|
||||
sess = sess.Join("LEFT", "follow", "`user`.id=follow.user_id")
|
||||
} else {
|
||||
sess = sess.Join("LEFT", "follow", "user.id=follow.user_id")
|
||||
sess = sess.Join("LEFT", "follow", "`user`.id=follow.user_id")
|
||||
}
|
||||
return users, sess.Find(&users)
|
||||
}
|
||||
|
@ -393,9 +393,9 @@ func (u *User) GetFollowing(page int) ([]*User, error) {
|
|||
Limit(ItemsPerPage, (page-1)*ItemsPerPage).
|
||||
Where("follow.user_id=?", u.ID)
|
||||
if setting.UsePostgreSQL {
|
||||
sess = sess.Join("LEFT", "follow", `"user".id=follow.follow_id`)
|
||||
sess = sess.Join("LEFT", "follow", "`user`.id=follow.follow_id")
|
||||
} else {
|
||||
sess = sess.Join("LEFT", "follow", "user.id=follow.follow_id")
|
||||
sess = sess.Join("LEFT", "follow", "`user`.id=follow.follow_id")
|
||||
}
|
||||
return users, sess.Find(&users)
|
||||
}
|
||||
|
|
|
@ -113,6 +113,7 @@ type RepoSettingForm struct {
|
|||
PullsAllowSquash bool
|
||||
EnableTimetracker bool
|
||||
AllowOnlyContributorsToTrackTime bool
|
||||
EnableIssueDependencies bool
|
||||
|
||||
// Admin settings
|
||||
EnableHealthCheck bool
|
||||
|
|
|
@ -104,6 +104,11 @@ func (r *Repository) CanUseTimetracker(issue *models.Issue, user *models.User) b
|
|||
r.IsWriter() || issue.IsPoster(user.ID) || isAssigned)
|
||||
}
|
||||
|
||||
// CanCreateIssueDependencies returns whether or not a user can create dependencies.
|
||||
func (r *Repository) CanCreateIssueDependencies(user *models.User) bool {
|
||||
return r.Repository.IsDependenciesEnabled() && r.IsWriter()
|
||||
}
|
||||
|
||||
// GetCommitsCount returns cached commit count for current view
|
||||
func (r *Repository) GetCommitsCount() (int64, error) {
|
||||
var contextName string
|
||||
|
|
|
@ -85,9 +85,12 @@ type link struct {
|
|||
|
||||
var oidRegExp = regexp.MustCompile(`^[A-Fa-f0-9]+$`)
|
||||
|
||||
func isOidValid(oid string) bool {
|
||||
return oidRegExp.MatchString(oid)
|
||||
}
|
||||
|
||||
// ObjectOidHandler is the main request routing entry point into LFS server functions
|
||||
func ObjectOidHandler(ctx *context.Context) {
|
||||
|
||||
if !setting.LFS.StartServer {
|
||||
writeStatus(ctx, 404)
|
||||
return
|
||||
|
@ -110,6 +113,11 @@ func ObjectOidHandler(ctx *context.Context) {
|
|||
}
|
||||
|
||||
func getAuthenticatedRepoAndMeta(ctx *context.Context, rv *RequestVars, requireWrite bool) (*models.LFSMetaObject, *models.Repository) {
|
||||
if !isOidValid(rv.Oid) {
|
||||
writeStatus(ctx, 404)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
repository, err := models.GetRepositoryByOwnerAndName(rv.User, rv.Repo)
|
||||
if err != nil {
|
||||
log.Debug("Could not find repository: %s/%s - %s", rv.User, rv.Repo, err)
|
||||
|
@ -222,7 +230,7 @@ func PostHandler(ctx *context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
if !oidRegExp.MatchString(rv.Oid) {
|
||||
if !isOidValid(rv.Oid) {
|
||||
writeStatus(ctx, 404)
|
||||
return
|
||||
}
|
||||
|
@ -249,7 +257,6 @@ func PostHandler(ctx *context.Context) {
|
|||
|
||||
// BatchHandler provides the batch api
|
||||
func BatchHandler(ctx *context.Context) {
|
||||
|
||||
if !setting.LFS.StartServer {
|
||||
writeStatus(ctx, 404)
|
||||
return
|
||||
|
@ -266,6 +273,10 @@ func BatchHandler(ctx *context.Context) {
|
|||
|
||||
// Create a response object
|
||||
for _, object := range bv.Objects {
|
||||
if !isOidValid(object.Oid) {
|
||||
continue
|
||||
}
|
||||
|
||||
repository, err := models.GetRepositoryByOwnerAndName(object.User, object.Repo)
|
||||
|
||||
if err != nil {
|
||||
|
@ -292,12 +303,10 @@ func BatchHandler(ctx *context.Context) {
|
|||
continue
|
||||
}
|
||||
|
||||
if oidRegExp.MatchString(object.Oid) {
|
||||
// Object is not found
|
||||
meta, err = models.NewLFSMetaObject(&models.LFSMetaObject{Oid: object.Oid, Size: object.Size, RepositoryID: repository.ID})
|
||||
if err == nil {
|
||||
responseObjects = append(responseObjects, Represent(object, meta, meta.Existing, !contentStore.Exists(meta)))
|
||||
}
|
||||
// Object is not found
|
||||
meta, err = models.NewLFSMetaObject(&models.LFSMetaObject{Oid: object.Oid, Size: object.Size, RepositoryID: repository.ID})
|
||||
if err == nil {
|
||||
responseObjects = append(responseObjects, Represent(object, meta, meta.Existing, !contentStore.Exists(meta)))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
58
modules/markup/csv/csv.go
Normal file
58
modules/markup/csv/csv.go
Normal file
|
@ -0,0 +1,58 @@
|
|||
// Copyright 2018 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package markup
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/csv"
|
||||
"html"
|
||||
"io"
|
||||
|
||||
"code.gitea.io/gitea/modules/markup"
|
||||
)
|
||||
|
||||
func init() {
|
||||
markup.RegisterParser(Parser{})
|
||||
}
|
||||
|
||||
// Parser implements markup.Parser for orgmode
|
||||
type Parser struct {
|
||||
}
|
||||
|
||||
// Name implements markup.Parser
|
||||
func (Parser) Name() string {
|
||||
return "csv"
|
||||
}
|
||||
|
||||
// Extensions implements markup.Parser
|
||||
func (Parser) Extensions() []string {
|
||||
return []string{".csv"}
|
||||
}
|
||||
|
||||
// Render implements markup.Parser
|
||||
func (Parser) Render(rawBytes []byte, urlPrefix string, metas map[string]string, isWiki bool) []byte {
|
||||
rd := csv.NewReader(bytes.NewReader(rawBytes))
|
||||
var tmpBlock bytes.Buffer
|
||||
tmpBlock.WriteString(`<table class="table">`)
|
||||
for {
|
||||
fields, err := rd.Read()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
tmpBlock.WriteString("<tr>")
|
||||
for _, field := range fields {
|
||||
tmpBlock.WriteString("<td>")
|
||||
tmpBlock.WriteString(html.EscapeString(field))
|
||||
tmpBlock.WriteString("</td>")
|
||||
}
|
||||
tmpBlock.WriteString("<tr>")
|
||||
}
|
||||
tmpBlock.WriteString("</table>")
|
||||
|
||||
return tmpBlock.Bytes()
|
||||
}
|
25
modules/markup/csv/csv_test.go
Normal file
25
modules/markup/csv/csv_test.go
Normal file
|
@ -0,0 +1,25 @@
|
|||
// Copyright 2018 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package markup
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestRenderCSV(t *testing.T) {
|
||||
var parser Parser
|
||||
var kases = map[string]string{
|
||||
"a": "<table class=\"table\"><tr><td>a</td><tr></table>",
|
||||
"1,2": "<table class=\"table\"><tr><td>1</td><td>2</td><tr></table>",
|
||||
"<br/>": "<table class=\"table\"><tr><td><br/></td><tr></table>",
|
||||
}
|
||||
|
||||
for k, v := range kases {
|
||||
res := parser.Render([]byte(k), "", nil, false)
|
||||
assert.EqualValues(t, v, string(res))
|
||||
}
|
||||
}
|
|
@ -1180,6 +1180,7 @@ var Service struct {
|
|||
DefaultAllowCreateOrganization bool
|
||||
EnableTimetracking bool
|
||||
DefaultEnableTimetracking bool
|
||||
DefaultEnableDependencies bool
|
||||
DefaultAllowOnlyContributorsToTrackTime bool
|
||||
NoReplyAddress string
|
||||
|
||||
|
@ -1210,6 +1211,7 @@ func newService() {
|
|||
if Service.EnableTimetracking {
|
||||
Service.DefaultEnableTimetracking = sec.Key("DEFAULT_ENABLE_TIMETRACKING").MustBool(true)
|
||||
}
|
||||
Service.DefaultEnableDependencies = sec.Key("DEFAULT_ENABLE_DEPENDENCIES").MustBool(true)
|
||||
Service.DefaultAllowOnlyContributorsToTrackTime = sec.Key("DEFAULT_ALLOW_ONLY_CONTRIBUTORS_TO_TRACK_TIME").MustBool(true)
|
||||
Service.NoReplyAddress = sec.Key("NO_REPLY_ADDRESS").MustString("noreply.example.org")
|
||||
|
||||
|
|
|
@ -32,16 +32,8 @@ twofa_scratch=Zwei-Faktor-Einmalpasswort
|
|||
passcode=PIN
|
||||
|
||||
u2f_insert_key=Hardware-Sicherheitsschlüssel einstecken
|
||||
u2f_sign_in=Drücke den Knopf auf deinem Sicherheitsschlüssel. Wenn deiner keinen Knopf hat, stecke ihn erneut ein.
|
||||
u2f_press_button=Drücke den Knopf auf deinem Sicherheitsschlüssel…
|
||||
u2f_use_twofa=Zwei-Faktor-Authentifizierung via Handy verwenden
|
||||
u2f_error=Wir können deinen Hardware-Sicherheitsschlüssel nicht lesen!
|
||||
u2f_unsupported_browser=Dein Browser unterstützt keine U2F-Geräte. Bitte benutze einen anderen Browser.
|
||||
u2f_error_1=Ein unbekannter Fehler ist aufgetreten. Bitte versuche es erneut.
|
||||
u2f_error_2=Stelle sicher, dass du einen verschlüsselte Verbindung (https://) benutzt und die richtige URL eingeben hast.
|
||||
u2f_error_3=Der Server kann deine Anfrage nicht bearbeiten.
|
||||
u2f_error_4=Dieser Sicherheitsschlüssel ist nicht berechtigt. Wenn du versuchst, einen neuen Sicherheitsschlüssel zu registrieren, stelle bitte sicher, dass du ihn nicht bereits registriert hast.
|
||||
u2f_error_5=Das Zeitlimit wurde erreicht bevor dein Schlüssel gelesen werden konnte. Bitte lade die Seite neu.
|
||||
u2f_reload=Neu laden
|
||||
|
||||
repository=Repository
|
||||
|
@ -130,7 +122,6 @@ federated_avatar_lookup=Föderierte Profilbilder einschalten
|
|||
federated_avatar_lookup_popup=Föderierte Profilbilder via Libravatar aktivieren.
|
||||
disable_registration=Registrierung deaktivieren
|
||||
disable_registration_popup=Registrierung neuer Benutzer deaktivieren. Nur Administratoren werden neue Benutzerkonten anlegen können.
|
||||
allow_only_external_registration_popup=Registrierung nur über externe Services aktiveren.
|
||||
openid_signin=OpenID-Anmeldung aktivieren
|
||||
openid_signin_popup=Benutzeranmeldung via OpenID aktivieren.
|
||||
openid_signup=OpenID-Selbstregistrierung aktivieren
|
||||
|
@ -463,13 +454,10 @@ then_enter_passcode=Und gebe dann die angezeigte PIN der Anwendung ein:
|
|||
passcode_invalid=Die PIN ist falsch. Probiere es erneut.
|
||||
twofa_enrolled=Die Zwei-Faktor-Authentifizierung wurde für dein Konto aktiviert. Bewahre dein Einmalpasswort (%s) an einem sicheren Ort auf, da es nicht wieder angezeigt werden wird.
|
||||
|
||||
u2f_desc=Hardware-Sicherheitsschlüssel sind Geräte, die kryptografische Schlüssel beinhalten. Diese können für die Zwei-Faktor-Authentifizierung verwendet werden. Der Sicherheitsschlüssel muss den Standard <a href="https://fidoalliance.org/">FIDO U2F</a> unterstützen.
|
||||
u2f_require_twofa=Du musst die Zwei-Faktor-Authentifizierung aktivieren, um Hardware-Sicherheitsschlüssel nutzen zu können.
|
||||
u2f_register_key=Sicherheitsschlüssel hinzufügen
|
||||
u2f_nickname=Nickname
|
||||
u2f_press_button=Drücke den Knopf auf deinem Sicherheitsschlüssel, um diesen zu registrieren.
|
||||
u2f_delete_key=Sicherheitsschlüssel entfernen
|
||||
u2f_delete_key_desc=Wenn du den Sicherheitsschlüssel entfernst, kannst du dich nicht mehr mit diesem einloggen. Bist du sicher?
|
||||
|
||||
manage_account_links=Verknüpfte Accounts verwalten
|
||||
manage_account_links_desc=Diese externen Accounts sind mit deinem Gitea-Account verknüpft.
|
||||
|
@ -650,7 +638,6 @@ issues.new.open_milestone=Offene Meilensteine
|
|||
issues.new.closed_milestone=Geschlossene Meilensteine
|
||||
issues.new.assignees=Zuständig
|
||||
issues.new.clear_assignees=Zuständige entfernen
|
||||
issues.new.no_assignees=Niemand zugewiesen
|
||||
issues.no_ref=Keine Branch/Tag angegeben
|
||||
issues.create=Issue erstellen
|
||||
issues.new_label=Neues Label
|
||||
|
@ -1167,8 +1154,6 @@ branch.protected_deletion_failed=Branch „%s“ ist geschützt und kann nicht g
|
|||
|
||||
topic.manage_topics=Themen verwalten
|
||||
topic.done=Fertig
|
||||
topic.count_prompt=Du kannst nicht mehr als 25 Themen auswählen
|
||||
topic.format_prompt=Themen müssen mit einem Buchstaben oder einer Zahl beginnen. Sie können Bindestriche (-) enthalten und dürfen nicht länger als 35 Zeichen sein
|
||||
|
||||
[org]
|
||||
org_name_holder=Name der Organisation
|
||||
|
@ -1273,8 +1258,6 @@ dashboard.operation_switch=Wechseln
|
|||
dashboard.operation_run=Ausführen
|
||||
dashboard.clean_unbind_oauth=Nicht verbundene OAuth-Verbindungen löschen
|
||||
dashboard.clean_unbind_oauth_success=Alle unverbundene OAuth-Verbindungen wurden gelöscht.
|
||||
dashboard.delete_inactivate_accounts=Lösche alle nicht-aktivierten Accounts
|
||||
dashboard.delete_inactivate_accounts_success=Alle nicht-aktivierten Accounts wurden gelöscht.
|
||||
dashboard.delete_repo_archives=Alle Repository-Archive löschen
|
||||
dashboard.delete_repo_archives_success=Alle Repository-Archive wurden gelöscht.
|
||||
dashboard.delete_missing_repos=Alle Repository-Datensätze mit verlorenen gegangenen Git-Dateien löschen
|
||||
|
@ -1482,7 +1465,6 @@ config.db_path=Verzeichnis
|
|||
config.service_config=Service-Konfiguration
|
||||
config.register_email_confirm=E-Mail-Bestätigung benötigt zum Registrieren
|
||||
config.disable_register=Selbstegistrierung deaktivieren
|
||||
config.allow_only_external_registration=Registrierung nur über externe Services aktiveren
|
||||
config.enable_openid_signup=OpenID-Selbstregistrierung aktivieren
|
||||
config.enable_openid_signin=OpenID-Anmeldung aktivieren
|
||||
config.show_registration_button=Schaltfläche zum Registrieren anzeigen
|
||||
|
|
|
@ -32,16 +32,16 @@ twofa_scratch = Two-Factor Scratch Code
|
|||
passcode = Passcode
|
||||
|
||||
u2f_insert_key = Insert your security key
|
||||
u2f_sign_in = Press the button on your security key. If you can't find a button, re-insert it.
|
||||
u2f_sign_in = Press the button on your security key. If your security key has no button, re-insert it.
|
||||
u2f_press_button = Please press the button on your security key…
|
||||
u2f_use_twofa = Use a two-factor code from your phone
|
||||
u2f_error = We can't read your security key!
|
||||
u2f_unsupported_browser = Your browser don't support U2F keys. Please try another browser.
|
||||
u2f_error_1 = An unknown error occured. Please retry.
|
||||
u2f_error_2 = Please make sure that you're using an encrypted connection (https://) and visiting the correct URL.
|
||||
u2f_error_3 = The server could not proceed your request.
|
||||
u2f_error_4 = The presented key is not eligible for this request. If you try to register it, make sure that the key isn't already registered.
|
||||
u2f_error_5 = Timeout reached before your key could be read. Please reload to retry.
|
||||
u2f_error = Could not read your security key.
|
||||
u2f_unsupported_browser = Your browser does not support U2F security keys.
|
||||
u2f_error_1 = An unknown error occurred. Please retry.
|
||||
u2f_error_2 = Please make sure to use the correct, encrypted (https://) URL.
|
||||
u2f_error_3 = The server could not process your request.
|
||||
u2f_error_4 = The security key is not permitted for this request. Please make sure that the key is not already registered.
|
||||
u2f_error_5 = Timeout reached before your key could be read. Please reload this page and retry.
|
||||
u2f_reload = Reload
|
||||
|
||||
repository = Repository
|
||||
|
@ -130,7 +130,7 @@ federated_avatar_lookup = Enable Federated Avatars
|
|||
federated_avatar_lookup_popup = Enable federated avatar lookup using Libravatar.
|
||||
disable_registration = Disable Self-Registration
|
||||
disable_registration_popup = Disable user self-registration. Only administrators will be able to create new user accounts.
|
||||
allow_only_external_registration_popup=Enable the registration only through external services.
|
||||
allow_only_external_registration_popup = Allow Registration Only Through External Services
|
||||
openid_signin = Enable OpenID Sign-In
|
||||
openid_signin_popup = Enable user sign-in via OpenID.
|
||||
openid_signup = Enable OpenID Self-Registration
|
||||
|
@ -463,13 +463,13 @@ then_enter_passcode = And enter the passcode shown in the application:
|
|||
passcode_invalid = The passcode is incorrect. Try again.
|
||||
twofa_enrolled = Your account has been enrolled into two-factor authentication. Store your scratch token (%s) in a safe place as it is only shown once!
|
||||
|
||||
u2f_desc = Security keys are hardware devices containing cryptographic keys. They could be used for two factor authentication. The security key must support the <a href="https://fidoalliance.org/">FIDO U2F</a> standard.
|
||||
u2f_require_twofa = Two-Factor-Authentication must be enrolled in order to use security keys.
|
||||
u2f_desc = Security keys are hardware devices containing cryptographic keys. They can be used for two-factor authentication. Security keys must support the <a rel="noreferrer" href="https://fidoalliance.org/">FIDO U2F</a> standard.
|
||||
u2f_require_twofa = Your account must be enrolled in two-factor authentication to use security keys.
|
||||
u2f_register_key = Add Security Key
|
||||
u2f_nickname = Nickname
|
||||
u2f_press_button = Press the button on your security key to register it.
|
||||
u2f_delete_key = Remove Security Key
|
||||
u2f_delete_key_desc= If you remove a security key you cannot login with it anymore. Are you sure?
|
||||
u2f_delete_key_desc = If you remove a security key you can no longer sign in with it. Continue?
|
||||
|
||||
manage_account_links = Manage Linked Accounts
|
||||
manage_account_links_desc = These external accounts are linked to your Gitea account.
|
||||
|
@ -650,7 +650,7 @@ issues.new.open_milestone = Open Milestones
|
|||
issues.new.closed_milestone = Closed Milestones
|
||||
issues.new.assignees = Assignees
|
||||
issues.new.clear_assignees = Clear assignees
|
||||
issues.new.no_assignees = Nobody assigned
|
||||
issues.new.no_assignees = No Assignees
|
||||
issues.no_ref = No Branch/Tag Specified
|
||||
issues.create = Create Issue
|
||||
issues.new_label = New Label
|
||||
|
@ -781,7 +781,33 @@ issues.due_date_added = "added the due date %s %s"
|
|||
issues.due_date_modified = "modified the due date to %s from %s %s"
|
||||
issues.due_date_remove = "removed the due date %s %s"
|
||||
issues.due_date_overdue = "Overdue"
|
||||
issues.due_date_invalid = "The due date is invalid or out of range. Please use the format yyyy-mm-dd."
|
||||
issues.due_date_invalid = "The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'."
|
||||
issues.dependency.title = Dependencies
|
||||
issues.dependency.issue_no_dependencies = This issue currently doesn't have any dependencies.
|
||||
issues.dependency.pr_no_dependencies = This pull request currently doesn't have any dependencies.
|
||||
issues.dependency.add = Add dependency...
|
||||
issues.dependency.cancel = Cancel
|
||||
issues.dependency.remove = Remove
|
||||
issues.dependency.added_dependency = `<a href="%[1]s">%[2]s</a> added a new dependency %[3]s`
|
||||
issues.dependency.removed_dependency = `<a href="%[1]s">%[2]s</a> removed a dependency %[3]s`
|
||||
issues.dependency.issue_closing_blockedby = Closing this pull request is blocked by the following issues
|
||||
issues.dependency.pr_closing_blockedby = Closing this issue is blocked by the following issues
|
||||
issues.dependency.issue_close_blocks = This issue blocks closing of the following issues
|
||||
issues.dependency.pr_close_blocks = This pull request blocks closing of the following issues
|
||||
issues.dependency.issue_close_blocked = You need to close all issues blocking this issue before you can close it.
|
||||
issues.dependency.pr_close_blocked = You need to close all issues blocking this pull request before you can merge it.
|
||||
issues.dependency.blocks_short = Blocks
|
||||
issues.dependency.blocked_by_short = Depends on
|
||||
issues.dependency.remove_header = Remove Dependency
|
||||
issues.dependency.issue_remove_text = This will remove the dependency from this issue. Continue?
|
||||
issues.dependency.pr_remove_text = This will remove the dependency from this pull request. Continue?
|
||||
issues.dependency.setting = Enable Dependencies For Issues and Pull Requests
|
||||
issues.dependency.add_error_same_issue = You cannot make an issue depend on itself.
|
||||
issues.dependency.add_error_dep_issue_not_exist = Dependent issue does not exist.
|
||||
issues.dependency.add_error_dep_not_exist = Dependency does not exist.
|
||||
issues.dependency.add_error_dep_exists = Dependency already exists.
|
||||
issues.dependency.add_error_cannot_create_circular = You cannot create a dependency with two issues blocking each other.
|
||||
issues.dependency.add_error_dep_not_same_repo = Both issues must be in the same repository.
|
||||
|
||||
pulls.desc = Enable merge requests and code reviews.
|
||||
pulls.new = New Pull Request
|
||||
|
@ -1170,8 +1196,8 @@ branch.protected_deletion_failed = Branch '%s' is protected. It cannot be delete
|
|||
|
||||
topic.manage_topics = Manage Topics
|
||||
topic.done = Done
|
||||
topic.count_prompt = You can't select more than 25 topics
|
||||
topic.format_prompt = Topics must start with a letter or number, can include hyphens(-) and must be no more than 35 characters long
|
||||
topic.count_prompt = You can not select more than 25 topics
|
||||
topic.format_prompt = Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
||||
|
||||
[org]
|
||||
org_name_holder = Organization Name
|
||||
|
@ -1276,8 +1302,8 @@ dashboard.operation_switch = Switch
|
|||
dashboard.operation_run = Run
|
||||
dashboard.clean_unbind_oauth = Clean unbound OAuth connections
|
||||
dashboard.clean_unbind_oauth_success = All unbound OAuth connections have been deleted.
|
||||
dashboard.delete_inactivate_accounts = Delete all not activated accounts
|
||||
dashboard.delete_inactivate_accounts_success = All not activated accounts have been deleted.
|
||||
dashboard.delete_inactivate_accounts = Delete all unactivated accounts
|
||||
dashboard.delete_inactivate_accounts_success = All unactivated accounts have been deleted.
|
||||
dashboard.delete_repo_archives = Delete all repository archives
|
||||
dashboard.delete_repo_archives_success = All repository archives have been deleted.
|
||||
dashboard.delete_missing_repos = Delete all repositories missing their Git files
|
||||
|
@ -1485,7 +1511,7 @@ config.db_path = Path
|
|||
config.service_config = Service Configuration
|
||||
config.register_email_confirm = Require Email Confirmation to Register
|
||||
config.disable_register = Disable Self-Registration
|
||||
config.allow_only_external_registration = Enable the registration only through external services
|
||||
config.allow_only_external_registration = Allow Registration Only Through External Services
|
||||
config.enable_openid_signup = Enable OpenID Self-Registration
|
||||
config.enable_openid_signin = Enable OpenID Sign-In
|
||||
config.show_registration_button = Show Register Button
|
||||
|
@ -1501,6 +1527,7 @@ config.enable_timetracking = Enable Time Tracking
|
|||
config.default_enable_timetracking = Enable Time Tracking by Default
|
||||
config.default_allow_only_contributors_to_track_time = Let Only Contributors Track Time
|
||||
config.no_reply_address = Hidden Email Domain
|
||||
config.default_enable_dependencies = Enable Issue Dependencies by Default
|
||||
|
||||
config.webhook_config = Webhook Configuration
|
||||
config.queue_length = Queue Length
|
||||
|
|
|
@ -32,11 +32,6 @@ passcode=Contraseña
|
|||
|
||||
u2f_insert_key=Inserte su clave de seguridad
|
||||
u2f_use_twofa=Use un código de dos factores de su celular
|
||||
u2f_error=No podemos leer su llave de seguridad!
|
||||
u2f_unsupported_browser=Su navegador no soporta llaves U2F. Por favor utilicé otro navegador.
|
||||
u2f_error_1=Un error desconocido ha ocurrido. Por favor vuelva a intentarlo.
|
||||
u2f_error_2=Por favor asegúrese de que está utilizando una conexión cifrada (https://) y que esta visitando la dirección URL correcta.
|
||||
u2f_error_3=El servidor no pudo procesar su petición.
|
||||
u2f_reload=Recargar
|
||||
|
||||
repository=Repositorio
|
||||
|
|
|
@ -32,16 +32,8 @@ twofa_scratch=Code de secours pour l'authentification à deux facteurs
|
|||
passcode=Code d'accès
|
||||
|
||||
u2f_insert_key=Insérez votre clef de sécurité
|
||||
u2f_sign_in=Appuyez sur le bouton de votre clef de sécurité. Si vous ne voyez pas de bouton, ré-insérez là.
|
||||
u2f_press_button=Veuillez appuyer sur le bouton de votre clef de sécurité…
|
||||
u2f_use_twofa=Utilisez l'authentification à deux facteurs avec votre téléphone
|
||||
u2f_error=Nous ne pouvons pas lire votre clé de sécurité !
|
||||
u2f_unsupported_browser=Votre navigateur n'est pas compatible avec les clefs U2F. Veuillez réessayer avec un autre navigateur.
|
||||
u2f_error_1=Une erreur inconnue s'est produite. Veuillez réessayer.
|
||||
u2f_error_2=Veuillez vous assurer que vous utilisez une connexion chiffrée (https) et que vous visitez la bonne adresse.
|
||||
u2f_error_3=Le serveur n'a pas pu répondre à votre requête.
|
||||
u2f_error_4=Cette clef n'est pas compatible avec votre requête. Si vous êtes en train de l'enregistrer, veuillez vous assurer que cette clef n'est pas déjà enregistrée.
|
||||
u2f_error_5=Le délai d'attente imparti a été atteint avant que votre clef ne puisse être lue. Veuillez recharger la page pour réessayer.
|
||||
u2f_reload=Recharger
|
||||
|
||||
repository=Dépôt
|
||||
|
@ -129,7 +121,6 @@ federated_avatar_lookup=Activer les avatars unifiés
|
|||
federated_avatar_lookup_popup=Activer la recherche unifiée d'avatars en utilisant le service open source unifié basé sur libravatar.
|
||||
disable_registration=Désactiver le formulaire d'inscription
|
||||
disable_registration_popup=Désactiver les nouvelles inscriptions. Seuls les administrateurs pourront créer de nouveaux comptes utilisateurs.
|
||||
allow_only_external_registration_popup=N'autoriser l'inscription qu'à partir des services externes.
|
||||
openid_signin=Activer l'inscription OpenID
|
||||
openid_signin_popup=Activer l'authentification via OpenID.
|
||||
openid_signup=Activer l'inscription OpenID
|
||||
|
@ -462,13 +453,10 @@ then_enter_passcode=Et entrez le mot de passe s'affichant dans l'application :
|
|||
passcode_invalid=Le mot de passe est invalide. Réessayez.
|
||||
twofa_enrolled=L'authentification à deux facteurs a été activée pour votre compte. Gardez votre jeton de secours (%s) en lieu sûr car il ne vous sera montré qu'une seule fois !
|
||||
|
||||
u2f_desc=Les clefs de sécurité sont des dispositifs matériels contenant des clefs cryptographiques. Elles peuvent être utilisées pour l'authentification à deux facteurs. La clef de sécurité doit supporter le standard <a href="https://fidoalliance.org/">FIDO U2F</a>.
|
||||
u2f_require_twofa=L'authentification à deux facteurs doit être activée afin d'utiliser une clef de sécurité.
|
||||
u2f_register_key=Ajouter une clef de sécurité
|
||||
u2f_nickname=Pseudonyme
|
||||
u2f_press_button=Appuyer sur le bouton de votre clef de sécurité pour l'enregistrer.
|
||||
u2f_delete_key=Supprimer une clef de sécurité
|
||||
u2f_delete_key_desc=Si vous supprimez une clef de sécurité vous ne pourrez plus l'utiliser pour vous connecter. Continuer?
|
||||
|
||||
manage_account_links=Gérer les comptes liés
|
||||
manage_account_links_desc=Ces comptes externes sont liés à votre compte Gitea.
|
||||
|
@ -643,7 +631,6 @@ issues.new.open_milestone=Ouvrir un jalon
|
|||
issues.new.closed_milestone=Jalons fermés
|
||||
issues.new.assignees=Affecté à
|
||||
issues.new.clear_assignees=Supprimer les affectations
|
||||
issues.new.no_assignees=Aucune affectation
|
||||
issues.no_ref=Aucune branche/tag spécifiés
|
||||
issues.create=Créer un ticket
|
||||
issues.new_label=Nouvelle étiquette
|
||||
|
@ -1158,8 +1145,6 @@ branch.protected_deletion_failed=La branche '%s' est protégé. Il ne peut pas
|
|||
|
||||
topic.manage_topics=Gérer les sujets
|
||||
topic.done=Terminé
|
||||
topic.count_prompt=Vous ne pouvez pas sélectionner plus de 25 sujets
|
||||
topic.format_prompt=Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets (-), sans dépasser 35 caractères
|
||||
|
||||
[org]
|
||||
org_name_holder=Nom de l'organisation
|
||||
|
@ -1471,7 +1456,6 @@ config.db_path=Emplacement
|
|||
config.service_config=Configuration du service
|
||||
config.register_email_confirm=Exiger la confirmation de l'e-mail lors de l'inscription
|
||||
config.disable_register=Désactiver le formulaire d'inscription
|
||||
config.allow_only_external_registration=N'autoriser l'inscription qu'à partir des services externes
|
||||
config.enable_openid_signup=Activer l'inscription avec OpenID
|
||||
config.enable_openid_signin=Activer la connexion avec OpenID
|
||||
config.show_registration_button=Afficher le bouton d'enregistrement
|
||||
|
|
|
@ -32,16 +32,8 @@ twofa_scratch=Kode Awal Dua Faktor
|
|||
passcode=Kode Akses
|
||||
|
||||
u2f_insert_key=Masukkan kunci keamanan anda
|
||||
u2f_sign_in=Tekan tombol pada kunci keamanan anda. Jika anda tidak menemukan tombol, masukkan kembali.
|
||||
u2f_press_button=Silahkan tekan tombol pada kunci keamanan anda…
|
||||
u2f_use_twofa=Menggunakan kode dua faktor dari telepon anda
|
||||
u2f_error=Kami tidak bisa membaca kunci keamanan anda!
|
||||
u2f_unsupported_browser=Browser anda tidak mendukung kunci U2F. Silakan mencoba browser lain.
|
||||
u2f_error_1=Terdapat kesalahan yang tidak diketahui. Mohon coba lagi.
|
||||
u2f_error_2=Pastikan bahwa anda menggunakan koneksi terenkripsi (https://) dan mengunjungi URL yang benar.
|
||||
u2f_error_3=Server tidak bisa melanjutkan permintaan anda.
|
||||
u2f_error_4=Kunci tidak layak untuk permintaan ini. Jika Anda mencoba untuk mendaftarkanya, pastikan bahwa kunci sudah tidak terdaftar.
|
||||
u2f_error_5=Timeout tercapai sebelum kunci anda bisa terbaca. Silahkan muat ulang untuk mencoba kembali.
|
||||
u2f_reload=Muat Ulang
|
||||
|
||||
repository=Repositori
|
||||
|
|
|
@ -32,16 +32,8 @@ twofa_scratch=Codice di recupero per la verifica in due passaggi
|
|||
passcode=Codice di sicurezza
|
||||
|
||||
u2f_insert_key=Inserisci la chiave di sicurezza
|
||||
u2f_sign_in=Premi il pulsante sulla tua chiave di sicurezza. Se non riesci a trovare alcun pulsante, reinseriscilo.
|
||||
u2f_press_button=Si prega di premere il pulsante sulla tua chiave di sicurezza…
|
||||
u2f_use_twofa=Usa un codice di verifica in due passaggi dal tuo telefono
|
||||
u2f_error=Non riusciamo a leggere la tua chiave di sicurezza!
|
||||
u2f_unsupported_browser=Il tuo browser non supporta le chiavi U2F. Si prega di provare un altro browser.
|
||||
u2f_error_1=Si è verificato un errore sconosciuto. Si prega di riprovare.
|
||||
u2f_error_2=Si prega di assicurarsi che si sta utilizza una connessione crittografata (https://) e visitando l'URL corretto.
|
||||
u2f_error_3=Il server non ha potuto eseguire la richiesta.
|
||||
u2f_error_4=La chiave data non è idonea per questa richiesta. Se stai provando a registrarla, assicurati che la chiave non sia già stata registrata.
|
||||
u2f_error_5=Timeout raggiunto prima che la tua chiave potesse essere letta. Si prega di ricaricare per riprovare.
|
||||
u2f_reload=Ricarica
|
||||
|
||||
repository=Repository
|
||||
|
@ -129,7 +121,6 @@ federated_avatar_lookup=Attiva i Federated Avatar
|
|||
federated_avatar_lookup_popup=Enable federated avatars lookup to use federated open source service based on libravatar.
|
||||
disable_registration=Disattiva Self-Registration
|
||||
disable_registration_popup=Disattiva la user self-registration. Solo gli amministratori saranno in grado di creare account.
|
||||
allow_only_external_registration_popup=Attiva la registrazione solo tramite servizi esterni.
|
||||
openid_signin=Attiva l'accesso OpenID
|
||||
openid_signin_popup=Attiva registrazione utente via OpenID.
|
||||
openid_signup=Attiva OpenID Self-Registration
|
||||
|
@ -462,14 +453,10 @@ then_enter_passcode=E immetti il codice di accesso indicato nell'applicazione:
|
|||
passcode_invalid=Il codice di accesso non è corretto. Riprova.
|
||||
twofa_enrolled=Il tuo account è stato registrato alla verifica in due passaggi. Conserva il token di sicurezza (%s) in un luogo sicuro in quanto viene visualizzato sono una volta!
|
||||
|
||||
u2f_desc=Le chiavi di sicurezza sono dispositivi hardware contenenti chiavi crittografiche. Potrebbero essere usate per la verifica in due passaggi.
|
||||
La chiave di sicurezza deve supportare lo standard <a href="https://fidoalliance.org/">FIDO U2F</a>.
|
||||
u2f_require_twofa=La verifica in due passaggi deve essere attiva per poter utilizzare le chiavi di protezione.
|
||||
u2f_register_key=Aggiungi chiave di sicurezza
|
||||
u2f_nickname=Nickname
|
||||
u2f_press_button=Premi il pulsante sulla tua chiave di sicurezza per registrarla.
|
||||
u2f_delete_key=Rimuovi chiave di sicurezza
|
||||
u2f_delete_key_desc=Se si rimuove una chiave di sicurezza non sarà più possibile effettuare l'accesso con essa. Sei sicuro?
|
||||
|
||||
manage_account_links=Gestisci gli account collegati
|
||||
manage_account_links_desc=Questi account esterni sono collegati al tuo account Gitea.
|
||||
|
@ -644,7 +631,6 @@ issues.new.open_milestone=Apri Milestone
|
|||
issues.new.closed_milestone=Milestone chiuse
|
||||
issues.new.assignees=Assegnatari
|
||||
issues.new.clear_assignees=Cancella assegnatari
|
||||
issues.new.no_assignees=Nessuno assegnato
|
||||
issues.no_ref=Nessun Branch/Tag specificato
|
||||
issues.create=Crea Problema
|
||||
issues.new_label=Nuova etichetta
|
||||
|
@ -1159,8 +1145,6 @@ branch.protected_deletion_failed=Il branch '%s' è protetto. Non può essere eli
|
|||
|
||||
topic.manage_topics=Gestisci argomenti
|
||||
topic.done=Fatto
|
||||
topic.count_prompt=Non puoi selezione più di 25 argomenti
|
||||
topic.format_prompt=Gli argomenti devono iniziare con una lettera o un numero, possono includere il carattere hiphens(-) e non possono essere più lunghi di 35 caratteri
|
||||
|
||||
[org]
|
||||
org_name_holder=Nome dell'Organizzazione
|
||||
|
@ -1472,7 +1456,6 @@ config.db_path=Percorso
|
|||
config.service_config=Configurazione Servizio
|
||||
config.register_email_confirm=Richiedere la conferma Email per registrarsi
|
||||
config.disable_register=Disattiva Self-Registration
|
||||
config.allow_only_external_registration=Attiva la registrazione solo tramite servizi esterni
|
||||
config.enable_openid_signup=Attiva OpenID Self-Registration
|
||||
config.enable_openid_signin=Attiva l'accesso tramite OpenID
|
||||
config.show_registration_button=Mostra Pulsane Registrazione
|
||||
|
|
|
@ -32,16 +32,8 @@ twofa_scratch=Divu faktoru vienreizējais kods
|
|||
passcode=Kods
|
||||
|
||||
u2f_insert_key=Ievietojiet Jūsu drošības atslēgu
|
||||
u2f_sign_in=Nospiediet drošības atslēgas pogu. Ja nevarat to atrast, ievietojiet atkārtoti.
|
||||
u2f_press_button=Nospiediet drošības atslēgas pogu…
|
||||
u2f_use_twofa=Izmantot divu faktoru kodu no tālruņa
|
||||
u2f_error=Nav iespējams nolasīt drošības atslēgu!
|
||||
u2f_unsupported_browser=Jūsu pārlūks neatbalsta U2F atslēgas. Izmantojiet citu pārlūku.
|
||||
u2f_error_1=Notikusi nezināma kļūda. Atkārtojiet darbību vēlreiz.
|
||||
u2f_error_2=Pārliecinieties, ka izmantojat šifrētu savienojumu (https://) un apmeklējat pareizo URL.
|
||||
u2f_error_3=Serveris nevar apstrādāt Jūsu pieprasījumu.
|
||||
u2f_error_4=Nav iespējams izmantot atslēgu šim pieprasījumam. Ja mēģināt to reģistrēt, pārliecinieties, ka atslēga jau nav reģistrēta.
|
||||
u2f_error_5=Iestājusies noildze nolasot atslēgu. Pārlādējiet lapu, lai atkārtotu vēlreiz.
|
||||
u2f_reload=Pārlādēt
|
||||
|
||||
repository=Repozitorijs
|
||||
|
@ -130,7 +122,6 @@ federated_avatar_lookup=Iespējot apvienotās profila bildes
|
|||
federated_avatar_lookup_popup=Iespējot apvienoto profila bilžu meklētāju, lai izmantotu atvērtā koda apvienoto servisu balstītu uz libravatar.
|
||||
disable_registration=Atspējot lietotāju reģistrāciju
|
||||
disable_registration_popup=Atspējot iespēju reģistrēties. Tikai administratori varēs izveidot jaunus kontus.
|
||||
allow_only_external_registration_popup=Ļaut reģistrēties tikai izmantojot ārējos pakalpojumus.
|
||||
openid_signin=Iespējot OpenID autorizāciju
|
||||
openid_signin_popup=Iespējot lietotāju autorizāciju ar OpenID.
|
||||
openid_signup=Iespējot reģistrāciju, izmantojot OpenID
|
||||
|
@ -463,13 +454,10 @@ then_enter_passcode=Ievadiet piekļuves kodu no lietojumprogrammas:
|
|||
passcode_invalid=Nederīgs piekļuves kods. Mēģiniet ievadīt atkārtoti.
|
||||
twofa_enrolled=Kontam tagad ir ieslēgta divu faktoru autentifikācija. Saglabājiet savu vienreizējo kodu (%s), jo tas vairāk netiks parādīts!
|
||||
|
||||
u2f_desc=Drošības atslēgas ir aparatūras ierīces, kas satur kriptogrāfiskās atslēgas. Tās var tikt izmantotas, lai nodrošinātu divu faktoru autentifikāciju. Drošības atslēgām ir jāatbalsta <a href="https://fidoalliance.org/">FIDO U2F</a> standarts.
|
||||
u2f_require_twofa=Jābūt iespējotai divu faktoru autentifikācija, lai varētu izmantot drošības atslēgas.
|
||||
u2f_register_key=Pievienot drošības atslēgu
|
||||
u2f_nickname=Segvārds
|
||||
u2f_press_button=Nospiediet pogu uz Jūsu drošības atslēgas, lai to reģistrētu.
|
||||
u2f_delete_key=Noņemt drošības atslēgu
|
||||
u2f_delete_key_desc=Noņemot drošības atslēgu ar to vairs nebūs iespējams autorizēties. Vai turpināt?
|
||||
|
||||
manage_account_links=Pārvaldīt saistītos kontus
|
||||
manage_account_links_desc=Šādi ārējie konti ir piesaistīti Jūsu Gitea kontam.
|
||||
|
@ -646,7 +634,6 @@ issues.new.open_milestone=Atvērtie atskaites punktus
|
|||
issues.new.closed_milestone=Aizvērtie atskaites punkti
|
||||
issues.new.assignees=Atbildīgie
|
||||
issues.new.clear_assignees=Noņemt atbildīgo
|
||||
issues.new.no_assignees=Nav atbildīgā
|
||||
issues.no_ref=Nav norādīts atzars/tags
|
||||
issues.create=Pieteikt problēmu
|
||||
issues.new_label=Jauna etiķete
|
||||
|
@ -1163,8 +1150,6 @@ branch.protected_deletion_failed=Atzars '%s' ir aizsargāts. To nevar izdzēst.
|
|||
|
||||
topic.manage_topics=Pārvaldīt tēmas
|
||||
topic.done=Gatavs
|
||||
topic.count_prompt=Nevar pievienot vairāk kā 25 tēmas
|
||||
topic.format_prompt=Tēmas nosaukumam ir jāsākas ar burtu vai ciparu, tas var saturēt defisi(-), kā arī tas nevar būt garāks par 35 simboliem
|
||||
|
||||
[org]
|
||||
org_name_holder=Organizācijas nosaukums
|
||||
|
@ -1269,8 +1254,6 @@ dashboard.operation_switch=Pārslēgt
|
|||
dashboard.operation_run=Palaist
|
||||
dashboard.clean_unbind_oauth=Notīrīt nepiesaistītos OAuth savienojumus
|
||||
dashboard.clean_unbind_oauth_success=Visi nepiesaistītie OAuth savienojumu tika izdzēsti.
|
||||
dashboard.delete_inactivate_accounts=Dzēst visus neaktivizētos kontus
|
||||
dashboard.delete_inactivate_accounts_success=Visi neaktivizētie konti tika izdzēsti.
|
||||
dashboard.delete_repo_archives=Dzēst visu repozitoriju arhīvus
|
||||
dashboard.delete_repo_archives_success=Visu repozitoriju arhīvi tika izdzēsti.
|
||||
dashboard.delete_missing_repos=Dzēst visus repozitorijus, kam trūkst Git failu
|
||||
|
@ -1478,7 +1461,6 @@ config.db_path=Ceļš
|
|||
config.service_config=Pakalpojuma konfigurācija
|
||||
config.register_email_confirm=Reģistrējoties pieprasīt apstiprināt e-pasta adresi
|
||||
config.disable_register=Atspējot lietotāju reģistrāciju
|
||||
config.allow_only_external_registration=Ļaut reģistrēties tikai izmantojot ārējos pakalpojumus
|
||||
config.enable_openid_signup=Iespējot reģistrāciju, izmantojot OpenID
|
||||
config.enable_openid_signin=Iespējot OpenID autorizāciju
|
||||
config.show_registration_button=Rādīt reģistrēšanās pogu
|
||||
|
|
|
@ -32,14 +32,8 @@ twofa_scratch=Eenmalige twee factor authenticatie code
|
|||
passcode=PIN
|
||||
|
||||
u2f_insert_key=Uw beveiligingssleutel invoegen
|
||||
u2f_sign_in=Druk op de knop op uw beveiligingssleutel. Als u een knop niet kunt vinden, deze opnieuw invoegen.
|
||||
u2f_press_button=Druk op de knop op uw beveiligingssleutel…
|
||||
u2f_use_twofa=Gebruik een twee-factor code van uw telefoon
|
||||
u2f_error=Wij kunnen niet uw beveiligingssleutel lezen!
|
||||
u2f_unsupported_browser=Uw browser geen ondersteund U2F keys. Probeer een andere browser.
|
||||
u2f_error_1=Er is een onbekende fout opgetreden. Probeer het opnieuw.
|
||||
u2f_error_2=Zorg voor een versleutelde verbinding (https://) en een bezoek aan de juiste URL.
|
||||
u2f_error_3=De server kan uw aanvraag niet verhandelen.
|
||||
u2f_reload=Herladen
|
||||
|
||||
repository=Repository
|
||||
|
|
|
@ -32,16 +32,16 @@ twofa_scratch=Código de backup da autenticação de dois fatores
|
|||
passcode=Senha
|
||||
|
||||
u2f_insert_key=Insira sua chave de segurança
|
||||
u2f_sign_in=Pressione o botão na sua chave de segurança. Se você não encontrar um botão, insira-o novamente.
|
||||
u2f_sign_in=Pressione o botão na sua chave de segurança. Se a sua chave de segurança não tiver um botão, insira-a novamente.
|
||||
u2f_press_button=Por favor, pressione o botão na sua chave de segurança...
|
||||
u2f_use_twofa=Use um código de dois fatores no seu telefone
|
||||
u2f_error=Não conseguimos ler sua chave de segurança!
|
||||
u2f_unsupported_browser=Seu navegador não suporta chaves U2F. Por favor, tente outro navegador.
|
||||
u2f_error=Não foi possível ler sua chave de segurança.
|
||||
u2f_unsupported_browser=Seu navegador não suporta chaves de segurança U2F.
|
||||
u2f_error_1=Ocorreu um erro desconhecido. Por favor, tente novamente.
|
||||
u2f_error_2=Por favor, certifique-se de que você está usando uma conexão criptografada (https://) e visite a URL correta.
|
||||
u2f_error_3=O servidor não pôde prosseguir com sua solicitação.
|
||||
u2f_error_4=A chave apresentada não é elegível para esta solicitação. Se você tentar registrá-la, certifique-se de que a chave já não é registrada.
|
||||
u2f_error_5=Tempo limite atingido antes de sua chave poder ser lida. Por favor, recarregue para tentar novamente.
|
||||
u2f_error_2=Por favor, certifique-se de usar a URL correto, criptografado (https://).
|
||||
u2f_error_3=O servidor não pôde processar sua solicitação.
|
||||
u2f_error_4=A chave de segurança não é permitida para esta solicitação. Por favor, certifique-se que a chave já não está registrada.
|
||||
u2f_error_5=Tempo limite atingido antes de sua chave poder ser lida. Por favor, recarregue esta página e tente novamente.
|
||||
u2f_reload=Recarregar
|
||||
|
||||
repository=Repositório
|
||||
|
@ -53,7 +53,7 @@ new_mirror=Novo mirror
|
|||
new_fork=Novo Fork de Repositório
|
||||
new_org=Nova organização
|
||||
manage_org=Gerenciar organizações
|
||||
admin_panel=Administração do site
|
||||
admin_panel=Administração geral
|
||||
account_settings=Configurações da conta
|
||||
settings=Configurações
|
||||
your_profile=Perfil
|
||||
|
@ -93,7 +93,7 @@ no_admin_and_disable_registration=Você não pode desabilitar o auto-cadastro do
|
|||
err_empty_admin_password=A senha do administrador não pode ser em branco.
|
||||
|
||||
general_title=Configurações gerais
|
||||
app_name=Título do site
|
||||
app_name=Nome do servidor
|
||||
app_name_helper=Você pode inserir o nome da empresa aqui.
|
||||
repo_path=Caminho raíz do repositório
|
||||
repo_path_helper=Todos os repositórios remotos do Git serão salvos neste diretório.
|
||||
|
@ -130,7 +130,7 @@ federated_avatar_lookup=Habilitar avatares federativos
|
|||
federated_avatar_lookup_popup=Habilitar a busca federativa de avatares a usar o serviço federativo de código aberto baseado no libravatar.
|
||||
disable_registration=Desabilitar auto-cadastro
|
||||
disable_registration_popup=Desabilitar auto-cadastro de usuário. Somente os administradores serão capazes de criar novas contas de usuário.
|
||||
allow_only_external_registration_popup=Habilitar o cadastro apenas por meio de serviços externos.
|
||||
allow_only_external_registration_popup=Permitir cadastro somente por meio de serviços externos
|
||||
openid_signin=Habilitar acesso via OpenID
|
||||
openid_signin_popup=Habilitar o acesso de usuários via OpenID.
|
||||
openid_signup=Habilitar o auto-cadastro via OpenID
|
||||
|
@ -463,13 +463,13 @@ then_enter_passcode=E insira a senha mostrada no aplicativo:
|
|||
passcode_invalid=Esse código de acesso é inválido. Tente novamente.
|
||||
twofa_enrolled=Sua conta foi inscrita na autenticação de dois fatores. Armazene seu token de backup (%s) em um local seguro, pois ele é exibido apenas uma vez!
|
||||
|
||||
u2f_desc=Chaves de segurança são dispositivos de hardware que contém chaves de criptografia. Elas podem ser usadas para autenticação de dois fatores. A chave de segurança deve suportar o padrão <a href="https://fidoalliance.org/">FIDO U2F</a>.
|
||||
u2f_require_twofa=Autenticação de dois fatores deve estar inscrita para usar chaves de segurança.
|
||||
u2f_desc=Chaves de segurança são dispositivos de hardware contendo chaves criptográficas. Eles podem ser usados para autenticação de dois fatores. As chaves de segurança devem suportar o padrão <a rel="noreferrer" href="https://fidoalliance.org/">FIDO U2F</a>.
|
||||
u2f_require_twofa=Sua conta deve estar inscrita na autenticação de dois fatores para usar as chaves de segurança.
|
||||
u2f_register_key=Adicionar chave de segurança
|
||||
u2f_nickname=Apelido
|
||||
u2f_press_button=Pressione o botão na sua chave de segurança para registrá-la.
|
||||
u2f_delete_key=Remover chave de segurança
|
||||
u2f_delete_key_desc=Se você remover uma chave de segurança você não poderá mais acessar com ela. Tem certeza?
|
||||
u2f_delete_key_desc=Se você remover uma chave de segurança, não poderá mais entrar com ela. Continuar?
|
||||
|
||||
manage_account_links=Gerenciar contas vinculadas
|
||||
manage_account_links_desc=Estas contas externas estão vinculadas a sua conta de Gitea.
|
||||
|
@ -597,7 +597,7 @@ editor.name_your_file=Nomeie o seu arquivo…
|
|||
editor.filename_help=Adicione um diretório digitando seu nome seguido por uma barra ('/'). Remova um diretório digitando o backspace no início do campo de entrada.
|
||||
editor.or=ou
|
||||
editor.cancel_lower=Cancelar
|
||||
editor.commit_changes=Confirmar alterações
|
||||
editor.commit_changes=Realizar commit das alterações
|
||||
editor.add_tmpl=Adicionar '%s/<filename>'
|
||||
editor.add=Adicionar '%s'
|
||||
editor.update=Atualizar '%s'
|
||||
|
@ -650,7 +650,7 @@ issues.new.open_milestone=Marcos abertos
|
|||
issues.new.closed_milestone=Marcos fechados
|
||||
issues.new.assignees=Responsáveis
|
||||
issues.new.clear_assignees=Limpar responsáveis
|
||||
issues.new.no_assignees=Nenhum responsável
|
||||
issues.new.no_assignees=Sem responsável
|
||||
issues.no_ref=Nenhum branch/tag especificado
|
||||
issues.create=Criar issue
|
||||
issues.new_label=Nova etiqueta
|
||||
|
@ -682,7 +682,7 @@ issues.filter_milestone_no_select=Todos os marcos
|
|||
issues.filter_assignee=Atribuído
|
||||
issues.filter_assginee_no_select=Todos os responsáveis
|
||||
issues.filter_type=Tipo
|
||||
issues.filter_type.all_issues=Todos os issues
|
||||
issues.filter_type.all_issues=Todas as issues
|
||||
issues.filter_type.assigned_to_you=Atribuídos a você
|
||||
issues.filter_type.created_by_you=Criado por você
|
||||
issues.filter_type.mentioning_you=Mencionando você
|
||||
|
@ -781,6 +781,33 @@ issues.due_date_added=adicionou a data limite %s %s
|
|||
issues.due_date_modified=modificou a data limite para %s ao invés de %s %s
|
||||
issues.due_date_remove=removeu a data limite %s %s
|
||||
issues.due_date_overdue=Em atraso
|
||||
issues.due_date_invalid=A data limite é inválida ou está fora do intervalo. Por favor, use o formato 'dd/mm/aaaa'.
|
||||
issues.dependency.title=Dependências
|
||||
issues.dependency.issue_no_dependencies=Esta issue atualmente não tem dependências.
|
||||
issues.dependency.pr_no_dependencies=Este pull request atualmente não tem dependências.
|
||||
issues.dependency.add=Adicione...
|
||||
issues.dependency.cancel=Cancelar
|
||||
issues.dependency.remove=Remover
|
||||
issues.dependency.added_dependency=`<a href="%[1]s">%[2]s</a> adicionou uma nova dependência %[3]s`
|
||||
issues.dependency.removed_dependency=`<a href="%[1]s">%[2]s</a> removeu uma dependência %[3]s`
|
||||
issues.dependency.issue_closing_blockedby=Fechamento deste pull request está bloqueado pelas seguintes issues
|
||||
issues.dependency.pr_closing_blockedby=Fechamento desta issue está bloqueado pelas seguintes issues
|
||||
issues.dependency.issue_close_blocks=Esta issue bloqueia o fechamento das seguintes issues
|
||||
issues.dependency.pr_close_blocks=Este pull request bloqueia o fechamento das seguintes issues
|
||||
issues.dependency.issue_close_blocked=Você precisa fechar todas as issues que bloqueiam esta issue antes de poder fechá-la.
|
||||
issues.dependency.pr_close_blocked=Você precisa fechar todas issues que bloqueiam este pull request antes de poder fazer o merge.
|
||||
issues.dependency.blocks_short=Bloqueia
|
||||
issues.dependency.blocked_by_short=Depende de
|
||||
issues.dependency.remove_header=Remover dependência
|
||||
issues.dependency.issue_remove_text=Isto removerá a dependência desta issue. Continuar?
|
||||
issues.dependency.pr_remove_text=Isto removerá a dependência deste pull request. Continuar?
|
||||
issues.dependency.setting=Habilitar dependências para issues e pull requests
|
||||
issues.dependency.add_error_same_issue=Você não pode fazer uma issue depender de si mesma.
|
||||
issues.dependency.add_error_dep_issue_not_exist=Issue dependente não existe.
|
||||
issues.dependency.add_error_dep_not_exist=Dependência não existe.
|
||||
issues.dependency.add_error_dep_exists=Dependência já existe.
|
||||
issues.dependency.add_error_cannot_create_circular=Você não pode criar uma dependência com duas issues bloqueando uma a outra.
|
||||
issues.dependency.add_error_dep_not_same_repo=Ambas as issues devem estar no mesmo repositório.
|
||||
|
||||
pulls.desc=Habilitar solicitações de merge e revisões de código.
|
||||
pulls.new=Novo pull request
|
||||
|
@ -793,7 +820,7 @@ pulls.no_results=Nada encontrado.
|
|||
pulls.nothing_to_compare=Estes branches são iguais. Não há nenhuma necessidade para criar um pull request.
|
||||
pulls.has_pull_request=`Um pull request entre esses branches já existe: <a href="%[1]s/pulls/%[3]d">%[2]s#%[3]d</a>`
|
||||
pulls.create=Criar pull request
|
||||
pulls.title_desc=quer mesclar %[1]d commits de <code>%[2]s</code> em <code>%[3]s</code>
|
||||
pulls.title_desc=quer realizar o merge de %[1]d commits de <code>%[2]s</code> em <code>%[3]s</code>
|
||||
pulls.merged_title_desc=fez merge dos %[1]d commits de <code>%[2]s</code> em <code>%[3]s</code> %[4]s
|
||||
pulls.tab_conversation=Conversação
|
||||
pulls.tab_commits=Commits
|
||||
|
@ -818,14 +845,14 @@ milestones.new=Novo marco
|
|||
milestones.open_tab=%d Aberto
|
||||
milestones.close_tab=%d Fechado
|
||||
milestones.closed=Fechado %s
|
||||
milestones.no_due_date=Sem prazo
|
||||
milestones.no_due_date=Sem data limite
|
||||
milestones.open=Reabrir
|
||||
milestones.close=Fechar
|
||||
milestones.new_subheader=Marcos organizam as issues e acompanham o progresso.
|
||||
milestones.create=Criar marco
|
||||
milestones.title=Título
|
||||
milestones.desc=Descrição
|
||||
milestones.due_date=Prazo (opcional)
|
||||
milestones.due_date=Data limite (opcional)
|
||||
milestones.clear=Limpar
|
||||
milestones.invalid_due_date_format=Formato da data limite deve ser 'dd/mm/aaaa'.
|
||||
milestones.create_success=O marco '%s' foi criado.
|
||||
|
@ -837,8 +864,8 @@ milestones.edit_success=O marco '%s' foi atualizado.
|
|||
milestones.deletion=Excluir marco
|
||||
milestones.deletion_desc=A exclusão deste marco irá removê-lo de todas as issues. Tem certeza que deseja continuar?
|
||||
milestones.deletion_success=O marco foi excluído.
|
||||
milestones.filter_sort.closest_due_date=Prazo mais próximo
|
||||
milestones.filter_sort.furthest_due_date=Prazo mais longe
|
||||
milestones.filter_sort.closest_due_date=Data limite mais próxima
|
||||
milestones.filter_sort.furthest_due_date=Data limite mais distante
|
||||
milestones.filter_sort.least_complete=Menos completo
|
||||
milestones.filter_sort.most_complete=Mais completo
|
||||
milestones.filter_sort.most_issues=Com mais issues
|
||||
|
@ -894,15 +921,15 @@ activity.closed_issues_count_1=Issue fechada
|
|||
activity.closed_issues_count_n=Issues fechadas
|
||||
activity.title.issues_1=+%d Issue
|
||||
activity.title.issues_n=+%d Issues
|
||||
activity.title.issues_closed_by=%s fechado por %s
|
||||
activity.title.issues_created_by=%s criado por %s
|
||||
activity.title.issues_closed_by=%s fechada por %s
|
||||
activity.title.issues_created_by=%s criada por %s
|
||||
activity.closed_issue_label=Fechado
|
||||
activity.new_issues_count_1=Nova issue
|
||||
activity.new_issues_count_n=Novas issues
|
||||
activity.new_issue_label=Aberto
|
||||
activity.title.unresolved_conv_1=%d conversa não resolvida
|
||||
activity.title.unresolved_conv_n=%d conversas não resolvidas
|
||||
activity.unresolved_conv_desc=Estes problemas foram recentemente alterados e pull requests ainda não foram resolvidos.
|
||||
activity.unresolved_conv_desc=Estas issues foram recentemente alteradas e pull requests ainda não foram resolvidos.
|
||||
activity.unresolved_conv_label=Abrir
|
||||
activity.title.releases_1=%d Versão
|
||||
activity.title.releases_n=%d Versões
|
||||
|
@ -975,7 +1002,7 @@ settings.confirm_wiki_delete=Excluir dados da wiki
|
|||
settings.wiki_deletion_success=Os dados da wiki do repositório foi excluídos.
|
||||
settings.delete=Excluir este repositório
|
||||
settings.delete_desc=A exclusão de um repositório é permanente e não pode ser desfeita.
|
||||
settings.delete_notices_1=-Esta operação <strong>NÃO PODERÁ</strong> ser desfeita.
|
||||
settings.delete_notices_1=- Esta operação <strong>NÃO PODERÁ</strong> ser desfeita.
|
||||
settings.delete_notices_2=- Essa operação excluirá permanentemente o repositório <strong>%s</strong>, incluindo código, issues, comentários, dados da wiki e configurações do colaborador.
|
||||
settings.delete_notices_fork_1=- Forks deste repositório se tornarão independentes após a exclusão.
|
||||
settings.deletion_success=O repositório foi excluído.
|
||||
|
@ -1169,7 +1196,7 @@ branch.protected_deletion_failed=A branch '%s' está protegida. Ela não pode se
|
|||
topic.manage_topics=Gerenciar Tópicos
|
||||
topic.done=Feito
|
||||
topic.count_prompt=Você não pode selecionar mais de 25 tópicos
|
||||
topic.format_prompt=Tópicos devem começar com uma letra ou um número, podem incluir hífens (-) e não devem ter mais de 35 caracteres
|
||||
topic.format_prompt=Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
|
||||
|
||||
[org]
|
||||
org_name_holder=Nome da organização
|
||||
|
@ -1443,7 +1470,7 @@ auths.deletion_success=A fonte de autenticação foi excluída.
|
|||
auths.login_source_exist=A fonte de autenticação '%s' já existe.
|
||||
|
||||
config.server_config=Configuração do servidor
|
||||
config.app_name=Título do site
|
||||
config.app_name=Nome do servidor
|
||||
config.app_ver=Versão do Gitea
|
||||
config.app_url=URL base do Gitea
|
||||
config.custom_conf=Caminho do Arquivo de Configuração
|
||||
|
@ -1483,7 +1510,7 @@ config.db_path=Caminho
|
|||
config.service_config=Configuração do serviço
|
||||
config.register_email_confirm=Exigir confirmação de e-mail para se cadastrar
|
||||
config.disable_register=Desabilitar auto-cadastro
|
||||
config.allow_only_external_registration=Habilitar o cadastro apenas por meio de serviços externos
|
||||
config.allow_only_external_registration=Permitir cadastro somente por meio de serviços externos
|
||||
config.enable_openid_signup=Habilitar o auto-cadastro via OpenID
|
||||
config.enable_openid_signin=Habilitar acesso via OpenID
|
||||
config.show_registration_button=Mostrar botão de cadastro
|
||||
|
@ -1499,6 +1526,7 @@ config.enable_timetracking=Habilitar contador de tempo
|
|||
config.default_enable_timetracking=Habilitar o contador de tempo por padrão
|
||||
config.default_allow_only_contributors_to_track_time=Permitir que apenas os colaboradores acompanhem o contador de tempo
|
||||
config.no_reply_address=Ocultar domínio de e-mail
|
||||
config.default_enable_dependencies=Habilitar dependências de issue por padrão
|
||||
|
||||
config.webhook_config=Configuração de Hook da Web
|
||||
config.queue_length=Tamanho da fila
|
||||
|
@ -1586,7 +1614,7 @@ create_repo=criou o repositório <a href="%s">%s</a>
|
|||
rename_repo=renomeou o repositório <code>%[1]s</code> para <a href="%[2]s">%[3]s</a>
|
||||
commit_repo=fez push para <a href="%[1]s/src/%[2]s">%[3]s</a> em <a href="%[1]s">%[4]s</a>
|
||||
create_issue=`abriu a issue <a href="%s/issues/%s">%s#%[2]s</a>`
|
||||
close_issue=`fechou issue <a href="%s/issues/%s">%s#%[2]s</a>`
|
||||
close_issue=`fechou a issue <a href="%s/issues/%s">%s#%[2]s</a>`
|
||||
reopen_issue=`reabriu a issue <a href="%s/issues/%s">%s#%[2]s</a>`
|
||||
create_pull_request=`criou o pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
|
||||
close_pull_request=`fechou o pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
|
||||
|
|
|
@ -32,16 +32,8 @@ twofa_scratch=Двухфакторный scratch-код
|
|||
passcode=Пароль
|
||||
|
||||
u2f_insert_key=Вставьте ключ безопасности
|
||||
u2f_sign_in=Нажмите кнопку на ключе безопасности. Если вы не можете найти кнопку, вставьте его снова.
|
||||
u2f_press_button=Пожалуйста нажмите кнопку на вашем ключе безопасности…
|
||||
u2f_use_twofa=Используйте двухфакторный код с телефона
|
||||
u2f_error=Мы не можем прочитать ваш ключ безопасности!
|
||||
u2f_unsupported_browser=Ваш браузер не поддерживает U2F ключи. Попробуйте другой браузер.
|
||||
u2f_error_1=Произошла неизвестная ошибка. Повторите попытку.
|
||||
u2f_error_2=Пожалуйста, убедитесь, что вы используете зашифрованное соединение (https://) и используете правильный URL.
|
||||
u2f_error_3=Серверу не удалось обработать ваш запрос.
|
||||
u2f_error_4=Представленный ключ не подходит для этого запроса. Если вы пытаетесь зарегистрировать его, убедитесь, что ключ еще не зарегистрирован.
|
||||
u2f_error_5=Таймаут достигнут до того, как ваш ключ был прочитан. Перезагрузите, чтобы повторить попытку.
|
||||
u2f_reload=Обновить
|
||||
|
||||
repository=Репозиторий
|
||||
|
@ -130,7 +122,6 @@ federated_avatar_lookup=Включить федеративные аватары
|
|||
federated_avatar_lookup_popup=Включите поиск федеративного аватара для использования службы с открытым исходным кодом на основе libravatar.
|
||||
disable_registration=Отключить самостоятельную регистрацию
|
||||
disable_registration_popup=Запретить самостоятельную регистрацию. Только администраторы смогут создавать новые учетные записи пользователей.
|
||||
allow_only_external_registration_popup=Включить регистрацию только через сторонние сервисы.
|
||||
openid_signin=Включение входа через OpenID
|
||||
openid_signin_popup=Включение входа через OpenID.
|
||||
openid_signup=Включить саморегистрацию OpenID
|
||||
|
@ -463,13 +454,10 @@ then_enter_passcode=И введите пароль, показанный в пр
|
|||
passcode_invalid=Неверный пароль. попробуйте снова.
|
||||
twofa_enrolled=Для вашего аккаунта была включена двухфакторная аутентификация. Сохраните ваш scratch-токен (%s), он не сохраняется на сервере!
|
||||
|
||||
u2f_desc=Ключами безопасности являются аппаратные устройства, содержащие криптографические ключи. Они могут использоваться для двухфакторной аутентификации. Ключ безопасности должен поддерживать стандарт <a href="https://fidoalliance.org/">FIDO U2F</a>.
|
||||
u2f_require_twofa=Для использования ключей безопасности необходимо включить двухфакторную аутентификацию.
|
||||
u2f_register_key=Добавить ключ безопасности
|
||||
u2f_nickname=Имя пользователя
|
||||
u2f_press_button=Нажмите кнопку на ключе безопасности, чтобы зарегистрировать его.
|
||||
u2f_delete_key=Удалить ключ безопасности
|
||||
u2f_delete_key_desc=Если вы удалите ключ безопасности, вы не сможете использовать его для входа. Вы уверены?
|
||||
|
||||
manage_account_links=Управление привязанными аккаунтами
|
||||
manage_account_links_desc=Эти внешние аккаунты привязаны к вашему аккаунту Gitea.
|
||||
|
@ -650,7 +638,6 @@ issues.new.open_milestone=Открыть этап
|
|||
issues.new.closed_milestone=Завершенные этапы
|
||||
issues.new.assignees=Назначенные
|
||||
issues.new.clear_assignees=Убрать ответственных
|
||||
issues.new.no_assignees=Никто не назначен
|
||||
issues.no_ref=Не указана ветка или тэг
|
||||
issues.create=Добавить задачу
|
||||
issues.new_label=Новая метка
|
||||
|
@ -1168,8 +1155,6 @@ branch.protected_deletion_failed=Ветка '%s' защищена. Её нель
|
|||
|
||||
topic.manage_topics=Редактировать тематические метки
|
||||
topic.done=Сохранить
|
||||
topic.count_prompt=Вы не можете выбрать более 25 тем
|
||||
topic.format_prompt=Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов
|
||||
|
||||
[org]
|
||||
org_name_holder=Название организации
|
||||
|
@ -1274,8 +1259,6 @@ dashboard.operation_switch=Переключить
|
|||
dashboard.operation_run=Запуск
|
||||
dashboard.clean_unbind_oauth=Очистить список незавершённых авторизаций OAuth
|
||||
dashboard.clean_unbind_oauth_success=Все незавершённые связи OAuth были удалены.
|
||||
dashboard.delete_inactivate_accounts=Удалить все неактивированные учетные записи
|
||||
dashboard.delete_inactivate_accounts_success=Все не активированные учетные записи были удалены.
|
||||
dashboard.delete_repo_archives=Удаление всех архивов репозиториев
|
||||
dashboard.delete_repo_archives_success=Все архивы репозиториев удалены.
|
||||
dashboard.delete_missing_repos=Удалить все записи о репозиториях с отсутствующими файлами Git
|
||||
|
@ -1483,7 +1466,6 @@ config.db_path=Путь
|
|||
config.service_config=Сервисная конфигурация
|
||||
config.register_email_confirm=Требуется подтверждение по электронной почте
|
||||
config.disable_register=Отключить самостоятельную регистрацию
|
||||
config.allow_only_external_registration=Включить регистрацию только через сторонние сервисы
|
||||
config.enable_openid_signup=Включить cамостоятельную регистрацию OpenID
|
||||
config.enable_openid_signin=Включение входа через OpenID
|
||||
config.show_registration_button=Показать кнопку регистрации
|
||||
|
|
|
@ -32,16 +32,8 @@ twofa_scratch=Tvåfaktorsskrapkod
|
|||
passcode=Kod
|
||||
|
||||
u2f_insert_key=Sätt i din säkerhetsnyckel
|
||||
u2f_sign_in=Tryck på knappen på din säkerhetsnyckel. Om du inte kan hitta en knapp, dra ur och sätt i nyckeln igen.
|
||||
u2f_press_button=Vänligen tryck på knappen på din säkerhetsnyckel…
|
||||
u2f_use_twofa=Använd en tvåfaktorskod från din telefon
|
||||
u2f_error=Vi kan inte läsa din säkerhetsnyckel!
|
||||
u2f_unsupported_browser=Din webbläsare stödjer inte U2F-nycklar. Vänligen prova en annan webbläsare.
|
||||
u2f_error_1=Ett okänt fel uppstod. Vänligen försök igen.
|
||||
u2f_error_2=Kontrollera att du använder en krypterad anslutning (https://) och besöker korrekt länk.
|
||||
u2f_error_3=Servern kunde inte hantera din förfrågan.
|
||||
u2f_error_4=Den givna nyckeln är inte behörig för denna förfrågan. Om du försöker registrera den, se till att den inte redan är registrerad.
|
||||
u2f_error_5=Timeout uppnådd innan nyckeln kunde bli läst. Vänligen ladda om sidan och för att försök igen.
|
||||
u2f_reload=Ladda om
|
||||
|
||||
repository=Utvecklingskatalog
|
||||
|
@ -129,7 +121,6 @@ disable_gravatar_popup=Inaktivera Gravatar- och avatarskällor från tredjepart.
|
|||
federated_avatar_lookup_popup=Använd libravatar vid förenad uppslagning av avatarer.
|
||||
disable_registration=Inaktivera Självregistrering
|
||||
disable_registration_popup=Inaktivera självregistrering av användare. Endast administratörer kommer kunna skapa nya konton.
|
||||
allow_only_external_registration_popup=Aktivera registrering enbart via externa tjänster.
|
||||
openid_signin=Aktivera OpenID-inloggning
|
||||
openid_signin_popup=Aktivera användarinloggning via OpenID.
|
||||
openid_signup=Aktivera självregistrering genom OpenID
|
||||
|
@ -462,13 +453,10 @@ then_enter_passcode=Och ange den lösenkod som visas i programmet:
|
|||
passcode_invalid=Koden är ogiltig. Försök igen.
|
||||
twofa_enrolled=Tvåfaktorsautentisering har aktiverats för ditt konto. Förvara din skrapkod (%s) på en säker plats eftersom den bara visas en gång!
|
||||
|
||||
u2f_desc=Säkerhetsnycklar är maskinvaruenheter som innehåller kryptografiska nycklar. De kan användas för tvåfaktorautentisering. Säkerhetsnyckeln måste dock stödja <a href="https://fidoalliance.org/">FIDO U2F</a> standarden.
|
||||
u2f_require_twofa=Tvåfaktorautentisering måste aktiveras för att kunna använda säkerhetsnycklar.
|
||||
u2f_register_key=Lägg till säkerhetsnyckel
|
||||
u2f_nickname=Smeknamn
|
||||
u2f_press_button=Tryck på knappen på din säkerhetsnyckel för att registrera den.
|
||||
u2f_delete_key=Ta Bort Säkerhetsnyckel
|
||||
u2f_delete_key_desc=Om du tar bort en säkerhetsnyckel kommer du inte kunna logga in med den längre. Är du säker?
|
||||
|
||||
manage_account_links=Hantera Länkade Konton
|
||||
manage_account_links_desc=Dessa externa konton är länkade till ditt Gitea-konto.
|
||||
|
@ -646,7 +634,6 @@ issues.new.open_milestone=Öppna Milstenar
|
|||
issues.new.closed_milestone=Stängda Milstenar
|
||||
issues.new.assignees=Tilldelade
|
||||
issues.new.clear_assignees=Rensa tilldelade
|
||||
issues.new.no_assignees=Ingen tilldelad
|
||||
issues.no_ref=Ingen branch/Tag specificerad
|
||||
issues.create=Skapa Ärende
|
||||
issues.new_label=Ny etikett
|
||||
|
@ -1127,8 +1114,6 @@ branch.protected_deletion_failed=Branch '%s' är skyddad. Den kan inte bli bortt
|
|||
|
||||
topic.manage_topics=Hantera ämnen
|
||||
topic.done=Klar
|
||||
topic.count_prompt=Du kan inte markera mer än 25 ämnen
|
||||
topic.format_prompt=Ämnen måste starta med en bokstav eller nummer, kan inkludera bindestreck(-) och får inte vara längre än 35 tecken långt
|
||||
|
||||
[org]
|
||||
org_name_holder=Organisationsnamn
|
||||
|
@ -1229,8 +1214,6 @@ dashboard.operation_switch=Byt till
|
|||
dashboard.operation_run=Kör
|
||||
dashboard.clean_unbind_oauth=Rena obundna OAuth anslutningar
|
||||
dashboard.clean_unbind_oauth_success=Alla obundna OAuth anslutningar har raderats.
|
||||
dashboard.delete_inactivate_accounts=Ta bort alla inaktiva konton
|
||||
dashboard.delete_inactivate_accounts_success=Alla inaktiva konton har tagits bort.
|
||||
dashboard.delete_repo_archives=Ta bort alla utvecklingskatalogers arkiv
|
||||
dashboard.delete_missing_repos=Ta bort alla utvecklingskataloger som saknar filer specifika för Git
|
||||
dashboard.delete_missing_repos_success=Alla utvecklingskataloger som saknade sina Git-filer har tagits bort.
|
||||
|
@ -1417,7 +1400,6 @@ config.db_path=Sökväg
|
|||
config.service_config=Tjänstkonfiguration
|
||||
config.register_email_confirm=Kräv mejlbekräftelse för att registrera
|
||||
config.disable_register=Inaktivera självregistrering
|
||||
config.allow_only_external_registration=Aktivera registrering enbart genom externa tjänster
|
||||
config.enable_openid_signup=Aktivera självregistrering genom OpenID
|
||||
config.enable_openid_signin=Aktivera OpenID-inloggning
|
||||
config.show_registration_button=Visa registreringsknapp
|
||||
|
|
|
@ -32,16 +32,8 @@ twofa_scratch=Двофакторний одноразовий пароль
|
|||
passcode=Код доступу
|
||||
|
||||
u2f_insert_key=Вставте ключ безпеки
|
||||
u2f_sign_in=Натисніть кнопку на ключі безпеки. Якщо не вдається знайти кнопки, повторно вставте ключ.
|
||||
u2f_press_button=Будь ласка, натисніть кнопку на ключі захисту...
|
||||
u2f_use_twofa=Використовуйте дво-факторний код з вашого телефону
|
||||
u2f_error=Неможливо прочитати ваш ключ безпеки!
|
||||
u2f_unsupported_browser=Ваш браузер не підтримує U2F ключі. Будь ласка, спробуйте інший браузер.
|
||||
u2f_error_1=Сталася невідома помилка. Спробуйте ще раз.
|
||||
u2f_error_2=Переконайтеся, що ви використовуєте зашифроване з'єднання (https://) та відвідуєте правильну URL-адресу.
|
||||
u2f_error_3=Сервер не може обробити, ваш запит.
|
||||
u2f_error_4=Представлений ключ не дає право на цей запит. Якщо спробуєте зареєструвати його, переконайтеся, що ключ ще не зареєстровано.
|
||||
u2f_error_5=Таймаут досягнуто до того, як ваш ключ можна буде прочитати. Перезавантажте, щоб повторити спробу.
|
||||
u2f_reload=Оновити
|
||||
|
||||
repository=Репозиторій
|
||||
|
@ -130,7 +122,6 @@ federated_avatar_lookup=Увімкнути федеративні аватари
|
|||
federated_avatar_lookup_popup=Увімкнути зовнішний Аватар за допомогою Libravatar.
|
||||
disable_registration=Вимкнути самостійну реєстрацію
|
||||
disable_registration_popup=Вимкнути самостійну реєстрацію користувачів, тільки адміністратор може створювати нові облікові записи.
|
||||
allow_only_external_registration_popup=Включити реєстрацію тільки через зовнішні сервіси.
|
||||
openid_signin=Увімкнути реєстрацію за допомогою OpenID
|
||||
openid_signin_popup=Увімкнути вхід за допомогою OpenID.
|
||||
openid_signup=Увімкнути самостійну реєстрацію за допомогою OpenID
|
||||
|
@ -463,13 +454,10 @@ then_enter_passcode=І введіть пароль, який відобража
|
|||
passcode_invalid=Некоректний пароль. Спробуй ще раз.
|
||||
twofa_enrolled=Для вашого облікового запису було включена двофакторна автентифікація. Зберігайте свій scratch-токен (%s) у безпечному місці, оскільки він показується лише один раз!
|
||||
|
||||
u2f_desc=Ключами безпеки є апаратні пристрої, що містять криптографічні ключі. Вони можуть використовуватися для двофакторної автентифікації. Ключ безпеки повинен підтримувати стандарт <a href="https://fidoalliance.org/">FIDO U2F</a>.
|
||||
u2f_require_twofa=Для використання ключів безпеки необхідно зареєструвати двофакторну аутентифікацію.
|
||||
u2f_register_key=Додати ключ безпеки
|
||||
u2f_nickname=Псевдонім
|
||||
u2f_press_button=Натисніть кнопку на ключі безпеки, щоб зареєструвати його.
|
||||
u2f_delete_key=Видалити ключ безпеки
|
||||
u2f_delete_key_desc=Якщо ви видалите ключ безпеки, ви не зможете використати його для входу. Ти впевнені?
|
||||
|
||||
manage_account_links=Керування обліковими записами
|
||||
manage_account_links_desc=Ці зовнішні акаунти прив'язані до вашого аккаунту Gitea.
|
||||
|
@ -650,7 +638,6 @@ issues.new.open_milestone=Активні етапи
|
|||
issues.new.closed_milestone=Закриті етапи
|
||||
issues.new.assignees=Виконавеці
|
||||
issues.new.clear_assignees=Прибрати виконавеців
|
||||
issues.new.no_assignees=Ніхто не призначений
|
||||
issues.no_ref=Не вказана гілка або тег
|
||||
issues.create=Створити проблему
|
||||
issues.new_label=Нова мітка
|
||||
|
@ -781,6 +768,14 @@ issues.due_date_added=додав(ла) дату завершення %s %s
|
|||
issues.due_date_modified=термін змінено з %s %s на %s
|
||||
issues.due_date_remove=видалив(ла) дату завершення %s %s
|
||||
issues.due_date_overdue=Прострочено
|
||||
issues.dependency.title=Залежності
|
||||
issues.dependency.issue_no_dependencies=Ця проблема в даний час не має залежностей.
|
||||
issues.dependency.pr_no_dependencies=Цей запит на злиття в даний час не має залежностей.
|
||||
issues.dependency.cancel=Відмінити
|
||||
issues.dependency.remove=Видалити
|
||||
issues.dependency.added_dependency=<div class="notranslate"> 0%</div>[2]s</a> додано нову залежність %[3]s'
|
||||
issues.dependency.removed_dependency=<div class="notranslate"> 0%</div>[2]s</a> видалено залежність %[3]s'
|
||||
issues.dependency.blocks_short=Блоки
|
||||
|
||||
pulls.desc=Увімкнути запити на злиття та інтерфейс узгодження правок.
|
||||
pulls.new=Новий запит на злиття
|
||||
|
@ -1168,8 +1163,6 @@ branch.protected_deletion_failed=Гілка '%s' захищена. Її не м
|
|||
|
||||
topic.manage_topics=Керувати тематичними мітками
|
||||
topic.done=Готово
|
||||
topic.count_prompt=Ви не можете вибрати більше 25 тем
|
||||
topic.format_prompt=Теми мають починатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів
|
||||
|
||||
[org]
|
||||
org_name_holder=Назва організації
|
||||
|
@ -1274,8 +1267,6 @@ dashboard.operation_switch=Перемкнути
|
|||
dashboard.operation_run=Запустити
|
||||
dashboard.clean_unbind_oauth=Очистити список незавершених авторизацій OAuth
|
||||
dashboard.clean_unbind_oauth_success=Всі незавершені зв'язки OAuth були видалені.
|
||||
dashboard.delete_inactivate_accounts=Видалити всі неактивовані облікові записи
|
||||
dashboard.delete_inactivate_accounts_success=Усі неактивовані облікові записи успішно видалено.
|
||||
dashboard.delete_repo_archives=Видалити всі архіви репозиторіїв
|
||||
dashboard.delete_repo_archives_success=Всі архіви репозиторіїв були видалені.
|
||||
dashboard.delete_missing_repos=Видалити всі записи про репозиторії з відсутніми файлами Git
|
||||
|
@ -1483,7 +1474,6 @@ config.db_path=Шлях
|
|||
config.service_config=Конфігурація сервісу
|
||||
config.register_email_confirm=Потрібно підтвердити електронну пошту для реєстрації
|
||||
config.disable_register=Вимкнути самостійну реєстрацію
|
||||
config.allow_only_external_registration=Включити реєстрацію тільки через сторонні сервіси
|
||||
config.enable_openid_signup=Увімкнути самостійну реєстрацію за допомогою OpenID
|
||||
config.enable_openid_signin=Увімкнути реєстрацію за допомогою OpenID
|
||||
config.show_registration_button=Показувати кнопку "Реєстрація
|
||||
|
|
|
@ -32,16 +32,8 @@ twofa_scratch=两步验证口令
|
|||
passcode=验证码
|
||||
|
||||
u2f_insert_key=插入安全密钥
|
||||
u2f_sign_in=按下安全密钥上的按钮。如果找不到按钮, 请重新插入。
|
||||
u2f_press_button=请按下安全密钥上的按钮。
|
||||
u2f_use_twofa=使用来自你手机中的两步验证码
|
||||
u2f_error=没有找到你的安全密钥!
|
||||
u2f_unsupported_browser=您的浏览器不支持 U2F 密钥。请尝试其他浏览器。
|
||||
u2f_error_1=发生未知错误。请重试。
|
||||
u2f_error_2=请确保您使用的是加密连接 (https://) 并访问正确的 URL。
|
||||
u2f_error_3=服务器无法执行您的请求。
|
||||
u2f_error_4=所提交的密钥不符合此请求。如果您尝试注册它, 请确保该密钥尚未注册。
|
||||
u2f_error_5=在读取到密钥之前超时。请重新加载以重试。
|
||||
u2f_reload=重新加载
|
||||
|
||||
repository=仓库
|
||||
|
@ -130,7 +122,6 @@ federated_avatar_lookup=启用 Federated 头像
|
|||
federated_avatar_lookup_popup=启用 Federated Avatars 查找以使用开源的 Libravatar 服务。
|
||||
disable_registration=禁止用户自助注册
|
||||
disable_registration_popup=禁用用户自助注册。只有管理员才能创建新的用户帐户。
|
||||
allow_only_external_registration_popup=仅允许通过外部服务注册。
|
||||
openid_signin=启用 OpenID 登录
|
||||
openid_signin_popup=启用通过 OpenID 登录
|
||||
openid_signup=启用 OpenID 自助注册
|
||||
|
@ -463,13 +454,10 @@ then_enter_passcode=并输入应用程序中显示的密码:
|
|||
passcode_invalid=密码不正确。再试一次。
|
||||
twofa_enrolled=你的账号已经启用了两步验证。请保存初始令牌(%s)到一个安全的地方,此令牌仅当前显示一次。
|
||||
|
||||
u2f_desc=安全密钥是包含加密算法的硬件设备。它们可以用于两步验证。安全密钥必须支持 <a href="https://fidoalliance.org/">FIDO U2F</a> 标准。
|
||||
u2f_require_twofa=必须开启两步验证才能使用安全密钥。
|
||||
u2f_register_key=添加安全密钥
|
||||
u2f_nickname=昵称
|
||||
u2f_press_button=按安全密钥上的按钮进行注册。
|
||||
u2f_delete_key=移除安全密钥
|
||||
u2f_delete_key_desc=如果移除安全密钥, 则无法再使用它登录。是否确定?
|
||||
|
||||
manage_account_links=管理绑定过的账号
|
||||
manage_account_links_desc=这些外部帐户已经绑定到您的 Gitea 帐户。
|
||||
|
@ -650,7 +638,6 @@ issues.new.open_milestone=开启中的里程碑
|
|||
issues.new.closed_milestone=已关闭的里程碑
|
||||
issues.new.assignees=指派成员
|
||||
issues.new.clear_assignees=取消指派成员
|
||||
issues.new.no_assignees=未指派成员
|
||||
issues.no_ref=分支/标记未指定
|
||||
issues.create=创建工单
|
||||
issues.new_label=创建标签
|
||||
|
@ -1167,8 +1154,6 @@ branch.protected_deletion_failed=分支 '%s' 已被保护,不可删除。
|
|||
|
||||
topic.manage_topics=管理主题
|
||||
topic.done=保存
|
||||
topic.count_prompt=您最多选择25个主题
|
||||
topic.format_prompt=主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
|
||||
|
||||
[org]
|
||||
org_name_holder=组织名称
|
||||
|
@ -1273,8 +1258,6 @@ dashboard.operation_switch=开关
|
|||
dashboard.operation_run=执行
|
||||
dashboard.clean_unbind_oauth=清理未绑定的 OAuth 连接
|
||||
dashboard.clean_unbind_oauth_success=所有未绑定的 OAuth 连接已被删除。
|
||||
dashboard.delete_inactivate_accounts=删除所有未激活的帐户
|
||||
dashboard.delete_inactivate_accounts_success=所有未激活的帐户都已删除。
|
||||
dashboard.delete_repo_archives=删除所有仓库存档
|
||||
dashboard.delete_repo_archives_success=所有仓库存档清除成功!
|
||||
dashboard.delete_missing_repos=删除所有丢失 Git 文件的仓库
|
||||
|
@ -1482,7 +1465,6 @@ config.db_path=数据库路径
|
|||
config.service_config=服务配置
|
||||
config.register_email_confirm=需要电子邮件确认注册
|
||||
config.disable_register=禁止用户注册
|
||||
config.allow_only_external_registration=仅允许通过外部服务注册
|
||||
config.enable_openid_signup=启用 OpenID 自注册
|
||||
config.enable_openid_signin=启用 OpenID 登录
|
||||
config.show_registration_button=显示注册按钮
|
||||
|
|
|
@ -32,16 +32,8 @@ twofa_scratch=兩步驟驗證備用碼
|
|||
passcode=驗證碼
|
||||
|
||||
u2f_insert_key=插入安全金鑰
|
||||
u2f_sign_in=按下安全金鑰上的按鈕。如果找不到按鈕, 請重新插入。
|
||||
u2f_press_button=請按下安全金鑰上的按鈕…
|
||||
u2f_use_twofa=使用來自手機的兩步驟驗證碼
|
||||
u2f_error=找不到您的安全金鑰!
|
||||
u2f_unsupported_browser=您的瀏覽器不支援 U2F 二步驟驗證技術。請嘗試其他瀏覽器。
|
||||
u2f_error_1=發生未知的錯誤,請重試。
|
||||
u2f_error_2=請確保您使用的是加密連接 (https://) 並且 URL 是正確的。
|
||||
u2f_error_3=伺服器無法執行您的請求。
|
||||
u2f_error_4=所提交的金鑰不符合此請求。如果您嘗試註冊它, 請確保該金鑰尚未註冊。
|
||||
u2f_error_5=在讀取金鑰之前已逾時,請重新載入以重試。
|
||||
u2f_reload=重新載入
|
||||
|
||||
repository=儲存庫
|
||||
|
@ -129,7 +121,6 @@ federated_avatar_lookup=開啟聯合大頭貼
|
|||
federated_avatar_lookup_popup=開啟聯合頭像查詢並使用基於開放源碼的 libravatar 服務
|
||||
disable_registration=關閉註冊功能
|
||||
disable_registration_popup=關閉註冊功能,只有管理員可以新增帳號。
|
||||
allow_only_external_registration_popup=僅允許通過外部服務註冊。
|
||||
openid_signin=啟用 OpenID 登入
|
||||
openid_signin_popup=啟用 OpenID 登入
|
||||
openid_signup=啟用 OpenID 註冊
|
||||
|
@ -432,13 +423,10 @@ or_enter_secret=或者輸入密碼: %s
|
|||
then_enter_passcode=然後輸入應用程序中顯示的驗證碼:
|
||||
passcode_invalid=無效的驗證碼,請重試。
|
||||
|
||||
u2f_desc=安全密鑰是包含加密密鑰的硬體設備。 它們可以用於兩步驟認證。 安全密鑰必須符合 <a href="https://fidoalliance.org/">FIDO U2F</a> 標準。
|
||||
u2f_require_twofa=必須先開啟兩步驟驗證才能使用安全密鑰。
|
||||
u2f_register_key=新增安全密鑰
|
||||
u2f_nickname=暱稱
|
||||
u2f_press_button=按下安全密鑰上的密碼進行註冊。
|
||||
u2f_delete_key=移除安全密鑰
|
||||
u2f_delete_key_desc=如果您移除安全密鑰,則無法再使用它登錄。 確定嗎?
|
||||
|
||||
manage_account_links=管理已連結的帳號
|
||||
manage_account_links_desc=這些外部帳號與您的 Gitea 帳號相關聯。
|
||||
|
@ -591,7 +579,6 @@ issues.new.open_milestone=開啟中的里程碑
|
|||
issues.new.closed_milestone=已關閉的里程碑
|
||||
issues.new.assignees=指派成員
|
||||
issues.new.clear_assignees=取消指派成員
|
||||
issues.new.no_assignees=未指派成員
|
||||
issues.no_ref=未指定分支或標籤
|
||||
issues.create=建立問題
|
||||
issues.new_label=建立標籤
|
||||
|
@ -1260,7 +1247,6 @@ config.db_path=資料庫路徑
|
|||
config.service_config=服務設定
|
||||
config.register_email_confirm=要求註冊時確認電子郵件
|
||||
config.disable_register=關閉註冊功能
|
||||
config.allow_only_external_registration=僅允許通過外部服務註冊
|
||||
config.enable_openid_signup=啟用 OpenID 註冊
|
||||
config.enable_openid_signin=啟用 OpenID 登入
|
||||
config.show_registration_button=顯示註冊按鈕
|
||||
|
|
|
@ -1769,6 +1769,7 @@ $(document).ready(function () {
|
|||
initTopicbar();
|
||||
initU2FAuth();
|
||||
initU2FRegister();
|
||||
initIssueList();
|
||||
|
||||
// Repo clone url.
|
||||
if ($('#repo-clone-url').length > 0) {
|
||||
|
@ -2488,3 +2489,41 @@ function updateDeadline(deadlineString) {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
function deleteDependencyModal(id, type) {
|
||||
$('.remove-dependency')
|
||||
.modal({
|
||||
closable: false,
|
||||
duration: 200,
|
||||
onApprove: function () {
|
||||
$('#removeDependencyID').val(id);
|
||||
$('#dependencyType').val(type);
|
||||
$('#removeDependencyForm').submit();
|
||||
}
|
||||
}).modal('show')
|
||||
;
|
||||
}
|
||||
|
||||
function initIssueList() {
|
||||
var repolink = $('#repolink').val();
|
||||
$('.new-dependency-drop-list')
|
||||
.dropdown({
|
||||
apiSettings: {
|
||||
url: '/api/v1/repos' + repolink + '/issues?q={query}',
|
||||
onResponse: function(response) {
|
||||
var filteredResponse = {'success': true, 'results': []};
|
||||
// Parse the response from the api to work with our dropdown
|
||||
$.each(response, function(index, issue) {
|
||||
filteredResponse.results.push({
|
||||
'name' : '#' + issue.number + ' ' + issue.title,
|
||||
'value' : issue.id
|
||||
});
|
||||
});
|
||||
return filteredResponse;
|
||||
},
|
||||
},
|
||||
|
||||
fullTextSearch: true
|
||||
})
|
||||
;
|
||||
}
|
||||
|
|
48
public/vendor/librejs.html
vendored
48
public/vendor/librejs.html
vendored
|
@ -11,122 +11,122 @@
|
|||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><a href="/vendor/plugins/jquery.areyousure/jquery.are-you-sure.js">jquery.are-you-sure.js</a></td>
|
||||
<td><a href="./plugins/jquery.areyousure/jquery.are-you-sure.js">jquery.are-you-sure.js</a></td>
|
||||
<td><a href="http://www.freebsd.org/copyright/freebsd-license.html">Expat</a></td>
|
||||
<td><a href="https://github.com/codedance/jquery.AreYouSure/archive/1.9.0.tar.gz">jquery.areyousure-1.9.0.tar.gz</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/vendor/plugins/jquery/jquery.min.js">jquery.min.js</a></td>
|
||||
<td><a href="./plugins/jquery/jquery.min.js">jquery.min.js</a></td>
|
||||
<td><a href="http://www.freebsd.org/copyright/freebsd-license.html">Expat</a></td>
|
||||
<td><a href="https://code.jquery.com/jquery-1.11.3.min.js">jquery-1.11.3.min.js</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/vendor/plugins/semantic/semantic.min.js">semantic.min.js</a></td>
|
||||
<td><a href="./plugins/semantic/semantic.min.js">semantic.min.js</a></td>
|
||||
<td><a href="https://semantic-ui.mit-license.org/">Expat</a></td>
|
||||
<td><a href="https://github.com/Semantic-Org/Semantic-UI/archive/2.3.1.tar.gz">semantic-UI-2.3.1.tar.gz</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/js/index.js">index.js</a></td>
|
||||
<td><a href="../js/index.js">index.js</a></td>
|
||||
<td><a href="https://github.com/go-gitea/gitea/blob/master/LICENSE">Expat</a></td>
|
||||
<td><a href="https://github.com/go-gitea/gitea/tree/master/public/js">index.js</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/js/draw.js">draw.js</a></td>
|
||||
<td><a href="../js/draw.js">draw.js</a></td>
|
||||
<td><a href="https://github.com/go-gitea/gitea/blob/master/LICENSE">Expat</a></td>
|
||||
<td><a href="https://github.com/go-gitea/gitea/tree/master/public/js">draw.js</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/vendor/plugins/clipboard/clipboard.min.js">clipboard.min.js</a></td>
|
||||
<td><a href="./plugins/clipboard/clipboard.min.js">clipboard.min.js</a></td>
|
||||
<td><a href="http://www.freebsd.org/copyright/freebsd-license.html">Expat</a></td>
|
||||
<td><a href="https://github.com/zenorocha/clipboard.js/archive/v1.5.9.tar.gz">clipboard-1.5.9.tar.gz</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/vendor/plugins/gitgraph/gitgraph.js">gitgraph.js</a></td>
|
||||
<td><a href="./plugins/gitgraph/gitgraph.js">gitgraph.js</a></td>
|
||||
<td><a href="https://github.com/bluef/gitgraph.js/blob/master/LICENSE">BSD 3-Clause</a></td>
|
||||
<td><a href="https://github.com/bluef/gitgraph.js">gitgraph.js-latest</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/vendor/plugins/vue/vue.min.js">vue.min.js</a></td>
|
||||
<td><a href="./plugins/vue/vue.min.js">vue.min.js</a></td>
|
||||
<td><a href="https://github.com/vuejs/vue/blob/dev/LICENSE">Expat</a></td>
|
||||
<td><a href="https://github.com/vuejs/vue/archive/v2.1.10.tar.gz">vue.js-v2.1.10.tar.gz</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/vendor/plugins/emojify/emojify.min.js">emojify.min.js</a></td>
|
||||
<td><a href="./plugins/emojify/emojify.min.js">emojify.min.js</a></td>
|
||||
<td><a href="http://www.freebsd.org/copyright/freebsd-license.html">Expat</a></td>
|
||||
<td><a href="https://github.com/Ranks/emojify.js/archive/1.1.0.tar.gz">emojify-1.1.0.tar.gz</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/vendor/plugins/cssrelpreload/loadCSS.min.js">loadCSS.min.js</a></td>
|
||||
<td><a href="./plugins/cssrelpreload/loadCSS.min.js">loadCSS.min.js</a></td>
|
||||
<td><a href="http://www.freebsd.org/copyright/freebsd-license.html">Expat</a></td>
|
||||
<td><a href="https://github.com/filamentgroup/loadCSS/archive/v1.3.1.tar.gz">loadCSS-1.3.1.tar.gz</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/vendor/plugins/cssrelpreload/cssrelpreload.min.js">cssrelpreload.min.js</a></td>
|
||||
<td><a href="./plugins/cssrelpreload/cssrelpreload.min.js">cssrelpreload.min.js</a></td>
|
||||
<td><a href="http://www.freebsd.org/copyright/freebsd-license.html">Expat</a></td>
|
||||
<td><a href="https://github.com/filamentgroup/loadCSS/archive/v1.3.1.tar.gz">loadCSS-1.3.1.tar.gz</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/vendor/plugins/dropzone/dropzone.js">dropzone.js</a></td>
|
||||
<td><a href="./plugins/dropzone/dropzone.js">dropzone.js</a></td>
|
||||
<td><a href="https://github.com/enyo/dropzone/blob/master/LICENSE">Expat</a></td>
|
||||
<td><a href="https://github.com/enyo/dropzone/archive/v4.2.0.tar.gz">dropzone.js-4.2.0.tar.gz</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/vendor/plugins/highlight/highlight.pack.js">highlight.pack.js</a></td>
|
||||
<td><a href="./plugins/highlight/highlight.pack.js">highlight.pack.js</a></td>
|
||||
<td><a href="https://github.com/isagalaev/highlight.js/blob/master/LICENSE">BSD 3-Clause</a></td>
|
||||
<td><a href="https://github.com/isagalaev/highlight.js/archive/9.6.0.tar.gz">highlight.js-9.6.0.tar.gz</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/vendor/plugins/jquery.datetimepicker/jquery.datetimepicker.js">jquery.datetimepicker.js</a></td>
|
||||
<td><a href="./plugins/jquery.datetimepicker/jquery.datetimepicker.js">jquery.datetimepicker.js</a></td>
|
||||
<td><a href="https://github.com/xdan/datetimepicker/blob/master/MIT-LICENSE.txt">Expat</a></td>
|
||||
<td><a href="https://github.com/xdan/datetimepicker/archive/2.4.5.tar.gz">jquery.datetimepicker-2.4.5.tar.gz</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/vendor/plugins/jquery.minicolors/jquery.minicolors.min.js">jquery.minicolors.min.js</a></td>
|
||||
<td><a href="./plugins/jquery.minicolors/jquery.minicolors.min.js">jquery.minicolors.min.js</a></td>
|
||||
<td><a href="https://github.com/claviska/jquery-minicolors/blob/master/LICENSE.md">Expat</a></td>
|
||||
<td><a href="https://github.com/claviska/jquery-minicolors/archive/2.2.3.tar.gz">jquery.minicolors-2.2.3.tar.gz</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/vendor/plugins/codemirror/addon/mode/loadmode.js">loadmode.js</a></td>
|
||||
<td><a href="./plugins/codemirror/addon/mode/loadmode.js">loadmode.js</a></td>
|
||||
<td><a href="https://github.com/codemirror/CodeMirror/blob/master/LICENSE">Expat</a></td>
|
||||
<td><a href="https://github.com/codemirror/CodeMirror/archive/5.17.0.tar.gz">codemirror-5.17.0.tar.gz</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/vendor/plugins/codemirror/mode/meta.js">meta.js</a></td>
|
||||
<td><a href="./plugins/codemirror/mode/meta.js">meta.js</a></td>
|
||||
<td><a href="https://github.com/codemirror/CodeMirror/blob/master/LICENSE">Expat</a></td>
|
||||
<td><a href="https://github.com/codemirror/CodeMirror/archive/5.17.0.tar.gz">codemirror-5.17.0.tar.gz</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/vendor/plugins/simplemde/simplemde.min.js">simplemde.min.js</a></td>
|
||||
<td><a href="./plugins/simplemde/simplemde.min.js">simplemde.min.js</a></td>
|
||||
<td><a href="https://github.com/sparksuite/simplemde-markdown-editor/blob/master/LICENSE">Expat</a></td>
|
||||
<td><a href="https://github.com/NextStepWebs/simplemde-markdown-editor/archive/1.10.1.tar.gz">simplemde-markdown-editor-1.10.1.tar.gz</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/vendor/plugins/pdfjs/">pdf.js</a></td>
|
||||
<td><a href="./plugins/pdfjs/">pdf.js</a></td>
|
||||
<td><a href="https://github.com/mozilla/pdf.js/blob/master/LICENSE">Apache-2.0-only</a></td>
|
||||
<td><a href="https://github.com/mozilla/pdf.js/archive/v1.4.20.tar.gz">pdf.js-v1.4.20.tar.gz</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/vendor/plugins/u2f/">u2f-api</a></td>
|
||||
<td><a href="./plugins/u2f/">u2f-api</a></td>
|
||||
<td><a href="https://github.com/go-gitea/u2f-api/blob/master/LICENSE">Expat</a></td>
|
||||
<td><a href="https://github.com/go-gitea/u2f-api/archive/v1.0.8.zip">u2f-api-1.0.8.zip</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/vendor/assets/font-awesome/fonts/">font-awesome - fonts</a></td>
|
||||
<td><a href="./assets/font-awesome/fonts/">font-awesome - fonts</a></td>
|
||||
<td><a href="http://fontawesome.io/license/">OFL</a></td>
|
||||
<td><a href="http://fontawesome.io/assets/font-awesome-4.6.0.zip">font-awesome-4.6.0.zip</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/vendor/assets/font-awesome/css/">font-awesome - code</a></td>
|
||||
<td><a href="./assets/font-awesome/css/">font-awesome - code</a></td>
|
||||
<td><a href="http://fontawesome.io/license/">Expat</a></td>
|
||||
<td><a href="http://fontawesome.io/assets/font-awesome-4.6.0.zip">font-awesome-4.6.0.zip</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/vendor/assets/octicons/">octicons</a></td>
|
||||
<td><a href="./assets/octicons/">octicons</a></td>
|
||||
<td><a href="https://github.com/primer/octicons/blob/master/LICENSE">Expat</a></td>
|
||||
<td><a href="https://github.com/primer/octicons/archive/v4.3.0.tar.gz">octicons-v4.3.0.tar.gz</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/vendor/assets/swagger-ui/">swagger-ui</a></td>
|
||||
<td><a href="./assets/swagger-ui/">swagger-ui</a></td>
|
||||
<td><a href="https://github.com/swagger-api/swagger-ui/blob/master/LICENSE">Apache-2.0</a></td>
|
||||
<td><a href="https://github.com/swagger-api/swagger-ui/archive/v3.0.4.tar.gz">swagger-ui-v3.0.4.tar.gz</a></td>
|
||||
</tr>
|
||||
|
|
|
@ -7,6 +7,7 @@ package repo
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
|
@ -208,6 +209,10 @@ func CreateIssue(ctx *context.APIContext, form api.CreateIssueOption) {
|
|||
|
||||
if form.Closed {
|
||||
if err := issue.ChangeStatus(ctx.User, ctx.Repo.Repository, true); err != nil {
|
||||
if models.IsErrDependenciesLeft(err) {
|
||||
ctx.Error(http.StatusPreconditionFailed, "DependenciesLeft", "cannot close this issue because it still has open dependencies")
|
||||
return
|
||||
}
|
||||
ctx.Error(500, "ChangeStatus", err)
|
||||
return
|
||||
}
|
||||
|
@ -325,6 +330,10 @@ func EditIssue(ctx *context.APIContext, form api.EditIssueOption) {
|
|||
}
|
||||
if form.State != nil {
|
||||
if err = issue.ChangeStatus(ctx.User, ctx.Repo.Repository, api.StateClosed == api.StateType(*form.State)); err != nil {
|
||||
if models.IsErrDependenciesLeft(err) {
|
||||
ctx.Error(http.StatusPreconditionFailed, "DependenciesLeft", "cannot close this issue because it still has open dependencies")
|
||||
return
|
||||
}
|
||||
ctx.Error(500, "ChangeStatus", err)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ package repo
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/git"
|
||||
|
@ -378,6 +379,10 @@ func EditPullRequest(ctx *context.APIContext, form api.EditPullRequestOption) {
|
|||
}
|
||||
if form.State != nil {
|
||||
if err = issue.ChangeStatus(ctx.User, ctx.Repo.Repository, api.StateClosed == api.StateType(*form.State)); err != nil {
|
||||
if models.IsErrDependenciesLeft(err) {
|
||||
ctx.Error(http.StatusPreconditionFailed, "DependenciesLeft", "cannot close this pull request because it still has open dependencies")
|
||||
return
|
||||
}
|
||||
ctx.Error(500, "ChangeStatus", err)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -302,6 +303,9 @@ func RetrieveRepoMetas(ctx *context.Context, repo *models.Repository) []*models.
|
|||
}
|
||||
ctx.Data["Branches"] = brs
|
||||
|
||||
// Contains true if the user can create issue dependencies
|
||||
ctx.Data["CanCreateIssueDependencies"] = ctx.Repo.CanCreateIssueDependencies(ctx.User)
|
||||
|
||||
return labels
|
||||
}
|
||||
|
||||
|
@ -665,6 +669,9 @@ func ViewIssue(ctx *context.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
// Check if the user can use the dependencies
|
||||
ctx.Data["CanCreateIssueDependencies"] = ctx.Repo.CanCreateIssueDependencies(ctx.User)
|
||||
|
||||
// Render comments and and fetch participants.
|
||||
participants[0] = issue.Poster
|
||||
for _, comment = range issue.Comments {
|
||||
|
@ -721,6 +728,11 @@ func ViewIssue(ctx *context.Context) {
|
|||
ctx.ServerError("LoadAssigneeUser", err)
|
||||
return
|
||||
}
|
||||
} else if comment.Type == models.CommentTypeRemoveDependency || comment.Type == models.CommentTypeAddDependency {
|
||||
if err = comment.LoadDepIssueDetails(); err != nil {
|
||||
ctx.ServerError("LoadDepIssueDetails", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -774,6 +786,10 @@ func ViewIssue(ctx *context.Context) {
|
|||
ctx.Data["IsPullBranchDeletable"] = canDelete && pull.HeadRepo != nil && git.IsBranchExist(pull.HeadRepo.RepoPath(), pull.HeadBranch)
|
||||
}
|
||||
|
||||
// Get Dependencies
|
||||
ctx.Data["BlockedByDependencies"], err = issue.BlockedByDependencies()
|
||||
ctx.Data["BlockingDependencies"], err = issue.BlockingDependencies()
|
||||
|
||||
ctx.Data["Participants"] = participants
|
||||
ctx.Data["NumParticipants"] = len(participants)
|
||||
ctx.Data["Issue"] = issue
|
||||
|
@ -971,6 +987,12 @@ func UpdateIssueStatus(ctx *context.Context) {
|
|||
}
|
||||
for _, issue := range issues {
|
||||
if err := issue.ChangeStatus(ctx.User, issue.Repo, isClosed); err != nil {
|
||||
if models.IsErrDependenciesLeft(err) {
|
||||
ctx.JSON(http.StatusPreconditionFailed, map[string]interface{}{
|
||||
"error": "cannot close this issue because it still has open dependencies",
|
||||
})
|
||||
return
|
||||
}
|
||||
ctx.ServerError("ChangeStatus", err)
|
||||
return
|
||||
}
|
||||
|
@ -1034,6 +1056,17 @@ func NewComment(ctx *context.Context, form auth.CreateCommentForm) {
|
|||
} else {
|
||||
if err := issue.ChangeStatus(ctx.User, ctx.Repo.Repository, form.Status == "close"); err != nil {
|
||||
log.Error(4, "ChangeStatus: %v", err)
|
||||
|
||||
if models.IsErrDependenciesLeft(err) {
|
||||
if issue.IsPull {
|
||||
ctx.Flash.Error(ctx.Tr("repo.issues.dependency.pr_close_blocked"))
|
||||
ctx.Redirect(fmt.Sprintf("%s/pulls/%d", ctx.Repo.RepoLink, issue.Index), http.StatusSeeOther)
|
||||
} else {
|
||||
ctx.Flash.Error(ctx.Tr("repo.issues.dependency.issue_close_blocked"))
|
||||
ctx.Redirect(fmt.Sprintf("%s/issues/%d", ctx.Repo.RepoLink, issue.Index), http.StatusSeeOther)
|
||||
}
|
||||
return
|
||||
}
|
||||
} else {
|
||||
log.Trace("Issue [%d] status changed to closed: %v", issue.ID, issue.IsClosed)
|
||||
|
||||
|
|
119
routers/repo/issue_dependency.go
Normal file
119
routers/repo/issue_dependency.go
Normal file
|
@ -0,0 +1,119 @@
|
|||
// Copyright 2018 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package repo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
)
|
||||
|
||||
// AddDependency adds new dependencies
|
||||
func AddDependency(ctx *context.Context) {
|
||||
// Check if the Repo is allowed to have dependencies
|
||||
if !ctx.Repo.CanCreateIssueDependencies(ctx.User) {
|
||||
ctx.Error(http.StatusForbidden, "CanCreateIssueDependencies")
|
||||
return
|
||||
}
|
||||
|
||||
depID := ctx.QueryInt64("newDependency")
|
||||
|
||||
issueIndex := ctx.ParamsInt64("index")
|
||||
issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, issueIndex)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetIssueByIndex", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Redirect
|
||||
defer ctx.Redirect(fmt.Sprintf("%s/issues/%d", ctx.Repo.RepoLink, issueIndex), http.StatusSeeOther)
|
||||
|
||||
// Dependency
|
||||
dep, err := models.GetIssueByID(depID)
|
||||
if err != nil {
|
||||
ctx.Flash.Error(ctx.Tr("repo.issues.dependency.add_error_dep_issue_not_exist"))
|
||||
return
|
||||
}
|
||||
|
||||
// Check if both issues are in the same repo
|
||||
if issue.RepoID != dep.RepoID {
|
||||
ctx.Flash.Error(ctx.Tr("repo.issues.dependency.add_error_dep_not_same_repo"))
|
||||
return
|
||||
}
|
||||
|
||||
// Check if issue and dependency is the same
|
||||
if dep.Index == issueIndex {
|
||||
ctx.Flash.Error(ctx.Tr("repo.issues.dependency.add_error_same_issue"))
|
||||
return
|
||||
}
|
||||
|
||||
err = models.CreateIssueDependency(ctx.User, issue, dep)
|
||||
if err != nil {
|
||||
if models.IsErrDependencyExists(err) {
|
||||
ctx.Flash.Error(ctx.Tr("repo.issues.dependency.add_error_dep_exists"))
|
||||
return
|
||||
} else if models.IsErrCircularDependency(err) {
|
||||
ctx.Flash.Error(ctx.Tr("repo.issues.dependency.add_error_cannot_create_circular"))
|
||||
return
|
||||
} else {
|
||||
ctx.ServerError("CreateOrUpdateIssueDependency", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveDependency removes the dependency
|
||||
func RemoveDependency(ctx *context.Context) {
|
||||
// Check if the Repo is allowed to have dependencies
|
||||
if !ctx.Repo.CanCreateIssueDependencies(ctx.User) {
|
||||
ctx.Error(http.StatusForbidden, "CanCreateIssueDependencies")
|
||||
return
|
||||
}
|
||||
|
||||
depID := ctx.QueryInt64("removeDependencyID")
|
||||
|
||||
issueIndex := ctx.ParamsInt64("index")
|
||||
issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, issueIndex)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetIssueByIndex", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Redirect
|
||||
ctx.Redirect(fmt.Sprintf("%s/issues/%d", ctx.Repo.RepoLink, issueIndex), http.StatusSeeOther)
|
||||
|
||||
// Dependency Type
|
||||
depTypeStr := ctx.Req.PostForm.Get("dependencyType")
|
||||
|
||||
var depType models.DependencyType
|
||||
|
||||
switch depTypeStr {
|
||||
case "blockedBy":
|
||||
depType = models.DependencyTypeBlockedBy
|
||||
case "blocking":
|
||||
depType = models.DependencyTypeBlocking
|
||||
default:
|
||||
ctx.Error(http.StatusBadRequest, "GetDependecyType")
|
||||
return
|
||||
}
|
||||
|
||||
// Dependency
|
||||
dep, err := models.GetIssueByID(depID)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetIssueByID", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err = models.RemoveIssueDependency(ctx.User, issue, dep, depType); err != nil {
|
||||
if models.IsErrDependencyNotExists(err) {
|
||||
ctx.Flash.Error(ctx.Tr("repo.issues.dependency.add_error_dep_not_exist"))
|
||||
return
|
||||
}
|
||||
ctx.ServerError("RemoveIssueDependency", err)
|
||||
return
|
||||
}
|
||||
}
|
|
@ -524,6 +524,18 @@ func MergePullRequest(ctx *context.Context, form auth.MergePullRequestForm) {
|
|||
|
||||
pr.Issue = issue
|
||||
pr.Issue.Repo = ctx.Repo.Repository
|
||||
|
||||
noDeps, err := models.IssueNoDependenciesLeft(issue)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !noDeps {
|
||||
ctx.Flash.Error(ctx.Tr("repo.issues.dependency.pr_close_blocked"))
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + com.ToStr(pr.Index))
|
||||
return
|
||||
}
|
||||
|
||||
if err = pr.Merge(ctx.User, ctx.Repo.GitRepo, models.MergeStyle(form.Do), message); err != nil {
|
||||
if models.IsErrInvalidMergeStyle(err) {
|
||||
ctx.Flash.Error(ctx.Tr("repo.pulls.invalid_merge_option"))
|
||||
|
|
|
@ -202,6 +202,7 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
|
|||
Config: &models.IssuesConfig{
|
||||
EnableTimetracker: form.EnableTimetracker,
|
||||
AllowOnlyContributorsToTrackTime: form.AllowOnlyContributorsToTrackTime,
|
||||
EnableDependencies: form.EnableIssueDependencies,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
|
@ -527,6 +527,10 @@ func RegisterRoutes(m *macaron.Macaron) {
|
|||
m.Post("/title", repo.UpdateIssueTitle)
|
||||
m.Post("/content", repo.UpdateIssueContent)
|
||||
m.Post("/watch", repo.IssueWatch)
|
||||
m.Group("/dependency", func() {
|
||||
m.Post("/add", repo.AddDependency)
|
||||
m.Post("/delete", repo.RemoveDependency)
|
||||
})
|
||||
m.Combo("/comments").Post(bindIgnErr(auth.CreateCommentForm{}), repo.NewComment)
|
||||
m.Group("/times", func() {
|
||||
m.Post("/add", bindIgnErr(auth.AddTimeManuallyForm{}), repo.AddTimeManually)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Copyright 2018 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
|
@ -320,7 +321,7 @@ func TwoFactorScratchPost(ctx *context.Context, form auth.TwoFactorScratchAuthFo
|
|||
|
||||
handleSignInFull(ctx, u, remember, false)
|
||||
ctx.Flash.Info(ctx.Tr("auth.twofa_scratch_used"))
|
||||
ctx.Redirect(setting.AppSubURL + "/user/settings/two_factor")
|
||||
ctx.Redirect(setting.AppSubURL + "/user/settings/security")
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -150,6 +150,8 @@
|
|||
{{end}}
|
||||
<dt>{{.i18n.Tr "admin.config.no_reply_address"}}</dt>
|
||||
<dd>{{if .Service.NoReplyAddress}}{{.Service.NoReplyAddress}}{{else}}-{{end}}</dd>
|
||||
<dt>{{.i18n.Tr "admin.config.default_enable_dependencies"}}</dt>
|
||||
<dd><i class="fa fa{{if .Service.DefaultEnableDependencies}}-check{{end}}-square-o"></i></dd>
|
||||
<div class="ui divider"></div>
|
||||
<dt>{{.i18n.Tr "admin.config.active_code_lives"}}</dt>
|
||||
<dd>{{.Service.ActiveCodeLives}} {{.i18n.Tr "tool.raw_minutes"}}</dd>
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
{{.i18n.Tr "repo.branch.delete_html"}} <span class="branch-name"></span>
|
||||
</div>
|
||||
<div class="content">
|
||||
<p>{{.i18n.Tr "repo.branch.delete_desc"}}</p>
|
||||
<p>{{.i18n.Tr "repo.branch.delete_desc" | Str2html}}</p>
|
||||
</div>
|
||||
{{template "base/delete_modal_actions" .}}
|
||||
</div>
|
||||
|
|
|
@ -137,7 +137,7 @@
|
|||
{{.i18n.Tr "repo.branch.delete" .HeadTarget }}
|
||||
</div>
|
||||
<div class="content">
|
||||
<p>{{.i18n.Tr "repo.branch.delete_desc"}}</p>
|
||||
<p>{{.i18n.Tr "repo.branch.delete_desc" | Str2html}}</p>
|
||||
</div>
|
||||
{{template "base/delete_modal_actions" .}}
|
||||
</div>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{{range .Issue.Comments}}
|
||||
{{ $createdStr:= TimeSinceUnix .CreatedUnix $.Lang }}
|
||||
|
||||
<!-- 0 = COMMENT, 1 = REOPEN, 2 = CLOSE, 3 = ISSUE_REF, 4 = COMMIT_REF, 5 = COMMENT_REF, 6 = PULL_REF, 7 = COMMENT_LABEL, 12 = START_TRACKING, 13 = STOP_TRACKING, 14 = ADD_TIME_MANUAL, 16 = ADDED_DEADLINE, 17 = MODIFIED_DEADLINE, 18 = REMOVED_DEADLINE -->
|
||||
<!-- 0 = COMMENT, 1 = REOPEN, 2 = CLOSE, 3 = ISSUE_REF, 4 = COMMIT_REF, 5 = COMMENT_REF, 6 = PULL_REF, 7 = COMMENT_LABEL, 12 = START_TRACKING, 13 = STOP_TRACKING, 14 = ADD_TIME_MANUAL, 16 = ADDED_DEADLINE, 17 = MODIFIED_DEADLINE, 18 = REMOVED_DEADLINE, 19 = ADD_DEPENDENCY, 20 = REMOVE_DEPENDENCY -->
|
||||
{{if eq .Type 0}}
|
||||
<div class="comment" id="{{.HashTag}}">
|
||||
<a class="avatar" {{if gt .Poster.ID 0}}href="{{.Poster.HomeLink}}"{{end}}>
|
||||
|
@ -65,7 +65,6 @@
|
|||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{else if eq .Type 1}}
|
||||
<div class="event">
|
||||
<span class="octicon octicon-primitive-dot"></span>
|
||||
|
@ -233,5 +232,33 @@
|
|||
{{$.i18n.Tr "repo.issues.due_date_remove" .Content $createdStr | Safe}}
|
||||
</span>
|
||||
</div>
|
||||
{{end}}
|
||||
{{else if eq .Type 19}}
|
||||
<div class="event">
|
||||
<span class="octicon octicon-primitive-dot"></span>
|
||||
<a class="ui avatar image" href="{{.Poster.HomeLink}}">
|
||||
<img src="{{.Poster.RelAvatarLink}}">
|
||||
</a>
|
||||
<span class="text grey">
|
||||
{{$.i18n.Tr "repo.issues.dependency.added_dependency" .Poster.HomeLink .Poster.Name $createdStr | Safe}}
|
||||
</span>
|
||||
<div class="detail">
|
||||
<span class="octicon octicon-plus"></span>
|
||||
<span class="text grey"><a href="{{$.RepoLink}}/issues/{{.DependentIssue.Index}}">#{{.DependentIssue.Index}} {{.DependentIssue.Title}}</a></span>
|
||||
</div>
|
||||
</div>
|
||||
{{else if eq .Type 20}}
|
||||
<div class="event">
|
||||
<span class="octicon octicon-primitive-dot"></span>
|
||||
<a class="ui avatar image" href="{{.Poster.HomeLink}}">
|
||||
<img src="{{.Poster.RelAvatarLink}}">
|
||||
</a>
|
||||
<span class="text grey">
|
||||
{{$.i18n.Tr "repo.issues.dependency.removed_dependency" .Poster.HomeLink .Poster.Name $createdStr | Safe}}
|
||||
</span>
|
||||
<div class="detail">
|
||||
<span class="text grey octicon octicon-trashcan"></span>
|
||||
<span class="text grey"><a href="{{$.RepoLink}}/issues/{{.DependentIssue.Index}}">#{{.DependentIssue.Index}} {{.DependentIssue.Title}}</a></span>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
|
|
@ -249,5 +249,142 @@
|
|||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
{{if .Repository.IsDependenciesEnabled}}
|
||||
<div class="ui divider"></div>
|
||||
|
||||
<div class="ui depending">
|
||||
<span class="text"><strong>{{.i18n.Tr "repo.issues.dependency.title"}}</strong></span>
|
||||
<br>
|
||||
{{if .BlockedByDependencies}}
|
||||
<span class="text" data-tooltip="{{if .Issue.IsPull}}
|
||||
{{.i18n.Tr "repo.issues.dependency.issue_closing_blockedby"}}
|
||||
{{else}}
|
||||
{{.i18n.Tr "repo.issues.dependency.pr_closing_blockedby"}}
|
||||
{{end}}" data-inverted="">
|
||||
{{.i18n.Tr "repo.issues.dependency.blocked_by_short"}}:
|
||||
</span>
|
||||
<div class="ui relaxed divided list">
|
||||
{{range .BlockedByDependencies}}
|
||||
<div class="item">
|
||||
<div class="right floated content">
|
||||
{{if $.CanCreateIssueDependencies}}
|
||||
<a class="delete-dependency-button" onclick="deleteDependencyModal({{.ID}}, 'blockedBy');">
|
||||
<i class="delete icon text red"></i>
|
||||
</a>
|
||||
{{end}}
|
||||
{{if .IsClosed}}
|
||||
<div class="ui red mini label">
|
||||
<i class="octicon octicon-issue-closed"></i>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="ui green mini label">
|
||||
<i class="octicon octicon-issue-opened"></i>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="ui black label">#{{.Index}}</div>
|
||||
<a class="title has-emoji" href="{{$.RepoLink}}/issues/{{.Index}}">{{.Title}}</a>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{if .BlockingDependencies}}
|
||||
<span class="text" data-tooltip="{{if .Issue.IsPull}}
|
||||
{{.i18n.Tr "repo.issues.dependency.pr_close_blocks"}}
|
||||
{{else}}
|
||||
{{.i18n.Tr "repo.issues.dependency.issue_close_blocks"}}
|
||||
{{end}}" data-inverted="">
|
||||
{{.i18n.Tr "repo.issues.dependency.blocks_short"}}:
|
||||
</span>
|
||||
<div class="ui relaxed divided list">
|
||||
{{range .BlockingDependencies}}
|
||||
<div class="item">
|
||||
<div class="right floated content">
|
||||
{{if $.CanCreateIssueDependencies}}
|
||||
<a class="delete-dependency-button" onclick="deleteDependencyModal({{.ID}}, 'blocking');">
|
||||
<i class="delete icon text red"></i>
|
||||
</a>
|
||||
{{end}}
|
||||
{{if .IsClosed}}
|
||||
<div class="ui red tiny label">
|
||||
<i class="octicon octicon-issue-closed"></i>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="ui green mini label">
|
||||
<i class="octicon octicon-issue-opened"></i>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="ui black label">#{{.Index}}</div>
|
||||
<a class="title has-emoji" href="{{$.RepoLink}}/issues/{{.Index}}">{{.Title}}</a>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{if (and (not .BlockedByDependencies) (not .BlockingDependencies))}}
|
||||
<p>{{if .Issue.IsPull}}
|
||||
{{.i18n.Tr "repo.issues.dependency.pr_no_dependencies"}}
|
||||
{{else}}
|
||||
{{.i18n.Tr "repo.issues.dependency.issue_no_dependencies"}}
|
||||
{{end}}</p>
|
||||
{{end}}
|
||||
|
||||
{{if .CanCreateIssueDependencies}}
|
||||
<div>
|
||||
<form method="POST" action="{{$.RepoLink}}/issues/{{.Issue.Index}}/dependency/add" id="addDependencyForm">
|
||||
{{$.CsrfTokenHtml}}
|
||||
<div class="ui fluid action input">
|
||||
<div class="ui search selection dropdown new-dependency-drop-list" style="min-width: 13.9rem;border-radius: 4px 0 0 4px;border-right: 0;white-space: nowrap;">
|
||||
<input name="newDependency" type="hidden">
|
||||
<i class="dropdown icon"></i>
|
||||
<input type="text" class="search">
|
||||
<div class="default text">{{.i18n.Tr "repo.issues.dependency.add"}}</div>
|
||||
</div>
|
||||
<button class="ui green icon button">
|
||||
<i class="plus icon"></i>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{if .CanCreateIssueDependencies}}
|
||||
<input type="hidden" id="repolink" value="{{$.RepoLink}}">
|
||||
<!-- I know, there is probably a better way to do this -->
|
||||
<input type="hidden" id="issueIndex" value="{{.Issue.Index}}"/>
|
||||
|
||||
<div class="ui basic modal remove-dependency">
|
||||
<div class="ui icon header">
|
||||
<i class="trash icon"></i>
|
||||
{{.i18n.Tr "repo.issues.dependency.remove_header"}}
|
||||
</div>
|
||||
<div class="content">
|
||||
<form method="POST" action="{{$.RepoLink}}/issues/{{.Issue.Index}}/dependency/delete" id="removeDependencyForm">
|
||||
{{$.CsrfTokenHtml}}
|
||||
<input type="hidden" value="" name="removeDependencyID" id="removeDependencyID"/>
|
||||
<input type="hidden" value="" name="dependencyType" id="dependencyType"/>
|
||||
</form>
|
||||
<p>{{if .Issue.IsPull}}
|
||||
{{.i18n.Tr "repo.issues.dependency.pr_remove_text"}}
|
||||
{{else}}
|
||||
{{.i18n.Tr "repo.issues.dependency.issue_remove_text"}}
|
||||
{{end}}</p>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<div class="ui basic red cancel inverted button">
|
||||
<i class="remove icon"></i>
|
||||
{{.i18n.Tr "repo.issues.dependency.cancel"}}
|
||||
</div>
|
||||
<div class="ui basic green ok inverted button">
|
||||
<i class="checkmark icon"></i>
|
||||
{{.i18n.Tr "repo.issues.dependency.remove"}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
|
|
@ -153,6 +153,12 @@
|
|||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input name="enable_issue_dependencies" type="checkbox" {{if (.Repository.IsDependenciesEnabled)}}checked{{end}}>
|
||||
<label>{{.i18n.Tr "repo.issues.dependency.setting"}}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui radio checkbox">
|
||||
|
|
39
vendor/github.com/go-xorm/builder/builder.go
generated
vendored
39
vendor/github.com/go-xorm/builder/builder.go
generated
vendored
|
@ -4,6 +4,10 @@
|
|||
|
||||
package builder
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type optype byte
|
||||
|
||||
const (
|
||||
|
@ -29,6 +33,9 @@ type Builder struct {
|
|||
joins []join
|
||||
inserts Eq
|
||||
updates []Eq
|
||||
orderBy string
|
||||
groupBy string
|
||||
having string
|
||||
}
|
||||
|
||||
// Select creates a select Builder
|
||||
|
@ -67,6 +74,11 @@ func (b *Builder) From(tableName string) *Builder {
|
|||
return b
|
||||
}
|
||||
|
||||
// TableName returns the table name
|
||||
func (b *Builder) TableName() string {
|
||||
return b.tableName
|
||||
}
|
||||
|
||||
// Into sets insert table name
|
||||
func (b *Builder) Into(tableName string) *Builder {
|
||||
b.tableName = tableName
|
||||
|
@ -178,6 +190,33 @@ func (b *Builder) ToSQL() (string, []interface{}, error) {
|
|||
return w.writer.String(), w.args, nil
|
||||
}
|
||||
|
||||
// ConvertPlaceholder replaces ? to $1, $2 ... or :1, :2 ... according prefix
|
||||
func ConvertPlaceholder(sql, prefix string) (string, error) {
|
||||
buf := StringBuilder{}
|
||||
var j, start = 0, 0
|
||||
for i := 0; i < len(sql); i++ {
|
||||
if sql[i] == '?' {
|
||||
_, err := buf.WriteString(sql[start:i])
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
start = i + 1
|
||||
|
||||
_, err = buf.WriteString(prefix)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
j = j + 1
|
||||
_, err = buf.WriteString(fmt.Sprintf("%d", j))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
}
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
// ToSQL convert a builder or condtions to SQL and args
|
||||
func ToSQL(cond interface{}) (string, []interface{}, error) {
|
||||
switch cond.(type) {
|
||||
|
|
6
vendor/github.com/go-xorm/builder/builder_insert.go
generated
vendored
6
vendor/github.com/go-xorm/builder/builder_insert.go
generated
vendored
|
@ -15,7 +15,7 @@ func (b *Builder) insertWriteTo(w Writer) error {
|
|||
return errors.New("no table indicated")
|
||||
}
|
||||
if len(b.inserts) <= 0 {
|
||||
return errors.New("no column to be update")
|
||||
return errors.New("no column to be insert")
|
||||
}
|
||||
|
||||
if _, err := fmt.Fprintf(w, "INSERT INTO %s (", b.tableName); err != nil {
|
||||
|
@ -26,7 +26,9 @@ func (b *Builder) insertWriteTo(w Writer) error {
|
|||
var bs []byte
|
||||
var valBuffer = bytes.NewBuffer(bs)
|
||||
var i = 0
|
||||
for col, value := range b.inserts {
|
||||
|
||||
for _, col := range b.inserts.sortedKeys() {
|
||||
value := b.inserts[col]
|
||||
fmt.Fprint(w, col)
|
||||
if e, ok := value.(expr); ok {
|
||||
fmt.Fprint(valBuffer, e.sql)
|
||||
|
|
55
vendor/github.com/go-xorm/builder/builder_select.go
generated
vendored
55
vendor/github.com/go-xorm/builder/builder_select.go
generated
vendored
|
@ -34,24 +34,65 @@ func (b *Builder) selectWriteTo(w Writer) error {
|
|||
}
|
||||
}
|
||||
|
||||
if _, err := fmt.Fprintf(w, " FROM %s", b.tableName); err != nil {
|
||||
if _, err := fmt.Fprint(w, " FROM ", b.tableName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, v := range b.joins {
|
||||
fmt.Fprintf(w, " %s JOIN %s ON ", v.joinType, v.joinTable)
|
||||
if _, err := fmt.Fprintf(w, " %s JOIN %s ON ", v.joinType, v.joinTable); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := v.joinCond.WriteTo(w); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if !b.cond.IsValid() {
|
||||
return nil
|
||||
if b.cond.IsValid() {
|
||||
if _, err := fmt.Fprint(w, " WHERE "); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := b.cond.WriteTo(w); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := fmt.Fprint(w, " WHERE "); err != nil {
|
||||
return err
|
||||
if len(b.groupBy) > 0 {
|
||||
if _, err := fmt.Fprint(w, " GROUP BY ", b.groupBy); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return b.cond.WriteTo(w)
|
||||
if len(b.having) > 0 {
|
||||
if _, err := fmt.Fprint(w, " HAVING ", b.having); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(b.orderBy) > 0 {
|
||||
if _, err := fmt.Fprint(w, " ORDER BY ", b.orderBy); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// OrderBy orderBy SQL
|
||||
func (b *Builder) OrderBy(orderBy string) *Builder {
|
||||
b.orderBy = orderBy
|
||||
return b
|
||||
}
|
||||
|
||||
// GroupBy groupby SQL
|
||||
func (b *Builder) GroupBy(groupby string) *Builder {
|
||||
b.groupBy = groupby
|
||||
return b
|
||||
}
|
||||
|
||||
// Having having SQL
|
||||
func (b *Builder) Having(having string) *Builder {
|
||||
b.having = having
|
||||
return b
|
||||
}
|
||||
|
|
9
vendor/github.com/go-xorm/builder/cond.go
generated
vendored
9
vendor/github.com/go-xorm/builder/cond.go
generated
vendored
|
@ -5,7 +5,6 @@
|
|||
package builder
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
)
|
||||
|
||||
|
@ -19,15 +18,15 @@ var _ Writer = NewWriter()
|
|||
|
||||
// BytesWriter implments Writer and save SQL in bytes.Buffer
|
||||
type BytesWriter struct {
|
||||
writer *bytes.Buffer
|
||||
buffer []byte
|
||||
writer *StringBuilder
|
||||
args []interface{}
|
||||
}
|
||||
|
||||
// NewWriter creates a new string writer
|
||||
func NewWriter() *BytesWriter {
|
||||
w := &BytesWriter{}
|
||||
w.writer = bytes.NewBuffer(w.buffer)
|
||||
w := &BytesWriter{
|
||||
writer: &StringBuilder{},
|
||||
}
|
||||
return w
|
||||
}
|
||||
|
||||
|
|
8
vendor/github.com/go-xorm/builder/cond_compare.go
generated
vendored
8
vendor/github.com/go-xorm/builder/cond_compare.go
generated
vendored
|
@ -10,7 +10,13 @@ import "fmt"
|
|||
func WriteMap(w Writer, data map[string]interface{}, op string) error {
|
||||
var args = make([]interface{}, 0, len(data))
|
||||
var i = 0
|
||||
for k, v := range data {
|
||||
keys := make([]string, 0, len(data))
|
||||
for k := range data {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
|
||||
for _, k := range keys {
|
||||
v := data[k]
|
||||
switch v.(type) {
|
||||
case expr:
|
||||
if _, err := fmt.Fprintf(w, "%s%s(", k, op); err != nil {
|
||||
|
|
20
vendor/github.com/go-xorm/builder/cond_eq.go
generated
vendored
20
vendor/github.com/go-xorm/builder/cond_eq.go
generated
vendored
|
@ -4,7 +4,10 @@
|
|||
|
||||
package builder
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// Incr implements a type used by Eq
|
||||
type Incr int
|
||||
|
@ -19,7 +22,8 @@ var _ Cond = Eq{}
|
|||
|
||||
func (eq Eq) opWriteTo(op string, w Writer) error {
|
||||
var i = 0
|
||||
for k, v := range eq {
|
||||
for _, k := range eq.sortedKeys() {
|
||||
v := eq[k]
|
||||
switch v.(type) {
|
||||
case []int, []int64, []string, []int32, []int16, []int8, []uint, []uint64, []uint32, []uint16, []interface{}:
|
||||
if err := In(k, v).WriteTo(w); err != nil {
|
||||
|
@ -94,3 +98,15 @@ func (eq Eq) Or(conds ...Cond) Cond {
|
|||
func (eq Eq) IsValid() bool {
|
||||
return len(eq) > 0
|
||||
}
|
||||
|
||||
// sortedKeys returns all keys of this Eq sorted with sort.Strings.
|
||||
// It is used internally for consistent ordering when generating
|
||||
// SQL, see https://github.com/go-xorm/builder/issues/10
|
||||
func (eq Eq) sortedKeys() []string {
|
||||
keys := make([]string, 0, len(eq))
|
||||
for key := range eq {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
return keys
|
||||
}
|
||||
|
|
2
vendor/github.com/go-xorm/builder/cond_like.go
generated
vendored
2
vendor/github.com/go-xorm/builder/cond_like.go
generated
vendored
|
@ -16,7 +16,7 @@ func (like Like) WriteTo(w Writer) error {
|
|||
if _, err := fmt.Fprintf(w, "%s LIKE ?", like[0]); err != nil {
|
||||
return err
|
||||
}
|
||||
// FIXME: if use other regular express, this will be failed. but for compitable, keep this
|
||||
// FIXME: if use other regular express, this will be failed. but for compatible, keep this
|
||||
if like[1][0] == '%' || like[1][len(like[1])-1] == '%' {
|
||||
w.Append(like[1])
|
||||
} else {
|
||||
|
|
20
vendor/github.com/go-xorm/builder/cond_neq.go
generated
vendored
20
vendor/github.com/go-xorm/builder/cond_neq.go
generated
vendored
|
@ -4,7 +4,10 @@
|
|||
|
||||
package builder
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// Neq defines not equal conditions
|
||||
type Neq map[string]interface{}
|
||||
|
@ -15,7 +18,8 @@ var _ Cond = Neq{}
|
|||
func (neq Neq) WriteTo(w Writer) error {
|
||||
var args = make([]interface{}, 0, len(neq))
|
||||
var i = 0
|
||||
for k, v := range neq {
|
||||
for _, k := range neq.sortedKeys() {
|
||||
v := neq[k]
|
||||
switch v.(type) {
|
||||
case []int, []int64, []string, []int32, []int16, []int8:
|
||||
if err := NotIn(k, v).WriteTo(w); err != nil {
|
||||
|
@ -76,3 +80,15 @@ func (neq Neq) Or(conds ...Cond) Cond {
|
|||
func (neq Neq) IsValid() bool {
|
||||
return len(neq) > 0
|
||||
}
|
||||
|
||||
// sortedKeys returns all keys of this Neq sorted with sort.Strings.
|
||||
// It is used internally for consistent ordering when generating
|
||||
// SQL, see https://github.com/go-xorm/builder/issues/10
|
||||
func (neq Neq) sortedKeys() []string {
|
||||
keys := make([]string, 0, len(neq))
|
||||
for key := range neq {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
return keys
|
||||
}
|
||||
|
|
24
vendor/github.com/go-xorm/builder/cond_not.go
generated
vendored
24
vendor/github.com/go-xorm/builder/cond_not.go
generated
vendored
|
@ -21,6 +21,18 @@ func (not Not) WriteTo(w Writer) error {
|
|||
if _, err := fmt.Fprint(w, "("); err != nil {
|
||||
return err
|
||||
}
|
||||
case Eq:
|
||||
if len(not[0].(Eq)) > 1 {
|
||||
if _, err := fmt.Fprint(w, "("); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
case Neq:
|
||||
if len(not[0].(Neq)) > 1 {
|
||||
if _, err := fmt.Fprint(w, "("); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := not[0].WriteTo(w); err != nil {
|
||||
|
@ -32,6 +44,18 @@ func (not Not) WriteTo(w Writer) error {
|
|||
if _, err := fmt.Fprint(w, ")"); err != nil {
|
||||
return err
|
||||
}
|
||||
case Eq:
|
||||
if len(not[0].(Eq)) > 1 {
|
||||
if _, err := fmt.Fprint(w, ")"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
case Neq:
|
||||
if len(not[0].(Neq)) > 1 {
|
||||
if _, err := fmt.Fprint(w, ")"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
119
vendor/github.com/go-xorm/builder/strings_builder.go
generated
vendored
Normal file
119
vendor/github.com/go-xorm/builder/strings_builder.go
generated
vendored
Normal file
|
@ -0,0 +1,119 @@
|
|||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package builder
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// A StringBuilder is used to efficiently build a string using Write methods.
|
||||
// It minimizes memory copying. The zero value is ready to use.
|
||||
// Do not copy a non-zero Builder.
|
||||
type StringBuilder struct {
|
||||
addr *StringBuilder // of receiver, to detect copies by value
|
||||
buf []byte
|
||||
}
|
||||
|
||||
// noescape hides a pointer from escape analysis. noescape is
|
||||
// the identity function but escape analysis doesn't think the
|
||||
// output depends on the input. noescape is inlined and currently
|
||||
// compiles down to zero instructions.
|
||||
// USE CAREFULLY!
|
||||
// This was copied from the runtime; see issues 23382 and 7921.
|
||||
//go:nosplit
|
||||
func noescape(p unsafe.Pointer) unsafe.Pointer {
|
||||
x := uintptr(p)
|
||||
return unsafe.Pointer(x ^ 0)
|
||||
}
|
||||
|
||||
func (b *StringBuilder) copyCheck() {
|
||||
if b.addr == nil {
|
||||
// This hack works around a failing of Go's escape analysis
|
||||
// that was causing b to escape and be heap allocated.
|
||||
// See issue 23382.
|
||||
// TODO: once issue 7921 is fixed, this should be reverted to
|
||||
// just "b.addr = b".
|
||||
b.addr = (*StringBuilder)(noescape(unsafe.Pointer(b)))
|
||||
} else if b.addr != b {
|
||||
panic("strings: illegal use of non-zero Builder copied by value")
|
||||
}
|
||||
}
|
||||
|
||||
// String returns the accumulated string.
|
||||
func (b *StringBuilder) String() string {
|
||||
return *(*string)(unsafe.Pointer(&b.buf))
|
||||
}
|
||||
|
||||
// Len returns the number of accumulated bytes; b.Len() == len(b.String()).
|
||||
func (b *StringBuilder) Len() int { return len(b.buf) }
|
||||
|
||||
// Reset resets the Builder to be empty.
|
||||
func (b *StringBuilder) Reset() {
|
||||
b.addr = nil
|
||||
b.buf = nil
|
||||
}
|
||||
|
||||
// grow copies the buffer to a new, larger buffer so that there are at least n
|
||||
// bytes of capacity beyond len(b.buf).
|
||||
func (b *StringBuilder) grow(n int) {
|
||||
buf := make([]byte, len(b.buf), 2*cap(b.buf)+n)
|
||||
copy(buf, b.buf)
|
||||
b.buf = buf
|
||||
}
|
||||
|
||||
// Grow grows b's capacity, if necessary, to guarantee space for
|
||||
// another n bytes. After Grow(n), at least n bytes can be written to b
|
||||
// without another allocation. If n is negative, Grow panics.
|
||||
func (b *StringBuilder) Grow(n int) {
|
||||
b.copyCheck()
|
||||
if n < 0 {
|
||||
panic("strings.Builder.Grow: negative count")
|
||||
}
|
||||
if cap(b.buf)-len(b.buf) < n {
|
||||
b.grow(n)
|
||||
}
|
||||
}
|
||||
|
||||
// Write appends the contents of p to b's buffer.
|
||||
// Write always returns len(p), nil.
|
||||
func (b *StringBuilder) Write(p []byte) (int, error) {
|
||||
b.copyCheck()
|
||||
b.buf = append(b.buf, p...)
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
// WriteByte appends the byte c to b's buffer.
|
||||
// The returned error is always nil.
|
||||
func (b *StringBuilder) WriteByte(c byte) error {
|
||||
b.copyCheck()
|
||||
b.buf = append(b.buf, c)
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteRune appends the UTF-8 encoding of Unicode code point r to b's buffer.
|
||||
// It returns the length of r and a nil error.
|
||||
func (b *StringBuilder) WriteRune(r rune) (int, error) {
|
||||
b.copyCheck()
|
||||
if r < utf8.RuneSelf {
|
||||
b.buf = append(b.buf, byte(r))
|
||||
return 1, nil
|
||||
}
|
||||
l := len(b.buf)
|
||||
if cap(b.buf)-l < utf8.UTFMax {
|
||||
b.grow(utf8.UTFMax)
|
||||
}
|
||||
n := utf8.EncodeRune(b.buf[l:l+utf8.UTFMax], r)
|
||||
b.buf = b.buf[:l+n]
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// WriteString appends the contents of s to b's buffer.
|
||||
// It returns the length of s and a nil error.
|
||||
func (b *StringBuilder) WriteString(s string) (int, error) {
|
||||
b.copyCheck()
|
||||
b.buf = append(b.buf, s...)
|
||||
return len(s), nil
|
||||
}
|
4
vendor/github.com/go-xorm/core/column.go
generated
vendored
4
vendor/github.com/go-xorm/core/column.go
generated
vendored
|
@ -147,12 +147,12 @@ func (col *Column) ValueOfV(dataStruct *reflect.Value) (*reflect.Value, error) {
|
|||
}
|
||||
fieldValue = fieldValue.Elem().FieldByName(fieldPath[i+1])
|
||||
} else {
|
||||
return nil, fmt.Errorf("field %v is not valid", col.FieldName)
|
||||
return nil, fmt.Errorf("field %v is not valid", col.FieldName)
|
||||
}
|
||||
}
|
||||
|
||||
if !fieldValue.IsValid() {
|
||||
return nil, fmt.Errorf("field %v is not valid", col.FieldName)
|
||||
return nil, fmt.Errorf("field %v is not valid", col.FieldName)
|
||||
}
|
||||
|
||||
return &fieldValue, nil
|
||||
|
|
57
vendor/github.com/go-xorm/core/db.go
generated
vendored
57
vendor/github.com/go-xorm/core/db.go
generated
vendored
|
@ -7,6 +7,11 @@ import (
|
|||
"fmt"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
DefaultCacheSize = 200
|
||||
)
|
||||
|
||||
func MapToSlice(query string, mp interface{}) (string, []interface{}, error) {
|
||||
|
@ -58,9 +63,16 @@ func StructToSlice(query string, st interface{}) (string, []interface{}, error)
|
|||
return query, args, nil
|
||||
}
|
||||
|
||||
type cacheStruct struct {
|
||||
value reflect.Value
|
||||
idx int
|
||||
}
|
||||
|
||||
type DB struct {
|
||||
*sql.DB
|
||||
Mapper IMapper
|
||||
Mapper IMapper
|
||||
reflectCache map[reflect.Type]*cacheStruct
|
||||
reflectCacheMutex sync.RWMutex
|
||||
}
|
||||
|
||||
func Open(driverName, dataSourceName string) (*DB, error) {
|
||||
|
@ -68,11 +80,32 @@ func Open(driverName, dataSourceName string) (*DB, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &DB{db, NewCacheMapper(&SnakeMapper{})}, nil
|
||||
return &DB{
|
||||
DB: db,
|
||||
Mapper: NewCacheMapper(&SnakeMapper{}),
|
||||
reflectCache: make(map[reflect.Type]*cacheStruct),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func FromDB(db *sql.DB) *DB {
|
||||
return &DB{db, NewCacheMapper(&SnakeMapper{})}
|
||||
return &DB{
|
||||
DB: db,
|
||||
Mapper: NewCacheMapper(&SnakeMapper{}),
|
||||
reflectCache: make(map[reflect.Type]*cacheStruct),
|
||||
}
|
||||
}
|
||||
|
||||
func (db *DB) reflectNew(typ reflect.Type) reflect.Value {
|
||||
db.reflectCacheMutex.Lock()
|
||||
defer db.reflectCacheMutex.Unlock()
|
||||
cs, ok := db.reflectCache[typ]
|
||||
if !ok || cs.idx+1 > DefaultCacheSize-1 {
|
||||
cs = &cacheStruct{reflect.MakeSlice(reflect.SliceOf(typ), DefaultCacheSize, DefaultCacheSize), 0}
|
||||
db.reflectCache[typ] = cs
|
||||
} else {
|
||||
cs.idx = cs.idx + 1
|
||||
}
|
||||
return cs.value.Index(cs.idx).Addr()
|
||||
}
|
||||
|
||||
func (db *DB) Query(query string, args ...interface{}) (*Rows, error) {
|
||||
|
@ -83,7 +116,7 @@ func (db *DB) Query(query string, args ...interface{}) (*Rows, error) {
|
|||
}
|
||||
return nil, err
|
||||
}
|
||||
return &Rows{rows, db.Mapper}, nil
|
||||
return &Rows{rows, db}, nil
|
||||
}
|
||||
|
||||
func (db *DB) QueryMap(query string, mp interface{}) (*Rows, error) {
|
||||
|
@ -128,8 +161,8 @@ func (db *DB) QueryRowStruct(query string, st interface{}) *Row {
|
|||
|
||||
type Stmt struct {
|
||||
*sql.Stmt
|
||||
Mapper IMapper
|
||||
names map[string]int
|
||||
db *DB
|
||||
names map[string]int
|
||||
}
|
||||
|
||||
func (db *DB) Prepare(query string) (*Stmt, error) {
|
||||
|
@ -145,7 +178,7 @@ func (db *DB) Prepare(query string) (*Stmt, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Stmt{stmt, db.Mapper, names}, nil
|
||||
return &Stmt{stmt, db, names}, nil
|
||||
}
|
||||
|
||||
func (s *Stmt) ExecMap(mp interface{}) (sql.Result, error) {
|
||||
|
@ -179,7 +212,7 @@ func (s *Stmt) Query(args ...interface{}) (*Rows, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Rows{rows, s.Mapper}, nil
|
||||
return &Rows{rows, s.db}, nil
|
||||
}
|
||||
|
||||
func (s *Stmt) QueryMap(mp interface{}) (*Rows, error) {
|
||||
|
@ -274,7 +307,7 @@ func (EmptyScanner) Scan(src interface{}) error {
|
|||
|
||||
type Tx struct {
|
||||
*sql.Tx
|
||||
Mapper IMapper
|
||||
db *DB
|
||||
}
|
||||
|
||||
func (db *DB) Begin() (*Tx, error) {
|
||||
|
@ -282,7 +315,7 @@ func (db *DB) Begin() (*Tx, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Tx{tx, db.Mapper}, nil
|
||||
return &Tx{tx, db}, nil
|
||||
}
|
||||
|
||||
func (tx *Tx) Prepare(query string) (*Stmt, error) {
|
||||
|
@ -298,7 +331,7 @@ func (tx *Tx) Prepare(query string) (*Stmt, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Stmt{stmt, tx.Mapper, names}, nil
|
||||
return &Stmt{stmt, tx.db, names}, nil
|
||||
}
|
||||
|
||||
func (tx *Tx) Stmt(stmt *Stmt) *Stmt {
|
||||
|
@ -327,7 +360,7 @@ func (tx *Tx) Query(query string, args ...interface{}) (*Rows, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Rows{rows, tx.Mapper}, nil
|
||||
return &Rows{rows, tx.db}, nil
|
||||
}
|
||||
|
||||
func (tx *Tx) QueryMap(query string, mp interface{}) (*Rows, error) {
|
||||
|
|
7
vendor/github.com/go-xorm/core/dialect.go
generated
vendored
7
vendor/github.com/go-xorm/core/dialect.go
generated
vendored
|
@ -74,6 +74,7 @@ type Dialect interface {
|
|||
GetIndexes(tableName string) (map[string]*Index, error)
|
||||
|
||||
Filters() []Filter
|
||||
SetParams(params map[string]string)
|
||||
}
|
||||
|
||||
func OpenDialect(dialect Dialect) (*DB, error) {
|
||||
|
@ -148,7 +149,8 @@ func (db *Base) SupportDropIfExists() bool {
|
|||
}
|
||||
|
||||
func (db *Base) DropTableSql(tableName string) string {
|
||||
return fmt.Sprintf("DROP TABLE IF EXISTS `%s`", tableName)
|
||||
quote := db.dialect.Quote
|
||||
return fmt.Sprintf("DROP TABLE IF EXISTS %s", quote(tableName))
|
||||
}
|
||||
|
||||
func (db *Base) HasRecords(query string, args ...interface{}) (bool, error) {
|
||||
|
@ -289,6 +291,9 @@ func (b *Base) LogSQL(sql string, args []interface{}) {
|
|||
}
|
||||
}
|
||||
|
||||
func (b *Base) SetParams(params map[string]string) {
|
||||
}
|
||||
|
||||
var (
|
||||
dialects = map[string]func() Dialect{}
|
||||
)
|
||||
|
|
6
vendor/github.com/go-xorm/core/filter.go
generated
vendored
6
vendor/github.com/go-xorm/core/filter.go
generated
vendored
|
@ -37,9 +37,9 @@ func (q *Quoter) Quote(content string) string {
|
|||
func (i *IdFilter) Do(sql string, dialect Dialect, table *Table) string {
|
||||
quoter := NewQuoter(dialect)
|
||||
if table != nil && len(table.PrimaryKeys) == 1 {
|
||||
sql = strings.Replace(sql, "`(id)`", quoter.Quote(table.PrimaryKeys[0]), -1)
|
||||
sql = strings.Replace(sql, quoter.Quote("(id)"), quoter.Quote(table.PrimaryKeys[0]), -1)
|
||||
return strings.Replace(sql, "(id)", quoter.Quote(table.PrimaryKeys[0]), -1)
|
||||
sql = strings.Replace(sql, " `(id)` ", " "+quoter.Quote(table.PrimaryKeys[0])+" ", -1)
|
||||
sql = strings.Replace(sql, " "+quoter.Quote("(id)")+" ", " "+quoter.Quote(table.PrimaryKeys[0])+" ", -1)
|
||||
return strings.Replace(sql, " (id) ", " "+quoter.Quote(table.PrimaryKeys[0])+" ", -1)
|
||||
}
|
||||
return sql
|
||||
}
|
||||
|
|
2
vendor/github.com/go-xorm/core/index.go
generated
vendored
2
vendor/github.com/go-xorm/core/index.go
generated
vendored
|
@ -22,6 +22,8 @@ type Index struct {
|
|||
func (index *Index) XName(tableName string) string {
|
||||
if !strings.HasPrefix(index.Name, "UQE_") &&
|
||||
!strings.HasPrefix(index.Name, "IDX_") {
|
||||
tableName = strings.Replace(tableName, `"`, "", -1)
|
||||
tableName = strings.Replace(tableName, `.`, "_", -1)
|
||||
if index.Type == UniqueType {
|
||||
return fmt.Sprintf("UQE_%v_%v", tableName, index.Name)
|
||||
}
|
||||
|
|
64
vendor/github.com/go-xorm/core/rows.go
generated
vendored
64
vendor/github.com/go-xorm/core/rows.go
generated
vendored
|
@ -9,7 +9,7 @@ import (
|
|||
|
||||
type Rows struct {
|
||||
*sql.Rows
|
||||
Mapper IMapper
|
||||
db *DB
|
||||
}
|
||||
|
||||
func (rs *Rows) ToMapString() ([]map[string]string, error) {
|
||||
|
@ -105,7 +105,7 @@ func (rs *Rows) ScanStructByName(dest interface{}) error {
|
|||
newDest := make([]interface{}, len(cols))
|
||||
var v EmptyScanner
|
||||
for j, name := range cols {
|
||||
f := fieldByName(vv.Elem(), rs.Mapper.Table2Obj(name))
|
||||
f := fieldByName(vv.Elem(), rs.db.Mapper.Table2Obj(name))
|
||||
if f.IsValid() {
|
||||
newDest[j] = f.Addr().Interface()
|
||||
} else {
|
||||
|
@ -116,36 +116,6 @@ func (rs *Rows) ScanStructByName(dest interface{}) error {
|
|||
return rs.Rows.Scan(newDest...)
|
||||
}
|
||||
|
||||
type cacheStruct struct {
|
||||
value reflect.Value
|
||||
idx int
|
||||
}
|
||||
|
||||
var (
|
||||
reflectCache = make(map[reflect.Type]*cacheStruct)
|
||||
reflectCacheMutex sync.RWMutex
|
||||
)
|
||||
|
||||
func ReflectNew(typ reflect.Type) reflect.Value {
|
||||
reflectCacheMutex.RLock()
|
||||
cs, ok := reflectCache[typ]
|
||||
reflectCacheMutex.RUnlock()
|
||||
|
||||
const newSize = 200
|
||||
|
||||
if !ok || cs.idx+1 > newSize-1 {
|
||||
cs = &cacheStruct{reflect.MakeSlice(reflect.SliceOf(typ), newSize, newSize), 0}
|
||||
reflectCacheMutex.Lock()
|
||||
reflectCache[typ] = cs
|
||||
reflectCacheMutex.Unlock()
|
||||
} else {
|
||||
reflectCacheMutex.Lock()
|
||||
cs.idx = cs.idx + 1
|
||||
reflectCacheMutex.Unlock()
|
||||
}
|
||||
return cs.value.Index(cs.idx).Addr()
|
||||
}
|
||||
|
||||
// scan data to a slice's pointer, slice's length should equal to columns' number
|
||||
func (rs *Rows) ScanSlice(dest interface{}) error {
|
||||
vv := reflect.ValueOf(dest)
|
||||
|
@ -197,9 +167,7 @@ func (rs *Rows) ScanMap(dest interface{}) error {
|
|||
vvv := vv.Elem()
|
||||
|
||||
for i, _ := range cols {
|
||||
newDest[i] = ReflectNew(vvv.Type().Elem()).Interface()
|
||||
//v := reflect.New(vvv.Type().Elem())
|
||||
//newDest[i] = v.Interface()
|
||||
newDest[i] = rs.db.reflectNew(vvv.Type().Elem()).Interface()
|
||||
}
|
||||
|
||||
err = rs.Rows.Scan(newDest...)
|
||||
|
@ -215,32 +183,6 @@ func (rs *Rows) ScanMap(dest interface{}) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
/*func (rs *Rows) ScanMap(dest interface{}) error {
|
||||
vv := reflect.ValueOf(dest)
|
||||
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
|
||||
return errors.New("dest should be a map's pointer")
|
||||
}
|
||||
|
||||
cols, err := rs.Columns()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
newDest := make([]interface{}, len(cols))
|
||||
err = rs.ScanSlice(newDest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
vvv := vv.Elem()
|
||||
|
||||
for i, name := range cols {
|
||||
vname := reflect.ValueOf(name)
|
||||
vvv.SetMapIndex(vname, reflect.ValueOf(newDest[i]).Elem())
|
||||
}
|
||||
|
||||
return nil
|
||||
}*/
|
||||
type Row struct {
|
||||
rows *Rows
|
||||
// One of these two will be non-nil:
|
||||
|
|
2
vendor/github.com/go-xorm/core/table.go
generated
vendored
2
vendor/github.com/go-xorm/core/table.go
generated
vendored
|
@ -49,7 +49,6 @@ func NewTable(name string, t reflect.Type) *Table {
|
|||
}
|
||||
|
||||
func (table *Table) columnsByName(name string) []*Column {
|
||||
|
||||
n := len(name)
|
||||
|
||||
for k := range table.columnsMap {
|
||||
|
@ -75,7 +74,6 @@ func (table *Table) GetColumn(name string) *Column {
|
|||
}
|
||||
|
||||
func (table *Table) GetColumnIdx(name string, idx int) *Column {
|
||||
|
||||
cols := table.columnsByName(name)
|
||||
|
||||
if cols != nil && idx < len(cols) {
|
||||
|
|
38
vendor/github.com/go-xorm/core/type.go
generated
vendored
38
vendor/github.com/go-xorm/core/type.go
generated
vendored
|
@ -69,15 +69,18 @@ var (
|
|||
Enum = "ENUM"
|
||||
Set = "SET"
|
||||
|
||||
Char = "CHAR"
|
||||
Varchar = "VARCHAR"
|
||||
NVarchar = "NVARCHAR"
|
||||
TinyText = "TINYTEXT"
|
||||
Text = "TEXT"
|
||||
Clob = "CLOB"
|
||||
MediumText = "MEDIUMTEXT"
|
||||
LongText = "LONGTEXT"
|
||||
Uuid = "UUID"
|
||||
Char = "CHAR"
|
||||
Varchar = "VARCHAR"
|
||||
NVarchar = "NVARCHAR"
|
||||
TinyText = "TINYTEXT"
|
||||
Text = "TEXT"
|
||||
NText = "NTEXT"
|
||||
Clob = "CLOB"
|
||||
MediumText = "MEDIUMTEXT"
|
||||
LongText = "LONGTEXT"
|
||||
Uuid = "UUID"
|
||||
UniqueIdentifier = "UNIQUEIDENTIFIER"
|
||||
SysName = "SYSNAME"
|
||||
|
||||
Date = "DATE"
|
||||
DateTime = "DATETIME"
|
||||
|
@ -128,10 +131,12 @@ var (
|
|||
NVarchar: TEXT_TYPE,
|
||||
TinyText: TEXT_TYPE,
|
||||
Text: TEXT_TYPE,
|
||||
NText: TEXT_TYPE,
|
||||
MediumText: TEXT_TYPE,
|
||||
LongText: TEXT_TYPE,
|
||||
Uuid: TEXT_TYPE,
|
||||
Clob: TEXT_TYPE,
|
||||
SysName: TEXT_TYPE,
|
||||
|
||||
Date: TIME_TYPE,
|
||||
DateTime: TIME_TYPE,
|
||||
|
@ -148,11 +153,12 @@ var (
|
|||
Binary: BLOB_TYPE,
|
||||
VarBinary: BLOB_TYPE,
|
||||
|
||||
TinyBlob: BLOB_TYPE,
|
||||
Blob: BLOB_TYPE,
|
||||
MediumBlob: BLOB_TYPE,
|
||||
LongBlob: BLOB_TYPE,
|
||||
Bytea: BLOB_TYPE,
|
||||
TinyBlob: BLOB_TYPE,
|
||||
Blob: BLOB_TYPE,
|
||||
MediumBlob: BLOB_TYPE,
|
||||
LongBlob: BLOB_TYPE,
|
||||
Bytea: BLOB_TYPE,
|
||||
UniqueIdentifier: BLOB_TYPE,
|
||||
|
||||
Bool: NUMERIC_TYPE,
|
||||
|
||||
|
@ -289,9 +295,9 @@ func SQLType2Type(st SQLType) reflect.Type {
|
|||
return reflect.TypeOf(float32(1))
|
||||
case Double:
|
||||
return reflect.TypeOf(float64(1))
|
||||
case Char, Varchar, NVarchar, TinyText, Text, MediumText, LongText, Enum, Set, Uuid, Clob:
|
||||
case Char, Varchar, NVarchar, TinyText, Text, NText, MediumText, LongText, Enum, Set, Uuid, Clob, SysName:
|
||||
return reflect.TypeOf("")
|
||||
case TinyBlob, Blob, LongBlob, Bytea, Binary, MediumBlob, VarBinary:
|
||||
case TinyBlob, Blob, LongBlob, Bytea, Binary, MediumBlob, VarBinary, UniqueIdentifier:
|
||||
return reflect.TypeOf([]byte{})
|
||||
case Bool:
|
||||
return reflect.TypeOf(true)
|
||||
|
|
74
vendor/github.com/go-xorm/xorm/dialect_mysql.go
generated
vendored
74
vendor/github.com/go-xorm/xorm/dialect_mysql.go
generated
vendored
|
@ -172,12 +172,33 @@ type mysql struct {
|
|||
allowAllFiles bool
|
||||
allowOldPasswords bool
|
||||
clientFoundRows bool
|
||||
rowFormat string
|
||||
}
|
||||
|
||||
func (db *mysql) Init(d *core.DB, uri *core.Uri, drivername, dataSourceName string) error {
|
||||
return db.Base.Init(d, db, uri, drivername, dataSourceName)
|
||||
}
|
||||
|
||||
func (db *mysql) SetParams(params map[string]string) {
|
||||
rowFormat, ok := params["rowFormat"]
|
||||
if ok {
|
||||
var t = strings.ToUpper(rowFormat)
|
||||
switch t {
|
||||
case "COMPACT":
|
||||
fallthrough
|
||||
case "REDUNDANT":
|
||||
fallthrough
|
||||
case "DYNAMIC":
|
||||
fallthrough
|
||||
case "COMPRESSED":
|
||||
db.rowFormat = t
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (db *mysql) SqlType(c *core.Column) string {
|
||||
var res string
|
||||
switch t := c.SQLType.Name; t {
|
||||
|
@ -487,6 +508,59 @@ func (db *mysql) GetIndexes(tableName string) (map[string]*core.Index, error) {
|
|||
return indexes, nil
|
||||
}
|
||||
|
||||
func (db *mysql) CreateTableSql(table *core.Table, tableName, storeEngine, charset string) string {
|
||||
var sql string
|
||||
sql = "CREATE TABLE IF NOT EXISTS "
|
||||
if tableName == "" {
|
||||
tableName = table.Name
|
||||
}
|
||||
|
||||
sql += db.Quote(tableName)
|
||||
sql += " ("
|
||||
|
||||
if len(table.ColumnsSeq()) > 0 {
|
||||
pkList := table.PrimaryKeys
|
||||
|
||||
for _, colName := range table.ColumnsSeq() {
|
||||
col := table.GetColumn(colName)
|
||||
if col.IsPrimaryKey && len(pkList) == 1 {
|
||||
sql += col.String(db)
|
||||
} else {
|
||||
sql += col.StringNoPk(db)
|
||||
}
|
||||
sql = strings.TrimSpace(sql)
|
||||
if len(col.Comment) > 0 {
|
||||
sql += " COMMENT '" + col.Comment + "'"
|
||||
}
|
||||
sql += ", "
|
||||
}
|
||||
|
||||
if len(pkList) > 1 {
|
||||
sql += "PRIMARY KEY ( "
|
||||
sql += db.Quote(strings.Join(pkList, db.Quote(",")))
|
||||
sql += " ), "
|
||||
}
|
||||
|
||||
sql = sql[:len(sql)-2]
|
||||
}
|
||||
sql += ")"
|
||||
|
||||
if storeEngine != "" {
|
||||
sql += " ENGINE=" + storeEngine
|
||||
}
|
||||
|
||||
if len(charset) == 0 {
|
||||
charset = db.URI().Charset
|
||||
} else if len(charset) > 0 {
|
||||
sql += " DEFAULT CHARSET " + charset
|
||||
}
|
||||
|
||||
if db.rowFormat != "" {
|
||||
sql += " ROW_FORMAT=" + db.rowFormat
|
||||
}
|
||||
return sql
|
||||
}
|
||||
|
||||
func (db *mysql) Filters() []core.Filter {
|
||||
return []core.Filter{&core.IdFilter{}}
|
||||
}
|
||||
|
|
105
vendor/github.com/go-xorm/xorm/dialect_postgres.go
generated
vendored
105
vendor/github.com/go-xorm/xorm/dialect_postgres.go
generated
vendored
|
@ -769,14 +769,21 @@ var (
|
|||
DefaultPostgresSchema = "public"
|
||||
)
|
||||
|
||||
const postgresPublicSchema = "public"
|
||||
|
||||
type postgres struct {
|
||||
core.Base
|
||||
schema string
|
||||
}
|
||||
|
||||
func (db *postgres) Init(d *core.DB, uri *core.Uri, drivername, dataSourceName string) error {
|
||||
db.schema = DefaultPostgresSchema
|
||||
return db.Base.Init(d, db, uri, drivername, dataSourceName)
|
||||
err := db.Base.Init(d, db, uri, drivername, dataSourceName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if db.Schema == "" {
|
||||
db.Schema = DefaultPostgresSchema
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *postgres) SqlType(c *core.Column) string {
|
||||
|
@ -873,32 +880,42 @@ func (db *postgres) IndexOnTable() bool {
|
|||
}
|
||||
|
||||
func (db *postgres) IndexCheckSql(tableName, idxName string) (string, []interface{}) {
|
||||
args := []interface{}{tableName, idxName}
|
||||
if len(db.Schema) == 0 {
|
||||
args := []interface{}{tableName, idxName}
|
||||
return `SELECT indexname FROM pg_indexes WHERE tablename = ? AND indexname = ?`, args
|
||||
}
|
||||
|
||||
args := []interface{}{db.Schema, tableName, idxName}
|
||||
return `SELECT indexname FROM pg_indexes ` +
|
||||
`WHERE tablename = ? AND indexname = ?`, args
|
||||
`WHERE schemaname = ? AND tablename = ? AND indexname = ?`, args
|
||||
}
|
||||
|
||||
func (db *postgres) TableCheckSql(tableName string) (string, []interface{}) {
|
||||
args := []interface{}{tableName}
|
||||
return `SELECT tablename FROM pg_tables WHERE tablename = ?`, args
|
||||
if len(db.Schema) == 0 {
|
||||
args := []interface{}{tableName}
|
||||
return `SELECT tablename FROM pg_tables WHERE tablename = ?`, args
|
||||
}
|
||||
|
||||
args := []interface{}{db.Schema, tableName}
|
||||
return `SELECT tablename FROM pg_tables WHERE schemaname = ? AND tablename = ?`, args
|
||||
}
|
||||
|
||||
/*func (db *postgres) ColumnCheckSql(tableName, colName string) (string, []interface{}) {
|
||||
args := []interface{}{tableName, colName}
|
||||
return "SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = ?" +
|
||||
" AND column_name = ?", args
|
||||
}*/
|
||||
|
||||
func (db *postgres) ModifyColumnSql(tableName string, col *core.Column) string {
|
||||
return fmt.Sprintf("alter table %s ALTER COLUMN %s TYPE %s",
|
||||
tableName, col.Name, db.SqlType(col))
|
||||
if len(db.Schema) == 0 {
|
||||
return fmt.Sprintf("alter table %s ALTER COLUMN %s TYPE %s",
|
||||
tableName, col.Name, db.SqlType(col))
|
||||
}
|
||||
return fmt.Sprintf("alter table %s.%s ALTER COLUMN %s TYPE %s",
|
||||
db.Schema, tableName, col.Name, db.SqlType(col))
|
||||
}
|
||||
|
||||
func (db *postgres) DropIndexSql(tableName string, index *core.Index) string {
|
||||
//var unique string
|
||||
quote := db.Quote
|
||||
idxName := index.Name
|
||||
|
||||
tableName = strings.Replace(tableName, `"`, "", -1)
|
||||
tableName = strings.Replace(tableName, `.`, "_", -1)
|
||||
|
||||
if !strings.HasPrefix(idxName, "UQE_") &&
|
||||
!strings.HasPrefix(idxName, "IDX_") {
|
||||
if index.Type == core.UniqueType {
|
||||
|
@ -907,13 +924,21 @@ func (db *postgres) DropIndexSql(tableName string, index *core.Index) string {
|
|||
idxName = fmt.Sprintf("IDX_%v_%v", tableName, index.Name)
|
||||
}
|
||||
}
|
||||
if db.Uri.Schema != "" {
|
||||
idxName = db.Uri.Schema + "." + idxName
|
||||
}
|
||||
return fmt.Sprintf("DROP INDEX %v", quote(idxName))
|
||||
}
|
||||
|
||||
func (db *postgres) IsColumnExist(tableName, colName string) (bool, error) {
|
||||
args := []interface{}{tableName, colName}
|
||||
query := "SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = $1" +
|
||||
" AND column_name = $2"
|
||||
args := []interface{}{db.Schema, tableName, colName}
|
||||
query := "SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = $1 AND table_name = $2" +
|
||||
" AND column_name = $3"
|
||||
if len(db.Schema) == 0 {
|
||||
args = []interface{}{tableName, colName}
|
||||
query = "SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = $1" +
|
||||
" AND column_name = $2"
|
||||
}
|
||||
db.LogSQL(query, args)
|
||||
|
||||
rows, err := db.DB().Query(query, args...)
|
||||
|
@ -926,8 +951,7 @@ func (db *postgres) IsColumnExist(tableName, colName string) (bool, error) {
|
|||
}
|
||||
|
||||
func (db *postgres) GetColumns(tableName string) ([]string, map[string]*core.Column, error) {
|
||||
// FIXME: the schema should be replaced by user custom's
|
||||
args := []interface{}{tableName, db.schema}
|
||||
args := []interface{}{tableName}
|
||||
s := `SELECT column_name, column_default, is_nullable, data_type, character_maximum_length, numeric_precision, numeric_precision_radix ,
|
||||
CASE WHEN p.contype = 'p' THEN true ELSE false END AS primarykey,
|
||||
CASE WHEN p.contype = 'u' THEN true ELSE false END AS uniquekey
|
||||
|
@ -938,7 +962,15 @@ FROM pg_attribute f
|
|||
LEFT JOIN pg_constraint p ON p.conrelid = c.oid AND f.attnum = ANY (p.conkey)
|
||||
LEFT JOIN pg_class AS g ON p.confrelid = g.oid
|
||||
LEFT JOIN INFORMATION_SCHEMA.COLUMNS s ON s.column_name=f.attname AND c.relname=s.table_name
|
||||
WHERE c.relkind = 'r'::char AND c.relname = $1 AND s.table_schema = $2 AND f.attnum > 0 ORDER BY f.attnum;`
|
||||
WHERE c.relkind = 'r'::char AND c.relname = $1%s AND f.attnum > 0 ORDER BY f.attnum;`
|
||||
|
||||
var f string
|
||||
if len(db.Schema) != 0 {
|
||||
args = append(args, db.Schema)
|
||||
f = " AND s.table_schema = $2"
|
||||
}
|
||||
s = fmt.Sprintf(s, f)
|
||||
|
||||
db.LogSQL(s, args)
|
||||
|
||||
rows, err := db.DB().Query(s, args...)
|
||||
|
@ -1028,8 +1060,13 @@ WHERE c.relkind = 'r'::char AND c.relname = $1 AND s.table_schema = $2 AND f.att
|
|||
}
|
||||
|
||||
func (db *postgres) GetTables() ([]*core.Table, error) {
|
||||
args := []interface{}{db.schema}
|
||||
s := fmt.Sprintf("SELECT tablename FROM pg_tables WHERE schemaname = $1")
|
||||
args := []interface{}{}
|
||||
s := "SELECT tablename FROM pg_tables"
|
||||
if len(db.Schema) != 0 {
|
||||
args = append(args, db.Schema)
|
||||
s = s + " WHERE schemaname = $1"
|
||||
}
|
||||
|
||||
db.LogSQL(s, args)
|
||||
|
||||
rows, err := db.DB().Query(s, args...)
|
||||
|
@ -1053,8 +1090,12 @@ func (db *postgres) GetTables() ([]*core.Table, error) {
|
|||
}
|
||||
|
||||
func (db *postgres) GetIndexes(tableName string) (map[string]*core.Index, error) {
|
||||
args := []interface{}{db.schema, tableName}
|
||||
s := fmt.Sprintf("SELECT indexname, indexdef FROM pg_indexes WHERE schemaname=$1 AND tablename=$2")
|
||||
args := []interface{}{tableName}
|
||||
s := fmt.Sprintf("SELECT indexname, indexdef FROM pg_indexes WHERE tablename=$1")
|
||||
if len(db.Schema) != 0 {
|
||||
args = append(args, db.Schema)
|
||||
s = s + " AND schemaname=$2"
|
||||
}
|
||||
db.LogSQL(s, args)
|
||||
|
||||
rows, err := db.DB().Query(s, args...)
|
||||
|
@ -1182,3 +1223,15 @@ func (p *pqDriver) Parse(driverName, dataSourceName string) (*core.Uri, error) {
|
|||
|
||||
return db, nil
|
||||
}
|
||||
|
||||
type pqDriverPgx struct {
|
||||
pqDriver
|
||||
}
|
||||
|
||||
func (pgx *pqDriverPgx) Parse(driverName, dataSourceName string) (*core.Uri, error) {
|
||||
// Remove the leading characters for driver to work
|
||||
if len(dataSourceName) >= 9 && dataSourceName[0] == 0 {
|
||||
dataSourceName = dataSourceName[9:]
|
||||
}
|
||||
return pgx.pqDriver.Parse(driverName, dataSourceName)
|
||||
}
|
||||
|
|
192
vendor/github.com/go-xorm/xorm/engine.go
generated
vendored
192
vendor/github.com/go-xorm/xorm/engine.go
generated
vendored
|
@ -49,6 +49,35 @@ type Engine struct {
|
|||
tagHandlers map[string]tagHandler
|
||||
|
||||
engineGroup *EngineGroup
|
||||
|
||||
cachers map[string]core.Cacher
|
||||
cacherLock sync.RWMutex
|
||||
}
|
||||
|
||||
func (engine *Engine) setCacher(tableName string, cacher core.Cacher) {
|
||||
engine.cacherLock.Lock()
|
||||
engine.cachers[tableName] = cacher
|
||||
engine.cacherLock.Unlock()
|
||||
}
|
||||
|
||||
func (engine *Engine) SetCacher(tableName string, cacher core.Cacher) {
|
||||
engine.setCacher(tableName, cacher)
|
||||
}
|
||||
|
||||
func (engine *Engine) getCacher(tableName string) core.Cacher {
|
||||
var cacher core.Cacher
|
||||
var ok bool
|
||||
engine.cacherLock.RLock()
|
||||
cacher, ok = engine.cachers[tableName]
|
||||
engine.cacherLock.RUnlock()
|
||||
if !ok && !engine.disableGlobalCache {
|
||||
cacher = engine.Cacher
|
||||
}
|
||||
return cacher
|
||||
}
|
||||
|
||||
func (engine *Engine) GetCacher(tableName string) core.Cacher {
|
||||
return engine.getCacher(tableName)
|
||||
}
|
||||
|
||||
// BufferSize sets buffer size for iterate
|
||||
|
@ -165,7 +194,7 @@ func (engine *Engine) Quote(value string) string {
|
|||
}
|
||||
|
||||
// QuoteTo quotes string and writes into the buffer
|
||||
func (engine *Engine) QuoteTo(buf *bytes.Buffer, value string) {
|
||||
func (engine *Engine) QuoteTo(buf *builder.StringBuilder, value string) {
|
||||
if buf == nil {
|
||||
return
|
||||
}
|
||||
|
@ -245,13 +274,7 @@ func (engine *Engine) NoCascade() *Session {
|
|||
|
||||
// MapCacher Set a table use a special cacher
|
||||
func (engine *Engine) MapCacher(bean interface{}, cacher core.Cacher) error {
|
||||
v := rValue(bean)
|
||||
tb, err := engine.autoMapType(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tb.Cacher = cacher
|
||||
engine.setCacher(engine.TableName(bean, true), cacher)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -536,33 +559,6 @@ func (engine *Engine) dumpTables(tables []*core.Table, w io.Writer, tp ...core.D
|
|||
return nil
|
||||
}
|
||||
|
||||
func (engine *Engine) tableName(beanOrTableName interface{}) (string, error) {
|
||||
v := rValue(beanOrTableName)
|
||||
if v.Type().Kind() == reflect.String {
|
||||
return beanOrTableName.(string), nil
|
||||
} else if v.Type().Kind() == reflect.Struct {
|
||||
return engine.tbName(v), nil
|
||||
}
|
||||
return "", errors.New("bean should be a struct or struct's point")
|
||||
}
|
||||
|
||||
func (engine *Engine) tbName(v reflect.Value) string {
|
||||
if tb, ok := v.Interface().(TableName); ok {
|
||||
return tb.TableName()
|
||||
}
|
||||
|
||||
if v.Type().Kind() == reflect.Ptr {
|
||||
if tb, ok := reflect.Indirect(v).Interface().(TableName); ok {
|
||||
return tb.TableName()
|
||||
}
|
||||
} else if v.CanAddr() {
|
||||
if tb, ok := v.Addr().Interface().(TableName); ok {
|
||||
return tb.TableName()
|
||||
}
|
||||
}
|
||||
return engine.TableMapper.Obj2Table(reflect.Indirect(v).Type().Name())
|
||||
}
|
||||
|
||||
// Cascade use cascade or not
|
||||
func (engine *Engine) Cascade(trueOrFalse ...bool) *Session {
|
||||
session := engine.NewSession()
|
||||
|
@ -846,7 +842,7 @@ func (engine *Engine) TableInfo(bean interface{}) *Table {
|
|||
if err != nil {
|
||||
engine.logger.Error(err)
|
||||
}
|
||||
return &Table{tb, engine.tbName(v)}
|
||||
return &Table{tb, engine.TableName(bean)}
|
||||
}
|
||||
|
||||
func addIndex(indexName string, table *core.Table, col *core.Column, indexType int) {
|
||||
|
@ -861,15 +857,6 @@ func addIndex(indexName string, table *core.Table, col *core.Column, indexType i
|
|||
}
|
||||
}
|
||||
|
||||
func (engine *Engine) newTable() *core.Table {
|
||||
table := core.NewEmptyTable()
|
||||
|
||||
if !engine.disableGlobalCache {
|
||||
table.Cacher = engine.Cacher
|
||||
}
|
||||
return table
|
||||
}
|
||||
|
||||
// TableName table name interface to define customerize table name
|
||||
type TableName interface {
|
||||
TableName() string
|
||||
|
@ -881,21 +868,9 @@ var (
|
|||
|
||||
func (engine *Engine) mapType(v reflect.Value) (*core.Table, error) {
|
||||
t := v.Type()
|
||||
table := engine.newTable()
|
||||
if tb, ok := v.Interface().(TableName); ok {
|
||||
table.Name = tb.TableName()
|
||||
} else {
|
||||
if v.CanAddr() {
|
||||
if tb, ok = v.Addr().Interface().(TableName); ok {
|
||||
table.Name = tb.TableName()
|
||||
}
|
||||
}
|
||||
if table.Name == "" {
|
||||
table.Name = engine.TableMapper.Obj2Table(t.Name())
|
||||
}
|
||||
}
|
||||
|
||||
table := core.NewEmptyTable()
|
||||
table.Type = t
|
||||
table.Name = engine.tbNameForMap(v)
|
||||
|
||||
var idFieldColName string
|
||||
var hasCacheTag, hasNoCacheTag bool
|
||||
|
@ -1049,15 +1024,15 @@ func (engine *Engine) mapType(v reflect.Value) (*core.Table, error) {
|
|||
if hasCacheTag {
|
||||
if engine.Cacher != nil { // !nash! use engine's cacher if provided
|
||||
engine.logger.Info("enable cache on table:", table.Name)
|
||||
table.Cacher = engine.Cacher
|
||||
engine.setCacher(table.Name, engine.Cacher)
|
||||
} else {
|
||||
engine.logger.Info("enable LRU cache on table:", table.Name)
|
||||
table.Cacher = NewLRUCacher2(NewMemoryStore(), time.Hour, 10000) // !nashtsai! HACK use LRU cacher for now
|
||||
engine.setCacher(table.Name, NewLRUCacher2(NewMemoryStore(), time.Hour, 10000))
|
||||
}
|
||||
}
|
||||
if hasNoCacheTag {
|
||||
engine.logger.Info("no cache on table:", table.Name)
|
||||
table.Cacher = nil
|
||||
engine.logger.Info("disable cache on table:", table.Name)
|
||||
engine.setCacher(table.Name, nil)
|
||||
}
|
||||
|
||||
return table, nil
|
||||
|
@ -1116,7 +1091,25 @@ func (engine *Engine) idOfV(rv reflect.Value) (core.PK, error) {
|
|||
pk := make([]interface{}, len(table.PrimaryKeys))
|
||||
for i, col := range table.PKColumns() {
|
||||
var err error
|
||||
pkField := v.FieldByName(col.FieldName)
|
||||
|
||||
fieldName := col.FieldName
|
||||
for {
|
||||
parts := strings.SplitN(fieldName, ".", 2)
|
||||
if len(parts) == 1 {
|
||||
break
|
||||
}
|
||||
|
||||
v = v.FieldByName(parts[0])
|
||||
if v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
if v.Kind() != reflect.Struct {
|
||||
return nil, ErrUnSupportedType
|
||||
}
|
||||
fieldName = parts[1]
|
||||
}
|
||||
|
||||
pkField := v.FieldByName(fieldName)
|
||||
switch pkField.Kind() {
|
||||
case reflect.String:
|
||||
pk[i], err = engine.idTypeAssertion(col, pkField.String())
|
||||
|
@ -1162,26 +1155,10 @@ func (engine *Engine) CreateUniques(bean interface{}) error {
|
|||
return session.CreateUniques(bean)
|
||||
}
|
||||
|
||||
func (engine *Engine) getCacher2(table *core.Table) core.Cacher {
|
||||
return table.Cacher
|
||||
}
|
||||
|
||||
// ClearCacheBean if enabled cache, clear the cache bean
|
||||
func (engine *Engine) ClearCacheBean(bean interface{}, id string) error {
|
||||
v := rValue(bean)
|
||||
t := v.Type()
|
||||
if t.Kind() != reflect.Struct {
|
||||
return errors.New("error params")
|
||||
}
|
||||
tableName := engine.tbName(v)
|
||||
table, err := engine.autoMapType(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cacher := table.Cacher
|
||||
if cacher == nil {
|
||||
cacher = engine.Cacher
|
||||
}
|
||||
tableName := engine.TableName(bean)
|
||||
cacher := engine.getCacher(tableName)
|
||||
if cacher != nil {
|
||||
cacher.ClearIds(tableName)
|
||||
cacher.DelBean(tableName, id)
|
||||
|
@ -1192,21 +1169,8 @@ func (engine *Engine) ClearCacheBean(bean interface{}, id string) error {
|
|||
// ClearCache if enabled cache, clear some tables' cache
|
||||
func (engine *Engine) ClearCache(beans ...interface{}) error {
|
||||
for _, bean := range beans {
|
||||
v := rValue(bean)
|
||||
t := v.Type()
|
||||
if t.Kind() != reflect.Struct {
|
||||
return errors.New("error params")
|
||||
}
|
||||
tableName := engine.tbName(v)
|
||||
table, err := engine.autoMapType(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cacher := table.Cacher
|
||||
if cacher == nil {
|
||||
cacher = engine.Cacher
|
||||
}
|
||||
tableName := engine.TableName(bean)
|
||||
cacher := engine.getCacher(tableName)
|
||||
if cacher != nil {
|
||||
cacher.ClearIds(tableName)
|
||||
cacher.ClearBeans(tableName)
|
||||
|
@ -1224,13 +1188,13 @@ func (engine *Engine) Sync(beans ...interface{}) error {
|
|||
|
||||
for _, bean := range beans {
|
||||
v := rValue(bean)
|
||||
tableName := engine.tbName(v)
|
||||
tableNameNoSchema := engine.TableName(bean)
|
||||
table, err := engine.autoMapType(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
isExist, err := session.Table(bean).isTableExist(tableName)
|
||||
isExist, err := session.Table(bean).isTableExist(tableNameNoSchema)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1256,12 +1220,12 @@ func (engine *Engine) Sync(beans ...interface{}) error {
|
|||
}
|
||||
} else {
|
||||
for _, col := range table.Columns() {
|
||||
isExist, err := engine.dialect.IsColumnExist(tableName, col.Name)
|
||||
isExist, err := engine.dialect.IsColumnExist(tableNameNoSchema, col.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !isExist {
|
||||
if err := session.statement.setRefValue(v); err != nil {
|
||||
if err := session.statement.setRefBean(bean); err != nil {
|
||||
return err
|
||||
}
|
||||
err = session.addColumn(col.Name)
|
||||
|
@ -1272,35 +1236,35 @@ func (engine *Engine) Sync(beans ...interface{}) error {
|
|||
}
|
||||
|
||||
for name, index := range table.Indexes {
|
||||
if err := session.statement.setRefValue(v); err != nil {
|
||||
if err := session.statement.setRefBean(bean); err != nil {
|
||||
return err
|
||||
}
|
||||
if index.Type == core.UniqueType {
|
||||
isExist, err := session.isIndexExist2(tableName, index.Cols, true)
|
||||
isExist, err := session.isIndexExist2(tableNameNoSchema, index.Cols, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !isExist {
|
||||
if err := session.statement.setRefValue(v); err != nil {
|
||||
if err := session.statement.setRefBean(bean); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = session.addUnique(tableName, name)
|
||||
err = session.addUnique(tableNameNoSchema, name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else if index.Type == core.IndexType {
|
||||
isExist, err := session.isIndexExist2(tableName, index.Cols, false)
|
||||
isExist, err := session.isIndexExist2(tableNameNoSchema, index.Cols, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !isExist {
|
||||
if err := session.statement.setRefValue(v); err != nil {
|
||||
if err := session.statement.setRefBean(bean); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = session.addIndex(tableName, name)
|
||||
err = session.addIndex(tableNameNoSchema, name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1453,6 +1417,13 @@ func (engine *Engine) Find(beans interface{}, condiBeans ...interface{}) error {
|
|||
return session.Find(beans, condiBeans...)
|
||||
}
|
||||
|
||||
// FindAndCount find the results and also return the counts
|
||||
func (engine *Engine) FindAndCount(rowsSlicePtr interface{}, condiBean ...interface{}) (int64, error) {
|
||||
session := engine.NewSession()
|
||||
defer session.Close()
|
||||
return session.FindAndCount(rowsSlicePtr, condiBean...)
|
||||
}
|
||||
|
||||
// Iterate record by record handle records from table, bean's non-empty fields
|
||||
// are conditions.
|
||||
func (engine *Engine) Iterate(bean interface{}, fun IterFunc) error {
|
||||
|
@ -1629,6 +1600,11 @@ func (engine *Engine) SetTZDatabase(tz *time.Location) {
|
|||
engine.DatabaseTZ = tz
|
||||
}
|
||||
|
||||
// SetSchema sets the schema of database
|
||||
func (engine *Engine) SetSchema(schema string) {
|
||||
engine.dialect.URI().Schema = schema
|
||||
}
|
||||
|
||||
// Unscoped always disable struct tag "deleted"
|
||||
func (engine *Engine) Unscoped() *Session {
|
||||
session := engine.NewSession()
|
||||
|
|
5
vendor/github.com/go-xorm/xorm/engine_cond.go
generated
vendored
5
vendor/github.com/go-xorm/xorm/engine_cond.go
generated
vendored
|
@ -9,6 +9,7 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-xorm/builder"
|
||||
|
@ -51,7 +52,9 @@ func (engine *Engine) buildConds(table *core.Table, bean interface{},
|
|||
|
||||
fieldValuePtr, err := col.ValueOf(bean)
|
||||
if err != nil {
|
||||
engine.logger.Error(err)
|
||||
if !strings.Contains(err.Error(), "is not valid") {
|
||||
engine.logger.Warn(err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
113
vendor/github.com/go-xorm/xorm/engine_table.go
generated
vendored
Normal file
113
vendor/github.com/go-xorm/xorm/engine_table.go
generated
vendored
Normal file
|
@ -0,0 +1,113 @@
|
|||
// Copyright 2018 The Xorm Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package xorm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/go-xorm/core"
|
||||
)
|
||||
|
||||
// TableNameWithSchema will automatically add schema prefix on table name
|
||||
func (engine *Engine) tbNameWithSchema(v string) string {
|
||||
// Add schema name as prefix of table name.
|
||||
// Only for postgres database.
|
||||
if engine.dialect.DBType() == core.POSTGRES &&
|
||||
engine.dialect.URI().Schema != "" &&
|
||||
engine.dialect.URI().Schema != postgresPublicSchema &&
|
||||
strings.Index(v, ".") == -1 {
|
||||
return engine.dialect.URI().Schema + "." + v
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// TableName returns table name with schema prefix if has
|
||||
func (engine *Engine) TableName(bean interface{}, includeSchema ...bool) string {
|
||||
tbName := engine.tbNameNoSchema(bean)
|
||||
if len(includeSchema) > 0 && includeSchema[0] {
|
||||
tbName = engine.tbNameWithSchema(tbName)
|
||||
}
|
||||
|
||||
return tbName
|
||||
}
|
||||
|
||||
// tbName get some table's table name
|
||||
func (session *Session) tbNameNoSchema(table *core.Table) string {
|
||||
if len(session.statement.AltTableName) > 0 {
|
||||
return session.statement.AltTableName
|
||||
}
|
||||
|
||||
return table.Name
|
||||
}
|
||||
|
||||
func (engine *Engine) tbNameForMap(v reflect.Value) string {
|
||||
if v.Type().Implements(tpTableName) {
|
||||
return v.Interface().(TableName).TableName()
|
||||
}
|
||||
if v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
if v.Type().Implements(tpTableName) {
|
||||
return v.Interface().(TableName).TableName()
|
||||
}
|
||||
}
|
||||
|
||||
return engine.TableMapper.Obj2Table(v.Type().Name())
|
||||
}
|
||||
|
||||
func (engine *Engine) tbNameNoSchema(tablename interface{}) string {
|
||||
switch tablename.(type) {
|
||||
case []string:
|
||||
t := tablename.([]string)
|
||||
if len(t) > 1 {
|
||||
return fmt.Sprintf("%v AS %v", engine.Quote(t[0]), engine.Quote(t[1]))
|
||||
} else if len(t) == 1 {
|
||||
return engine.Quote(t[0])
|
||||
}
|
||||
case []interface{}:
|
||||
t := tablename.([]interface{})
|
||||
l := len(t)
|
||||
var table string
|
||||
if l > 0 {
|
||||
f := t[0]
|
||||
switch f.(type) {
|
||||
case string:
|
||||
table = f.(string)
|
||||
case TableName:
|
||||
table = f.(TableName).TableName()
|
||||
default:
|
||||
v := rValue(f)
|
||||
t := v.Type()
|
||||
if t.Kind() == reflect.Struct {
|
||||
table = engine.tbNameForMap(v)
|
||||
} else {
|
||||
table = engine.Quote(fmt.Sprintf("%v", f))
|
||||
}
|
||||
}
|
||||
}
|
||||
if l > 1 {
|
||||
return fmt.Sprintf("%v AS %v", engine.Quote(table),
|
||||
engine.Quote(fmt.Sprintf("%v", t[1])))
|
||||
} else if l == 1 {
|
||||
return engine.Quote(table)
|
||||
}
|
||||
case TableName:
|
||||
return tablename.(TableName).TableName()
|
||||
case string:
|
||||
return tablename.(string)
|
||||
case reflect.Value:
|
||||
v := tablename.(reflect.Value)
|
||||
return engine.tbNameForMap(v)
|
||||
default:
|
||||
v := rValue(tablename)
|
||||
t := v.Type()
|
||||
if t.Kind() == reflect.Struct {
|
||||
return engine.tbNameForMap(v)
|
||||
}
|
||||
return engine.Quote(fmt.Sprintf("%v", tablename))
|
||||
}
|
||||
return ""
|
||||
}
|
31
vendor/github.com/go-xorm/xorm/error.go
generated
vendored
31
vendor/github.com/go-xorm/xorm/error.go
generated
vendored
|
@ -6,23 +6,44 @@ package xorm
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrParamsType params error
|
||||
ErrParamsType = errors.New("Params type error")
|
||||
// ErrTableNotFound table not found error
|
||||
ErrTableNotFound = errors.New("Not found table")
|
||||
ErrTableNotFound = errors.New("Table not found")
|
||||
// ErrUnSupportedType unsupported error
|
||||
ErrUnSupportedType = errors.New("Unsupported type error")
|
||||
// ErrNotExist record is not exist error
|
||||
ErrNotExist = errors.New("Not exist error")
|
||||
// ErrNotExist record does not exist error
|
||||
ErrNotExist = errors.New("Record does not exist")
|
||||
// ErrCacheFailed cache failed error
|
||||
ErrCacheFailed = errors.New("Cache failed")
|
||||
// ErrNeedDeletedCond delete needs less one condition error
|
||||
ErrNeedDeletedCond = errors.New("Delete need at least one condition")
|
||||
ErrNeedDeletedCond = errors.New("Delete action needs at least one condition")
|
||||
// ErrNotImplemented not implemented
|
||||
ErrNotImplemented = errors.New("Not implemented")
|
||||
// ErrConditionType condition type unsupported
|
||||
ErrConditionType = errors.New("Unsupported conditon type")
|
||||
ErrConditionType = errors.New("Unsupported condition type")
|
||||
)
|
||||
|
||||
// ErrFieldIsNotExist columns does not exist
|
||||
type ErrFieldIsNotExist struct {
|
||||
FieldName string
|
||||
TableName string
|
||||
}
|
||||
|
||||
func (e ErrFieldIsNotExist) Error() string {
|
||||
return fmt.Sprintf("field %s is not valid on table %s", e.FieldName, e.TableName)
|
||||
}
|
||||
|
||||
// ErrFieldIsNotValid is not valid
|
||||
type ErrFieldIsNotValid struct {
|
||||
FieldName string
|
||||
TableName string
|
||||
}
|
||||
|
||||
func (e ErrFieldIsNotValid) Error() string {
|
||||
return fmt.Sprintf("field %s is not valid on table %s", e.FieldName, e.TableName)
|
||||
}
|
||||
|
|
162
vendor/github.com/go-xorm/xorm/helpers.go
generated
vendored
162
vendor/github.com/go-xorm/xorm/helpers.go
generated
vendored
|
@ -11,7 +11,6 @@ import (
|
|||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-xorm/core"
|
||||
)
|
||||
|
@ -293,19 +292,6 @@ func structName(v reflect.Type) string {
|
|||
return v.Name()
|
||||
}
|
||||
|
||||
func col2NewCols(columns ...string) []string {
|
||||
newColumns := make([]string, 0, len(columns))
|
||||
for _, col := range columns {
|
||||
col = strings.Replace(col, "`", "", -1)
|
||||
col = strings.Replace(col, `"`, "", -1)
|
||||
ccols := strings.Split(col, ",")
|
||||
for _, c := range ccols {
|
||||
newColumns = append(newColumns, strings.TrimSpace(c))
|
||||
}
|
||||
}
|
||||
return newColumns
|
||||
}
|
||||
|
||||
func sliceEq(left, right []string) bool {
|
||||
if len(left) != len(right) {
|
||||
return false
|
||||
|
@ -320,154 +306,6 @@ func sliceEq(left, right []string) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func setColumnInt(bean interface{}, col *core.Column, t int64) {
|
||||
v, err := col.ValueOf(bean)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if v.CanSet() {
|
||||
switch v.Type().Kind() {
|
||||
case reflect.Int, reflect.Int64, reflect.Int32:
|
||||
v.SetInt(t)
|
||||
case reflect.Uint, reflect.Uint64, reflect.Uint32:
|
||||
v.SetUint(uint64(t))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setColumnTime(bean interface{}, col *core.Column, t time.Time) {
|
||||
v, err := col.ValueOf(bean)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if v.CanSet() {
|
||||
switch v.Type().Kind() {
|
||||
case reflect.Struct:
|
||||
v.Set(reflect.ValueOf(t).Convert(v.Type()))
|
||||
case reflect.Int, reflect.Int64, reflect.Int32:
|
||||
v.SetInt(t.Unix())
|
||||
case reflect.Uint, reflect.Uint64, reflect.Uint32:
|
||||
v.SetUint(uint64(t.Unix()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func genCols(table *core.Table, session *Session, bean interface{}, useCol bool, includeQuote bool) ([]string, []interface{}, error) {
|
||||
colNames := make([]string, 0, len(table.ColumnsSeq()))
|
||||
args := make([]interface{}, 0, len(table.ColumnsSeq()))
|
||||
|
||||
for _, col := range table.Columns() {
|
||||
if useCol && !col.IsVersion && !col.IsCreated && !col.IsUpdated {
|
||||
if _, ok := getFlagForColumn(session.statement.columnMap, col); !ok {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if col.MapType == core.ONLYFROMDB {
|
||||
continue
|
||||
}
|
||||
|
||||
fieldValuePtr, err := col.ValueOf(bean)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
fieldValue := *fieldValuePtr
|
||||
|
||||
if col.IsAutoIncrement {
|
||||
switch fieldValue.Type().Kind() {
|
||||
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int, reflect.Int64:
|
||||
if fieldValue.Int() == 0 {
|
||||
continue
|
||||
}
|
||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint, reflect.Uint64:
|
||||
if fieldValue.Uint() == 0 {
|
||||
continue
|
||||
}
|
||||
case reflect.String:
|
||||
if len(fieldValue.String()) == 0 {
|
||||
continue
|
||||
}
|
||||
case reflect.Ptr:
|
||||
if fieldValue.Pointer() == 0 {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if col.IsDeleted {
|
||||
continue
|
||||
}
|
||||
|
||||
if session.statement.ColumnStr != "" {
|
||||
if _, ok := getFlagForColumn(session.statement.columnMap, col); !ok {
|
||||
continue
|
||||
} else if _, ok := session.statement.incrColumns[col.Name]; ok {
|
||||
continue
|
||||
} else if _, ok := session.statement.decrColumns[col.Name]; ok {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if session.statement.OmitStr != "" {
|
||||
if _, ok := getFlagForColumn(session.statement.columnMap, col); ok {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// !evalphobia! set fieldValue as nil when column is nullable and zero-value
|
||||
if _, ok := getFlagForColumn(session.statement.nullableMap, col); ok {
|
||||
if col.Nullable && isZero(fieldValue.Interface()) {
|
||||
var nilValue *int
|
||||
fieldValue = reflect.ValueOf(nilValue)
|
||||
}
|
||||
}
|
||||
|
||||
if (col.IsCreated || col.IsUpdated) && session.statement.UseAutoTime /*&& isZero(fieldValue.Interface())*/ {
|
||||
// if time is non-empty, then set to auto time
|
||||
val, t := session.engine.nowTime(col)
|
||||
args = append(args, val)
|
||||
|
||||
var colName = col.Name
|
||||
session.afterClosures = append(session.afterClosures, func(bean interface{}) {
|
||||
col := table.GetColumn(colName)
|
||||
setColumnTime(bean, col, t)
|
||||
})
|
||||
} else if col.IsVersion && session.statement.checkVersion {
|
||||
args = append(args, 1)
|
||||
} else {
|
||||
arg, err := session.value2Interface(col, fieldValue)
|
||||
if err != nil {
|
||||
return colNames, args, err
|
||||
}
|
||||
args = append(args, arg)
|
||||
}
|
||||
|
||||
if includeQuote {
|
||||
colNames = append(colNames, session.engine.Quote(col.Name)+" = ?")
|
||||
} else {
|
||||
colNames = append(colNames, col.Name)
|
||||
}
|
||||
}
|
||||
return colNames, args, nil
|
||||
}
|
||||
|
||||
func indexName(tableName, idxName string) string {
|
||||
return fmt.Sprintf("IDX_%v_%v", tableName, idxName)
|
||||
}
|
||||
|
||||
func getFlagForColumn(m map[string]bool, col *core.Column) (val bool, has bool) {
|
||||
if len(m) == 0 {
|
||||
return false, false
|
||||
}
|
||||
|
||||
n := len(col.Name)
|
||||
|
||||
for mk := range m {
|
||||
if len(mk) != n {
|
||||
continue
|
||||
}
|
||||
if strings.EqualFold(mk, col.Name) {
|
||||
return m[mk], true
|
||||
}
|
||||
}
|
||||
|
||||
return false, false
|
||||
}
|
||||
|
|
6
vendor/github.com/go-xorm/xorm/interface.go
generated
vendored
6
vendor/github.com/go-xorm/xorm/interface.go
generated
vendored
|
@ -30,6 +30,7 @@ type Interface interface {
|
|||
Exec(string, ...interface{}) (sql.Result, error)
|
||||
Exist(bean ...interface{}) (bool, error)
|
||||
Find(interface{}, ...interface{}) error
|
||||
FindAndCount(interface{}, ...interface{}) (int64, error)
|
||||
Get(interface{}) (bool, error)
|
||||
GroupBy(keys string) *Session
|
||||
ID(interface{}) *Session
|
||||
|
@ -41,6 +42,7 @@ type Interface interface {
|
|||
IsTableExist(beanOrTableName interface{}) (bool, error)
|
||||
Iterate(interface{}, IterFunc) error
|
||||
Limit(int, ...int) *Session
|
||||
MustCols(columns ...string) *Session
|
||||
NoAutoCondition(...bool) *Session
|
||||
NotIn(string, ...interface{}) *Session
|
||||
Join(joinOperator string, tablename interface{}, condition string, args ...interface{}) *Session
|
||||
|
@ -75,6 +77,7 @@ type EngineInterface interface {
|
|||
Dialect() core.Dialect
|
||||
DropTables(...interface{}) error
|
||||
DumpAllToFile(fp string, tp ...core.DbType) error
|
||||
GetCacher(string) core.Cacher
|
||||
GetColumnMapper() core.IMapper
|
||||
GetDefaultCacher() core.Cacher
|
||||
GetTableMapper() core.IMapper
|
||||
|
@ -83,9 +86,11 @@ type EngineInterface interface {
|
|||
NewSession() *Session
|
||||
NoAutoTime() *Session
|
||||
Quote(string) string
|
||||
SetCacher(string, core.Cacher)
|
||||
SetDefaultCacher(core.Cacher)
|
||||
SetLogLevel(core.LogLevel)
|
||||
SetMapper(core.IMapper)
|
||||
SetSchema(string)
|
||||
SetTZDatabase(tz *time.Location)
|
||||
SetTZLocation(tz *time.Location)
|
||||
ShowSQL(show ...bool)
|
||||
|
@ -93,6 +98,7 @@ type EngineInterface interface {
|
|||
Sync2(...interface{}) error
|
||||
StoreEngine(storeEngine string) *Session
|
||||
TableInfo(bean interface{}) *Table
|
||||
TableName(interface{}, ...bool) string
|
||||
UnMapType(reflect.Type)
|
||||
}
|
||||
|
||||
|
|
6
vendor/github.com/go-xorm/xorm/rows.go
generated
vendored
6
vendor/github.com/go-xorm/xorm/rows.go
generated
vendored
|
@ -32,7 +32,7 @@ func newRows(session *Session, bean interface{}) (*Rows, error) {
|
|||
var args []interface{}
|
||||
var err error
|
||||
|
||||
if err = rows.session.statement.setRefValue(rValue(bean)); err != nil {
|
||||
if err = rows.session.statement.setRefBean(bean); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -94,8 +94,7 @@ func (rows *Rows) Scan(bean interface{}) error {
|
|||
return fmt.Errorf("scan arg is incompatible type to [%v]", rows.beanType)
|
||||
}
|
||||
|
||||
dataStruct := rValue(bean)
|
||||
if err := rows.session.statement.setRefValue(dataStruct); err != nil {
|
||||
if err := rows.session.statement.setRefBean(bean); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -104,6 +103,7 @@ func (rows *Rows) Scan(bean interface{}) error {
|
|||
return err
|
||||
}
|
||||
|
||||
dataStruct := rValue(bean)
|
||||
_, err = rows.session.slice2Bean(scanResults, rows.fields, bean, &dataStruct, rows.session.statement.RefTable)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
761
vendor/github.com/go-xorm/xorm/session.go
generated
vendored
761
vendor/github.com/go-xorm/xorm/session.go
generated
vendored
|
@ -278,24 +278,22 @@ func (session *Session) doPrepare(db *core.DB, sqlStr string) (stmt *core.Stmt,
|
|||
return
|
||||
}
|
||||
|
||||
func (session *Session) getField(dataStruct *reflect.Value, key string, table *core.Table, idx int) *reflect.Value {
|
||||
func (session *Session) getField(dataStruct *reflect.Value, key string, table *core.Table, idx int) (*reflect.Value, error) {
|
||||
var col *core.Column
|
||||
if col = table.GetColumnIdx(key, idx); col == nil {
|
||||
//session.engine.logger.Warnf("table %v has no column %v. %v", table.Name, key, table.ColumnsSeq())
|
||||
return nil
|
||||
return nil, ErrFieldIsNotExist{key, table.Name}
|
||||
}
|
||||
|
||||
fieldValue, err := col.ValueOfV(dataStruct)
|
||||
if err != nil {
|
||||
session.engine.logger.Error(err)
|
||||
return nil
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !fieldValue.IsValid() || !fieldValue.CanSet() {
|
||||
session.engine.logger.Warnf("table %v's column %v is not valid or cannot set", table.Name, key)
|
||||
return nil
|
||||
return nil, ErrFieldIsNotValid{key, table.Name}
|
||||
}
|
||||
return fieldValue
|
||||
|
||||
return fieldValue, nil
|
||||
}
|
||||
|
||||
// Cell cell is a result of one column field
|
||||
|
@ -407,409 +405,417 @@ func (session *Session) slice2Bean(scanResults []interface{}, fields []string, b
|
|||
}
|
||||
tempMap[lKey] = idx
|
||||
|
||||
if fieldValue := session.getField(dataStruct, key, table, idx); fieldValue != nil {
|
||||
rawValue := reflect.Indirect(reflect.ValueOf(scanResults[ii]))
|
||||
|
||||
// if row is null then ignore
|
||||
if rawValue.Interface() == nil {
|
||||
continue
|
||||
fieldValue, err := session.getField(dataStruct, key, table, idx)
|
||||
if err != nil {
|
||||
if !strings.Contains(err.Error(), "is not valid") {
|
||||
session.engine.logger.Warn(err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if fieldValue == nil {
|
||||
continue
|
||||
}
|
||||
rawValue := reflect.Indirect(reflect.ValueOf(scanResults[ii]))
|
||||
|
||||
if fieldValue.CanAddr() {
|
||||
if structConvert, ok := fieldValue.Addr().Interface().(core.Conversion); ok {
|
||||
if data, err := value2Bytes(&rawValue); err == nil {
|
||||
if err := structConvert.FromDB(data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
// if row is null then ignore
|
||||
if rawValue.Interface() == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if fieldValue.CanAddr() {
|
||||
if structConvert, ok := fieldValue.Addr().Interface().(core.Conversion); ok {
|
||||
if data, err := value2Bytes(&rawValue); err == nil {
|
||||
if err := structConvert.FromDB(data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if _, ok := fieldValue.Interface().(core.Conversion); ok {
|
||||
if data, err := value2Bytes(&rawValue); err == nil {
|
||||
if fieldValue.Kind() == reflect.Ptr && fieldValue.IsNil() {
|
||||
fieldValue.Set(reflect.New(fieldValue.Type().Elem()))
|
||||
}
|
||||
fieldValue.Interface().(core.Conversion).FromDB(data)
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
rawValueType := reflect.TypeOf(rawValue.Interface())
|
||||
vv := reflect.ValueOf(rawValue.Interface())
|
||||
col := table.GetColumnIdx(key, idx)
|
||||
if col.IsPrimaryKey {
|
||||
pk = append(pk, rawValue.Interface())
|
||||
if _, ok := fieldValue.Interface().(core.Conversion); ok {
|
||||
if data, err := value2Bytes(&rawValue); err == nil {
|
||||
if fieldValue.Kind() == reflect.Ptr && fieldValue.IsNil() {
|
||||
fieldValue.Set(reflect.New(fieldValue.Type().Elem()))
|
||||
}
|
||||
fieldValue.Interface().(core.Conversion).FromDB(data)
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
fieldType := fieldValue.Type()
|
||||
hasAssigned := false
|
||||
continue
|
||||
}
|
||||
|
||||
if col.SQLType.IsJson() {
|
||||
var bs []byte
|
||||
if rawValueType.Kind() == reflect.String {
|
||||
bs = []byte(vv.String())
|
||||
} else if rawValueType.ConvertibleTo(core.BytesType) {
|
||||
bs = vv.Bytes()
|
||||
rawValueType := reflect.TypeOf(rawValue.Interface())
|
||||
vv := reflect.ValueOf(rawValue.Interface())
|
||||
col := table.GetColumnIdx(key, idx)
|
||||
if col.IsPrimaryKey {
|
||||
pk = append(pk, rawValue.Interface())
|
||||
}
|
||||
fieldType := fieldValue.Type()
|
||||
hasAssigned := false
|
||||
|
||||
if col.SQLType.IsJson() {
|
||||
var bs []byte
|
||||
if rawValueType.Kind() == reflect.String {
|
||||
bs = []byte(vv.String())
|
||||
} else if rawValueType.ConvertibleTo(core.BytesType) {
|
||||
bs = vv.Bytes()
|
||||
} else {
|
||||
return nil, fmt.Errorf("unsupported database data type: %s %v", key, rawValueType.Kind())
|
||||
}
|
||||
|
||||
hasAssigned = true
|
||||
|
||||
if len(bs) > 0 {
|
||||
if fieldType.Kind() == reflect.String {
|
||||
fieldValue.SetString(string(bs))
|
||||
continue
|
||||
}
|
||||
if fieldValue.CanAddr() {
|
||||
err := json.Unmarshal(bs, fieldValue.Addr().Interface())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
return nil, fmt.Errorf("unsupported database data type: %s %v", key, rawValueType.Kind())
|
||||
}
|
||||
|
||||
hasAssigned = true
|
||||
|
||||
if len(bs) > 0 {
|
||||
if fieldType.Kind() == reflect.String {
|
||||
fieldValue.SetString(string(bs))
|
||||
continue
|
||||
}
|
||||
if fieldValue.CanAddr() {
|
||||
err := json.Unmarshal(bs, fieldValue.Addr().Interface())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
x := reflect.New(fieldType)
|
||||
err := json.Unmarshal(bs, x.Interface())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fieldValue.Set(x.Elem())
|
||||
x := reflect.New(fieldType)
|
||||
err := json.Unmarshal(bs, x.Interface())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fieldValue.Set(x.Elem())
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
switch fieldType.Kind() {
|
||||
case reflect.Complex64, reflect.Complex128:
|
||||
// TODO: reimplement this
|
||||
var bs []byte
|
||||
if rawValueType.Kind() == reflect.String {
|
||||
bs = []byte(vv.String())
|
||||
} else if rawValueType.ConvertibleTo(core.BytesType) {
|
||||
bs = vv.Bytes()
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
hasAssigned = true
|
||||
if len(bs) > 0 {
|
||||
if fieldValue.CanAddr() {
|
||||
err := json.Unmarshal(bs, fieldValue.Addr().Interface())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
x := reflect.New(fieldType)
|
||||
err := json.Unmarshal(bs, x.Interface())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fieldValue.Set(x.Elem())
|
||||
switch fieldType.Kind() {
|
||||
case reflect.Complex64, reflect.Complex128:
|
||||
// TODO: reimplement this
|
||||
var bs []byte
|
||||
if rawValueType.Kind() == reflect.String {
|
||||
bs = []byte(vv.String())
|
||||
} else if rawValueType.ConvertibleTo(core.BytesType) {
|
||||
bs = vv.Bytes()
|
||||
}
|
||||
|
||||
hasAssigned = true
|
||||
if len(bs) > 0 {
|
||||
if fieldValue.CanAddr() {
|
||||
err := json.Unmarshal(bs, fieldValue.Addr().Interface())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
x := reflect.New(fieldType)
|
||||
err := json.Unmarshal(bs, x.Interface())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fieldValue.Set(x.Elem())
|
||||
}
|
||||
}
|
||||
case reflect.Slice, reflect.Array:
|
||||
switch rawValueType.Kind() {
|
||||
case reflect.Slice, reflect.Array:
|
||||
switch rawValueType.Kind() {
|
||||
case reflect.Slice, reflect.Array:
|
||||
switch rawValueType.Elem().Kind() {
|
||||
case reflect.Uint8:
|
||||
if fieldType.Elem().Kind() == reflect.Uint8 {
|
||||
hasAssigned = true
|
||||
if col.SQLType.IsText() {
|
||||
x := reflect.New(fieldType)
|
||||
err := json.Unmarshal(vv.Bytes(), x.Interface())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fieldValue.Set(x.Elem())
|
||||
} else {
|
||||
if fieldValue.Len() > 0 {
|
||||
for i := 0; i < fieldValue.Len(); i++ {
|
||||
if i < vv.Len() {
|
||||
fieldValue.Index(i).Set(vv.Index(i))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for i := 0; i < vv.Len(); i++ {
|
||||
fieldValue.Set(reflect.Append(*fieldValue, vv.Index(i)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
case reflect.String:
|
||||
if rawValueType.Kind() == reflect.String {
|
||||
hasAssigned = true
|
||||
fieldValue.SetString(vv.String())
|
||||
}
|
||||
case reflect.Bool:
|
||||
if rawValueType.Kind() == reflect.Bool {
|
||||
hasAssigned = true
|
||||
fieldValue.SetBool(vv.Bool())
|
||||
}
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
switch rawValueType.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
hasAssigned = true
|
||||
fieldValue.SetInt(vv.Int())
|
||||
}
|
||||
case reflect.Float32, reflect.Float64:
|
||||
switch rawValueType.Kind() {
|
||||
case reflect.Float32, reflect.Float64:
|
||||
hasAssigned = true
|
||||
fieldValue.SetFloat(vv.Float())
|
||||
}
|
||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
|
||||
switch rawValueType.Kind() {
|
||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
|
||||
hasAssigned = true
|
||||
fieldValue.SetUint(vv.Uint())
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
hasAssigned = true
|
||||
fieldValue.SetUint(uint64(vv.Int()))
|
||||
}
|
||||
case reflect.Struct:
|
||||
if fieldType.ConvertibleTo(core.TimeType) {
|
||||
dbTZ := session.engine.DatabaseTZ
|
||||
if col.TimeZone != nil {
|
||||
dbTZ = col.TimeZone
|
||||
}
|
||||
|
||||
if rawValueType == core.TimeType {
|
||||
switch rawValueType.Elem().Kind() {
|
||||
case reflect.Uint8:
|
||||
if fieldType.Elem().Kind() == reflect.Uint8 {
|
||||
hasAssigned = true
|
||||
|
||||
t := vv.Convert(core.TimeType).Interface().(time.Time)
|
||||
|
||||
z, _ := t.Zone()
|
||||
// set new location if database don't save timezone or give an incorrect timezone
|
||||
if len(z) == 0 || t.Year() == 0 || t.Location().String() != dbTZ.String() { // !nashtsai! HACK tmp work around for lib/pq doesn't properly time with location
|
||||
session.engine.logger.Debugf("empty zone key[%v] : %v | zone: %v | location: %+v\n", key, t, z, *t.Location())
|
||||
t = time.Date(t.Year(), t.Month(), t.Day(), t.Hour(),
|
||||
t.Minute(), t.Second(), t.Nanosecond(), dbTZ)
|
||||
}
|
||||
|
||||
t = t.In(session.engine.TZLocation)
|
||||
fieldValue.Set(reflect.ValueOf(t).Convert(fieldType))
|
||||
} else if rawValueType == core.IntType || rawValueType == core.Int64Type ||
|
||||
rawValueType == core.Int32Type {
|
||||
hasAssigned = true
|
||||
|
||||
t := time.Unix(vv.Int(), 0).In(session.engine.TZLocation)
|
||||
fieldValue.Set(reflect.ValueOf(t).Convert(fieldType))
|
||||
} else {
|
||||
if d, ok := vv.Interface().([]uint8); ok {
|
||||
hasAssigned = true
|
||||
t, err := session.byte2Time(col, d)
|
||||
if err != nil {
|
||||
session.engine.logger.Error("byte2Time error:", err.Error())
|
||||
hasAssigned = false
|
||||
} else {
|
||||
fieldValue.Set(reflect.ValueOf(t).Convert(fieldType))
|
||||
}
|
||||
} else if d, ok := vv.Interface().(string); ok {
|
||||
hasAssigned = true
|
||||
t, err := session.str2Time(col, d)
|
||||
if err != nil {
|
||||
session.engine.logger.Error("byte2Time error:", err.Error())
|
||||
hasAssigned = false
|
||||
} else {
|
||||
fieldValue.Set(reflect.ValueOf(t).Convert(fieldType))
|
||||
}
|
||||
} else {
|
||||
return nil, fmt.Errorf("rawValueType is %v, value is %v", rawValueType, vv.Interface())
|
||||
}
|
||||
}
|
||||
} else if nulVal, ok := fieldValue.Addr().Interface().(sql.Scanner); ok {
|
||||
// !<winxxp>! 增加支持sql.Scanner接口的结构,如sql.NullString
|
||||
hasAssigned = true
|
||||
if err := nulVal.Scan(vv.Interface()); err != nil {
|
||||
session.engine.logger.Error("sql.Sanner error:", err.Error())
|
||||
hasAssigned = false
|
||||
}
|
||||
} else if col.SQLType.IsJson() {
|
||||
if rawValueType.Kind() == reflect.String {
|
||||
hasAssigned = true
|
||||
x := reflect.New(fieldType)
|
||||
if len([]byte(vv.String())) > 0 {
|
||||
err := json.Unmarshal([]byte(vv.String()), x.Interface())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fieldValue.Set(x.Elem())
|
||||
}
|
||||
} else if rawValueType.Kind() == reflect.Slice {
|
||||
hasAssigned = true
|
||||
x := reflect.New(fieldType)
|
||||
if len(vv.Bytes()) > 0 {
|
||||
if col.SQLType.IsText() {
|
||||
x := reflect.New(fieldType)
|
||||
err := json.Unmarshal(vv.Bytes(), x.Interface())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fieldValue.Set(x.Elem())
|
||||
}
|
||||
}
|
||||
} else if session.statement.UseCascade {
|
||||
table, err := session.engine.autoMapType(*fieldValue)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hasAssigned = true
|
||||
if len(table.PrimaryKeys) != 1 {
|
||||
return nil, errors.New("unsupported non or composited primary key cascade")
|
||||
}
|
||||
var pk = make(core.PK, len(table.PrimaryKeys))
|
||||
pk[0], err = asKind(vv, rawValueType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !isPKZero(pk) {
|
||||
// !nashtsai! TODO for hasOne relationship, it's preferred to use join query for eager fetch
|
||||
// however, also need to consider adding a 'lazy' attribute to xorm tag which allow hasOne
|
||||
// property to be fetched lazily
|
||||
structInter := reflect.New(fieldValue.Type())
|
||||
has, err := session.ID(pk).NoCascade().get(structInter.Interface())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if has {
|
||||
fieldValue.Set(structInter.Elem())
|
||||
} else {
|
||||
return nil, errors.New("cascade obj is not exist")
|
||||
if fieldValue.Len() > 0 {
|
||||
for i := 0; i < fieldValue.Len(); i++ {
|
||||
if i < vv.Len() {
|
||||
fieldValue.Index(i).Set(vv.Index(i))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for i := 0; i < vv.Len(); i++ {
|
||||
fieldValue.Set(reflect.Append(*fieldValue, vv.Index(i)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
case reflect.Ptr:
|
||||
// !nashtsai! TODO merge duplicated codes above
|
||||
switch fieldType {
|
||||
// following types case matching ptr's native type, therefore assign ptr directly
|
||||
case core.PtrStringType:
|
||||
if rawValueType.Kind() == reflect.String {
|
||||
x := vv.String()
|
||||
hasAssigned = true
|
||||
fieldValue.Set(reflect.ValueOf(&x))
|
||||
}
|
||||
case core.PtrBoolType:
|
||||
if rawValueType.Kind() == reflect.Bool {
|
||||
x := vv.Bool()
|
||||
hasAssigned = true
|
||||
fieldValue.Set(reflect.ValueOf(&x))
|
||||
}
|
||||
case core.PtrTimeType:
|
||||
if rawValueType == core.PtrTimeType {
|
||||
hasAssigned = true
|
||||
var x = rawValue.Interface().(time.Time)
|
||||
fieldValue.Set(reflect.ValueOf(&x))
|
||||
}
|
||||
case core.PtrFloat64Type:
|
||||
if rawValueType.Kind() == reflect.Float64 {
|
||||
x := vv.Float()
|
||||
hasAssigned = true
|
||||
fieldValue.Set(reflect.ValueOf(&x))
|
||||
}
|
||||
case core.PtrUint64Type:
|
||||
if rawValueType.Kind() == reflect.Int64 {
|
||||
var x = uint64(vv.Int())
|
||||
hasAssigned = true
|
||||
fieldValue.Set(reflect.ValueOf(&x))
|
||||
}
|
||||
case core.PtrInt64Type:
|
||||
if rawValueType.Kind() == reflect.Int64 {
|
||||
x := vv.Int()
|
||||
hasAssigned = true
|
||||
fieldValue.Set(reflect.ValueOf(&x))
|
||||
}
|
||||
case core.PtrFloat32Type:
|
||||
if rawValueType.Kind() == reflect.Float64 {
|
||||
var x = float32(vv.Float())
|
||||
hasAssigned = true
|
||||
fieldValue.Set(reflect.ValueOf(&x))
|
||||
}
|
||||
case core.PtrIntType:
|
||||
if rawValueType.Kind() == reflect.Int64 {
|
||||
var x = int(vv.Int())
|
||||
hasAssigned = true
|
||||
fieldValue.Set(reflect.ValueOf(&x))
|
||||
}
|
||||
case core.PtrInt32Type:
|
||||
if rawValueType.Kind() == reflect.Int64 {
|
||||
var x = int32(vv.Int())
|
||||
hasAssigned = true
|
||||
fieldValue.Set(reflect.ValueOf(&x))
|
||||
}
|
||||
case core.PtrInt8Type:
|
||||
if rawValueType.Kind() == reflect.Int64 {
|
||||
var x = int8(vv.Int())
|
||||
hasAssigned = true
|
||||
fieldValue.Set(reflect.ValueOf(&x))
|
||||
}
|
||||
case core.PtrInt16Type:
|
||||
if rawValueType.Kind() == reflect.Int64 {
|
||||
var x = int16(vv.Int())
|
||||
hasAssigned = true
|
||||
fieldValue.Set(reflect.ValueOf(&x))
|
||||
}
|
||||
case core.PtrUintType:
|
||||
if rawValueType.Kind() == reflect.Int64 {
|
||||
var x = uint(vv.Int())
|
||||
hasAssigned = true
|
||||
fieldValue.Set(reflect.ValueOf(&x))
|
||||
}
|
||||
case core.PtrUint32Type:
|
||||
if rawValueType.Kind() == reflect.Int64 {
|
||||
var x = uint32(vv.Int())
|
||||
hasAssigned = true
|
||||
fieldValue.Set(reflect.ValueOf(&x))
|
||||
}
|
||||
case core.Uint8Type:
|
||||
if rawValueType.Kind() == reflect.Int64 {
|
||||
var x = uint8(vv.Int())
|
||||
hasAssigned = true
|
||||
fieldValue.Set(reflect.ValueOf(&x))
|
||||
}
|
||||
case core.Uint16Type:
|
||||
if rawValueType.Kind() == reflect.Int64 {
|
||||
var x = uint16(vv.Int())
|
||||
hasAssigned = true
|
||||
fieldValue.Set(reflect.ValueOf(&x))
|
||||
}
|
||||
case core.Complex64Type:
|
||||
var x complex64
|
||||
if len([]byte(vv.String())) > 0 {
|
||||
err := json.Unmarshal([]byte(vv.String()), &x)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fieldValue.Set(reflect.ValueOf(&x))
|
||||
}
|
||||
hasAssigned = true
|
||||
case core.Complex128Type:
|
||||
var x complex128
|
||||
if len([]byte(vv.String())) > 0 {
|
||||
err := json.Unmarshal([]byte(vv.String()), &x)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fieldValue.Set(reflect.ValueOf(&x))
|
||||
}
|
||||
hasAssigned = true
|
||||
} // switch fieldType
|
||||
} // switch fieldType.Kind()
|
||||
}
|
||||
case reflect.String:
|
||||
if rawValueType.Kind() == reflect.String {
|
||||
hasAssigned = true
|
||||
fieldValue.SetString(vv.String())
|
||||
}
|
||||
case reflect.Bool:
|
||||
if rawValueType.Kind() == reflect.Bool {
|
||||
hasAssigned = true
|
||||
fieldValue.SetBool(vv.Bool())
|
||||
}
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
switch rawValueType.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
hasAssigned = true
|
||||
fieldValue.SetInt(vv.Int())
|
||||
}
|
||||
case reflect.Float32, reflect.Float64:
|
||||
switch rawValueType.Kind() {
|
||||
case reflect.Float32, reflect.Float64:
|
||||
hasAssigned = true
|
||||
fieldValue.SetFloat(vv.Float())
|
||||
}
|
||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
|
||||
switch rawValueType.Kind() {
|
||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
|
||||
hasAssigned = true
|
||||
fieldValue.SetUint(vv.Uint())
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
hasAssigned = true
|
||||
fieldValue.SetUint(uint64(vv.Int()))
|
||||
}
|
||||
case reflect.Struct:
|
||||
if fieldType.ConvertibleTo(core.TimeType) {
|
||||
dbTZ := session.engine.DatabaseTZ
|
||||
if col.TimeZone != nil {
|
||||
dbTZ = col.TimeZone
|
||||
}
|
||||
|
||||
// !nashtsai! for value can't be assigned directly fallback to convert to []byte then back to value
|
||||
if !hasAssigned {
|
||||
data, err := value2Bytes(&rawValue)
|
||||
if rawValueType == core.TimeType {
|
||||
hasAssigned = true
|
||||
|
||||
t := vv.Convert(core.TimeType).Interface().(time.Time)
|
||||
|
||||
z, _ := t.Zone()
|
||||
// set new location if database don't save timezone or give an incorrect timezone
|
||||
if len(z) == 0 || t.Year() == 0 || t.Location().String() != dbTZ.String() { // !nashtsai! HACK tmp work around for lib/pq doesn't properly time with location
|
||||
session.engine.logger.Debugf("empty zone key[%v] : %v | zone: %v | location: %+v\n", key, t, z, *t.Location())
|
||||
t = time.Date(t.Year(), t.Month(), t.Day(), t.Hour(),
|
||||
t.Minute(), t.Second(), t.Nanosecond(), dbTZ)
|
||||
}
|
||||
|
||||
t = t.In(session.engine.TZLocation)
|
||||
fieldValue.Set(reflect.ValueOf(t).Convert(fieldType))
|
||||
} else if rawValueType == core.IntType || rawValueType == core.Int64Type ||
|
||||
rawValueType == core.Int32Type {
|
||||
hasAssigned = true
|
||||
|
||||
t := time.Unix(vv.Int(), 0).In(session.engine.TZLocation)
|
||||
fieldValue.Set(reflect.ValueOf(t).Convert(fieldType))
|
||||
} else {
|
||||
if d, ok := vv.Interface().([]uint8); ok {
|
||||
hasAssigned = true
|
||||
t, err := session.byte2Time(col, d)
|
||||
if err != nil {
|
||||
session.engine.logger.Error("byte2Time error:", err.Error())
|
||||
hasAssigned = false
|
||||
} else {
|
||||
fieldValue.Set(reflect.ValueOf(t).Convert(fieldType))
|
||||
}
|
||||
} else if d, ok := vv.Interface().(string); ok {
|
||||
hasAssigned = true
|
||||
t, err := session.str2Time(col, d)
|
||||
if err != nil {
|
||||
session.engine.logger.Error("byte2Time error:", err.Error())
|
||||
hasAssigned = false
|
||||
} else {
|
||||
fieldValue.Set(reflect.ValueOf(t).Convert(fieldType))
|
||||
}
|
||||
} else {
|
||||
return nil, fmt.Errorf("rawValueType is %v, value is %v", rawValueType, vv.Interface())
|
||||
}
|
||||
}
|
||||
} else if nulVal, ok := fieldValue.Addr().Interface().(sql.Scanner); ok {
|
||||
// !<winxxp>! 增加支持sql.Scanner接口的结构,如sql.NullString
|
||||
hasAssigned = true
|
||||
if err := nulVal.Scan(vv.Interface()); err != nil {
|
||||
session.engine.logger.Error("sql.Sanner error:", err.Error())
|
||||
hasAssigned = false
|
||||
}
|
||||
} else if col.SQLType.IsJson() {
|
||||
if rawValueType.Kind() == reflect.String {
|
||||
hasAssigned = true
|
||||
x := reflect.New(fieldType)
|
||||
if len([]byte(vv.String())) > 0 {
|
||||
err := json.Unmarshal([]byte(vv.String()), x.Interface())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fieldValue.Set(x.Elem())
|
||||
}
|
||||
} else if rawValueType.Kind() == reflect.Slice {
|
||||
hasAssigned = true
|
||||
x := reflect.New(fieldType)
|
||||
if len(vv.Bytes()) > 0 {
|
||||
err := json.Unmarshal(vv.Bytes(), x.Interface())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fieldValue.Set(x.Elem())
|
||||
}
|
||||
}
|
||||
} else if session.statement.UseCascade {
|
||||
table, err := session.engine.autoMapType(*fieldValue)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = session.bytes2Value(col, fieldValue, data); err != nil {
|
||||
hasAssigned = true
|
||||
if len(table.PrimaryKeys) != 1 {
|
||||
return nil, errors.New("unsupported non or composited primary key cascade")
|
||||
}
|
||||
var pk = make(core.PK, len(table.PrimaryKeys))
|
||||
pk[0], err = asKind(vv, rawValueType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !isPKZero(pk) {
|
||||
// !nashtsai! TODO for hasOne relationship, it's preferred to use join query for eager fetch
|
||||
// however, also need to consider adding a 'lazy' attribute to xorm tag which allow hasOne
|
||||
// property to be fetched lazily
|
||||
structInter := reflect.New(fieldValue.Type())
|
||||
has, err := session.ID(pk).NoCascade().get(structInter.Interface())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if has {
|
||||
fieldValue.Set(structInter.Elem())
|
||||
} else {
|
||||
return nil, errors.New("cascade obj is not exist")
|
||||
}
|
||||
}
|
||||
}
|
||||
case reflect.Ptr:
|
||||
// !nashtsai! TODO merge duplicated codes above
|
||||
switch fieldType {
|
||||
// following types case matching ptr's native type, therefore assign ptr directly
|
||||
case core.PtrStringType:
|
||||
if rawValueType.Kind() == reflect.String {
|
||||
x := vv.String()
|
||||
hasAssigned = true
|
||||
fieldValue.Set(reflect.ValueOf(&x))
|
||||
}
|
||||
case core.PtrBoolType:
|
||||
if rawValueType.Kind() == reflect.Bool {
|
||||
x := vv.Bool()
|
||||
hasAssigned = true
|
||||
fieldValue.Set(reflect.ValueOf(&x))
|
||||
}
|
||||
case core.PtrTimeType:
|
||||
if rawValueType == core.PtrTimeType {
|
||||
hasAssigned = true
|
||||
var x = rawValue.Interface().(time.Time)
|
||||
fieldValue.Set(reflect.ValueOf(&x))
|
||||
}
|
||||
case core.PtrFloat64Type:
|
||||
if rawValueType.Kind() == reflect.Float64 {
|
||||
x := vv.Float()
|
||||
hasAssigned = true
|
||||
fieldValue.Set(reflect.ValueOf(&x))
|
||||
}
|
||||
case core.PtrUint64Type:
|
||||
if rawValueType.Kind() == reflect.Int64 {
|
||||
var x = uint64(vv.Int())
|
||||
hasAssigned = true
|
||||
fieldValue.Set(reflect.ValueOf(&x))
|
||||
}
|
||||
case core.PtrInt64Type:
|
||||
if rawValueType.Kind() == reflect.Int64 {
|
||||
x := vv.Int()
|
||||
hasAssigned = true
|
||||
fieldValue.Set(reflect.ValueOf(&x))
|
||||
}
|
||||
case core.PtrFloat32Type:
|
||||
if rawValueType.Kind() == reflect.Float64 {
|
||||
var x = float32(vv.Float())
|
||||
hasAssigned = true
|
||||
fieldValue.Set(reflect.ValueOf(&x))
|
||||
}
|
||||
case core.PtrIntType:
|
||||
if rawValueType.Kind() == reflect.Int64 {
|
||||
var x = int(vv.Int())
|
||||
hasAssigned = true
|
||||
fieldValue.Set(reflect.ValueOf(&x))
|
||||
}
|
||||
case core.PtrInt32Type:
|
||||
if rawValueType.Kind() == reflect.Int64 {
|
||||
var x = int32(vv.Int())
|
||||
hasAssigned = true
|
||||
fieldValue.Set(reflect.ValueOf(&x))
|
||||
}
|
||||
case core.PtrInt8Type:
|
||||
if rawValueType.Kind() == reflect.Int64 {
|
||||
var x = int8(vv.Int())
|
||||
hasAssigned = true
|
||||
fieldValue.Set(reflect.ValueOf(&x))
|
||||
}
|
||||
case core.PtrInt16Type:
|
||||
if rawValueType.Kind() == reflect.Int64 {
|
||||
var x = int16(vv.Int())
|
||||
hasAssigned = true
|
||||
fieldValue.Set(reflect.ValueOf(&x))
|
||||
}
|
||||
case core.PtrUintType:
|
||||
if rawValueType.Kind() == reflect.Int64 {
|
||||
var x = uint(vv.Int())
|
||||
hasAssigned = true
|
||||
fieldValue.Set(reflect.ValueOf(&x))
|
||||
}
|
||||
case core.PtrUint32Type:
|
||||
if rawValueType.Kind() == reflect.Int64 {
|
||||
var x = uint32(vv.Int())
|
||||
hasAssigned = true
|
||||
fieldValue.Set(reflect.ValueOf(&x))
|
||||
}
|
||||
case core.Uint8Type:
|
||||
if rawValueType.Kind() == reflect.Int64 {
|
||||
var x = uint8(vv.Int())
|
||||
hasAssigned = true
|
||||
fieldValue.Set(reflect.ValueOf(&x))
|
||||
}
|
||||
case core.Uint16Type:
|
||||
if rawValueType.Kind() == reflect.Int64 {
|
||||
var x = uint16(vv.Int())
|
||||
hasAssigned = true
|
||||
fieldValue.Set(reflect.ValueOf(&x))
|
||||
}
|
||||
case core.Complex64Type:
|
||||
var x complex64
|
||||
if len([]byte(vv.String())) > 0 {
|
||||
err := json.Unmarshal([]byte(vv.String()), &x)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fieldValue.Set(reflect.ValueOf(&x))
|
||||
}
|
||||
hasAssigned = true
|
||||
case core.Complex128Type:
|
||||
var x complex128
|
||||
if len([]byte(vv.String())) > 0 {
|
||||
err := json.Unmarshal([]byte(vv.String()), &x)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fieldValue.Set(reflect.ValueOf(&x))
|
||||
}
|
||||
hasAssigned = true
|
||||
} // switch fieldType
|
||||
} // switch fieldType.Kind()
|
||||
|
||||
// !nashtsai! for value can't be assigned directly fallback to convert to []byte then back to value
|
||||
if !hasAssigned {
|
||||
data, err := value2Bytes(&rawValue)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = session.bytes2Value(col, fieldValue, data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -828,15 +834,6 @@ func (session *Session) LastSQL() (string, []interface{}) {
|
|||
return session.lastSQL, session.lastSQLArgs
|
||||
}
|
||||
|
||||
// tbName get some table's table name
|
||||
func (session *Session) tbNameNoSchema(table *core.Table) string {
|
||||
if len(session.statement.AltTableName) > 0 {
|
||||
return session.statement.AltTableName
|
||||
}
|
||||
|
||||
return table.Name
|
||||
}
|
||||
|
||||
// Unscoped always disable struct tag "deleted"
|
||||
func (session *Session) Unscoped() *Session {
|
||||
session.statement.Unscoped()
|
||||
|
|
115
vendor/github.com/go-xorm/xorm/session_cols.go
generated
vendored
115
vendor/github.com/go-xorm/xorm/session_cols.go
generated
vendored
|
@ -4,6 +4,121 @@
|
|||
|
||||
package xorm
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-xorm/core"
|
||||
)
|
||||
|
||||
type incrParam struct {
|
||||
colName string
|
||||
arg interface{}
|
||||
}
|
||||
|
||||
type decrParam struct {
|
||||
colName string
|
||||
arg interface{}
|
||||
}
|
||||
|
||||
type exprParam struct {
|
||||
colName string
|
||||
expr string
|
||||
}
|
||||
|
||||
type columnMap []string
|
||||
|
||||
func (m columnMap) contain(colName string) bool {
|
||||
if len(m) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
n := len(colName)
|
||||
for _, mk := range m {
|
||||
if len(mk) != n {
|
||||
continue
|
||||
}
|
||||
if strings.EqualFold(mk, colName) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *columnMap) add(colName string) bool {
|
||||
if m.contain(colName) {
|
||||
return false
|
||||
}
|
||||
*m = append(*m, colName)
|
||||
return true
|
||||
}
|
||||
|
||||
func setColumnInt(bean interface{}, col *core.Column, t int64) {
|
||||
v, err := col.ValueOf(bean)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if v.CanSet() {
|
||||
switch v.Type().Kind() {
|
||||
case reflect.Int, reflect.Int64, reflect.Int32:
|
||||
v.SetInt(t)
|
||||
case reflect.Uint, reflect.Uint64, reflect.Uint32:
|
||||
v.SetUint(uint64(t))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setColumnTime(bean interface{}, col *core.Column, t time.Time) {
|
||||
v, err := col.ValueOf(bean)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if v.CanSet() {
|
||||
switch v.Type().Kind() {
|
||||
case reflect.Struct:
|
||||
v.Set(reflect.ValueOf(t).Convert(v.Type()))
|
||||
case reflect.Int, reflect.Int64, reflect.Int32:
|
||||
v.SetInt(t.Unix())
|
||||
case reflect.Uint, reflect.Uint64, reflect.Uint32:
|
||||
v.SetUint(uint64(t.Unix()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getFlagForColumn(m map[string]bool, col *core.Column) (val bool, has bool) {
|
||||
if len(m) == 0 {
|
||||
return false, false
|
||||
}
|
||||
|
||||
n := len(col.Name)
|
||||
|
||||
for mk := range m {
|
||||
if len(mk) != n {
|
||||
continue
|
||||
}
|
||||
if strings.EqualFold(mk, col.Name) {
|
||||
return m[mk], true
|
||||
}
|
||||
}
|
||||
|
||||
return false, false
|
||||
}
|
||||
|
||||
func col2NewCols(columns ...string) []string {
|
||||
newColumns := make([]string, 0, len(columns))
|
||||
for _, col := range columns {
|
||||
col = strings.Replace(col, "`", "", -1)
|
||||
col = strings.Replace(col, `"`, "", -1)
|
||||
ccols := strings.Split(col, ",")
|
||||
for _, c := range ccols {
|
||||
newColumns = append(newColumns, strings.TrimSpace(c))
|
||||
}
|
||||
}
|
||||
return newColumns
|
||||
}
|
||||
|
||||
// Incr provides a query string like "count = count + 1"
|
||||
func (session *Session) Incr(column string, arg ...interface{}) *Session {
|
||||
session.statement.Incr(column, arg...)
|
||||
|
|
6
vendor/github.com/go-xorm/xorm/session_delete.go
generated
vendored
6
vendor/github.com/go-xorm/xorm/session_delete.go
generated
vendored
|
@ -27,7 +27,7 @@ func (session *Session) cacheDelete(table *core.Table, tableName, sqlStr string,
|
|||
return ErrCacheFailed
|
||||
}
|
||||
|
||||
cacher := session.engine.getCacher2(table)
|
||||
cacher := session.engine.getCacher(tableName)
|
||||
pkColumns := table.PKColumns()
|
||||
ids, err := core.GetCacheSql(cacher, tableName, newsql, args)
|
||||
if err != nil {
|
||||
|
@ -79,7 +79,7 @@ func (session *Session) Delete(bean interface{}) (int64, error) {
|
|||
defer session.Close()
|
||||
}
|
||||
|
||||
if err := session.statement.setRefValue(rValue(bean)); err != nil {
|
||||
if err := session.statement.setRefBean(bean); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
|
@ -199,7 +199,7 @@ func (session *Session) Delete(bean interface{}) (int64, error) {
|
|||
})
|
||||
}
|
||||
|
||||
if cacher := session.engine.getCacher2(table); cacher != nil && session.statement.UseCache {
|
||||
if cacher := session.engine.getCacher(tableName); cacher != nil && session.statement.UseCache {
|
||||
session.cacheDelete(table, tableNameNoQuote, deleteSQL, argsForCache...)
|
||||
}
|
||||
|
||||
|
|
2
vendor/github.com/go-xorm/xorm/session_exist.go
generated
vendored
2
vendor/github.com/go-xorm/xorm/session_exist.go
generated
vendored
|
@ -57,7 +57,7 @@ func (session *Session) Exist(bean ...interface{}) (bool, error) {
|
|||
}
|
||||
|
||||
if beanValue.Elem().Kind() == reflect.Struct {
|
||||
if err := session.statement.setRefValue(beanValue.Elem()); err != nil {
|
||||
if err := session.statement.setRefBean(bean[0]); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
|
49
vendor/github.com/go-xorm/xorm/session_find.go
generated
vendored
49
vendor/github.com/go-xorm/xorm/session_find.go
generated
vendored
|
@ -29,6 +29,39 @@ func (session *Session) Find(rowsSlicePtr interface{}, condiBean ...interface{})
|
|||
return session.find(rowsSlicePtr, condiBean...)
|
||||
}
|
||||
|
||||
// FindAndCount find the results and also return the counts
|
||||
func (session *Session) FindAndCount(rowsSlicePtr interface{}, condiBean ...interface{}) (int64, error) {
|
||||
if session.isAutoClose {
|
||||
defer session.Close()
|
||||
}
|
||||
|
||||
session.autoResetStatement = false
|
||||
err := session.find(rowsSlicePtr, condiBean...)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
sliceValue := reflect.Indirect(reflect.ValueOf(rowsSlicePtr))
|
||||
if sliceValue.Kind() != reflect.Slice && sliceValue.Kind() != reflect.Map {
|
||||
return 0, errors.New("needs a pointer to a slice or a map")
|
||||
}
|
||||
|
||||
sliceElementType := sliceValue.Type().Elem()
|
||||
if sliceElementType.Kind() == reflect.Ptr {
|
||||
sliceElementType = sliceElementType.Elem()
|
||||
}
|
||||
session.autoResetStatement = true
|
||||
|
||||
if session.statement.selectStr != "" {
|
||||
session.statement.selectStr = ""
|
||||
}
|
||||
if session.statement.OrderStr != "" {
|
||||
session.statement.OrderStr = ""
|
||||
}
|
||||
|
||||
return session.Count(reflect.New(sliceElementType).Interface())
|
||||
}
|
||||
|
||||
func (session *Session) find(rowsSlicePtr interface{}, condiBean ...interface{}) error {
|
||||
sliceValue := reflect.Indirect(reflect.ValueOf(rowsSlicePtr))
|
||||
if sliceValue.Kind() != reflect.Slice && sliceValue.Kind() != reflect.Map {
|
||||
|
@ -42,7 +75,7 @@ func (session *Session) find(rowsSlicePtr interface{}, condiBean ...interface{})
|
|||
if sliceElementType.Kind() == reflect.Ptr {
|
||||
if sliceElementType.Elem().Kind() == reflect.Struct {
|
||||
pv := reflect.New(sliceElementType.Elem())
|
||||
if err := session.statement.setRefValue(pv.Elem()); err != nil {
|
||||
if err := session.statement.setRefValue(pv); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
|
@ -50,7 +83,7 @@ func (session *Session) find(rowsSlicePtr interface{}, condiBean ...interface{})
|
|||
}
|
||||
} else if sliceElementType.Kind() == reflect.Struct {
|
||||
pv := reflect.New(sliceElementType)
|
||||
if err := session.statement.setRefValue(pv.Elem()); err != nil {
|
||||
if err := session.statement.setRefValue(pv); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
|
@ -128,7 +161,7 @@ func (session *Session) find(rowsSlicePtr interface{}, condiBean ...interface{})
|
|||
}
|
||||
|
||||
args = append(session.statement.joinArgs, condArgs...)
|
||||
sqlStr, err = session.statement.genSelectSQL(columnStr, condSQL)
|
||||
sqlStr, err = session.statement.genSelectSQL(columnStr, condSQL, true, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -143,7 +176,7 @@ func (session *Session) find(rowsSlicePtr interface{}, condiBean ...interface{})
|
|||
}
|
||||
|
||||
if session.canCache() {
|
||||
if cacher := session.engine.getCacher2(table); cacher != nil &&
|
||||
if cacher := session.engine.getCacher(table.Name); cacher != nil &&
|
||||
!session.statement.IsDistinct &&
|
||||
!session.statement.unscoped {
|
||||
err = session.cacheFind(sliceElementType, sqlStr, rowsSlicePtr, args...)
|
||||
|
@ -288,6 +321,12 @@ func (session *Session) cacheFind(t reflect.Type, sqlStr string, rowsSlicePtr in
|
|||
return ErrCacheFailed
|
||||
}
|
||||
|
||||
tableName := session.statement.TableName()
|
||||
cacher := session.engine.getCacher(tableName)
|
||||
if cacher == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, filter := range session.engine.dialect.Filters() {
|
||||
sqlStr = filter.Do(sqlStr, session.engine.dialect, session.statement.RefTable)
|
||||
}
|
||||
|
@ -297,9 +336,7 @@ func (session *Session) cacheFind(t reflect.Type, sqlStr string, rowsSlicePtr in
|
|||
return ErrCacheFailed
|
||||
}
|
||||
|
||||
tableName := session.statement.TableName()
|
||||
table := session.statement.RefTable
|
||||
cacher := session.engine.getCacher2(table)
|
||||
ids, err := core.GetCacheSql(cacher, tableName, newsql, args)
|
||||
if err != nil {
|
||||
rows, err := session.queryRows(newsql, args...)
|
||||
|
|
7
vendor/github.com/go-xorm/xorm/session_get.go
generated
vendored
7
vendor/github.com/go-xorm/xorm/session_get.go
generated
vendored
|
@ -31,7 +31,7 @@ func (session *Session) get(bean interface{}) (bool, error) {
|
|||
}
|
||||
|
||||
if beanValue.Elem().Kind() == reflect.Struct {
|
||||
if err := session.statement.setRefValue(beanValue.Elem()); err != nil {
|
||||
if err := session.statement.setRefBean(bean); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ func (session *Session) get(bean interface{}) (bool, error) {
|
|||
table := session.statement.RefTable
|
||||
|
||||
if session.canCache() && beanValue.Elem().Kind() == reflect.Struct {
|
||||
if cacher := session.engine.getCacher2(table); cacher != nil &&
|
||||
if cacher := session.engine.getCacher(table.Name); cacher != nil &&
|
||||
!session.statement.unscoped {
|
||||
has, err := session.cacheGet(bean, sqlStr, args...)
|
||||
if err != ErrCacheFailed {
|
||||
|
@ -134,8 +134,9 @@ func (session *Session) cacheGet(bean interface{}, sqlStr string, args ...interf
|
|||
return false, ErrCacheFailed
|
||||
}
|
||||
|
||||
cacher := session.engine.getCacher2(session.statement.RefTable)
|
||||
tableName := session.statement.TableName()
|
||||
cacher := session.engine.getCacher(tableName)
|
||||
|
||||
session.engine.logger.Debug("[cacheGet] find sql:", newsql, args)
|
||||
table := session.statement.RefTable
|
||||
ids, err := core.GetCacheSql(cacher, tableName, newsql, args)
|
||||
|
|
168
vendor/github.com/go-xorm/xorm/session_insert.go
generated
vendored
168
vendor/github.com/go-xorm/xorm/session_insert.go
generated
vendored
|
@ -66,11 +66,12 @@ func (session *Session) innerInsertMulti(rowsSlicePtr interface{}) (int64, error
|
|||
return 0, errors.New("could not insert a empty slice")
|
||||
}
|
||||
|
||||
if err := session.statement.setRefValue(reflect.ValueOf(sliceValue.Index(0).Interface())); err != nil {
|
||||
if err := session.statement.setRefBean(sliceValue.Index(0).Interface()); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if len(session.statement.TableName()) <= 0 {
|
||||
tableName := session.statement.TableName()
|
||||
if len(tableName) <= 0 {
|
||||
return 0, ErrTableNotFound
|
||||
}
|
||||
|
||||
|
@ -115,15 +116,11 @@ func (session *Session) innerInsertMulti(rowsSlicePtr interface{}) (int64, error
|
|||
if col.IsDeleted {
|
||||
continue
|
||||
}
|
||||
if session.statement.ColumnStr != "" {
|
||||
if _, ok := getFlagForColumn(session.statement.columnMap, col); !ok {
|
||||
continue
|
||||
}
|
||||
if session.statement.omitColumnMap.contain(col.Name) {
|
||||
continue
|
||||
}
|
||||
if session.statement.OmitStr != "" {
|
||||
if _, ok := getFlagForColumn(session.statement.columnMap, col); ok {
|
||||
continue
|
||||
}
|
||||
if len(session.statement.columnMap) > 0 && !session.statement.columnMap.contain(col.Name) {
|
||||
continue
|
||||
}
|
||||
if (col.IsCreated || col.IsUpdated) && session.statement.UseAutoTime {
|
||||
val, t := session.engine.nowTime(col)
|
||||
|
@ -170,15 +167,11 @@ func (session *Session) innerInsertMulti(rowsSlicePtr interface{}) (int64, error
|
|||
if col.IsDeleted {
|
||||
continue
|
||||
}
|
||||
if session.statement.ColumnStr != "" {
|
||||
if _, ok := getFlagForColumn(session.statement.columnMap, col); !ok {
|
||||
continue
|
||||
}
|
||||
if session.statement.omitColumnMap.contain(col.Name) {
|
||||
continue
|
||||
}
|
||||
if session.statement.OmitStr != "" {
|
||||
if _, ok := getFlagForColumn(session.statement.columnMap, col); ok {
|
||||
continue
|
||||
}
|
||||
if len(session.statement.columnMap) > 0 && !session.statement.columnMap.contain(col.Name) {
|
||||
continue
|
||||
}
|
||||
if (col.IsCreated || col.IsUpdated) && session.statement.UseAutoTime {
|
||||
val, t := session.engine.nowTime(col)
|
||||
|
@ -211,38 +204,33 @@ func (session *Session) innerInsertMulti(rowsSlicePtr interface{}) (int64, error
|
|||
}
|
||||
cleanupProcessorsClosures(&session.beforeClosures)
|
||||
|
||||
var sql = "INSERT INTO %s (%v%v%v) VALUES (%v)"
|
||||
var statement string
|
||||
var tableName = session.statement.TableName()
|
||||
var sql string
|
||||
if session.engine.dialect.DBType() == core.ORACLE {
|
||||
sql = "INSERT ALL INTO %s (%v%v%v) VALUES (%v) SELECT 1 FROM DUAL"
|
||||
temp := fmt.Sprintf(") INTO %s (%v%v%v) VALUES (",
|
||||
session.engine.Quote(tableName),
|
||||
session.engine.QuoteStr(),
|
||||
strings.Join(colNames, session.engine.QuoteStr()+", "+session.engine.QuoteStr()),
|
||||
session.engine.QuoteStr())
|
||||
statement = fmt.Sprintf(sql,
|
||||
sql = fmt.Sprintf("INSERT ALL INTO %s (%v%v%v) VALUES (%v) SELECT 1 FROM DUAL",
|
||||
session.engine.Quote(tableName),
|
||||
session.engine.QuoteStr(),
|
||||
strings.Join(colNames, session.engine.QuoteStr()+", "+session.engine.QuoteStr()),
|
||||
session.engine.QuoteStr(),
|
||||
strings.Join(colMultiPlaces, temp))
|
||||
} else {
|
||||
statement = fmt.Sprintf(sql,
|
||||
sql = fmt.Sprintf("INSERT INTO %s (%v%v%v) VALUES (%v)",
|
||||
session.engine.Quote(tableName),
|
||||
session.engine.QuoteStr(),
|
||||
strings.Join(colNames, session.engine.QuoteStr()+", "+session.engine.QuoteStr()),
|
||||
session.engine.QuoteStr(),
|
||||
strings.Join(colMultiPlaces, "),("))
|
||||
}
|
||||
res, err := session.exec(statement, args...)
|
||||
res, err := session.exec(sql, args...)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if cacher := session.engine.getCacher2(table); cacher != nil && session.statement.UseCache {
|
||||
session.cacheInsert(table, tableName)
|
||||
}
|
||||
session.cacheInsert(tableName)
|
||||
|
||||
lenAfterClosures := len(session.afterClosures)
|
||||
for i := 0; i < size; i++ {
|
||||
|
@ -298,7 +286,7 @@ func (session *Session) InsertMulti(rowsSlicePtr interface{}) (int64, error) {
|
|||
}
|
||||
|
||||
func (session *Session) innerInsert(bean interface{}) (int64, error) {
|
||||
if err := session.statement.setRefValue(rValue(bean)); err != nil {
|
||||
if err := session.statement.setRefBean(bean); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if len(session.statement.TableName()) <= 0 {
|
||||
|
@ -316,8 +304,8 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
|
|||
if processor, ok := interface{}(bean).(BeforeInsertProcessor); ok {
|
||||
processor.BeforeInsert()
|
||||
}
|
||||
// --
|
||||
colNames, args, err := genCols(session.statement.RefTable, session, bean, false, false)
|
||||
|
||||
colNames, args, err := session.genInsertColumns(bean)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
@ -402,9 +390,7 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
|
|||
|
||||
defer handleAfterInsertProcessorFunc(bean)
|
||||
|
||||
if cacher := session.engine.getCacher2(table); cacher != nil && session.statement.UseCache {
|
||||
session.cacheInsert(table, tableName)
|
||||
}
|
||||
session.cacheInsert(tableName)
|
||||
|
||||
if table.Version != "" && session.statement.checkVersion {
|
||||
verValue, err := table.VersionColumn().ValueOf(bean)
|
||||
|
@ -447,9 +433,7 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
|
|||
}
|
||||
defer handleAfterInsertProcessorFunc(bean)
|
||||
|
||||
if cacher := session.engine.getCacher2(table); cacher != nil && session.statement.UseCache {
|
||||
session.cacheInsert(table, tableName)
|
||||
}
|
||||
session.cacheInsert(tableName)
|
||||
|
||||
if table.Version != "" && session.statement.checkVersion {
|
||||
verValue, err := table.VersionColumn().ValueOf(bean)
|
||||
|
@ -490,9 +474,7 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
|
|||
|
||||
defer handleAfterInsertProcessorFunc(bean)
|
||||
|
||||
if cacher := session.engine.getCacher2(table); cacher != nil && session.statement.UseCache {
|
||||
session.cacheInsert(table, tableName)
|
||||
}
|
||||
session.cacheInsert(tableName)
|
||||
|
||||
if table.Version != "" && session.statement.checkVersion {
|
||||
verValue, err := table.VersionColumn().ValueOf(bean)
|
||||
|
@ -539,16 +521,104 @@ func (session *Session) InsertOne(bean interface{}) (int64, error) {
|
|||
return session.innerInsert(bean)
|
||||
}
|
||||
|
||||
func (session *Session) cacheInsert(table *core.Table, tables ...string) error {
|
||||
if table == nil {
|
||||
return ErrCacheFailed
|
||||
func (session *Session) cacheInsert(table string) error {
|
||||
if !session.statement.UseCache {
|
||||
return nil
|
||||
}
|
||||
|
||||
cacher := session.engine.getCacher2(table)
|
||||
for _, t := range tables {
|
||||
session.engine.logger.Debug("[cache] clear sql:", t)
|
||||
cacher.ClearIds(t)
|
||||
cacher := session.engine.getCacher(table)
|
||||
if cacher == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
session.engine.logger.Debug("[cache] clear sql:", table)
|
||||
cacher.ClearIds(table)
|
||||
return nil
|
||||
}
|
||||
|
||||
// genInsertColumns generates insert needed columns
|
||||
func (session *Session) genInsertColumns(bean interface{}) ([]string, []interface{}, error) {
|
||||
table := session.statement.RefTable
|
||||
colNames := make([]string, 0, len(table.ColumnsSeq()))
|
||||
args := make([]interface{}, 0, len(table.ColumnsSeq()))
|
||||
|
||||
for _, col := range table.Columns() {
|
||||
if col.MapType == core.ONLYFROMDB {
|
||||
continue
|
||||
}
|
||||
|
||||
if col.IsDeleted {
|
||||
continue
|
||||
}
|
||||
|
||||
if session.statement.omitColumnMap.contain(col.Name) {
|
||||
continue
|
||||
}
|
||||
|
||||
if len(session.statement.columnMap) > 0 && !session.statement.columnMap.contain(col.Name) {
|
||||
continue
|
||||
}
|
||||
|
||||
if _, ok := session.statement.incrColumns[col.Name]; ok {
|
||||
continue
|
||||
} else if _, ok := session.statement.decrColumns[col.Name]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
fieldValuePtr, err := col.ValueOf(bean)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
fieldValue := *fieldValuePtr
|
||||
|
||||
if col.IsAutoIncrement {
|
||||
switch fieldValue.Type().Kind() {
|
||||
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int, reflect.Int64:
|
||||
if fieldValue.Int() == 0 {
|
||||
continue
|
||||
}
|
||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint, reflect.Uint64:
|
||||
if fieldValue.Uint() == 0 {
|
||||
continue
|
||||
}
|
||||
case reflect.String:
|
||||
if len(fieldValue.String()) == 0 {
|
||||
continue
|
||||
}
|
||||
case reflect.Ptr:
|
||||
if fieldValue.Pointer() == 0 {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// !evalphobia! set fieldValue as nil when column is nullable and zero-value
|
||||
if _, ok := getFlagForColumn(session.statement.nullableMap, col); ok {
|
||||
if col.Nullable && isZero(fieldValue.Interface()) {
|
||||
var nilValue *int
|
||||
fieldValue = reflect.ValueOf(nilValue)
|
||||
}
|
||||
}
|
||||
|
||||
if (col.IsCreated || col.IsUpdated) && session.statement.UseAutoTime /*&& isZero(fieldValue.Interface())*/ {
|
||||
// if time is non-empty, then set to auto time
|
||||
val, t := session.engine.nowTime(col)
|
||||
args = append(args, val)
|
||||
|
||||
var colName = col.Name
|
||||
session.afterClosures = append(session.afterClosures, func(bean interface{}) {
|
||||
col := table.GetColumn(colName)
|
||||
setColumnTime(bean, col, t)
|
||||
})
|
||||
} else if col.IsVersion && session.statement.checkVersion {
|
||||
args = append(args, 1)
|
||||
} else {
|
||||
arg, err := session.value2Interface(col, fieldValue)
|
||||
if err != nil {
|
||||
return colNames, args, err
|
||||
}
|
||||
args = append(args, arg)
|
||||
}
|
||||
|
||||
colNames = append(colNames, col.Name)
|
||||
}
|
||||
return colNames, args, nil
|
||||
}
|
||||
|
|
6
vendor/github.com/go-xorm/xorm/session_query.go
generated
vendored
6
vendor/github.com/go-xorm/xorm/session_query.go
generated
vendored
|
@ -64,13 +64,17 @@ func (session *Session) genQuerySQL(sqlorArgs ...interface{}) (string, []interfa
|
|||
}
|
||||
}
|
||||
|
||||
if err := session.statement.processIDParam(); err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
condSQL, condArgs, err := builder.ToSQL(session.statement.cond)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
args := append(session.statement.joinArgs, condArgs...)
|
||||
sqlStr, err := session.statement.genSelectSQL(columnStr, condSQL)
|
||||
sqlStr, err := session.statement.genSelectSQL(columnStr, condSQL, true, true)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
|
87
vendor/github.com/go-xorm/xorm/session_schema.go
generated
vendored
87
vendor/github.com/go-xorm/xorm/session_schema.go
generated
vendored
|
@ -6,9 +6,7 @@ package xorm
|
|||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/go-xorm/core"
|
||||
|
@ -34,8 +32,7 @@ func (session *Session) CreateTable(bean interface{}) error {
|
|||
}
|
||||
|
||||
func (session *Session) createTable(bean interface{}) error {
|
||||
v := rValue(bean)
|
||||
if err := session.statement.setRefValue(v); err != nil {
|
||||
if err := session.statement.setRefBean(bean); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -54,8 +51,7 @@ func (session *Session) CreateIndexes(bean interface{}) error {
|
|||
}
|
||||
|
||||
func (session *Session) createIndexes(bean interface{}) error {
|
||||
v := rValue(bean)
|
||||
if err := session.statement.setRefValue(v); err != nil {
|
||||
if err := session.statement.setRefBean(bean); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -78,8 +74,7 @@ func (session *Session) CreateUniques(bean interface{}) error {
|
|||
}
|
||||
|
||||
func (session *Session) createUniques(bean interface{}) error {
|
||||
v := rValue(bean)
|
||||
if err := session.statement.setRefValue(v); err != nil {
|
||||
if err := session.statement.setRefBean(bean); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -103,8 +98,7 @@ func (session *Session) DropIndexes(bean interface{}) error {
|
|||
}
|
||||
|
||||
func (session *Session) dropIndexes(bean interface{}) error {
|
||||
v := rValue(bean)
|
||||
if err := session.statement.setRefValue(v); err != nil {
|
||||
if err := session.statement.setRefBean(bean); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -128,11 +122,7 @@ func (session *Session) DropTable(beanOrTableName interface{}) error {
|
|||
}
|
||||
|
||||
func (session *Session) dropTable(beanOrTableName interface{}) error {
|
||||
tableName, err := session.engine.tableName(beanOrTableName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tableName := session.engine.TableName(beanOrTableName)
|
||||
var needDrop = true
|
||||
if !session.engine.dialect.SupportDropIfExists() {
|
||||
sqlStr, args := session.engine.dialect.TableCheckSql(tableName)
|
||||
|
@ -144,8 +134,8 @@ func (session *Session) dropTable(beanOrTableName interface{}) error {
|
|||
}
|
||||
|
||||
if needDrop {
|
||||
sqlStr := session.engine.Dialect().DropTableSql(tableName)
|
||||
_, err = session.exec(sqlStr)
|
||||
sqlStr := session.engine.Dialect().DropTableSql(session.engine.TableName(tableName, true))
|
||||
_, err := session.exec(sqlStr)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
@ -157,10 +147,7 @@ func (session *Session) IsTableExist(beanOrTableName interface{}) (bool, error)
|
|||
defer session.Close()
|
||||
}
|
||||
|
||||
tableName, err := session.engine.tableName(beanOrTableName)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
tableName := session.engine.TableName(beanOrTableName)
|
||||
|
||||
return session.isTableExist(tableName)
|
||||
}
|
||||
|
@ -173,24 +160,15 @@ func (session *Session) isTableExist(tableName string) (bool, error) {
|
|||
|
||||
// IsTableEmpty if table have any records
|
||||
func (session *Session) IsTableEmpty(bean interface{}) (bool, error) {
|
||||
v := rValue(bean)
|
||||
t := v.Type()
|
||||
|
||||
if t.Kind() == reflect.String {
|
||||
if session.isAutoClose {
|
||||
defer session.Close()
|
||||
}
|
||||
return session.isTableEmpty(bean.(string))
|
||||
} else if t.Kind() == reflect.Struct {
|
||||
rows, err := session.Count(bean)
|
||||
return rows == 0, err
|
||||
if session.isAutoClose {
|
||||
defer session.Close()
|
||||
}
|
||||
return false, errors.New("bean should be a struct or struct's point")
|
||||
return session.isTableEmpty(session.engine.TableName(bean))
|
||||
}
|
||||
|
||||
func (session *Session) isTableEmpty(tableName string) (bool, error) {
|
||||
var total int64
|
||||
sqlStr := fmt.Sprintf("select count(*) from %s", session.engine.Quote(tableName))
|
||||
sqlStr := fmt.Sprintf("select count(*) from %s", session.engine.Quote(session.engine.TableName(tableName, true)))
|
||||
err := session.queryRow(sqlStr).Scan(&total)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
|
@ -255,6 +233,12 @@ func (session *Session) Sync2(beans ...interface{}) error {
|
|||
return err
|
||||
}
|
||||
|
||||
session.autoResetStatement = false
|
||||
defer func() {
|
||||
session.autoResetStatement = true
|
||||
session.resetStatement()
|
||||
}()
|
||||
|
||||
var structTables []*core.Table
|
||||
|
||||
for _, bean := range beans {
|
||||
|
@ -264,7 +248,8 @@ func (session *Session) Sync2(beans ...interface{}) error {
|
|||
return err
|
||||
}
|
||||
structTables = append(structTables, table)
|
||||
var tbName = session.tbNameNoSchema(table)
|
||||
tbName := engine.TableName(bean)
|
||||
tbNameWithSchema := engine.TableName(tbName, true)
|
||||
|
||||
var oriTable *core.Table
|
||||
for _, tb := range tables {
|
||||
|
@ -309,32 +294,32 @@ func (session *Session) Sync2(beans ...interface{}) error {
|
|||
if engine.dialect.DBType() == core.MYSQL ||
|
||||
engine.dialect.DBType() == core.POSTGRES {
|
||||
engine.logger.Infof("Table %s column %s change type from %s to %s\n",
|
||||
tbName, col.Name, curType, expectedType)
|
||||
_, err = session.exec(engine.dialect.ModifyColumnSql(table.Name, col))
|
||||
tbNameWithSchema, col.Name, curType, expectedType)
|
||||
_, err = session.exec(engine.dialect.ModifyColumnSql(tbNameWithSchema, col))
|
||||
} else {
|
||||
engine.logger.Warnf("Table %s column %s db type is %s, struct type is %s\n",
|
||||
tbName, col.Name, curType, expectedType)
|
||||
tbNameWithSchema, col.Name, curType, expectedType)
|
||||
}
|
||||
} else if strings.HasPrefix(curType, core.Varchar) && strings.HasPrefix(expectedType, core.Varchar) {
|
||||
if engine.dialect.DBType() == core.MYSQL {
|
||||
if oriCol.Length < col.Length {
|
||||
engine.logger.Infof("Table %s column %s change type from varchar(%d) to varchar(%d)\n",
|
||||
tbName, col.Name, oriCol.Length, col.Length)
|
||||
_, err = session.exec(engine.dialect.ModifyColumnSql(table.Name, col))
|
||||
tbNameWithSchema, col.Name, oriCol.Length, col.Length)
|
||||
_, err = session.exec(engine.dialect.ModifyColumnSql(tbNameWithSchema, col))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if !(strings.HasPrefix(curType, expectedType) && curType[len(expectedType)] == '(') {
|
||||
engine.logger.Warnf("Table %s column %s db type is %s, struct type is %s",
|
||||
tbName, col.Name, curType, expectedType)
|
||||
tbNameWithSchema, col.Name, curType, expectedType)
|
||||
}
|
||||
}
|
||||
} else if expectedType == core.Varchar {
|
||||
if engine.dialect.DBType() == core.MYSQL {
|
||||
if oriCol.Length < col.Length {
|
||||
engine.logger.Infof("Table %s column %s change type from varchar(%d) to varchar(%d)\n",
|
||||
tbName, col.Name, oriCol.Length, col.Length)
|
||||
_, err = session.exec(engine.dialect.ModifyColumnSql(table.Name, col))
|
||||
tbNameWithSchema, col.Name, oriCol.Length, col.Length)
|
||||
_, err = session.exec(engine.dialect.ModifyColumnSql(tbNameWithSchema, col))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -348,7 +333,7 @@ func (session *Session) Sync2(beans ...interface{}) error {
|
|||
}
|
||||
} else {
|
||||
session.statement.RefTable = table
|
||||
session.statement.tableName = tbName
|
||||
session.statement.tableName = tbNameWithSchema
|
||||
err = session.addColumn(col.Name)
|
||||
}
|
||||
if err != nil {
|
||||
|
@ -371,7 +356,7 @@ func (session *Session) Sync2(beans ...interface{}) error {
|
|||
|
||||
if oriIndex != nil {
|
||||
if oriIndex.Type != index.Type {
|
||||
sql := engine.dialect.DropIndexSql(tbName, oriIndex)
|
||||
sql := engine.dialect.DropIndexSql(tbNameWithSchema, oriIndex)
|
||||
_, err = session.exec(sql)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -387,7 +372,7 @@ func (session *Session) Sync2(beans ...interface{}) error {
|
|||
|
||||
for name2, index2 := range oriTable.Indexes {
|
||||
if _, ok := foundIndexNames[name2]; !ok {
|
||||
sql := engine.dialect.DropIndexSql(tbName, index2)
|
||||
sql := engine.dialect.DropIndexSql(tbNameWithSchema, index2)
|
||||
_, err = session.exec(sql)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -398,12 +383,12 @@ func (session *Session) Sync2(beans ...interface{}) error {
|
|||
for name, index := range addedNames {
|
||||
if index.Type == core.UniqueType {
|
||||
session.statement.RefTable = table
|
||||
session.statement.tableName = tbName
|
||||
err = session.addUnique(tbName, name)
|
||||
session.statement.tableName = tbNameWithSchema
|
||||
err = session.addUnique(tbNameWithSchema, name)
|
||||
} else if index.Type == core.IndexType {
|
||||
session.statement.RefTable = table
|
||||
session.statement.tableName = tbName
|
||||
err = session.addIndex(tbName, name)
|
||||
session.statement.tableName = tbNameWithSchema
|
||||
err = session.addIndex(tbNameWithSchema, name)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -428,7 +413,7 @@ func (session *Session) Sync2(beans ...interface{}) error {
|
|||
|
||||
for _, colName := range table.ColumnsSeq() {
|
||||
if oriTable.GetColumn(colName) == nil {
|
||||
engine.logger.Warnf("Table %s has column %s but struct has not related field", table.Name, colName)
|
||||
engine.logger.Warnf("Table %s has column %s but struct has not related field", engine.TableName(table.Name, true), colName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
2
vendor/github.com/go-xorm/xorm/session_tx.go
generated
vendored
2
vendor/github.com/go-xorm/xorm/session_tx.go
generated
vendored
|
@ -24,6 +24,7 @@ func (session *Session) Rollback() error {
|
|||
if !session.isAutoCommit && !session.isCommitedOrRollbacked {
|
||||
session.saveLastSQL(session.engine.dialect.RollBackStr())
|
||||
session.isCommitedOrRollbacked = true
|
||||
session.isAutoCommit = true
|
||||
return session.tx.Rollback()
|
||||
}
|
||||
return nil
|
||||
|
@ -34,6 +35,7 @@ func (session *Session) Commit() error {
|
|||
if !session.isAutoCommit && !session.isCommitedOrRollbacked {
|
||||
session.saveLastSQL("COMMIT")
|
||||
session.isCommitedOrRollbacked = true
|
||||
session.isAutoCommit = true
|
||||
var err error
|
||||
if err = session.tx.Commit(); err == nil {
|
||||
// handle processors after tx committed
|
||||
|
|
115
vendor/github.com/go-xorm/xorm/session_update.go
generated
vendored
115
vendor/github.com/go-xorm/xorm/session_update.go
generated
vendored
|
@ -40,7 +40,7 @@ func (session *Session) cacheUpdate(table *core.Table, tableName, sqlStr string,
|
|||
}
|
||||
}
|
||||
|
||||
cacher := session.engine.getCacher2(table)
|
||||
cacher := session.engine.getCacher(tableName)
|
||||
session.engine.logger.Debug("[cacheUpdate] get cache sql", newsql, args[nStart:])
|
||||
ids, err := core.GetCacheSql(cacher, tableName, newsql, args[nStart:])
|
||||
if err != nil {
|
||||
|
@ -167,7 +167,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
|
|||
var isMap = t.Kind() == reflect.Map
|
||||
var isStruct = t.Kind() == reflect.Struct
|
||||
if isStruct {
|
||||
if err := session.statement.setRefValue(v); err != nil {
|
||||
if err := session.statement.setRefBean(bean); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
|
@ -176,12 +176,10 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
|
|||
}
|
||||
|
||||
if session.statement.ColumnStr == "" {
|
||||
colNames, args = buildUpdates(session.engine, session.statement.RefTable, bean, false, false,
|
||||
false, false, session.statement.allUseBool, session.statement.useAllCols,
|
||||
session.statement.mustColumnMap, session.statement.nullableMap,
|
||||
session.statement.columnMap, true, session.statement.unscoped)
|
||||
colNames, args = session.statement.buildUpdates(bean, false, false,
|
||||
false, false, true)
|
||||
} else {
|
||||
colNames, args, err = genCols(session.statement.RefTable, session, bean, true, true)
|
||||
colNames, args, err = session.genUpdateColumns(bean)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
@ -202,7 +200,8 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
|
|||
table := session.statement.RefTable
|
||||
|
||||
if session.statement.UseAutoTime && table != nil && table.Updated != "" {
|
||||
if _, ok := session.statement.columnMap[strings.ToLower(table.Updated)]; !ok {
|
||||
if !session.statement.columnMap.contain(table.Updated) &&
|
||||
!session.statement.omitColumnMap.contain(table.Updated) {
|
||||
colNames = append(colNames, session.engine.Quote(table.Updated)+" = ?")
|
||||
col := table.UpdatedColumn()
|
||||
val, t := session.engine.nowTime(col)
|
||||
|
@ -362,12 +361,11 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
|
|||
}
|
||||
}
|
||||
|
||||
if table != nil {
|
||||
if cacher := session.engine.getCacher2(table); cacher != nil && session.statement.UseCache {
|
||||
//session.cacheUpdate(table, tableName, sqlStr, args...)
|
||||
cacher.ClearIds(tableName)
|
||||
cacher.ClearBeans(tableName)
|
||||
}
|
||||
if cacher := session.engine.getCacher(tableName); cacher != nil && session.statement.UseCache {
|
||||
//session.cacheUpdate(table, tableName, sqlStr, args...)
|
||||
session.engine.logger.Debug("[cacheUpdate] clear table ", tableName)
|
||||
cacher.ClearIds(tableName)
|
||||
cacher.ClearBeans(tableName)
|
||||
}
|
||||
|
||||
// handle after update processors
|
||||
|
@ -402,3 +400,92 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
|
|||
|
||||
return res.RowsAffected()
|
||||
}
|
||||
|
||||
func (session *Session) genUpdateColumns(bean interface{}) ([]string, []interface{}, error) {
|
||||
table := session.statement.RefTable
|
||||
colNames := make([]string, 0, len(table.ColumnsSeq()))
|
||||
args := make([]interface{}, 0, len(table.ColumnsSeq()))
|
||||
|
||||
for _, col := range table.Columns() {
|
||||
if !col.IsVersion && !col.IsCreated && !col.IsUpdated {
|
||||
if session.statement.omitColumnMap.contain(col.Name) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if col.MapType == core.ONLYFROMDB {
|
||||
continue
|
||||
}
|
||||
|
||||
fieldValuePtr, err := col.ValueOf(bean)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
fieldValue := *fieldValuePtr
|
||||
|
||||
if col.IsAutoIncrement {
|
||||
switch fieldValue.Type().Kind() {
|
||||
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int, reflect.Int64:
|
||||
if fieldValue.Int() == 0 {
|
||||
continue
|
||||
}
|
||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint, reflect.Uint64:
|
||||
if fieldValue.Uint() == 0 {
|
||||
continue
|
||||
}
|
||||
case reflect.String:
|
||||
if len(fieldValue.String()) == 0 {
|
||||
continue
|
||||
}
|
||||
case reflect.Ptr:
|
||||
if fieldValue.Pointer() == 0 {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if col.IsDeleted || col.IsCreated {
|
||||
continue
|
||||
}
|
||||
|
||||
if len(session.statement.columnMap) > 0 {
|
||||
if !session.statement.columnMap.contain(col.Name) {
|
||||
continue
|
||||
} else if _, ok := session.statement.incrColumns[col.Name]; ok {
|
||||
continue
|
||||
} else if _, ok := session.statement.decrColumns[col.Name]; ok {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// !evalphobia! set fieldValue as nil when column is nullable and zero-value
|
||||
if _, ok := getFlagForColumn(session.statement.nullableMap, col); ok {
|
||||
if col.Nullable && isZero(fieldValue.Interface()) {
|
||||
var nilValue *int
|
||||
fieldValue = reflect.ValueOf(nilValue)
|
||||
}
|
||||
}
|
||||
|
||||
if col.IsUpdated && session.statement.UseAutoTime /*&& isZero(fieldValue.Interface())*/ {
|
||||
// if time is non-empty, then set to auto time
|
||||
val, t := session.engine.nowTime(col)
|
||||
args = append(args, val)
|
||||
|
||||
var colName = col.Name
|
||||
session.afterClosures = append(session.afterClosures, func(bean interface{}) {
|
||||
col := table.GetColumn(colName)
|
||||
setColumnTime(bean, col, t)
|
||||
})
|
||||
} else if col.IsVersion && session.statement.checkVersion {
|
||||
args = append(args, 1)
|
||||
} else {
|
||||
arg, err := session.value2Interface(col, fieldValue)
|
||||
if err != nil {
|
||||
return colNames, args, err
|
||||
}
|
||||
args = append(args, arg)
|
||||
}
|
||||
|
||||
colNames = append(colNames, session.engine.Quote(col.Name)+" = ?")
|
||||
}
|
||||
return colNames, args, nil
|
||||
}
|
||||
|
|
280
vendor/github.com/go-xorm/xorm/statement.go
generated
vendored
280
vendor/github.com/go-xorm/xorm/statement.go
generated
vendored
|
@ -5,7 +5,6 @@
|
|||
package xorm
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"database/sql/driver"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
@ -18,21 +17,6 @@ import (
|
|||
"github.com/go-xorm/core"
|
||||
)
|
||||
|
||||
type incrParam struct {
|
||||
colName string
|
||||
arg interface{}
|
||||
}
|
||||
|
||||
type decrParam struct {
|
||||
colName string
|
||||
arg interface{}
|
||||
}
|
||||
|
||||
type exprParam struct {
|
||||
colName string
|
||||
expr string
|
||||
}
|
||||
|
||||
// Statement save all the sql info for executing SQL
|
||||
type Statement struct {
|
||||
RefTable *core.Table
|
||||
|
@ -47,7 +31,6 @@ type Statement struct {
|
|||
HavingStr string
|
||||
ColumnStr string
|
||||
selectStr string
|
||||
columnMap map[string]bool
|
||||
useAllCols bool
|
||||
OmitStr string
|
||||
AltTableName string
|
||||
|
@ -67,6 +50,8 @@ type Statement struct {
|
|||
allUseBool bool
|
||||
checkVersion bool
|
||||
unscoped bool
|
||||
columnMap columnMap
|
||||
omitColumnMap columnMap
|
||||
mustColumnMap map[string]bool
|
||||
nullableMap map[string]bool
|
||||
incrColumns map[string]incrParam
|
||||
|
@ -89,7 +74,8 @@ func (statement *Statement) Init() {
|
|||
statement.HavingStr = ""
|
||||
statement.ColumnStr = ""
|
||||
statement.OmitStr = ""
|
||||
statement.columnMap = make(map[string]bool)
|
||||
statement.columnMap = columnMap{}
|
||||
statement.omitColumnMap = columnMap{}
|
||||
statement.AltTableName = ""
|
||||
statement.tableName = ""
|
||||
statement.idParam = nil
|
||||
|
@ -221,34 +207,33 @@ func (statement *Statement) setRefValue(v reflect.Value) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
statement.tableName = statement.Engine.tbName(v)
|
||||
statement.tableName = statement.Engine.TableName(v, true)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Table tempororily set table name, the parameter could be a string or a pointer of struct
|
||||
func (statement *Statement) Table(tableNameOrBean interface{}) *Statement {
|
||||
v := rValue(tableNameOrBean)
|
||||
t := v.Type()
|
||||
if t.Kind() == reflect.String {
|
||||
statement.AltTableName = tableNameOrBean.(string)
|
||||
} else if t.Kind() == reflect.Struct {
|
||||
var err error
|
||||
statement.RefTable, err = statement.Engine.autoMapType(v)
|
||||
if err != nil {
|
||||
statement.Engine.logger.Error(err)
|
||||
return statement
|
||||
}
|
||||
statement.AltTableName = statement.Engine.tbName(v)
|
||||
func (statement *Statement) setRefBean(bean interface{}) error {
|
||||
var err error
|
||||
statement.RefTable, err = statement.Engine.autoMapType(rValue(bean))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return statement
|
||||
statement.tableName = statement.Engine.TableName(bean, true)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Auto generating update columnes and values according a struct
|
||||
func buildUpdates(engine *Engine, table *core.Table, bean interface{},
|
||||
includeVersion bool, includeUpdated bool, includeNil bool,
|
||||
includeAutoIncr bool, allUseBool bool, useAllCols bool,
|
||||
mustColumnMap map[string]bool, nullableMap map[string]bool,
|
||||
columnMap map[string]bool, update, unscoped bool) ([]string, []interface{}) {
|
||||
func (statement *Statement) buildUpdates(bean interface{},
|
||||
includeVersion, includeUpdated, includeNil,
|
||||
includeAutoIncr, update bool) ([]string, []interface{}) {
|
||||
engine := statement.Engine
|
||||
table := statement.RefTable
|
||||
allUseBool := statement.allUseBool
|
||||
useAllCols := statement.useAllCols
|
||||
mustColumnMap := statement.mustColumnMap
|
||||
nullableMap := statement.nullableMap
|
||||
columnMap := statement.columnMap
|
||||
omitColumnMap := statement.omitColumnMap
|
||||
unscoped := statement.unscoped
|
||||
|
||||
var colNames = make([]string, 0)
|
||||
var args = make([]interface{}, 0)
|
||||
|
@ -268,7 +253,14 @@ func buildUpdates(engine *Engine, table *core.Table, bean interface{},
|
|||
if col.IsDeleted && !unscoped {
|
||||
continue
|
||||
}
|
||||
if use, ok := columnMap[strings.ToLower(col.Name)]; ok && !use {
|
||||
if omitColumnMap.contain(col.Name) {
|
||||
continue
|
||||
}
|
||||
if len(columnMap) > 0 && !columnMap.contain(col.Name) {
|
||||
continue
|
||||
}
|
||||
|
||||
if col.MapType == core.ONLYFROMDB {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -604,17 +596,10 @@ func (statement *Statement) col2NewColsWithQuote(columns ...string) []string {
|
|||
}
|
||||
|
||||
func (statement *Statement) colmap2NewColsWithQuote() []string {
|
||||
newColumns := make([]string, 0, len(statement.columnMap))
|
||||
for col := range statement.columnMap {
|
||||
fields := strings.Split(strings.TrimSpace(col), ".")
|
||||
if len(fields) == 1 {
|
||||
newColumns = append(newColumns, statement.Engine.quote(fields[0]))
|
||||
} else if len(fields) == 2 {
|
||||
newColumns = append(newColumns, statement.Engine.quote(fields[0])+"."+
|
||||
statement.Engine.quote(fields[1]))
|
||||
} else {
|
||||
panic(errors.New("unwanted colnames"))
|
||||
}
|
||||
newColumns := make([]string, len(statement.columnMap), len(statement.columnMap))
|
||||
copy(newColumns, statement.columnMap)
|
||||
for i := 0; i < len(statement.columnMap); i++ {
|
||||
newColumns[i] = statement.Engine.Quote(newColumns[i])
|
||||
}
|
||||
return newColumns
|
||||
}
|
||||
|
@ -642,10 +627,11 @@ func (statement *Statement) Select(str string) *Statement {
|
|||
func (statement *Statement) Cols(columns ...string) *Statement {
|
||||
cols := col2NewCols(columns...)
|
||||
for _, nc := range cols {
|
||||
statement.columnMap[strings.ToLower(nc)] = true
|
||||
statement.columnMap.add(nc)
|
||||
}
|
||||
|
||||
newColumns := statement.colmap2NewColsWithQuote()
|
||||
|
||||
statement.ColumnStr = strings.Join(newColumns, ", ")
|
||||
statement.ColumnStr = strings.Replace(statement.ColumnStr, statement.Engine.quote("*"), "*", -1)
|
||||
return statement
|
||||
|
@ -680,7 +666,7 @@ func (statement *Statement) UseBool(columns ...string) *Statement {
|
|||
func (statement *Statement) Omit(columns ...string) {
|
||||
newColumns := col2NewCols(columns...)
|
||||
for _, nc := range newColumns {
|
||||
statement.columnMap[strings.ToLower(nc)] = false
|
||||
statement.omitColumnMap = append(statement.omitColumnMap, nc)
|
||||
}
|
||||
statement.OmitStr = statement.Engine.Quote(strings.Join(newColumns, statement.Engine.Quote(", ")))
|
||||
}
|
||||
|
@ -719,10 +705,9 @@ func (statement *Statement) OrderBy(order string) *Statement {
|
|||
|
||||
// Desc generate `ORDER BY xx DESC`
|
||||
func (statement *Statement) Desc(colNames ...string) *Statement {
|
||||
var buf bytes.Buffer
|
||||
fmt.Fprintf(&buf, statement.OrderStr)
|
||||
var buf builder.StringBuilder
|
||||
if len(statement.OrderStr) > 0 {
|
||||
fmt.Fprint(&buf, ", ")
|
||||
fmt.Fprint(&buf, statement.OrderStr, ", ")
|
||||
}
|
||||
newColNames := statement.col2NewColsWithQuote(colNames...)
|
||||
fmt.Fprintf(&buf, "%v DESC", strings.Join(newColNames, " DESC, "))
|
||||
|
@ -732,10 +717,9 @@ func (statement *Statement) Desc(colNames ...string) *Statement {
|
|||
|
||||
// Asc provide asc order by query condition, the input parameters are columns.
|
||||
func (statement *Statement) Asc(colNames ...string) *Statement {
|
||||
var buf bytes.Buffer
|
||||
fmt.Fprintf(&buf, statement.OrderStr)
|
||||
var buf builder.StringBuilder
|
||||
if len(statement.OrderStr) > 0 {
|
||||
fmt.Fprint(&buf, ", ")
|
||||
fmt.Fprint(&buf, statement.OrderStr, ", ")
|
||||
}
|
||||
newColNames := statement.col2NewColsWithQuote(colNames...)
|
||||
fmt.Fprintf(&buf, "%v ASC", strings.Join(newColNames, " ASC, "))
|
||||
|
@ -743,48 +727,35 @@ func (statement *Statement) Asc(colNames ...string) *Statement {
|
|||
return statement
|
||||
}
|
||||
|
||||
// Table tempororily set table name, the parameter could be a string or a pointer of struct
|
||||
func (statement *Statement) Table(tableNameOrBean interface{}) *Statement {
|
||||
v := rValue(tableNameOrBean)
|
||||
t := v.Type()
|
||||
if t.Kind() == reflect.Struct {
|
||||
var err error
|
||||
statement.RefTable, err = statement.Engine.autoMapType(v)
|
||||
if err != nil {
|
||||
statement.Engine.logger.Error(err)
|
||||
return statement
|
||||
}
|
||||
}
|
||||
|
||||
statement.AltTableName = statement.Engine.TableName(tableNameOrBean, true)
|
||||
return statement
|
||||
}
|
||||
|
||||
// Join The joinOP should be one of INNER, LEFT OUTER, CROSS etc - this will be prepended to JOIN
|
||||
func (statement *Statement) Join(joinOP string, tablename interface{}, condition string, args ...interface{}) *Statement {
|
||||
var buf bytes.Buffer
|
||||
var buf builder.StringBuilder
|
||||
if len(statement.JoinStr) > 0 {
|
||||
fmt.Fprintf(&buf, "%v %v JOIN ", statement.JoinStr, joinOP)
|
||||
} else {
|
||||
fmt.Fprintf(&buf, "%v JOIN ", joinOP)
|
||||
}
|
||||
|
||||
switch tablename.(type) {
|
||||
case []string:
|
||||
t := tablename.([]string)
|
||||
if len(t) > 1 {
|
||||
fmt.Fprintf(&buf, "%v AS %v", statement.Engine.Quote(t[0]), statement.Engine.Quote(t[1]))
|
||||
} else if len(t) == 1 {
|
||||
fmt.Fprintf(&buf, statement.Engine.Quote(t[0]))
|
||||
}
|
||||
case []interface{}:
|
||||
t := tablename.([]interface{})
|
||||
l := len(t)
|
||||
var table string
|
||||
if l > 0 {
|
||||
f := t[0]
|
||||
v := rValue(f)
|
||||
t := v.Type()
|
||||
if t.Kind() == reflect.String {
|
||||
table = f.(string)
|
||||
} else if t.Kind() == reflect.Struct {
|
||||
table = statement.Engine.tbName(v)
|
||||
}
|
||||
}
|
||||
if l > 1 {
|
||||
fmt.Fprintf(&buf, "%v AS %v", statement.Engine.Quote(table),
|
||||
statement.Engine.Quote(fmt.Sprintf("%v", t[1])))
|
||||
} else if l == 1 {
|
||||
fmt.Fprintf(&buf, statement.Engine.Quote(table))
|
||||
}
|
||||
default:
|
||||
fmt.Fprintf(&buf, statement.Engine.Quote(fmt.Sprintf("%v", tablename)))
|
||||
}
|
||||
tbName := statement.Engine.TableName(tablename, true)
|
||||
|
||||
fmt.Fprintf(&buf, " ON %v", condition)
|
||||
fmt.Fprintf(&buf, "%s ON %v", tbName, condition)
|
||||
statement.JoinStr = buf.String()
|
||||
statement.joinArgs = append(statement.joinArgs, args...)
|
||||
return statement
|
||||
|
@ -809,18 +780,20 @@ func (statement *Statement) Unscoped() *Statement {
|
|||
}
|
||||
|
||||
func (statement *Statement) genColumnStr() string {
|
||||
var buf bytes.Buffer
|
||||
if statement.RefTable == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
var buf builder.StringBuilder
|
||||
columns := statement.RefTable.Columns()
|
||||
|
||||
for _, col := range columns {
|
||||
if statement.OmitStr != "" {
|
||||
if _, ok := getFlagForColumn(statement.columnMap, col); ok {
|
||||
continue
|
||||
}
|
||||
if statement.omitColumnMap.contain(col.Name) {
|
||||
continue
|
||||
}
|
||||
|
||||
if len(statement.columnMap) > 0 && !statement.columnMap.contain(col.Name) {
|
||||
continue
|
||||
}
|
||||
|
||||
if col.MapType == core.ONLYTODB {
|
||||
|
@ -831,10 +804,6 @@ func (statement *Statement) genColumnStr() string {
|
|||
buf.WriteString(", ")
|
||||
}
|
||||
|
||||
if col.IsPrimaryKey && statement.Engine.Dialect().DBType() == "ql" {
|
||||
buf.WriteString("id() AS ")
|
||||
}
|
||||
|
||||
if statement.JoinStr != "" {
|
||||
if statement.TableAlias != "" {
|
||||
buf.WriteString(statement.TableAlias)
|
||||
|
@ -859,11 +828,13 @@ func (statement *Statement) genCreateTableSQL() string {
|
|||
func (statement *Statement) genIndexSQL() []string {
|
||||
var sqls []string
|
||||
tbName := statement.TableName()
|
||||
quote := statement.Engine.Quote
|
||||
for idxName, index := range statement.RefTable.Indexes {
|
||||
for _, index := range statement.RefTable.Indexes {
|
||||
if index.Type == core.IndexType {
|
||||
sql := fmt.Sprintf("CREATE INDEX %v ON %v (%v);", quote(indexName(tbName, idxName)),
|
||||
quote(tbName), quote(strings.Join(index.Cols, quote(","))))
|
||||
sql := statement.Engine.dialect.CreateIndexSql(tbName, index)
|
||||
/*idxTBName := strings.Replace(tbName, ".", "_", -1)
|
||||
idxTBName = strings.Replace(idxTBName, `"`, "", -1)
|
||||
sql := fmt.Sprintf("CREATE INDEX %v ON %v (%v);", quote(indexName(idxTBName, idxName)),
|
||||
quote(tbName), quote(strings.Join(index.Cols, quote(","))))*/
|
||||
sqls = append(sqls, sql)
|
||||
}
|
||||
}
|
||||
|
@ -889,16 +860,18 @@ func (statement *Statement) genUniqueSQL() []string {
|
|||
func (statement *Statement) genDelIndexSQL() []string {
|
||||
var sqls []string
|
||||
tbName := statement.TableName()
|
||||
idxPrefixName := strings.Replace(tbName, `"`, "", -1)
|
||||
idxPrefixName = strings.Replace(idxPrefixName, `.`, "_", -1)
|
||||
for idxName, index := range statement.RefTable.Indexes {
|
||||
var rIdxName string
|
||||
if index.Type == core.UniqueType {
|
||||
rIdxName = uniqueName(tbName, idxName)
|
||||
rIdxName = uniqueName(idxPrefixName, idxName)
|
||||
} else if index.Type == core.IndexType {
|
||||
rIdxName = indexName(tbName, idxName)
|
||||
rIdxName = indexName(idxPrefixName, idxName)
|
||||
}
|
||||
sql := fmt.Sprintf("DROP INDEX %v", statement.Engine.Quote(rIdxName))
|
||||
sql := fmt.Sprintf("DROP INDEX %v", statement.Engine.Quote(statement.Engine.TableName(rIdxName, true)))
|
||||
if statement.Engine.dialect.IndexOnTable() {
|
||||
sql += fmt.Sprintf(" ON %v", statement.Engine.Quote(statement.TableName()))
|
||||
sql += fmt.Sprintf(" ON %v", statement.Engine.Quote(tbName))
|
||||
}
|
||||
sqls = append(sqls, sql)
|
||||
}
|
||||
|
@ -949,7 +922,7 @@ func (statement *Statement) genGetSQL(bean interface{}) (string, []interface{},
|
|||
v := rValue(bean)
|
||||
isStruct := v.Kind() == reflect.Struct
|
||||
if isStruct {
|
||||
statement.setRefValue(v)
|
||||
statement.setRefBean(bean)
|
||||
}
|
||||
|
||||
var columnStr = statement.ColumnStr
|
||||
|
@ -982,13 +955,17 @@ func (statement *Statement) genGetSQL(bean interface{}) (string, []interface{},
|
|||
if err := statement.mergeConds(bean); err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
} else {
|
||||
if err := statement.processIDParam(); err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
}
|
||||
condSQL, condArgs, err := builder.ToSQL(statement.cond)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
sqlStr, err := statement.genSelectSQL(columnStr, condSQL)
|
||||
sqlStr, err := statement.genSelectSQL(columnStr, condSQL, true, true)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
@ -1001,7 +978,7 @@ func (statement *Statement) genCountSQL(beans ...interface{}) (string, []interfa
|
|||
var condArgs []interface{}
|
||||
var err error
|
||||
if len(beans) > 0 {
|
||||
statement.setRefValue(rValue(beans[0]))
|
||||
statement.setRefBean(beans[0])
|
||||
condSQL, condArgs, err = statement.genConds(beans[0])
|
||||
} else {
|
||||
condSQL, condArgs, err = builder.ToSQL(statement.cond)
|
||||
|
@ -1018,7 +995,7 @@ func (statement *Statement) genCountSQL(beans ...interface{}) (string, []interfa
|
|||
selectSQL = "count(*)"
|
||||
}
|
||||
}
|
||||
sqlStr, err := statement.genSelectSQL(selectSQL, condSQL)
|
||||
sqlStr, err := statement.genSelectSQL(selectSQL, condSQL, false, false)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
@ -1027,7 +1004,7 @@ func (statement *Statement) genCountSQL(beans ...interface{}) (string, []interfa
|
|||
}
|
||||
|
||||
func (statement *Statement) genSumSQL(bean interface{}, columns ...string) (string, []interface{}, error) {
|
||||
statement.setRefValue(rValue(bean))
|
||||
statement.setRefBean(bean)
|
||||
|
||||
var sumStrs = make([]string, 0, len(columns))
|
||||
for _, colName := range columns {
|
||||
|
@ -1043,7 +1020,7 @@ func (statement *Statement) genSumSQL(bean interface{}, columns ...string) (stri
|
|||
return "", nil, err
|
||||
}
|
||||
|
||||
sqlStr, err := statement.genSelectSQL(sumSelect, condSQL)
|
||||
sqlStr, err := statement.genSelectSQL(sumSelect, condSQL, true, true)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
@ -1051,27 +1028,20 @@ func (statement *Statement) genSumSQL(bean interface{}, columns ...string) (stri
|
|||
return sqlStr, append(statement.joinArgs, condArgs...), nil
|
||||
}
|
||||
|
||||
func (statement *Statement) genSelectSQL(columnStr, condSQL string) (a string, err error) {
|
||||
var distinct string
|
||||
func (statement *Statement) genSelectSQL(columnStr, condSQL string, needLimit, needOrderBy bool) (string, error) {
|
||||
var (
|
||||
distinct string
|
||||
dialect = statement.Engine.Dialect()
|
||||
quote = statement.Engine.Quote
|
||||
fromStr = " FROM "
|
||||
top, mssqlCondi, whereStr string
|
||||
)
|
||||
if statement.IsDistinct && !strings.HasPrefix(columnStr, "count") {
|
||||
distinct = "DISTINCT "
|
||||
}
|
||||
|
||||
var dialect = statement.Engine.Dialect()
|
||||
var quote = statement.Engine.Quote
|
||||
var top string
|
||||
var mssqlCondi string
|
||||
|
||||
if err := statement.processIDParam(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
if len(condSQL) > 0 {
|
||||
fmt.Fprintf(&buf, " WHERE %v", condSQL)
|
||||
whereStr = " WHERE " + condSQL
|
||||
}
|
||||
var whereStr = buf.String()
|
||||
var fromStr = " FROM "
|
||||
|
||||
if dialect.DBType() == core.MSSQL && strings.Contains(statement.TableName(), "..") {
|
||||
fromStr += statement.TableName()
|
||||
|
@ -1118,9 +1088,10 @@ func (statement *Statement) genSelectSQL(columnStr, condSQL string) (a string, e
|
|||
}
|
||||
|
||||
var orderStr string
|
||||
if len(statement.OrderStr) > 0 {
|
||||
if needOrderBy && len(statement.OrderStr) > 0 {
|
||||
orderStr = " ORDER BY " + statement.OrderStr
|
||||
}
|
||||
|
||||
var groupStr string
|
||||
if len(statement.GroupByStr) > 0 {
|
||||
groupStr = " GROUP BY " + statement.GroupByStr
|
||||
|
@ -1130,45 +1101,50 @@ func (statement *Statement) genSelectSQL(columnStr, condSQL string) (a string, e
|
|||
}
|
||||
}
|
||||
|
||||
// !nashtsai! REVIEW Sprintf is considered slowest mean of string concatnation, better to work with builder pattern
|
||||
a = fmt.Sprintf("SELECT %v%v%v%v%v", distinct, top, columnStr, fromStr, whereStr)
|
||||
var buf builder.StringBuilder
|
||||
fmt.Fprintf(&buf, "SELECT %v%v%v%v%v", distinct, top, columnStr, fromStr, whereStr)
|
||||
if len(mssqlCondi) > 0 {
|
||||
if len(whereStr) > 0 {
|
||||
a += " AND " + mssqlCondi
|
||||
fmt.Fprint(&buf, " AND ", mssqlCondi)
|
||||
} else {
|
||||
a += " WHERE " + mssqlCondi
|
||||
fmt.Fprint(&buf, " WHERE ", mssqlCondi)
|
||||
}
|
||||
}
|
||||
|
||||
if statement.GroupByStr != "" {
|
||||
a = fmt.Sprintf("%v GROUP BY %v", a, statement.GroupByStr)
|
||||
fmt.Fprint(&buf, " GROUP BY ", statement.GroupByStr)
|
||||
}
|
||||
if statement.HavingStr != "" {
|
||||
a = fmt.Sprintf("%v %v", a, statement.HavingStr)
|
||||
fmt.Fprint(&buf, " ", statement.HavingStr)
|
||||
}
|
||||
if statement.OrderStr != "" {
|
||||
a = fmt.Sprintf("%v ORDER BY %v", a, statement.OrderStr)
|
||||
if needOrderBy && statement.OrderStr != "" {
|
||||
fmt.Fprint(&buf, " ORDER BY ", statement.OrderStr)
|
||||
}
|
||||
if dialect.DBType() != core.MSSQL && dialect.DBType() != core.ORACLE {
|
||||
if statement.Start > 0 {
|
||||
a = fmt.Sprintf("%v LIMIT %v OFFSET %v", a, statement.LimitN, statement.Start)
|
||||
} else if statement.LimitN > 0 {
|
||||
a = fmt.Sprintf("%v LIMIT %v", a, statement.LimitN)
|
||||
}
|
||||
} else if dialect.DBType() == core.ORACLE {
|
||||
if statement.Start != 0 || statement.LimitN != 0 {
|
||||
a = fmt.Sprintf("SELECT %v FROM (SELECT %v,ROWNUM RN FROM (%v) at WHERE ROWNUM <= %d) aat WHERE RN > %d", columnStr, columnStr, a, statement.Start+statement.LimitN, statement.Start)
|
||||
if needLimit {
|
||||
if dialect.DBType() != core.MSSQL && dialect.DBType() != core.ORACLE {
|
||||
if statement.Start > 0 {
|
||||
fmt.Fprintf(&buf, " LIMIT %v OFFSET %v", statement.LimitN, statement.Start)
|
||||
} else if statement.LimitN > 0 {
|
||||
fmt.Fprint(&buf, " LIMIT ", statement.LimitN)
|
||||
}
|
||||
} else if dialect.DBType() == core.ORACLE {
|
||||
if statement.Start != 0 || statement.LimitN != 0 {
|
||||
oldString := buf.String()
|
||||
buf.Reset()
|
||||
fmt.Fprintf(&buf, "SELECT %v FROM (SELECT %v,ROWNUM RN FROM (%v) at WHERE ROWNUM <= %d) aat WHERE RN > %d",
|
||||
columnStr, columnStr, oldString, statement.Start+statement.LimitN, statement.Start)
|
||||
}
|
||||
}
|
||||
}
|
||||
if statement.IsForUpdate {
|
||||
a = dialect.ForUpdateSql(a)
|
||||
return dialect.ForUpdateSql(buf.String()), nil
|
||||
}
|
||||
|
||||
return
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
func (statement *Statement) processIDParam() error {
|
||||
if statement.idParam == nil {
|
||||
if statement.idParam == nil || statement.RefTable == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
12
vendor/github.com/go-xorm/xorm/xorm.go
generated
vendored
12
vendor/github.com/go-xorm/xorm/xorm.go
generated
vendored
|
@ -17,7 +17,7 @@ import (
|
|||
|
||||
const (
|
||||
// Version show the xorm's version
|
||||
Version string = "0.6.4.0910"
|
||||
Version string = "0.7.0.0504"
|
||||
)
|
||||
|
||||
func regDrvsNDialects() bool {
|
||||
|
@ -31,7 +31,7 @@ func regDrvsNDialects() bool {
|
|||
"mysql": {"mysql", func() core.Driver { return &mysqlDriver{} }, func() core.Dialect { return &mysql{} }},
|
||||
"mymysql": {"mysql", func() core.Driver { return &mymysqlDriver{} }, func() core.Dialect { return &mysql{} }},
|
||||
"postgres": {"postgres", func() core.Driver { return &pqDriver{} }, func() core.Dialect { return &postgres{} }},
|
||||
"pgx": {"postgres", func() core.Driver { return &pqDriver{} }, func() core.Dialect { return &postgres{} }},
|
||||
"pgx": {"postgres", func() core.Driver { return &pqDriverPgx{} }, func() core.Dialect { return &postgres{} }},
|
||||
"sqlite3": {"sqlite3", func() core.Driver { return &sqlite3Driver{} }, func() core.Dialect { return &sqlite3{} }},
|
||||
"oci8": {"oracle", func() core.Driver { return &oci8Driver{} }, func() core.Dialect { return &oracle{} }},
|
||||
"goracle": {"oracle", func() core.Driver { return &goracleDriver{} }, func() core.Dialect { return &oracle{} }},
|
||||
|
@ -90,6 +90,7 @@ func NewEngine(driverName string, dataSourceName string) (*Engine, error) {
|
|||
TagIdentifier: "xorm",
|
||||
TZLocation: time.Local,
|
||||
tagHandlers: defaultTagHandlers,
|
||||
cachers: make(map[string]core.Cacher),
|
||||
}
|
||||
|
||||
if uri.DbType == core.SQLITE {
|
||||
|
@ -108,6 +109,13 @@ func NewEngine(driverName string, dataSourceName string) (*Engine, error) {
|
|||
return engine, nil
|
||||
}
|
||||
|
||||
// NewEngineWithParams new a db manager with params. The params will be passed to dialect.
|
||||
func NewEngineWithParams(driverName string, dataSourceName string, params map[string]string) (*Engine, error) {
|
||||
engine, err := NewEngine(driverName, dataSourceName)
|
||||
engine.dialect.SetParams(params)
|
||||
return engine, err
|
||||
}
|
||||
|
||||
// Clone clone an engine
|
||||
func (engine *Engine) Clone() (*Engine, error) {
|
||||
return NewEngine(engine.DriverName(), engine.DataSourceName())
|
||||
|
|
Loading…
Reference in New Issue
Block a user