github.com/haagen/force@v0.19.6-0.20140911230915-22addd930b34/bulk.go (about) 1 package main 2 3 /* 4 5 bulk command 6 force bulk insert mydata.csv 7 8 The load process involves these steps 9 1. Create a job 10 https://instance_name—api.salesforce.com/services/async/APIversion/job 11 payload: 12 <jobInfo xmlns="http://www.force.com/2009/06/asyncapi/dataload"> 13 <operation>insert</operation> 14 <object>Account</object> 15 <contentType>CSV</contentType> 16 </jobInfo> 17 2. Add batches to the created job 18 https://instance_name—api.salesforce.com/services/async/APIversion/job/jobid/batch 19 payload: 20 <sObjects xmlns="http://www.force.com/2009/06/asyncapi/dataload"> 21 <sObject> 22 <description>Created from Bulk API on Tue Apr 14 11:15:59 PDT 2009</description> 23 <name>[Bulk API] Account 0 (batch 0)</name> 24 </sObject> 25 <sObject> 26 <description>Created from Bulk API on Tue Apr 14 11:15:59 PDT 2009</description> 27 <name>[Bulk API] Account 1 (batch 0)</name> 28 </sObject> 29 </sObjects> 30 3. Close job (I assume this submits the job???) 31 https://instance_name—api.salesforce.com/services/async/APIversion/job/jobId 32 payload: 33 <jobInfo xmlns="http://www.force.com/2009/06/asyncapi/dataload"> 34 <state>Closed</state> 35 </jobInfo> 36 37 Jobs and batches can be monitored. 38 39 bulk command 40 force bulk job <jobId> 41 42 bulk command 43 force bulk batches <jobId> 44 45 bulk command 46 force bulk batch <batchId> 47 48 49 50 51 52 */ 53 54 import ( 55 "encoding/xml" 56 "fmt" 57 "io/ioutil" 58 ) 59 60 var cmdBulk = &Command{ 61 Run: runBulk, 62 Usage: "bulk insert Account [csv file]", 63 Short: "Load csv file use Bulk API", 64 Long: ` 65 Load csv file use Bulk API 66 67 Examples: 68 69 force bulk insert Account [csv file] 70 71 force bulk update Account [csv file] 72 73 force bulk job [job id] 74 75 force bulk batches [job id] 76 77 force bulk batch [job id] [batch id] 78 79 force bulk batch retrieve [job id] [batch id] 80 81 force bulk query Account [SOQL] 82 83 force bulk query retrieve [job id] [batch id] 84 `, 85 } 86 87 func runBulk(cmd *Command, args []string) { 88 89 if len(args) == 1 { 90 ErrorAndExit("Invalid command") 91 } else if len(args) == 2 { 92 if args[0] == "insert" { 93 ErrorAndExit("Missing argument for insert") 94 } else if args[0] == "job" { 95 showJobDetails(args[1]) 96 } else if args[0] == "batches" { 97 listBatches(args[1]) 98 } else { 99 ErrorAndExit("Invalid command") 100 } 101 } else if len(args) == 3 { 102 if args[0] == "insert" { 103 createBulkInsertJob(args[2], args[1], "CSV") 104 } else if args[0] == "update" { 105 createBulkUpdateJob(args[2], args[1], "CSV") 106 } else if args[0] == "batch" { 107 showBatchDetails(args[1], args[2]) 108 } else if args[0] == "query" { 109 if args[1] == "retrieve" { 110 ErrorAndExit("Query retrieve requires a job id and a batch id") 111 } else { 112 doBulkQuery(args[1], args[2], "CSV") 113 } 114 } 115 } else if len(args) == 4 { 116 if args[0] == "insert" { 117 createBulkInsertJob(args[2], args[1], args[3]) 118 } else if args[0] == "update" { 119 createBulkUpdateJob(args[2], args[1], args[3]) 120 } else if args[0] == "batch" { 121 getBatchResults(args[2], args[3]) 122 } else if args[0] == "query" { 123 if args[1] == "retrieve" { 124 fmt.Println(string(getBulkQueryResults(args[2], args[3]))) 125 } else if args[1] == "status" { 126 DisplayBatchInfo(getBatchDetails(args[2], args[3])) 127 } else { 128 doBulkQuery(args[1], args[2], args[3]) 129 } 130 } 131 } 132 } 133 134 func doBulkQuery(objectType string, soql string, contenttype string) { 135 jobInfo, err := createBulkJob(objectType, "query", contenttype) 136 force, _ := ActiveForce() 137 138 result, err := force.BulkQuery(soql, jobInfo.Id, contenttype) 139 if err != nil { 140 closeBulkJob(jobInfo.Id) 141 ErrorAndExit(err.Error()) 142 } 143 fmt.Println("Query Submitted") 144 fmt.Printf("To retrieve query status use\nforce bulk query status %s %s\n\n", jobInfo.Id, result.Id) 145 fmt.Printf("To retrieve query data use\nforce bulk query retrieve %s %s\n\n", jobInfo.Id, result.Id) 146 closeBulkJob(jobInfo.Id) 147 } 148 149 func getBulkQueryResults(jobId string, batchId string) (data []byte) { 150 resultId := retrieveBulkQuery(jobId, batchId) 151 data = retrieveBulkQueryResults(jobId, batchId, resultId) 152 return 153 } 154 155 func retrieveBulkQuery(jobId string, batchId string) (resultId string) { 156 force, _ := ActiveForce() 157 158 jobInfo, err := force.RetrieveBulkQuery(jobId, batchId) 159 if err != nil { 160 ErrorAndExit(err.Error()) 161 } 162 163 var result struct { 164 Result string `xml:"result"` 165 } 166 167 xml.Unmarshal(jobInfo, &result) 168 resultId = result.Result 169 return 170 } 171 172 func retrieveBulkQueryResults(jobId string, batchId string, resultId string) (data []byte) { 173 force, _ := ActiveForce() 174 175 data, err := force.RetrieveBulkQueryResults(jobId, batchId, resultId) 176 if err != nil { 177 ErrorAndExit(err.Error()) 178 } 179 return 180 } 181 182 func showJobDetails(jobId string) { 183 jobInfo := getJobDetails(jobId) 184 DisplayJobInfo(jobInfo) 185 } 186 187 func listBatches(jobId string) { 188 batchInfos := getBatches(jobId) 189 DisplayBatchList(batchInfos) 190 } 191 192 func showBatchDetails(jobId string, batchId string) { 193 batchInfo := getBatchDetails(jobId, batchId) 194 DisplayBatchInfo(batchInfo) 195 } 196 197 func getBatchResults(jobId string, batchId string) { 198 force, _ := ActiveForce() 199 200 data, err := force.RetrieveBulkBatchResults(jobId, batchId) 201 fmt.Println(data) 202 if err != nil { 203 ErrorAndExit(err.Error()) 204 } 205 return 206 } 207 208 func getJobDetails(jobId string) (jobInfo JobInfo) { 209 force, _ := ActiveForce() 210 211 jobInfo, err := force.GetJobInfo(jobId) 212 213 if err != nil { 214 ErrorAndExit(err.Error()) 215 } 216 return 217 } 218 219 func getBatches(jobId string) (batchInfos []BatchInfo) { 220 force, _ := ActiveForce() 221 222 batchInfos, err := force.GetBatches(jobId) 223 224 if err != nil { 225 ErrorAndExit(err.Error()) 226 } 227 return 228 } 229 230 func getBatchDetails(jobId string, batchId string) (batchInfo BatchInfo) { 231 force, _ := ActiveForce() 232 233 batchInfo, err := force.GetBatchInfo(jobId, batchId) 234 235 if err != nil { 236 ErrorAndExit(err.Error()) 237 } 238 return 239 } 240 241 func createBulkInsertJob(csvFilePath string, objectType string, format string) { 242 jobInfo, err := createBulkJob(objectType, "insert", format) 243 if err != nil { 244 ErrorAndExit(err.Error()) 245 } else { 246 batchInfo, err := addBatchToJob(csvFilePath, jobInfo.Id) 247 if err != nil { 248 closeBulkJob(jobInfo.Id) 249 ErrorAndExit(err.Error()) 250 } else { 251 closeBulkJob(jobInfo.Id) 252 fmt.Printf("Job created ( %s ) - for job status use\n force bulk batch %s %s\n", jobInfo.Id, jobInfo.Id, batchInfo.Id) 253 } 254 } 255 } 256 257 func createBulkUpdateJob(csvFilePath string, objectType string, format string) { 258 jobInfo, err := createBulkJob(objectType, "update", format) 259 if err != nil { 260 ErrorAndExit(err.Error()) 261 } else { 262 _, err := addBatchToJob(csvFilePath, jobInfo.Id) 263 if err != nil { 264 closeBulkJob(jobInfo.Id) 265 ErrorAndExit(err.Error()) 266 } else { 267 closeBulkJob(jobInfo.Id) 268 } 269 } 270 } 271 272 func addBatchToJob(csvFilePath string, jobId string) (result BatchInfo, err error) { 273 274 force, _ := ActiveForce() 275 276 filedata, err := ioutil.ReadFile(csvFilePath) 277 278 result, err = force.AddBatchToJob(string(filedata), jobId) 279 return 280 } 281 282 func getBatchInfo(jobId string, batchId string) (batchInfo BatchInfo, err error) { 283 force, _ := ActiveForce() 284 batchInfo, err = force.GetBatchInfo(jobId, batchId) 285 return 286 } 287 288 func createBulkJob(objectType string, operation string, fileFormat string) (jobInfo JobInfo, err error) { 289 force, _ := ActiveForce() 290 291 xml := ` 292 <jobInfo xmlns="http://www.force.com/2009/06/asyncapi/dataload"> 293 <operation>%s</operation> 294 <object>%s</object> 295 <contentType>%s</contentType> 296 </jobInfo> 297 ` 298 data := fmt.Sprintf(xml, operation, objectType, fileFormat) 299 jobInfo, err = force.CreateBulkJob(data) 300 return 301 } 302 303 func closeBulkJob(jobId string) (jobInfo JobInfo, err error) { 304 force, _ := ActiveForce() 305 306 xml := ` 307 <jobInfo xmlns="http://www.force.com/2009/06/asyncapi/dataload"> 308 <state>Closed</state> 309 </jobInfo> 310 ` 311 jobInfo, err = force.CloseBulkJob(jobId, xml) 312 if err != nil { 313 ErrorAndExit(err.Error()) 314 } 315 return 316 }