Пример #1
0
// Checks whether or not a patch has been applied on database
func hasPatchApplied(dbConfig *patchsql.DatabaseConfig, patchConfig *PatchConfig) (result bool, err error) {
	result = false

	err = dbConfig.Execute(
		func(db *dbsql.DB) (err error) {
			var successRow = -1

			if err = db.QueryRow(
				`
				SELECT COUNT(dcl_id)
				FROM sysdb_change_log
				WHERE dcl_named_id = ?
					AND dcl_result = 2
				ORDER BY dcl_time_update DESC
				LIMIT 1
				`,
				patchConfig.Id,
			).Scan(&successRow); err != nil {
				return
			}

			result = successRow == 1
			return
		},
	)

	return
}
Пример #2
0
// Checks whether or not a patch has been applied on database
func hasPatchApplied(dbConfig *patchsql.DatabaseConfig, patchConfig *PatchConfig) (result bool, err error) {
	result = false

	err = dbConfig.Execute(
		func(db *dbsql.DB) (err error) {
			var successRow = -1

			/**
			 * Since MySQL would gives you total number of COUNT(*)
			 * even if you use limit express,
			 * we just check the counting of success patching >= 1
			 */
			if err = db.QueryRow(
				`
				SELECT COUNT(*)
				FROM sysdb_change_log
				WHERE dcl_named_id = ?
					AND dcl_result = 2
				ORDER BY dcl_time_update DESC
				`,
				patchConfig.Id,
			).Scan(&successRow); err != nil {
				return
			}

			result = successRow >= 1
			return
		},
	)

	return
}
Пример #3
0
// 1. Add log to database
// 2. Applies patch to database
// 3. Update result patching on log in database
func applyPatch(
	dbConfig *patchsql.DatabaseConfig,
	patchConfig *PatchConfig,
	scripts []string,
) (err error) {
	var patchContent = patchResult{
		patchConfig: patchConfig,
	}

	/**
	 * Add log to dtaabase
	 */
	if err = dbConfig.Execute(newChangeLogFunc(&patchContent)); err != nil {
		return
	}
	// :~)

	/**
	 * Applies scripts to database
	 */
	for _, script := range scripts {
		log.Printf("Applying script:\n%v\n", script)

		if err = dbConfig.Execute(
			func(db *dbsql.DB) (err error) {
				_, err = db.Exec(script)
				return
			},
		); err != nil {

			/**
			 * Logs the failed result to database
			 */
			patchContent.result = failed
			patchContent.message = fmt.Sprintf("Error: [%v]\nScript:\n%v\n", err, script)
			if logErr := dbConfig.Execute(updateChangeLogFunc(&patchContent)); logErr != nil {
				panic(fmt.Errorf("Cannot log failed patching: [%v]. Error: %f.\nScript:\n%v\n", patchConfig.Id, err, script))
			}
			// :~)

			return
		}
	}
	// :~)

	/**
	 * Update result patching on log in database
	 */
	patchContent.result = success
	if err = dbConfig.Execute(updateChangeLogFunc(&patchContent)); err != nil {
		return
	}
	// :~)

	return
}
Пример #4
0
// Executes the patches in change log
func ExecutePatches(changeLogConfig *ChangeLogConfig) (err error) {
	/**
	 * Loads configuration of patches
	 */
	var loadedPatches []PatchConfig
	if loadedPatches, err = LoadChangeLogFromFile(changeLogConfig.ChangeLog); err != nil {
		return
	}
	// :~)

	/**
	 * Connect to database
	 */
	var dbConfig *patchsql.DatabaseConfig
	if dbConfig, err = patchsql.NewDatabaseConfig(
		changeLogConfig.DriverName,
		changeLogConfig.Dsn,
	); err != nil {
		return
	}

	defer dbConfig.Close()
	// :~)

	/**
	 * Checking the schema for change log
	 */
	if err = dbConfig.Execute(checkChangeLogSchema); err != nil {
		return
	}
	// :~)

	/**
	 * Iterates each patch and applies it to database
	 */
	var numberOfApplied = 0
	for _, p := range loadedPatches {
		/**
		 * Checks if the patch has been applied
		 */
		if patchApplied, _ := hasPatchApplied(dbConfig, &p); patchApplied {
			continue
		}
		// :~)

		log.Printf("Applying patch: [%v](%v)...", p.Id, p.Filename)

		var scripts []string

		/**
		 * Loads scripts from file
		 */
		if scripts, err = p.loadScripts(changeLogConfig.PatchFileBase, changeLogConfig.Delimiter); err != nil {
			return fmt.Errorf("Load script file[%v/%v] error: %v", changeLogConfig.PatchFileBase, p.Filename, err)
		}
		// :~)

		/**
		 * Applies patch to database
		 */
		if err = applyPatch(dbConfig, &p, scripts); err != nil {

			var patchErr = fmt.Errorf("Patch [%v](%v) has error: %v", p.Id, p.Filename, err)
			log.Println(patchErr)

			return patchErr
		}
		// :~)

		numberOfApplied++
		log.Printf("Applying patch success. [%v](%v).", p.Id, p.Filename)
	}
	// :~)

	log.Printf("Number of applied patches: %v", numberOfApplied)
	return
}