package xugu import ( "errors" "fmt" "strings" ) // cgo_xgc_sql_type -> fun_sql_type // 判断sql类型 func xgSqlType(sql string) int { // 去掉首尾的空格、换行符和回车符 sql = strings.TrimSpace(sql) if len(sql) < 6 { return SQL_OTHER } // 取前6个字符并转为大写 kstr := strings.ToUpper(sql[:6]) // 根据SQL语句前缀判断类型 switch { case strings.HasPrefix(kstr, "SELECT"): if strings.Contains(sql, ";") && len(sql[strings.Index(sql, ";"):]) > 5 { return SQL_OTHER // 多结果集 } return SQL_SELECT case strings.HasPrefix(kstr, "INSERT"): return SQL_INSERT case strings.HasPrefix(kstr, "UPDATE"): return SQL_UPDATE case strings.HasPrefix(kstr, "DELETE"): return SQL_DELETE case strings.HasPrefix(kstr, "CREATE"): return SQL_CREATE case strings.HasPrefix(kstr, "ALTER "): return SQL_ALTER case strings.HasPrefix(kstr, "EXEC "): return SQL_PROCEDURE case strings.HasPrefix(kstr, "EXECUT"): return SQL_PROCEDURE case strings.HasPrefix(kstr, "STC"): return SQL_SELECT default: return SQL_OTHER } } func xgSockPrepare(conn *xugusqlConn, sql string) (int, error) { ret := 0 //p_params := &conn.params if conn.havePrepare != 0 { ret = xgCmdUnprepare(conn, conn.prepareName) if ret < 0 { return ret, nil } conn.prepareName = "" } conn.prepareName = fmt.Sprintf(conn.prepareName+"STC%d", conn.prepareNo) ret, err := xgCmdPrepare(conn, sql, &conn.prepareName) if err != nil { return ret, err } return ret, err } // SQL语句prepare准备执行 func xgSockPrepare2(conn *xugusqlConn, cmd_sql string, prepareName *string) (int, error) { if "" == *prepareName { return xgSockPrepare(conn, cmd_sql) } ret := 0 pconn := conn // XGCSParam* p_params= pconn->params; old_p := pconn.havePrepare // char* sql=strdup(cmd_sql); *prepareName = fmt.Sprintf("STC%d", pconn.prepareNo) pconn.prepareNo++ // 递增 prepare_no 的值 ret, err := xgCmdPrepare(conn, cmd_sql, &conn.prepareName) if err != nil { return 0, err } pconn.havePrepare = old_p // this keeped by prepare_name return ret, nil } func xgCmdUnprepare(pconn *xugusqlConn, prepareName string) int { var ch byte var err error ret := XG_OK sql := fmt.Sprintf("DEALLOCATE %s ", prepareName) pconn.mu.Lock() sockSendCommand0(pconn, sql) boolRet, err := rhRecvChar(pconn, &ch) if boolRet || err != nil { ret = XG_NET_ERROR } else if ch == 'K' { pconn.havePrepare = 0 } else { pconn.havePrepare = 0 var errStre []byte ret, err = rhRecvStr(pconn, &errStre) if err != nil || ret < 0 { pconn.mu.Unlock() return ret } rhRecvChar(pconn, &ch) ret = XG_ERROR } pconn.mu.Unlock() return 0 } func xgCmdPrepare(pconn *xugusqlConn, cmd_sql string, prepareName *string) (int, error) { sqlRet := fmt.Sprintf("PREPARE %s AS %s", prepareName, cmd_sql) //上锁 //lockConnect(pconn) pconn.mu.Lock() sockSendCommand0(pconn, sqlRet) var ch byte var ret int for { recvRet, err := rhRecvChar(pconn, &ch) if err != nil { return 0, err } if !recvRet { pconn.mu.Unlock() return -4, errors.New("XG_NET_ERROR") } //A: SelectResult A在协议里为select返回 if ch == 'A' { pres := Result{} pres.Type = HT_RS ret, err = recvFiledsInfo(pconn, &pres) if err != nil { return ret, err } pconn.presPrepareCata = &pres ret = RETURN_PREPARE_SELECT continue } else if ch == '$' { var params XGCSParam params.Type = HT_PARAMS params.ImpExpType = 2 recvParamsInfo2(pconn, ¶ms) pconn.params = ¶ms continue } else if ch == 'K' { pconn.havePrepare = 1 } else { var errStr []byte ret, err = rhRecvStr(pconn, &errStr) if ret < 0 || err != nil { pconn.mu.Unlock() return ret, err } pconn.errStr = errStr ret = XG_ERROR rhRecvChar(pconn, &ch) if ch != 'K' { pconn.bkChar = ch continue } } break } pconn.mu.Unlock() return ret, nil }