コード例 #1
0
ファイル: select.go プロジェクト: arteev/dsql
func fillDatasetsByErrors(datasets *dataset.CollectionDataset, dbs []db.Database, ctx *action.Context) error {
	for _, d := range dbs {
		localCtx := ctx.Get("context" + d.Code).(*action.Context)
		if !localCtx.Get("success").(bool) {
			ds := datasets.GetOrCreateDataset(d.Code)
			ds.Error = true
			ds.TextError = localCtx.Snap.Error().Error()
		}
	}
	return nil
}
コード例 #2
0
ファイル: select.go プロジェクト: arteev/dsql
//SelectAfter trigger after for select action
func SelectAfter(dbs []db.Database, ctx *action.Context) error {
	done := ctx.Get("chandone")
	logger.Trace.Println("SelectAfter")
	if done != nil {
		done.(chan bool) <- true
	}
	switch ctx.Get("format") {
	case "table":
		return doOutputTable(dbs, ctx)
	case "json":
		return doOutputJSON(dbs, ctx)
	case "xml":
		return doOutputXML(dbs, ctx)

	}
	return nil
}
コード例 #3
0
ファイル: select.go プロジェクト: arteev/dsql
func doOutputXML(dbs []db.Database, ctx *action.Context) error {
	datasets := ctx.Get("datasets").(*dataset.CollectionDataset)
	if err := fillDatasetsByErrors(datasets, dbs, ctx); err != nil {
		return err
	}
	subformat := ctx.GetDef("subformat", "").(string)
	if subformat == "" {
		datasets.WriteXML(os.Stdout)
		return nil
	}
	f, err := os.Create(subformat)
	if err != nil {
		return err
	}
	defer f.Close()
	_, err = datasets.WriteXML(f)
	return err
}
コード例 #4
0
ファイル: remotedb.go プロジェクト: arteev/dsql
func parseOthersFlagsForRunContext(ctx *cli.Context, ctxRun *action.Context) error {
	if ctx.IsSet("format") {
		format := ctx.String("format")
		subformat := ""
		//TODO: refactor it!
		if strings.Contains(format, "raw:") {
			subformat = format[len("raw:"):]
			format = "raw"
		}
		if strings.Contains(format, "table:") {
			subformat = format[len("table:"):]
			format = "table"
		}
		if strings.Contains(format, "json:") {
			subformat = format[len("json:"):]
			format = "json"
		}
		if strings.Contains(format, "xml:") {
			subformat = format[len("xml:"):]
			format = "xml"
		}

		switch format {
		case "table", "raw", "json", "xml":
			ctxRun.Set("format", format)
			ctxRun.Set("subformat", subformat)
			break
		default:
			return fmt.Errorf("Unknown format:%s", format)
		}
	} else {
		ctxRun.Set("format", "raw")
	}

	if ctx.IsSet("timeout") {
		ctxRun.Set("timeout", ctx.Int("timeout"))
	}
	if ctx.IsSet("commit") {
		ctxRun.Set("commit", ctx.Bool("commit"))
	}
	return nil
}
コード例 #5
0
ファイル: outstatistic.go プロジェクト: arteev/dsql
//PrintStatistic - print common statistic after execute action
func PrintStatistic(dbs []db.Database, ctx *action.Context) error {
	var buf bytes.Buffer
	pget := ctx.Get("params").(parametergetter.ParameterGetter)
	if pget.GetDef(parametergetter.Statistic, false).(bool) {
		mSec := ctx.Snap.Finished().Sub(ctx.Snap.Started()).Nanoseconds() / 1000 / 1000
		exec := ctx.GetDef("exec", 0).(int)
		success := ctx.GetDef("success", 0).(int)
		failed := ctx.GetDef("failed", 0).(int)
		buf.WriteString(fmt.Sprintf("Executed: %-4d Success:%-3d (%3.2f%%) Failed:%-3d \n", exec, success, float64(success)/float64(exec)*100, failed))
		buf.WriteString(fmt.Sprintf("Completed: %v msec", mSec))
		fmt.Println(buf.String())
	}
	return nil
}
コード例 #6
0
ファイル: select.go プロジェクト: arteev/dsql
//SelectBefore trigger before for select action
func SelectBefore(dbs []db.Database, ctx *action.Context) error {
	// Prepare data in ctx.datasets
	logger.Trace.Println("SelectBefore")
	format := ctx.Get("format")
	subformat := ctx.GetDef("subformat", "").(string)

	datasets := dataset.NewColllection()
	chanHdr := make(chanHeader)
	chandata := make(chanData)
	chanDone := make(chan bool)

	ctx.Set("chanheader", chanHdr)
	ctx.Set("chandata", chandata)
	ctx.Set("chandone", chanDone)
	ctx.Set("datasets", datasets)

	line := 0
	go func() {
		for {
			select {
			case hdr := <-chanHdr:
				ds := datasets.GetOrCreateDataset(hdr.Code)
				ds.AddColumns(hdr.Columns...)
			case cudata := <-chandata:
				line++
				ds := datasets.GetOrCreateDataset(cudata.Code)
				ds.Append(cudata.Data)
				if format == "raw" {
					fmt.Println(formatRaw(subformat, ds.RowsCount(), line, ds.GetColumnsNames(), cudata.Data))
				}
			case <-chanDone:
				logger.Trace.Println("SelectBefore do done")
				return
			}
		}
	}()

	return nil
}
コード例 #7
0
ファイル: outstatistic.go プロジェクト: arteev/dsql
//PrintStatisticQuery - print statistic for each database after execute action
func PrintStatisticQuery(dbs []db.Database, ctx *action.Context) error {
	pget := ctx.Get("params").(parametergetter.ParameterGetter)
	if pget.GetDef(parametergetter.QueryStatistic, false).(bool) {
		for _, d := range dbs {
			localCtx := ctx.Get("context" + d.Code).(*action.Context)
			mSec := localCtx.Snap.Finished().Sub(localCtx.Snap.Started()).Nanoseconds() / 1000 / 1000
			if localCtx.Get("success").(bool) {
				rowcount := localCtx.GetDef("rowcount", 0).(int)
				rowsaffected := localCtx.GetDef("rowsaffected", int64(0)).(int64)
				fmt.Printf("%s: Success. Elapsed time:%d msec. Rows count:%d  Rows affected: %d\n", d.Code, mSec, rowcount, rowsaffected)
			} else {

				var errmsg string
				if errs := localCtx.Snap.Error(); errs != nil {
					errmsg = errs.Error()
				}
				fmt.Printf("%s: Failed! Elapsed time:%d msec. Error message: %s \n", d.Code, mSec, strings.Replace(errmsg, "\n", " ", -1))
			}
		}
	}
	return nil
}
コード例 #8
0
ファイル: select.go プロジェクト: arteev/dsql
//SelectError trigger error for select action
func SelectError(dbs []db.Database, ctx *action.Context) error {

	logger.Trace.Println("Failed execute")
	if !ctx.GetDef("silent", false).(bool) {
		fmt.Println("All requests will fail.")
	}
	switch ctx.Get("format") {
	case "json", "xml":
		return SelectAfter(dbs, ctx)
	}

	done := ctx.Get("chandone")
	if done != nil {
		done.(chan bool) <- true
	}
	return nil
}
コード例 #9
0
ファイル: exec.go プロジェクト: arteev/dsql
//Exec - execute sql for the databases
func Exec(dbContext db.Database, dbHandle *sql.DB, cmd *sqlcommand.SQLCommand, ctx *action.Context) error {
	logger.Trace.Println("run exec", dbContext.Code)
	defer logger.Trace.Println("done exec", dbContext.Code)

	localCtx := ctx.Get("context" + dbContext.Code).(*action.Context)
	commit := ctx.GetDef("commit", false).(bool)
	var pint []interface{}
	for _, p := range cmd.Params {
		pint = append(pint, p)
	}

	tx, err := dbHandle.Begin()
	if err != nil {
		return err
	}
	sqmt, err := tx.Prepare(cmd.Script)
	if err != nil {
		return err
	}
	defer sqmt.Close()
	res, err := sqmt.Exec(pint...)
	if err != nil {
		return err
	}
	defer sqmt.Close()

	if commit {
		logger.Debug.Printf("%s Transaction commited", dbContext.Code)
		if err := tx.Commit(); err != nil {
			return err
		}
	} else {
		if err := tx.Rollback(); err != nil {
			return err
		}
		logger.Warn.Printf("%s: Transaction rollback.Use a special flag for commit the transaction\n", dbContext.Code)
	}
	ra, err := res.RowsAffected()
	if err != nil {
		return err
	}

	localCtx.IncInt64("rowsaffected", ra)
	ctx.IncInt64("rowsaffected", ra)
	return nil
}
コード例 #10
0
ファイル: run.go プロジェクト: arteev/dsql
//Run concrete action for all databases
func Run(dbs []db.Database, sql *sqlcommand.SQLCommand, act action.Actioner, ctx *action.Context, pget parametergetter.ParameterGetter) (*action.Context, error) {
	logger.Trace.Println("rdb run")
	defer logger.Trace.Println("rdb run done")
	ctx.Set("params", pget)
	ctx.Set("silent", pget.GetDef(parametergetter.Silent, false).(bool))
	ctx.Snap.Start()

	colParams, err := parameters.GetInstance().All()
	if err != nil {
		return nil, err
	}
	ctx.Set("Params", colParams.Get())

	for _, d := range dbs {
		err := runItem(d, sql, act, ctx, pget)
		if err != nil {
			logger.Error.Println(err)
			//todo: в общий список ошибок
		}
	}
	wg.Wait()
	ctx.Snap.Done(nil)
	return ctx, nil
}
コード例 #11
0
ファイル: run.go プロジェクト: arteev/dsql
func runItem(d db.Database, s *sqlcommand.SQLCommand, doaction action.Actioner, ctx *action.Context, pget parametergetter.ParameterGetter) error {
	logger.Trace.Println("runItem")
	defer logger.Trace.Println(d.Code, "runItem done")
	if s != nil {
		logger.Trace.Println(d.Code, s.Script)
	}
	wg.Add(1)
	ctx.IncInt("exec", 1)
	params := ctx.Get("Params").([]parameters.Parameter)

	go func() {

		timeout := ctx.GetDef("timeout", 0).(int)
		defer wg.Done()

		var (
			ctxExec context.Context
			cancel  context.CancelFunc
		)
		ch := make(chan bool)
		if timeout > 0 {
			ctxExec, cancel = context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second)
		} else {
			ctxExec, cancel = context.WithCancel(context.Background())
		}

		defer cancel()
		localCtx := action.NewContext()

		go func() {

			defer func() {
				ch <- true
				close(ch)
			}()

			ctx.Set("context"+d.Code, localCtx)
			ctx.Set("iscancel", ch)
			localCtx.Snap.Start()
			localCtx.Set("success", false)

			connectionString, e := paramsreplace.Replace(d.ConnectionString, params)
			if e != nil {
				ctx.IncInt("failed", 1)
				logger.Error.Println(e)

				return
			}
			logger.Debug.Println(d.Code, "Connection string:", connectionString)
			connection, err := rdb.Open(d.Engine, connectionString)
			if err != nil {
				ctx.IncInt("failed", 1)
				logger.Error.Println(d.Code, err)
				return
			}
			defer func() {
				if err := connection.Close(); err != nil {
					panic(err)
				} else {
					logger.Trace.Printf("%s disconnected", d.Code)
				}
			}()

			err = doaction(d, connection, s, ctx)
			if err != nil {
				if err.Error() != "cancel" {
					ctx.IncInt("failed", 1)
					localCtx.Snap.Done(err)
					logger.Error.Println(d.Code, err)
					if !ctx.GetDef("silent", false).(bool) {
						fmt.Fprintf(os.Stdout, "%s: %s\n", d.Code, strings.Replace(err.Error(), "\n", " ", -1))
					}
				}

				return
			}

			localCtx.Set("success", true)
			ctx.IncInt("success", 1)
			localCtx.Snap.Done(nil)
			runtime.Gosched()
		}()

		select {
		case <-ch:
			logger.Trace.Println("operation done w/o timeout")
			return
		case <-ctxExec.Done():
			err := ctxExec.Err()
			logger.Trace.Printf("operation done: %s\n", err)

			ctx.IncInt("failed", 1)
			localCtx.Snap.Done(err)
			logger.Error.Println(d.Code, err)

			//	ch <- true

			return
		}

	}()
	return nil
}
コード例 #12
0
ファイル: select.go プロジェクト: arteev/dsql
//Select - it action for select command
func Select(dbs1 db.Database, dsrc *sql.DB, cmd *sqlcommand.SQLCommand, ctx *action.Context) error {
	logger.Trace.Println("run select", dbs1.Code)

	timeout := ctx.GetDef("timeout", 0).(int)
	logger.Debug.Printf("run select timeout %d sec", timeout)

	var pint []interface{}

	chanCancel := ctx.Get("iscancel").(chan bool)
	for _, p := range cmd.Params {
		pint = append(pint, p)
	}

	/*tx,err:=dsrc.Begin()
	if err!=nil {
		return err
	}
	defer tx.Rollback()
	rw, err := tx.Query(cmd.Script, pint...)*/
	tx, err := dsrc.Begin()
	if err != nil {
		return err
	}
	defer tx.Rollback()
	stmt, err := tx.Prepare(cmd.Script)
	if err != nil {
		return err
	}
	defer stmt.Close()

	rw, err := tx.Query(cmd.Script, pint...)
	if err != nil {
		return err
	}

	defer func() {
		if err := rw.Close(); err != nil {
			panic(err)
		}
	}()

	cols, _ := rw.Columns()

	localCtx := ctx.Get("context" + dbs1.Code).(*action.Context)
	chanHdr := ctx.Get("chanheader")
	chandata := ctx.Get("chandata")
	if chanHdr != nil {
		chanHdr.(chanHeader) <- &headerTable{
			Code:    dbs1.Code,
			Columns: cols,
		}
	}

	rg := rowgetter.MustRowGetter(rw)
	for {
		select {
		case <-chanCancel:
			logger.Info.Println("run select canceled", dbs1.Code)
			return fmt.Errorf("cancel")
		default:
		}
		row, ok := rg.Next()
		if !ok {
			break
		}

		localCtx.IncInt("rowcount", 1)

		if /*format=="table" &&*/ chandata != nil {
			data := make(map[string]interface{})
			for i, r := range row {
				data[cols[i]] = r
			}
			data["_CODE_"] = dbs1.Code

			chandata.(chanData) <- &dataTable{
				Code: dbs1.Code,
				Data: data,
			}
		}

	}

	return nil
}
コード例 #13
0
ファイル: select.go プロジェクト: arteev/dsql
func doOutputTable(dbs []db.Database, ctx *action.Context) error {
	datasets := ctx.Get("datasets").(*dataset.CollectionDataset)
	table := fmttab.New("", fmttab.BorderThin, nil)
	table.AddColumn("_CODE_", 10, fmttab.AlignLeft)
	ctx.Set("table", table)

	for _, col := range datasets.GetUniqueColumnsNames() {
		table.AddColumn(col, 15, fmttab.AlignLeft)
	}
	for _, ds := range datasets.GetDatasets() {
		for _, row := range ds.Rows {
			table.AppendData(row.GetDataMap())
		}
	}

	pget := ctx.Get("params").(parametergetter.ParameterGetter)

	if pget.GetDef(parametergetter.AutoFitWidthColumns, true).(bool) {
		//todo: move into fmttab
		cols := table.Columns.ColumnsVisible()
		for c, col := range cols {
			max := utf8.RuneCountInString(col.Name)
			for i := 0; i < len(table.Data); i++ {
				val, ok := table.Data[i][col.Name]

				if ok && val != nil {
					fval := fmt.Sprintf("%v", val)
					l := utf8.RuneCountInString(fval)
					if l > max {
						max = l
					}
				}
			}
			if max != 0 {
				cols[c].Width = max
			}
		}
	}

	switch pget.GetDef(parametergetter.BorderTable, "").(string) {
	case "Thin":
		table.SetBorder(fmttab.BorderThin)
	case "Double":
		table.SetBorder(fmttab.BorderDouble)
	case "None":
		table.SetBorder(fmttab.BorderNone)
	case "Simple":
		table.SetBorder(fmttab.BorderSimple)
	}

	tabex.SetTableSubFormat(table, ctx.GetDef("subformat", "").(string))

	if pget.GetDef(parametergetter.Fit, true).(bool) {

		if e := termbox.Init(); e != nil {
			return e
		}
		tw, _ := termbox.Size()
		table.AutoSize(true, tw)
		termbox.Close()
	}

	if _, err := table.WriteTo(os.Stdout); err != nil {
		return err
	}
	return nil
}