mirror of
https://github.com/MariaDB/server.git
synced 2025-01-31 11:01:52 +01:00
Nuke all of the old_* directories in the ndb tree.
This commit is contained in:
parent
1d1040e1ea
commit
0302bb4fdd
581 changed files with 0 additions and 90603 deletions
|
@ -7,7 +7,6 @@ include $(top_srcdir)/storage/ndb/config/common.mk.am
|
|||
|
||||
dist-hook:
|
||||
-rm -rf `find $(distdir) -type d -name SCCS`
|
||||
-rm -rf `find $(distdir) -type d -name old_files`
|
||||
-rm -rf `find $(distdir)/ndbapi-examples -name '*.o'`
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
if test "$$subdir" != "." -a "$$subdir" != "include"; then \
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
CC=gcc
|
||||
LD=$(CC)
|
||||
SOURCES=memtest.c
|
||||
OUTPUT=memtest
|
||||
all:
|
||||
$(CC) $(SOURCES) -o $(OUTPUT)
|
||||
|
||||
debug:
|
||||
$(CC) -g $(SOURCES) -o $(OUTPUT)
|
||||
|
||||
clean: rm -rf *.o
|
||||
rm -rf core*
|
|
@ -1,14 +0,0 @@
|
|||
include .defs.mk
|
||||
|
||||
TYPE := ndbapitest
|
||||
BIN_TARGET := munmaptest
|
||||
|
||||
|
||||
SOURCES = munmaptest.cpp
|
||||
|
||||
include $(NDB_TOP)/Epilogue.mk
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
include .defs.mk
|
||||
|
||||
TYPE :=
|
||||
|
||||
PIC_ARCHIVE := Y
|
||||
ARCHIVE_TARGET := portlib
|
||||
|
||||
SOURCES = NdbOut.cpp
|
||||
|
||||
SOURCES.c = NdbCondition.c \
|
||||
NdbMutex.c \
|
||||
NdbSleep.c \
|
||||
NdbTick.c \
|
||||
NdbEnv.c \
|
||||
NdbThread.c \
|
||||
NdbHost.c \
|
||||
NdbTCP.c
|
||||
|
||||
ifeq ($(NDB_OS), SOFTOSE)
|
||||
SOURCES += NdbMem_SoftOse.cpp
|
||||
else
|
||||
SOURCES.c += NdbMem.c
|
||||
endif
|
||||
|
||||
include $(NDB_TOP)/Epilogue.mk
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,243 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
|
||||
#include "NdbCondition.h"
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#include <NdbMutex.h>
|
||||
|
||||
#include "NdbConditionOSE.h"
|
||||
struct NdbCondition
|
||||
{
|
||||
PROCESS condserv_pid;
|
||||
};
|
||||
|
||||
|
||||
OS_PROCESS(ndbcond_serv){
|
||||
|
||||
union SIGNAL* sig;
|
||||
union SIGNAL* sig2;
|
||||
|
||||
static const SIGSELECT sel_signal[] = {2, NDBCOND_SIGNAL, NDBCOND_BROADCAST};
|
||||
static const SIGSELECT sel_cond[] = {2, NDBCOND_WAIT, NDBCOND_WAITTIMEOUT};
|
||||
|
||||
for(;;){
|
||||
/* Receive condition wait signal */
|
||||
sig = receive((SIGSELECT*)sel_cond);
|
||||
if (sig != NIL){
|
||||
switch (sig->sigNo){
|
||||
|
||||
case NDBCOND_WAIT:
|
||||
/* Wait for a SIGNAL or BROADCAST from anyone */
|
||||
sig2 = receive((SIGSELECT*)sel_signal);
|
||||
if (sig2 != NIL){
|
||||
switch(sig2->sigNo){
|
||||
|
||||
case NDBCOND_SIGNAL:
|
||||
((struct NdbCondWait*)sig)->status = NDBCOND_SIGNALED;
|
||||
/* Send signal back to the one waiting for this condition */
|
||||
send(&sig, sender(&sig));
|
||||
break;
|
||||
case NDBCOND_BROADCAST:
|
||||
/* Not handled yet */
|
||||
assert(1==0);
|
||||
break;
|
||||
default:
|
||||
assert(1==0);
|
||||
break;
|
||||
}
|
||||
free_buf(&sig2);
|
||||
}
|
||||
break;
|
||||
|
||||
case NDBCOND_WAITTIMEOUT:
|
||||
/* Wait for a SIGNAL or BROADCAST from anyone */
|
||||
sig2 = receive_w_tmo(((struct NdbCondWaitTimeout*)sig)->timeout, (SIGSELECT*)sel_signal);
|
||||
if (sig2 != NIL){
|
||||
switch(sig2->sigNo){
|
||||
|
||||
case NDBCOND_SIGNAL:
|
||||
((struct NdbCondWaitTimeout*)sig)->status = NDBCOND_SIGNALED;
|
||||
/* Send signal back to the one waiting for this condition */
|
||||
send(&sig, sender(&sig));
|
||||
break;
|
||||
case NDBCOND_BROADCAST:
|
||||
/* Not handled yet */
|
||||
assert(1==0);
|
||||
break;
|
||||
default:
|
||||
assert(1==0);
|
||||
break;
|
||||
}
|
||||
free_buf(&sig2);
|
||||
}else{
|
||||
((struct NdbCondWaitTimeout*)sig)->status = NDBCOND_TIMEOUT;
|
||||
send(&sig, sender(&sig));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(1==0);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct NdbCondition*
|
||||
NdbCondition_Create(void)
|
||||
{
|
||||
struct NdbCondition* tmpCond;
|
||||
|
||||
|
||||
tmpCond = (struct NdbCondition*)malloc(sizeof(struct NdbCondition));
|
||||
|
||||
if (tmpCond == NULL)
|
||||
return NULL;
|
||||
|
||||
/**
|
||||
* Start this process with a quite high
|
||||
* priority, we want it to be responsive
|
||||
*/
|
||||
tmpCond->condserv_pid = create_process(OS_PRI_PROC, /* Process type */
|
||||
"ndbcond_serv", /* Name */
|
||||
ndbcond_serv, /* Entry point */
|
||||
2048, /* Stack size */
|
||||
10, /* Priority */
|
||||
0, /* Time slice */
|
||||
get_bid(current_process()), /* Block */
|
||||
NULL, /* Redir table */
|
||||
0,
|
||||
0);
|
||||
|
||||
start(tmpCond->condserv_pid);
|
||||
|
||||
return tmpCond;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
NdbCondition_Wait(struct NdbCondition* p_cond,
|
||||
NdbMutex* p_mutex)
|
||||
{
|
||||
static const SIGSELECT sel_cond[] = {1, NDBCOND_WAIT};
|
||||
union SIGNAL* sig;
|
||||
int result;
|
||||
if (p_cond == NULL || p_mutex == NULL)
|
||||
return 0;
|
||||
|
||||
sig = alloc(sizeof(struct NdbCondWait), NDBCOND_WAIT);
|
||||
send(&sig, p_cond->condserv_pid);
|
||||
|
||||
NdbMutex_Unlock(p_mutex);
|
||||
|
||||
result = 1;
|
||||
while(NIL == (sig = receive_from((OSTIME)-1, (SIGSELECT*)sel_cond, p_cond->condserv_pid)));
|
||||
if (sig != NIL){
|
||||
if (sig->sigNo == NDBCOND_WAIT){
|
||||
/* Condition is signaled */
|
||||
result = 0;
|
||||
}else{
|
||||
assert(1==0);
|
||||
}
|
||||
free_buf(&sig);
|
||||
|
||||
}
|
||||
NdbMutex_Lock(p_mutex);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
NdbCondition_WaitTimeout(struct NdbCondition* p_cond,
|
||||
NdbMutex* p_mutex,
|
||||
int msecs){
|
||||
static const SIGSELECT sel_cond[] = {1, NDBCOND_WAITTIMEOUT};
|
||||
union SIGNAL* sig;
|
||||
int result;
|
||||
if (p_cond == NULL || p_mutex == NULL)
|
||||
return 0;
|
||||
|
||||
sig = alloc(sizeof(struct NdbCondWaitTimeout), NDBCOND_WAITTIMEOUT);
|
||||
((struct NdbCondWaitTimeout*)sig)->timeout = msecs;
|
||||
send(&sig, p_cond->condserv_pid);
|
||||
|
||||
NdbMutex_Unlock(p_mutex);
|
||||
|
||||
result = 1;
|
||||
while(NIL == (sig = receive_from((OSTIME)-1, (SIGSELECT*)sel_cond, p_cond->condserv_pid)));
|
||||
if (sig != NIL){
|
||||
if (sig->sigNo == NDBCOND_WAITTIMEOUT){
|
||||
/* Condition is signaled */
|
||||
result = 0;
|
||||
}else{
|
||||
assert(1==0);
|
||||
}
|
||||
free_buf(&sig);
|
||||
|
||||
}
|
||||
|
||||
NdbMutex_Lock(p_mutex);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
NdbCondition_Signal(struct NdbCondition* p_cond){
|
||||
|
||||
union SIGNAL* sig;
|
||||
if (p_cond == NULL)
|
||||
return 1;
|
||||
|
||||
sig = alloc(sizeof(struct NdbCondSignal), NDBCOND_SIGNAL);
|
||||
send(&sig, p_cond->condserv_pid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int NdbCondition_Broadcast(struct NdbCondition* p_cond)
|
||||
{
|
||||
union SIGNAL* sig;
|
||||
if (p_cond == NULL)
|
||||
return 1;
|
||||
|
||||
sig = alloc(sizeof(struct NdbCondBroadcast), NDBCOND_BROADCAST);
|
||||
send(&sig, p_cond->condserv_pid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int NdbCondition_Destroy(struct NdbCondition* p_cond)
|
||||
{
|
||||
if (p_cond == NULL)
|
||||
return 1;
|
||||
|
||||
kill_proc(p_cond->condserv_pid);
|
||||
free(p_cond);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef NDB_CONDITIONOSE_H
|
||||
#define NDB_CONDITIONOSE_H
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define NDBCOND_SIGBASE 4000
|
||||
|
||||
#define NDBCOND_WAIT (NDBCOND_SIGBASE + 1) /* !-SIGNO(struct NdbCondWait)-! */
|
||||
#define NDBCOND_WAITTIMEOUT (NDBCOND_SIGBASE + 2) /* !-SIGNO(struct NdbCondWaitTimeOut)-! */
|
||||
#define NDBCOND_SIGNAL (NDBCOND_SIGBASE + 3) /* !-SIGNO(struct NdbCondSignal)-! */
|
||||
#define NDBCOND_BROADCAST (NDBCOND_SIGBASE + 4) /* !-SIGNO(struct NdbCondBroadcast)-! */
|
||||
|
||||
|
||||
const char *
|
||||
sigNo2String(SIGSELECT sigNo){
|
||||
switch(sigNo){
|
||||
case NDBCOND_WAIT:
|
||||
return "NDBCOND_WAIT";
|
||||
break;
|
||||
case NDBCOND_WAITTIMEOUT:
|
||||
return "NDBCOND_WAITTIMEOUT";
|
||||
break;
|
||||
case NDBCOND_SIGNAL:
|
||||
return "NDBCOND_SIGNAL";
|
||||
break;
|
||||
case NDBCOND_BROADCAST:
|
||||
return "NDBCOND_BROADCAST";
|
||||
break;
|
||||
}
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
struct NdbCondWait
|
||||
{
|
||||
SIGSELECT sigNo;
|
||||
int status;
|
||||
};
|
||||
|
||||
/**
|
||||
* Signal received
|
||||
*/
|
||||
#define NDBCOND_SIGNALED 1
|
||||
|
||||
/**
|
||||
* Timeout occured
|
||||
*/
|
||||
#define NDBCOND_TIMEOUT 2
|
||||
|
||||
struct NdbCondWaitTimeout
|
||||
{
|
||||
SIGSELECT sigNo;
|
||||
int timeout;
|
||||
int status;
|
||||
|
||||
};
|
||||
|
||||
struct NdbCondSignal
|
||||
{
|
||||
SIGSELECT sigNo;
|
||||
};
|
||||
|
||||
struct NdbCondBroadcast
|
||||
{
|
||||
SIGSELECT sigNo;
|
||||
};
|
||||
|
||||
|
||||
union SIGNAL
|
||||
{
|
||||
SIGSELECT sigNo;
|
||||
struct NdbCondWait condWait;
|
||||
struct NdbCondWaitTimeout condWaitTimeout;
|
||||
struct NdbCondSignal condSignal;
|
||||
struct NdbCondBroadcast condBroadcast;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,55 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
|
||||
#include "NdbEnv.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
const char* NdbEnv_GetEnv(const char* name, char * buf, int buflen)
|
||||
{
|
||||
/**
|
||||
* All environment variables are associated with a process
|
||||
* it's important to read env from the correct process
|
||||
* for now read from own process, own block and last the "ose_shell" process.
|
||||
*
|
||||
* TODO! What process should this be read from in the future?
|
||||
*
|
||||
*/
|
||||
PROCESS proc_;
|
||||
char* p = NULL;
|
||||
/* Look in own process */
|
||||
p = get_env(current_process(), (char*)name);
|
||||
if (p == NULL){
|
||||
/* Look in block process */
|
||||
p = get_env(get_bid(current_process()), (char*)name);
|
||||
if (p == NULL){
|
||||
/* Look in ose_shell process */
|
||||
if (hunt("ose_shell", 0, &proc_, NULL)){
|
||||
p = get_env(proc_, (char*)name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p != NULL){
|
||||
strncpy(buf, p, buflen);
|
||||
buf[buflen-1] = 0;
|
||||
free_buf((union SIGNAL **)&p);
|
||||
p = buf;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
|
||||
#include "NdbHost.h"
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
#include <inet.sig>
|
||||
#include <string.h>
|
||||
|
||||
union SIGNAL
|
||||
{
|
||||
SIGSELECT sigNo;
|
||||
struct InetIfUp inetIfUp;
|
||||
};
|
||||
|
||||
int NdbHost_GetHostName(char* buf)
|
||||
{
|
||||
#if 0
|
||||
extern PROCESS ose_inet_;
|
||||
union SIGNAL *signal;
|
||||
static const SIGSELECT select_if_up_reply[] = { 1, INET_IF_UP_REPLY };
|
||||
|
||||
signal = alloc(sizeof(struct InetIfUp), INET_IF_UP_REQUEST);
|
||||
strcpy(signal->inetIfUp.ifName, "*");
|
||||
send((union SIGNAL **)&signal, ose_inet_);
|
||||
signal = receive((SIGSELECT *)select_if_up_reply);
|
||||
strcpy(buf, signal->inetIfUp.ifName);
|
||||
free_buf(&signal);
|
||||
return 0;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int NdbHost_GetProcessId(void)
|
||||
{
|
||||
return current_process();
|
||||
}
|
||||
|
|
@ -1,181 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
|
||||
#include "NdbMem.h"
|
||||
|
||||
|
||||
#if defined NDB_OSE
|
||||
#include <ose.h>
|
||||
#include <mms.sig>
|
||||
#include <mms_err.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <NdbOut.hpp>
|
||||
|
||||
// Page size for mp750 is 4096 bytes.
|
||||
#define PAGE_SIZE 4096
|
||||
|
||||
/**
|
||||
* NOTE: To use NdbMem from a OSE system ose_mms has to be defined
|
||||
* as a "Required External Process"(see OSE Kernel User's Guide/R1.1(p. 148)),
|
||||
* like this in osemain.con:
|
||||
* EXT_PROC(ose_mms, ose_mms, 50000)
|
||||
* This will create a global variable ose_mms_ that is used from here.
|
||||
*/
|
||||
|
||||
union SIGNAL
|
||||
{
|
||||
SIGSELECT sigNo;
|
||||
struct MmsAllocateRegionRequest mmsAllocateRegionRequest;
|
||||
struct MmsAllocateRegionReply mmsAllocateRegionReply;
|
||||
struct MmsFreeRegionRequest mmsFreeRegionRequest;
|
||||
struct MmsFreeRegionReply mmsFreeRegionReply;
|
||||
}; /* union SIGNAL */
|
||||
|
||||
extern PROCESS ose_mms_;
|
||||
|
||||
void NdbMem_Create(void)
|
||||
{
|
||||
/* Do nothing */
|
||||
return;
|
||||
}
|
||||
|
||||
void NdbMem_Destroy(void)
|
||||
{
|
||||
/* Do nothing */
|
||||
return;
|
||||
}
|
||||
|
||||
void* NdbMem_Allocate(size_t size)
|
||||
{
|
||||
static SIGSELECT allocate_sig[] = {1,MMS_ALLOCATE_REGION_REPLY};
|
||||
union SIGNAL *sig;
|
||||
U32 allocatedAdress;
|
||||
|
||||
assert(size > 0);
|
||||
|
||||
// Only allowed to allocate multiples of the page size.
|
||||
if(size % PAGE_SIZE != 0) {
|
||||
size += PAGE_SIZE - size%PAGE_SIZE;
|
||||
}
|
||||
|
||||
/* Allocate a new region in the callers memory segment. */
|
||||
sig = alloc(sizeof(struct MmsAllocateRegionRequest),
|
||||
MMS_ALLOCATE_REGION_REQUEST);
|
||||
/* -1: The callers domain is used */
|
||||
sig->mmsAllocateRegionRequest.domain = (MemoryDomain)-1;
|
||||
sig->mmsAllocateRegionRequest.useAddr = False;
|
||||
sig->mmsAllocateRegionRequest.size = size;
|
||||
sig->mmsAllocateRegionRequest.access = SuperRW_UserRW;
|
||||
sig->mmsAllocateRegionRequest.resident = False;
|
||||
sig->mmsAllocateRegionRequest.memory = CodeData;
|
||||
sig->mmsAllocateRegionRequest.cache = CopyBack;
|
||||
strcpy(sig->mmsAllocateRegionRequest.name, "NDB_DATA");
|
||||
send(&sig, ose_mms_);
|
||||
sig = receive(allocate_sig);
|
||||
|
||||
if (sig->mmsAllocateRegionReply.status != MMS_SUCCESS){
|
||||
/* Memory allocation failed, make sure this function returns NULL */
|
||||
allocatedAdress = NULL;
|
||||
}
|
||||
else{
|
||||
allocatedAdress = sig->mmsAllocateRegionReply.address;
|
||||
}
|
||||
free_buf(&sig);
|
||||
return (void*)allocatedAdress;
|
||||
}
|
||||
|
||||
void* NdbMem_AllocateAlign(size_t size, size_t alignment)
|
||||
{
|
||||
return NdbMem_Allocate(size);
|
||||
}
|
||||
|
||||
|
||||
void NdbMem_Free(void* ptr)
|
||||
{
|
||||
static SIGSELECT free_sig[] = {1,MMS_FREE_REGION_REPLY};
|
||||
union SIGNAL *sig;
|
||||
|
||||
/* Free a region in the callers domain. */
|
||||
sig = alloc(sizeof(struct MmsFreeRegionRequest),
|
||||
MMS_FREE_REGION_REQUEST);
|
||||
sig->mmsFreeRegionRequest.address = (U32)ptr;
|
||||
send(&sig, ose_mms_);
|
||||
sig = receive(free_sig);
|
||||
|
||||
if (sig->mmsFreeRegionReply.status != MMS_SUCCESS){
|
||||
ndbout_c("The MMS Region could not be deallocated.\r\n");
|
||||
error(sig->mmsFreeRegionReply.status);
|
||||
};
|
||||
free_buf(&sig);
|
||||
}
|
||||
|
||||
int NdbMem_MemLockAll(){
|
||||
return -1;
|
||||
}
|
||||
|
||||
int NdbMem_MemUnlockAll(){
|
||||
return -1;
|
||||
}
|
||||
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
void NdbMem_Create()
|
||||
{
|
||||
/* Do nothing */
|
||||
return;
|
||||
}
|
||||
|
||||
void NdbMem_Destroy()
|
||||
{
|
||||
/* Do nothing */
|
||||
return;
|
||||
}
|
||||
|
||||
void* NdbMem_Allocate(size_t size)
|
||||
{
|
||||
assert(size > 0);
|
||||
return (void*)malloc(size);
|
||||
}
|
||||
|
||||
void* NdbMem_AllocateAlign(size_t size, size_t alignment)
|
||||
{
|
||||
/*
|
||||
return (void*)memalign(alignment, size);
|
||||
TEMP fix
|
||||
*/
|
||||
return (void*)malloc(size);
|
||||
}
|
||||
|
||||
|
||||
void NdbMem_Free(void* ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
|
||||
int NdbMem_MemLockAll(){
|
||||
return -1;
|
||||
}
|
||||
|
||||
int NdbMem_MemUnlockAll(){
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,53 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include "NdbMem.h"
|
||||
|
||||
extern "C"
|
||||
void NdbMem_Create()
|
||||
{
|
||||
}
|
||||
extern "C"
|
||||
void NdbMem_Destroy()
|
||||
{
|
||||
}
|
||||
|
||||
extern "C"
|
||||
void* NdbMem_Allocate(size_t size)
|
||||
{
|
||||
return new char[size];
|
||||
}
|
||||
|
||||
extern "C"
|
||||
void* NdbMem_AllocateAlign(size_t size, size_t alignment)
|
||||
{
|
||||
return NdbMem_Allocate(size);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
void NdbMem_Free(void* ptr)
|
||||
{
|
||||
delete [] (char *)(ptr);
|
||||
}
|
||||
|
||||
int NdbMem_MemLockAll(){
|
||||
return -1;
|
||||
}
|
||||
|
||||
int NdbMem_MemUnlockAll(){
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
|
||||
#include "NdbMutex.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
NdbMutex* NdbMutex_Create(void)
|
||||
{
|
||||
NdbMutex* pNdbMutex;
|
||||
|
||||
pNdbMutex = create_sem(1);
|
||||
|
||||
return pNdbMutex;
|
||||
}
|
||||
|
||||
|
||||
int NdbMutex_Destroy(NdbMutex* p_mutex)
|
||||
{
|
||||
|
||||
if (p_mutex == NULL)
|
||||
return -1;
|
||||
|
||||
kill_sem(p_mutex);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int NdbMutex_Lock(NdbMutex* p_mutex)
|
||||
{
|
||||
if (p_mutex == NULL)
|
||||
return -1;
|
||||
|
||||
wait_sem(p_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int NdbMutex_Unlock(NdbMutex* p_mutex)
|
||||
{
|
||||
|
||||
if (p_mutex == NULL)
|
||||
return -1;
|
||||
|
||||
signal_sem(p_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int NdbMutex_Trylock(NdbMutex* p_mutex)
|
||||
{
|
||||
int result = -1;
|
||||
|
||||
if (p_mutex != NULL) {
|
||||
OSSEMVAL semvalue = get_sem(p_mutex);
|
||||
if (semvalue > 0) {
|
||||
wait_sem(p_mutex);
|
||||
result = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include <ndb_global.h>
|
||||
|
||||
#include "NdbOut.hpp"
|
||||
|
||||
#if defined NDB_SOFTOSE
|
||||
#include <dbgprintf.h>
|
||||
#define printfunc dbgprintf
|
||||
#else
|
||||
#define printfunc printf
|
||||
#endif
|
||||
|
||||
static char const* const endlineString = "\r\n";
|
||||
|
||||
static int CtrlC = 0;
|
||||
NdbOut ndbout;
|
||||
|
||||
|
||||
NdbOut& NdbOut::operator<<(int aVal)
|
||||
{
|
||||
char* format;
|
||||
char HexFormat[] = "0x%08x";
|
||||
char DecFormat[] = "%d";
|
||||
if (isHexFormat == 1)
|
||||
format = HexFormat;
|
||||
else
|
||||
format = DecFormat;
|
||||
|
||||
printfunc(format, aVal);
|
||||
return *this;
|
||||
}
|
||||
|
||||
NdbOut& NdbOut::operator<<(char* pVal)
|
||||
{
|
||||
printfunc("%s", pVal);
|
||||
return *this;
|
||||
}
|
||||
|
||||
NdbOut& NdbOut::endline()
|
||||
{
|
||||
isHexFormat = 0; // Reset hex to normal, if user forgot this
|
||||
printfunc(endlineString);
|
||||
return *this;
|
||||
}
|
||||
|
||||
NdbOut& NdbOut::flushline()
|
||||
{
|
||||
isHexFormat = 0; // Reset hex to normal, if user forgot this
|
||||
return *this;
|
||||
}
|
||||
|
||||
NdbOut& NdbOut::setHexFormat(int _format)
|
||||
{
|
||||
isHexFormat = _format;
|
||||
return *this;
|
||||
}
|
||||
|
||||
NdbOut::NdbOut()
|
||||
{
|
||||
CtrlC = 0;
|
||||
isHexFormat = 0;
|
||||
}
|
||||
|
||||
NdbOut::~NdbOut()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
extern "C"
|
||||
void
|
||||
ndbout_c(const char * fmt, ...){
|
||||
va_list ap;
|
||||
char buf[1000];
|
||||
|
||||
va_start(ap, fmt);
|
||||
if (fmt != 0)
|
||||
vsnprintf(buf, sizeof(buf)-1, fmt, ap);
|
||||
ndbout << buf << endl;
|
||||
va_end(ap);
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
|
||||
#include "NdbSleep.h"
|
||||
|
||||
#include <ose.h>
|
||||
|
||||
|
||||
int
|
||||
NdbSleep_MilliSleep(int milliseconds){
|
||||
const OSTIME millisecond_delay = milliseconds;
|
||||
delay(millisecond_delay);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
NdbSleep_SecSleep(int seconds){
|
||||
const OSTIME millisecond_delay = seconds*1000;
|
||||
delay(millisecond_delay);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
|
||||
#include "NdbTCP.h"
|
||||
|
||||
|
||||
int
|
||||
Ndb_getInAddr(struct in_addr * dst, const char *address) {
|
||||
struct hostent * host;
|
||||
host = gethostbyname_r(address);
|
||||
if(host != 0){
|
||||
dst->s_addr = ((struct in_addr *) *host->h_addr_list)->s_addr;
|
||||
free_buf((union SIGNAL **)&host);
|
||||
return 0;
|
||||
}
|
||||
/* Try it as aaa.bbb.ccc.ddd. */
|
||||
dst->s_addr = inet_addr(address);
|
||||
if (dst->s_addr != INADDR_NONE) {
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -1,183 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
|
||||
#include "NdbThread.h"
|
||||
#include <pthread.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include <NdbOut.hpp>
|
||||
|
||||
#define MAX_THREAD_NAME 16
|
||||
|
||||
|
||||
struct NdbThread
|
||||
{
|
||||
PROCESS pid;
|
||||
char thread_name[MAX_THREAD_NAME];
|
||||
};
|
||||
|
||||
#define NDBTHREAD_SIGBASE 4010
|
||||
|
||||
#define NDBTHREAD_START (NDBTHREAD_SIGBASE + 1) /* !-SIGNO(struct NdbThreadStart)-! */
|
||||
|
||||
struct NdbThreadStart
|
||||
{
|
||||
SIGSELECT sigNo;
|
||||
NDB_THREAD_FUNC* func;
|
||||
NDB_THREAD_ARG arg;
|
||||
};
|
||||
|
||||
struct NdbThreadStopped
|
||||
{
|
||||
SIGSELECT sigNo;
|
||||
};
|
||||
|
||||
union SIGNAL
|
||||
{
|
||||
SIGSELECT sigNo;
|
||||
struct NdbThreadStart threadStart;
|
||||
struct NdbThreadStopped threadStopped;
|
||||
};
|
||||
|
||||
OS_PROCESS(thread_starter){
|
||||
static const SIGSELECT sel_start[] = {1, NDBTHREAD_START};
|
||||
struct NdbThreadStart* sigstart;
|
||||
union SIGNAL* sig;
|
||||
|
||||
/* Receive function adress and params */
|
||||
sig = receive((SIGSELECT*)sel_start);
|
||||
if (sig != NIL){
|
||||
if (sig->sigNo == NDBTHREAD_START){
|
||||
sigstart = ((struct NdbThreadStart*)sig);
|
||||
/* Execute function with arg */
|
||||
(*sigstart->func)(sigstart->arg);
|
||||
}else{
|
||||
assert(1==0);
|
||||
}
|
||||
free_buf(&sig);
|
||||
}
|
||||
}
|
||||
|
||||
struct NdbThread* NdbThread_Create(NDB_THREAD_FUNC* p_thread_func,
|
||||
NDB_THREAD_ARG *p_thread_arg,
|
||||
const NDB_THREAD_STACKSIZE thread_stack_size,
|
||||
const char* p_thread_name,
|
||||
NDB_THREAD_PRIO thread_prio)
|
||||
{
|
||||
struct NdbThread* tmpThread;
|
||||
union SIGNAL* sig;
|
||||
int ose_prio;
|
||||
|
||||
if (p_thread_func == NULL)
|
||||
return 0;
|
||||
|
||||
tmpThread = (struct NdbThread*)malloc(sizeof(struct NdbThread));
|
||||
if (tmpThread == NULL)
|
||||
return NULL;
|
||||
|
||||
strncpy((char*)&tmpThread->thread_name, p_thread_name, MAX_THREAD_NAME);
|
||||
|
||||
switch(thread_prio){
|
||||
case NDB_THREAD_PRIO_HIGHEST:
|
||||
ose_prio = 1;
|
||||
break;
|
||||
case NDB_THREAD_PRIO_HIGH:
|
||||
ose_prio = 10;
|
||||
break;
|
||||
case NDB_THREAD_PRIO_MEAN:
|
||||
ose_prio = 16;
|
||||
break;
|
||||
case NDB_THREAD_PRIO_LOW:
|
||||
ose_prio = 23;
|
||||
break;
|
||||
case NDB_THREAD_PRIO_LOWEST:
|
||||
ose_prio = 31;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Create process */
|
||||
tmpThread->pid = create_process(OS_PRI_PROC, /* Process type */
|
||||
(char*)p_thread_name, /* Name */
|
||||
thread_starter, /* Entry point */
|
||||
thread_stack_size, /* Stack size */
|
||||
ose_prio, /* Priority */
|
||||
0, /* Time slice */
|
||||
get_bid(current_process()), /* Block */
|
||||
NULL, /* Redir table */
|
||||
0,
|
||||
0);
|
||||
|
||||
/* Send params to process */
|
||||
sig = alloc(sizeof(struct NdbThreadStart), NDBTHREAD_START);
|
||||
((struct NdbThreadStart*)sig)->func = p_thread_func;
|
||||
((struct NdbThreadStart*)sig)->arg = p_thread_arg;
|
||||
send(&sig, tmpThread->pid);
|
||||
|
||||
/* Enable NDB_HOME environment variable for the thread */
|
||||
{
|
||||
/* Hardcoded NDB_HOME...*/
|
||||
char* ndb_home_env = get_env(current_process(), "NDB_HOME");
|
||||
if (ndb_home_env != NULL)
|
||||
{
|
||||
/* Set NDB_HOME */
|
||||
int rc = set_env(tmpThread->pid, "NDB_HOME", ndb_home_env);
|
||||
if (rc != 0)
|
||||
{
|
||||
/* Not really a problem */
|
||||
}
|
||||
} /* Enable NDB_HOME */
|
||||
}
|
||||
|
||||
/* Start process */
|
||||
start(tmpThread->pid);
|
||||
|
||||
return tmpThread;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void NdbThread_Destroy(struct NdbThread** p_thread)
|
||||
{
|
||||
free(* p_thread); * p_thread = 0;
|
||||
}
|
||||
|
||||
|
||||
int NdbThread_WaitFor(struct NdbThread* p_wait_thread, void** status)
|
||||
{
|
||||
while(hunt(p_wait_thread->thread_name, 0, NULL, NULL) != 0)
|
||||
delay(1000);
|
||||
|
||||
* status = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void NdbThread_Exit(int a)
|
||||
{
|
||||
kill_proc(current_process());
|
||||
}
|
||||
|
||||
|
||||
int NdbThread_SetConcurrencyLevel(int level)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
|
||||
#include "NdbTick.h"
|
||||
#include <time.h>
|
||||
|
||||
#define NANOSEC_PER_SEC 1000000000
|
||||
#define MICROSEC_PER_SEC 1000000
|
||||
#define MILLISEC_PER_SEC 1000
|
||||
#define MICROSEC_PER_MILLISEC 1000
|
||||
#define MILLISEC_PER_NANOSEC 1000000
|
||||
|
||||
#ifdef NDB_OSE
|
||||
NDB_TICKS NdbTick_CurrentMillisecond(void)
|
||||
{
|
||||
return get_ticks()*4;
|
||||
}
|
||||
#include <rtc.h>
|
||||
int
|
||||
NdbTick_CurrentMicrosecond(NDB_TICKS * secs, Uint32 * micros){
|
||||
struct TimePair tvp;
|
||||
rtc_get_time(&tvp);
|
||||
* secs = tvp.seconds;
|
||||
* micros = tvp.micros;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined NDB_SOFTOSE
|
||||
NDB_TICKS NdbTick_CurrentMillisecond(void)
|
||||
{
|
||||
/**
|
||||
* Depends on the interval counter in solaris
|
||||
* that means each "tick" in OSE is really 10 milliseconds
|
||||
*/
|
||||
return get_ticks()*10;
|
||||
}
|
||||
|
||||
#include <rtc.h>
|
||||
int
|
||||
NdbTick_CurrentMicrosecond(NDB_TICKS * secs, Uint32 * micros){
|
||||
struct TimePair tvp;
|
||||
rtc_get_time(&tvp);
|
||||
* secs = tvp.seconds;
|
||||
* micros = tvp.micros;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
include .defs.mk
|
||||
|
||||
TYPE := kernel
|
||||
|
||||
BIN_TARGET := PortLibTest
|
||||
BIN_TARGET_ARCHIVES := portlib general
|
||||
|
||||
SOURCES = NdbPortLibTest.cpp
|
||||
|
||||
include $(NDB_TOP)/Epilogue.mk
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
include .defs.mk
|
||||
|
||||
TYPE := util
|
||||
|
||||
PIC_ARCHIVE := Y
|
||||
ARCHIVE_TARGET := portlib
|
||||
|
||||
SOURCES.c = NdbCondition.c \
|
||||
NdbMutex.c \
|
||||
NdbSleep.c \
|
||||
NdbTick.c \
|
||||
NdbEnv.c \
|
||||
NdbThread.c \
|
||||
NdbHost.c \
|
||||
NdbTCP.c \
|
||||
NdbDaemon.c
|
||||
|
||||
ifeq ($(NDB_OS), SOFTOSE)
|
||||
SOURCES += NdbMem_SoftOse.cpp
|
||||
else
|
||||
SOURCES.c += NdbMem.c
|
||||
endif
|
||||
|
||||
include $(NDB_TOP)/Epilogue.mk
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,183 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <windows.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "NdbCondition.h"
|
||||
#include <NdbMutex.h>
|
||||
|
||||
|
||||
struct NdbCondition
|
||||
{
|
||||
long nWaiters;
|
||||
NdbMutex* pNdbMutexWaitersLock;
|
||||
HANDLE hSemaphore;
|
||||
HANDLE hEventWaitersDone;
|
||||
int bWasBroadcast;
|
||||
};
|
||||
|
||||
|
||||
struct NdbCondition*
|
||||
NdbCondition_Create(void)
|
||||
{
|
||||
int result = 0;
|
||||
struct NdbCondition* pNdbCondition = (struct NdbCondition*)malloc(sizeof(struct NdbCondition));
|
||||
if(!pNdbCondition)
|
||||
return 0;
|
||||
|
||||
pNdbCondition->nWaiters = 0;
|
||||
pNdbCondition->bWasBroadcast = 0;
|
||||
if(!(pNdbCondition->hSemaphore = CreateSemaphore(0, 0, MAXLONG, 0)))
|
||||
result = -1;
|
||||
else if(!(pNdbCondition->pNdbMutexWaitersLock = NdbMutex_Create()))
|
||||
result = -1;
|
||||
else if(!(pNdbCondition->hEventWaitersDone = CreateEvent(0, 0, 0, 0)))
|
||||
result = -1;
|
||||
|
||||
assert(!result);
|
||||
return pNdbCondition;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
NdbCondition_Wait(struct NdbCondition* p_cond,
|
||||
NdbMutex* p_mutex)
|
||||
{
|
||||
int result;
|
||||
int bLastWaiter;
|
||||
if(!p_cond || !p_mutex)
|
||||
return 1;
|
||||
|
||||
NdbMutex_Lock(p_cond->pNdbMutexWaitersLock);
|
||||
p_cond->nWaiters++;
|
||||
NdbMutex_Unlock(p_cond->pNdbMutexWaitersLock);
|
||||
|
||||
if(NdbMutex_Unlock(p_mutex))
|
||||
return -1;
|
||||
result = WaitForSingleObject (p_cond->hSemaphore, INFINITE);
|
||||
|
||||
NdbMutex_Lock(p_cond->pNdbMutexWaitersLock);
|
||||
p_cond->nWaiters--;
|
||||
bLastWaiter = (p_cond->bWasBroadcast && p_cond->nWaiters==0);
|
||||
NdbMutex_Unlock(p_cond->pNdbMutexWaitersLock);
|
||||
|
||||
if(result==WAIT_OBJECT_0 && bLastWaiter)
|
||||
SetEvent(p_cond->hEventWaitersDone);
|
||||
|
||||
NdbMutex_Lock(p_mutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
NdbCondition_WaitTimeout(struct NdbCondition* p_cond,
|
||||
NdbMutex* p_mutex,
|
||||
int msecs)
|
||||
{
|
||||
int result;
|
||||
int bLastWaiter;
|
||||
if (!p_cond || !p_mutex)
|
||||
return 1;
|
||||
|
||||
NdbMutex_Lock(p_cond->pNdbMutexWaitersLock);
|
||||
p_cond->nWaiters++;
|
||||
NdbMutex_Unlock(p_cond->pNdbMutexWaitersLock);
|
||||
if(msecs<0)
|
||||
msecs = 0;
|
||||
|
||||
if(NdbMutex_Unlock(p_mutex))
|
||||
return -1;
|
||||
result = WaitForSingleObject(p_cond->hSemaphore, msecs);
|
||||
|
||||
NdbMutex_Lock(p_cond->pNdbMutexWaitersLock);
|
||||
p_cond->nWaiters--;
|
||||
bLastWaiter = (p_cond->bWasBroadcast && p_cond->nWaiters==0);
|
||||
NdbMutex_Unlock(p_cond->pNdbMutexWaitersLock);
|
||||
|
||||
if(result!=WAIT_OBJECT_0)
|
||||
result = -1;
|
||||
|
||||
if(bLastWaiter)
|
||||
SetEvent(p_cond->hEventWaitersDone);
|
||||
|
||||
NdbMutex_Lock(p_mutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
NdbCondition_Signal(struct NdbCondition* p_cond)
|
||||
{
|
||||
int bHaveWaiters;
|
||||
if(!p_cond)
|
||||
return 1;
|
||||
|
||||
NdbMutex_Lock(p_cond->pNdbMutexWaitersLock);
|
||||
bHaveWaiters = (p_cond->nWaiters > 0);
|
||||
NdbMutex_Unlock(p_cond->pNdbMutexWaitersLock);
|
||||
|
||||
if(bHaveWaiters)
|
||||
return (ReleaseSemaphore(p_cond->hSemaphore, 1, 0) ? 0 : -1);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int NdbCondition_Broadcast(struct NdbCondition* p_cond)
|
||||
{
|
||||
int bHaveWaiters;
|
||||
int result = 0;
|
||||
if(!p_cond)
|
||||
return 1;
|
||||
|
||||
NdbMutex_Lock(p_cond->pNdbMutexWaitersLock);
|
||||
bHaveWaiters = 0;
|
||||
if(p_cond->nWaiters > 0)
|
||||
{
|
||||
p_cond->bWasBroadcast = !0;
|
||||
bHaveWaiters = 1;
|
||||
}
|
||||
NdbMutex_Unlock(p_cond->pNdbMutexWaitersLock);
|
||||
if(bHaveWaiters)
|
||||
{
|
||||
if(!ReleaseSemaphore(p_cond->hSemaphore, p_cond->nWaiters, 0))
|
||||
result = -1;
|
||||
else if(WaitForSingleObject (p_cond->hEventWaitersDone, INFINITE) != WAIT_OBJECT_0)
|
||||
result = -1;
|
||||
p_cond->bWasBroadcast = 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int NdbCondition_Destroy(struct NdbCondition* p_cond)
|
||||
{
|
||||
int result;
|
||||
if(!p_cond)
|
||||
return 1;
|
||||
|
||||
CloseHandle(p_cond->hEventWaitersDone);
|
||||
NdbMutex_Destroy(p_cond->pNdbMutexWaitersLock);
|
||||
result = (CloseHandle(p_cond->hSemaphore) ? 0 : -1);
|
||||
|
||||
free(p_cond);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include <ndb_global.h>
|
||||
#include "NdbDaemon.h"
|
||||
|
||||
#define NdbDaemon_ErrorSize 500
|
||||
long NdbDaemon_DaemonPid;
|
||||
int NdbDaemon_ErrorCode;
|
||||
char NdbDaemon_ErrorText[NdbDaemon_ErrorSize];
|
||||
|
||||
int
|
||||
NdbDaemon_Make(const char* lockfile, const char* logfile, unsigned flags)
|
||||
{
|
||||
/* Fail */
|
||||
snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
|
||||
"Daemon mode not implemented");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef NDB_DAEMON_TEST
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
if (NdbDaemon_Make("test.pid", "test.log", 0) == -1) {
|
||||
fprintf(stderr, "NdbDaemon_Make: %s\n", NdbDaemon_ErrorText);
|
||||
return 1;
|
||||
}
|
||||
sleep(10);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,33 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
|
||||
#include "NdbEnv.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
const char* NdbEnv_GetEnv(const char* name, char * buf, int buflen)
|
||||
{
|
||||
char* p = NULL;
|
||||
p = getenv(name);
|
||||
|
||||
if (p != NULL && buf != NULL){
|
||||
strncpy(buf, p, buflen);
|
||||
buf[buflen-1] = 0;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
|
||||
#include "NdbHost.h"
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
|
||||
|
||||
int NdbHost_GetHostName(char* buf)
|
||||
{
|
||||
/* We must initialize TCP/IP if we want to call gethostname */
|
||||
WORD wVersionRequested;
|
||||
WSADATA wsaData;
|
||||
int err;
|
||||
|
||||
wVersionRequested = MAKEWORD( 2, 0 );
|
||||
err = WSAStartup( wVersionRequested, &wsaData );
|
||||
if ( err != 0 ) {
|
||||
/**
|
||||
* Tell the user that we couldn't find a usable
|
||||
* WinSock DLL.
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get host name */
|
||||
if(gethostname(buf, MAXHOSTNAMELEN))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int NdbHost_GetProcessId(void)
|
||||
{
|
||||
return _getpid();
|
||||
}
|
||||
|
|
@ -1,235 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "NdbMem.h"
|
||||
|
||||
|
||||
struct AWEINFO
|
||||
{
|
||||
SIZE_T dwSizeInBytesRequested;
|
||||
ULONG_PTR nNumberOfPagesRequested;
|
||||
ULONG_PTR nNumberOfPagesActual;
|
||||
ULONG_PTR nNumberOfPagesFreed;
|
||||
ULONG_PTR* pnPhysicalMemoryPageArray;
|
||||
void* pRegionReserved;
|
||||
};
|
||||
|
||||
const size_t cNdbMem_nMaxAWEinfo = 256;
|
||||
size_t gNdbMem_nAWEinfo = 0;
|
||||
|
||||
struct AWEINFO* gNdbMem_pAWEinfo = 0;
|
||||
|
||||
|
||||
void ShowLastError(const char* szContext, const char* szFunction)
|
||||
{
|
||||
DWORD dwError = GetLastError();
|
||||
LPVOID lpMsgBuf;
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
dwError,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||
(LPTSTR)&lpMsgBuf,
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
printf("%s : %s failed : %lu : %s\n", szContext, szFunction, dwError, (char*)lpMsgBuf);
|
||||
LocalFree(lpMsgBuf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void NdbMem_Create()
|
||||
{
|
||||
// Address Windowing Extensions
|
||||
struct PRIVINFO
|
||||
{
|
||||
DWORD Count;
|
||||
LUID_AND_ATTRIBUTES Privilege[1];
|
||||
} Info;
|
||||
|
||||
HANDLE hProcess = GetCurrentProcess();
|
||||
HANDLE hToken;
|
||||
if(!OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken))
|
||||
{
|
||||
ShowLastError("NdbMem_Create", "OpenProcessToken");
|
||||
}
|
||||
|
||||
Info.Count = 1;
|
||||
Info.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||
if(!LookupPrivilegeValue(0, SE_LOCK_MEMORY_NAME, &(Info.Privilege[0].Luid)))
|
||||
{
|
||||
ShowLastError("NdbMem_Create", "LookupPrivilegeValue");
|
||||
}
|
||||
|
||||
if(!AdjustTokenPrivileges(hToken, FALSE, (PTOKEN_PRIVILEGES)&Info, 0, 0, 0))
|
||||
{
|
||||
ShowLastError("NdbMem_Create", "AdjustTokenPrivileges");
|
||||
}
|
||||
|
||||
if(!CloseHandle(hToken))
|
||||
{
|
||||
ShowLastError("NdbMem_Create", "CloseHandle");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void NdbMem_Destroy()
|
||||
{
|
||||
/* Do nothing */
|
||||
return;
|
||||
}
|
||||
|
||||
void* NdbMem_Allocate(size_t size)
|
||||
{
|
||||
// Address Windowing Extensions
|
||||
struct AWEINFO* pAWEinfo;
|
||||
HANDLE hProcess;
|
||||
SYSTEM_INFO sysinfo;
|
||||
|
||||
if(!gNdbMem_pAWEinfo)
|
||||
{
|
||||
gNdbMem_pAWEinfo = VirtualAlloc(0,
|
||||
sizeof(struct AWEINFO)*cNdbMem_nMaxAWEinfo,
|
||||
MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
|
||||
}
|
||||
|
||||
assert(gNdbMem_nAWEinfo < cNdbMem_nMaxAWEinfo);
|
||||
pAWEinfo = gNdbMem_pAWEinfo+gNdbMem_nAWEinfo++;
|
||||
|
||||
hProcess = GetCurrentProcess();
|
||||
GetSystemInfo(&sysinfo);
|
||||
pAWEinfo->nNumberOfPagesRequested = (size+sysinfo.dwPageSize-1)/sysinfo.dwPageSize;
|
||||
pAWEinfo->pnPhysicalMemoryPageArray = VirtualAlloc(0,
|
||||
sizeof(ULONG_PTR)*pAWEinfo->nNumberOfPagesRequested,
|
||||
MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
|
||||
pAWEinfo->nNumberOfPagesActual = pAWEinfo->nNumberOfPagesRequested;
|
||||
if(!AllocateUserPhysicalPages(hProcess, &(pAWEinfo->nNumberOfPagesActual), pAWEinfo->pnPhysicalMemoryPageArray))
|
||||
{
|
||||
ShowLastError("NdbMem_Allocate", "AllocateUserPhysicalPages");
|
||||
return 0;
|
||||
}
|
||||
if(pAWEinfo->nNumberOfPagesRequested != pAWEinfo->nNumberOfPagesActual)
|
||||
{
|
||||
ShowLastError("NdbMem_Allocate", "nNumberOfPagesRequested != nNumberOfPagesActual");
|
||||
return 0;
|
||||
}
|
||||
|
||||
pAWEinfo->dwSizeInBytesRequested = size;
|
||||
pAWEinfo->pRegionReserved = VirtualAlloc(0, pAWEinfo->dwSizeInBytesRequested, MEM_RESERVE | MEM_PHYSICAL, PAGE_READWRITE);
|
||||
if(!pAWEinfo->pRegionReserved)
|
||||
{
|
||||
ShowLastError("NdbMem_Allocate", "VirtualAlloc");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!MapUserPhysicalPages(pAWEinfo->pRegionReserved, pAWEinfo->nNumberOfPagesActual, pAWEinfo->pnPhysicalMemoryPageArray))
|
||||
{
|
||||
ShowLastError("NdbMem_Allocate", "MapUserPhysicalPages");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
printf("allocate AWE memory: %lu bytes, %lu pages, address %lx\n",
|
||||
pAWEinfo->dwSizeInBytesRequested,
|
||||
pAWEinfo->nNumberOfPagesActual,
|
||||
pAWEinfo->pRegionReserved);
|
||||
*/
|
||||
return pAWEinfo->pRegionReserved;
|
||||
}
|
||||
|
||||
|
||||
void* NdbMem_AllocateAlign(size_t size, size_t alignment)
|
||||
{
|
||||
/*
|
||||
return (void*)memalign(alignment, size);
|
||||
TEMP fix
|
||||
*/
|
||||
return NdbMem_Allocate(size);
|
||||
}
|
||||
|
||||
|
||||
void NdbMem_Free(void* ptr)
|
||||
{
|
||||
// VirtualFree(ptr, 0, MEM_DECOMMIT|MEM_RELEASE);
|
||||
|
||||
// Address Windowing Extensions
|
||||
struct AWEINFO* pAWEinfo = 0;
|
||||
size_t i;
|
||||
HANDLE hProcess;
|
||||
|
||||
for(i=0; i<gNdbMem_nAWEinfo; ++i)
|
||||
{
|
||||
if(ptr==gNdbMem_pAWEinfo[i].pRegionReserved)
|
||||
{
|
||||
pAWEinfo = gNdbMem_pAWEinfo+i;
|
||||
}
|
||||
}
|
||||
if(!pAWEinfo)
|
||||
{
|
||||
ShowLastError("NdbMem_Free", "ptr is not AWE memory");
|
||||
}
|
||||
|
||||
hProcess = GetCurrentProcess();
|
||||
if(!MapUserPhysicalPages(ptr, pAWEinfo->nNumberOfPagesActual, 0))
|
||||
{
|
||||
ShowLastError("NdbMem_Free", "MapUserPhysicalPages");
|
||||
}
|
||||
|
||||
if(!VirtualFree(ptr, 0, MEM_RELEASE))
|
||||
{
|
||||
ShowLastError("NdbMem_Free", "VirtualFree");
|
||||
}
|
||||
|
||||
pAWEinfo->nNumberOfPagesFreed = pAWEinfo->nNumberOfPagesActual;
|
||||
if(!FreeUserPhysicalPages(hProcess, &(pAWEinfo->nNumberOfPagesFreed), pAWEinfo->pnPhysicalMemoryPageArray))
|
||||
{
|
||||
ShowLastError("NdbMem_Free", "FreeUserPhysicalPages");
|
||||
}
|
||||
|
||||
VirtualFree(pAWEinfo->pnPhysicalMemoryPageArray, 0, MEM_DECOMMIT|MEM_RELEASE);
|
||||
}
|
||||
|
||||
|
||||
int NdbMem_MemLockAll()
|
||||
{
|
||||
/*
|
||||
HANDLE hProcess = GetCurrentProcess();
|
||||
SIZE_T nMinimumWorkingSetSize;
|
||||
SIZE_T nMaximumWorkingSetSize;
|
||||
GetProcessWorkingSetSize(hProcess, &nMinimumWorkingSetSize, &nMaximumWorkingSetSize);
|
||||
ndbout << "nMinimumWorkingSetSize=" << nMinimumWorkingSetSize << ", nMaximumWorkingSetSize=" << nMaximumWorkingSetSize << endl;
|
||||
|
||||
SetProcessWorkingSetSize(hProcess, 50000000, 100000000);
|
||||
|
||||
GetProcessWorkingSetSize(hProcess, &nMinimumWorkingSetSize, &nMaximumWorkingSetSize);
|
||||
ndbout << "nMinimumWorkingSetSize=" << nMinimumWorkingSetSize << ", nMaximumWorkingSetSize=" << nMaximumWorkingSetSize << endl;
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
|
||||
int NdbMem_MemUnlockAll()
|
||||
{
|
||||
//VirtualUnlock();
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <windows.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "NdbMutex.h"
|
||||
|
||||
|
||||
NdbMutex* NdbMutex_Create(void)
|
||||
{
|
||||
NdbMutex* pNdbMutex = (NdbMutex*)malloc(sizeof(NdbMutex));
|
||||
if(!pNdbMutex)
|
||||
return 0;
|
||||
|
||||
InitializeCriticalSection(pNdbMutex);
|
||||
return pNdbMutex;
|
||||
}
|
||||
|
||||
|
||||
int NdbMutex_Destroy(NdbMutex* p_mutex)
|
||||
{
|
||||
if(!p_mutex)
|
||||
return -1;
|
||||
|
||||
DeleteCriticalSection(p_mutex);
|
||||
free(p_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int NdbMutex_Lock(NdbMutex* p_mutex)
|
||||
{
|
||||
if(!p_mutex)
|
||||
return -1;
|
||||
|
||||
EnterCriticalSection (p_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int NdbMutex_Unlock(NdbMutex* p_mutex)
|
||||
{
|
||||
if(!p_mutex)
|
||||
return -1;
|
||||
|
||||
LeaveCriticalSection(p_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int NdbMutex_Trylock(NdbMutex* p_mutex)
|
||||
{
|
||||
int result = -1;
|
||||
if(p_mutex)
|
||||
{
|
||||
result = (TryEnterCriticalSection(p_mutex) ? 0 : -1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
|
||||
#include "NdbSleep.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
int
|
||||
NdbSleep_MilliSleep(int milliseconds)
|
||||
{
|
||||
Sleep(milliseconds);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
NdbSleep_SecSleep(int seconds)
|
||||
{
|
||||
return NdbSleep_MilliSleep(seconds*1000);
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
|
||||
#include "NdbTCP.h"
|
||||
|
||||
int
|
||||
Ndb_getInAddr(struct in_addr * dst, const char *address)
|
||||
{
|
||||
struct hostent * hostPtr;
|
||||
|
||||
/* Try it as aaa.bbb.ccc.ddd. */
|
||||
dst->s_addr = inet_addr(address);
|
||||
if (dst->s_addr != -1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
hostPtr = gethostbyname(address);
|
||||
if (hostPtr != NULL) {
|
||||
dst->s_addr = ((struct in_addr *) *hostPtr->h_addr_list)->s_addr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -1,117 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
|
||||
#include "NdbThread.h"
|
||||
|
||||
|
||||
#define MAX_THREAD_NAME 16
|
||||
|
||||
typedef unsigned (WINAPI* NDB_WIN32_THREAD_FUNC)(void*);
|
||||
|
||||
|
||||
struct NdbThread
|
||||
{
|
||||
HANDLE hThread;
|
||||
unsigned nThreadId;
|
||||
char thread_name[MAX_THREAD_NAME];
|
||||
};
|
||||
|
||||
|
||||
struct NdbThread* NdbThread_Create(NDB_THREAD_FUNC *p_thread_func,
|
||||
NDB_THREAD_ARG *p_thread_arg,
|
||||
const NDB_THREAD_STACKSIZE thread_stack_size,
|
||||
const char* p_thread_name,
|
||||
NDB_THREAD_PRIO thread_prio)
|
||||
{
|
||||
struct NdbThread* tmpThread;
|
||||
unsigned initflag;
|
||||
int nPriority = 0;
|
||||
|
||||
if(!p_thread_func)
|
||||
return 0;
|
||||
|
||||
tmpThread = (struct NdbThread*)malloc(sizeof(struct NdbThread));
|
||||
if(!tmpThread)
|
||||
return 0;
|
||||
|
||||
strncpy((char*)&tmpThread->thread_name, p_thread_name, MAX_THREAD_NAME);
|
||||
|
||||
switch(thread_prio)
|
||||
{
|
||||
case NDB_THREAD_PRIO_HIGHEST: nPriority=THREAD_PRIORITY_HIGHEST; break;
|
||||
case NDB_THREAD_PRIO_HIGH: nPriority=THREAD_PRIORITY_ABOVE_NORMAL; break;
|
||||
case NDB_THREAD_PRIO_MEAN: nPriority=THREAD_PRIORITY_NORMAL; break;
|
||||
case NDB_THREAD_PRIO_LOW: nPriority=THREAD_PRIORITY_BELOW_NORMAL; break;
|
||||
case NDB_THREAD_PRIO_LOWEST: nPriority=THREAD_PRIORITY_LOWEST; break;
|
||||
}
|
||||
initflag = (nPriority ? CREATE_SUSPENDED : 0);
|
||||
|
||||
tmpThread->hThread = (HANDLE)_beginthreadex(0, thread_stack_size,
|
||||
(NDB_WIN32_THREAD_FUNC)p_thread_func, p_thread_arg,
|
||||
initflag, &tmpThread->nThreadId);
|
||||
|
||||
if(nPriority && tmpThread->hThread)
|
||||
{
|
||||
SetThreadPriority(tmpThread->hThread, nPriority);
|
||||
ResumeThread (tmpThread->hThread);
|
||||
}
|
||||
|
||||
assert(tmpThread->hThread);
|
||||
return tmpThread;
|
||||
}
|
||||
|
||||
|
||||
void NdbThread_Destroy(struct NdbThread** p_thread)
|
||||
{
|
||||
CloseHandle((*p_thread)->hThread);
|
||||
(*p_thread)->hThread = 0;
|
||||
free(*p_thread);
|
||||
*p_thread = 0;
|
||||
}
|
||||
|
||||
|
||||
int NdbThread_WaitFor(struct NdbThread* p_wait_thread, void** status)
|
||||
{
|
||||
void *local_status = 0;
|
||||
if (status == 0)
|
||||
status = &local_status;
|
||||
|
||||
if(WaitForSingleObject(p_wait_thread->hThread, INFINITE) == WAIT_OBJECT_0
|
||||
&& GetExitCodeThread(p_wait_thread->hThread, (LPDWORD)status))
|
||||
{
|
||||
CloseHandle(p_wait_thread->hThread);
|
||||
p_wait_thread->hThread = 0;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void NdbThread_Exit(int status)
|
||||
{
|
||||
_endthreadex((DWORD) status);
|
||||
}
|
||||
|
||||
|
||||
int NdbThread_SetConcurrencyLevel(int level)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
|
||||
#include <windows.h>
|
||||
#include "NdbTick.h"
|
||||
|
||||
/*
|
||||
#define FILETIME_PER_MICROSEC 10
|
||||
#define FILETIME_PER_MILLISEC 10000
|
||||
#define FILETIME_PER_SEC 10000000
|
||||
|
||||
|
||||
NDB_TICKS NdbTick_CurrentMillisecond(void)
|
||||
{
|
||||
ULONGLONG ullTime;
|
||||
GetSystemTimeAsFileTime((LPFILETIME)&ullTime);
|
||||
return (ullTime / FILETIME_PER_MILLISEC);
|
||||
}
|
||||
|
||||
int
|
||||
NdbTick_CurrentMicrosecond(NDB_TICKS * secs, Uint32 * micros)
|
||||
{
|
||||
ULONGLONG ullTime;
|
||||
GetSystemTimeAsFileTime((LPFILETIME)&ullTime);
|
||||
*secs = (ullTime / FILETIME_PER_SEC);
|
||||
*micros = (Uint32)((ullTime % FILETIME_PER_SEC) / FILETIME_PER_MICROSEC);
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
NDB_TICKS NdbTick_CurrentMillisecond(void)
|
||||
{
|
||||
LARGE_INTEGER liCount, liFreq;
|
||||
QueryPerformanceCounter(&liCount);
|
||||
QueryPerformanceFrequency(&liFreq);
|
||||
return (liCount.QuadPart*1000) / liFreq.QuadPart;
|
||||
}
|
||||
|
||||
int
|
||||
NdbTick_CurrentMicrosecond(NDB_TICKS * secs, Uint32 * micros)
|
||||
{
|
||||
LARGE_INTEGER liCount, liFreq;
|
||||
QueryPerformanceCounter(&liCount);
|
||||
QueryPerformanceFrequency(&liFreq);
|
||||
*secs = liCount.QuadPart / liFreq.QuadPart;
|
||||
liCount.QuadPart -= *secs * liFreq.QuadPart;
|
||||
*micros = (liCount.QuadPart*1000000) / liFreq.QuadPart;
|
||||
return 0;
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
include .defs.mk
|
||||
|
||||
DIRS =
|
||||
|
||||
ifneq ($(NDB_ODBC),N)
|
||||
DIRS += odbc
|
||||
endif
|
||||
|
||||
include $(NDB_TOP)/Epilogue.mk
|
|
@ -1,59 +0,0 @@
|
|||
# before Epilogue.mk
|
||||
|
||||
CCFLAGS_LOC += -I..
|
||||
|
||||
CCFLAGS_LOC += \
|
||||
-I$(call fixpath,$(NDB_TOP)/include/ndbapi) \
|
||||
-I$(call fixpath,$(NDB_TOP)/include/util) \
|
||||
-I$(call fixpath,$(NDB_TOP)/include/portlib)
|
||||
|
||||
ifeq ($(NDB_OS),SOLARIS)
|
||||
|
||||
CCFLAGS_LOC += -I/usr/local/include
|
||||
|
||||
ifeq ($(NDB_COMPILER),GCC)
|
||||
LIBS_LOC += -Wl,-z,text
|
||||
CCFLAGS_WARNINGS += -Wno-unused -Wformat
|
||||
CCFLAGS_TOP += -D__STL_PTHREADS
|
||||
endif
|
||||
|
||||
ifeq ($(NDB_COMPILER),FORTE6)
|
||||
LIBS_LOC += -z text
|
||||
LIBS_SPEC += /usr/lib/libCrun.so.1
|
||||
endif
|
||||
|
||||
LIB_TARGET_LIBS += -lthread -lrt
|
||||
|
||||
endif
|
||||
ifneq ($(filter $(NDB_OS), LINUX MACOSX IBMAIX TRU64X),)
|
||||
|
||||
LIBS_LOC += -Wl,-z,text
|
||||
CCFLAGS_WARNINGS += -Wno-unused -Wformat
|
||||
GCC_VER := $(shell $(CC) --version)
|
||||
|
||||
ifeq ($(GCC_VER),2.96)
|
||||
CCFLAGS_TOP += -D__STL_PTHREADS
|
||||
CCFLAGS_TOP += -fmessage-length=0
|
||||
endif
|
||||
|
||||
CCFLAGS_TOP += -fno-rtti
|
||||
|
||||
LIB_TARGET_LIBS += -lpthread
|
||||
|
||||
endif
|
||||
|
||||
ifeq ($(NDB_OS),WIN32)
|
||||
ifeq (RELEASE, $(NDB_VERSION))
|
||||
CCFLAGS_WIN += /MT /GR /GS /Zi -D_WINDOWS -D_USRDLL -DNDBODBC_EXPORTS -DNO_COMMAND_HANDLER -D_MBCS -D_WINDLL -U_LIB
|
||||
else
|
||||
ifeq (RELEASE_TRACE, $(NDB_VERSION))
|
||||
CCFLAGS_WIN += /MT /GR /GS /Zi -D_WINDOWS -D_USRDLL -DNDBODBC_EXPORTS -DNO_COMMAND_HANDLER -D_MBCS -D_WINDLL -U_LIB
|
||||
else
|
||||
CCFLAGS_WIN += /MT /GR /GS /Zi -D_WINDOWS -D_USRDLL -DNDBODBC_EXPORTS -DNO_COMMAND_HANDLER -D_MBCS -D_WINDLL -U_LIB
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
CCFLAGS_TOP += -DYYDEBUG=0 -fexceptions
|
||||
|
||||
CCFLAGS_TOP += -DHAVE_LONG_LONG
|
|
@ -1,75 +0,0 @@
|
|||
include .defs.mk
|
||||
|
||||
TYPE = *
|
||||
|
||||
A_LIB = N
|
||||
PIC_LIB = Y
|
||||
SO_LIB = Y
|
||||
|
||||
LIB_TARGET = NDB_ODBC
|
||||
|
||||
LIB_TARGET_ARCHIVES = $(LIB_DIRS:%=odbc%) NDB_API
|
||||
|
||||
# Overide Defs.mk
|
||||
LDFLAGS_LAST = -lstdc++ -lm
|
||||
|
||||
XXX = \
|
||||
ndbapi \
|
||||
mgmsrvcommon \
|
||||
transporter \
|
||||
general \
|
||||
signaldataprint \
|
||||
portlib \
|
||||
logger \
|
||||
trace
|
||||
|
||||
ifeq ($(NDB_OS),WIN32)
|
||||
|
||||
LIB_DIRS = \
|
||||
handles \
|
||||
dictionary \
|
||||
codegen \
|
||||
executor \
|
||||
common
|
||||
|
||||
SOURCES += NdbOdbc.cpp
|
||||
CFLAGS_NdbOdbc.cpp += -I. -I$(call fixpath,driver)
|
||||
|
||||
PIC_ARCHIVE := Y
|
||||
NONPIC_ARCHIVE := N
|
||||
ARCHIVE_TARGET := ndb_odbcwin32
|
||||
LIB_TARGET_ARCHIVES += ndb_odbcwin32
|
||||
|
||||
ifeq (RELEASE, $(NDB_VERSION))
|
||||
WIN_LIBS += /VERSION:2.0x /NODEFAULTLIB:"odbc32" /INCREMENTAL:NO /DLL /SUBSYSTEM:WINDOWS /MACHINE:IX86 /OPT:REF /OPT:ICF /DEF:NdbOdbc.def odbc32.lib odbccp32.lib user32.lib
|
||||
else
|
||||
ifeq (RELEASE_TRACE, $(NDB_VERSION))
|
||||
WIN_LIBS += /VERSION:2.0x /NODEFAULTLIB:"odbc32" /INCREMENTAL:NO /DLL /SUBSYSTEM:WINDOWS /MACHINE:IX86 /OPT:REF /OPT:ICF /DEF:NdbOdbc.def odbc32.lib odbccp32.lib user32.lib
|
||||
else
|
||||
WIN_LIBS += /VERSION:2.0x /NODEFAULTLIB:"odbc32" /INCREMENTAL /DLL /DEBUG /SUBSYSTEM:WINDOWS /MACHINE:IX86 /DEF:NdbOdbc.def odbc32.lib odbccp32.lib user32.lib
|
||||
endif
|
||||
endif
|
||||
|
||||
else
|
||||
|
||||
LIB_DIRS = \
|
||||
driver \
|
||||
handles \
|
||||
dictionary \
|
||||
codegen \
|
||||
executor \
|
||||
common
|
||||
|
||||
endif
|
||||
|
||||
include Extra.mk
|
||||
include $(NDB_TOP)/Epilogue.mk
|
||||
|
||||
# yo
|
||||
|
||||
test:
|
||||
$(MAKE) -j4
|
||||
$(MAKE) -C $(NDB_TOP)/tools/ndbsql
|
||||
$(MAKE) -C $(NDB_TOP)/test/odbc/driver tidy
|
||||
$(MAKE) -C $(NDB_TOP)/test/odbc/driver
|
||||
$(MAKE) -C $(NDB_TOP)/test/ndbapi/testOIBasic
|
|
@ -1,78 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
|
||||
#include <NdbUnistd.h>
|
||||
#include <odbcinst.h>
|
||||
|
||||
#include "driver.cpp"
|
||||
|
||||
|
||||
BOOL APIENTRY DllMain( HANDLE hModule,
|
||||
DWORD ul_reason_for_call,
|
||||
LPVOID lpReserved
|
||||
)
|
||||
{
|
||||
switch (ul_reason_for_call)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
BOOL INSTAPI ConfigDSN(
|
||||
HWND hwndParent,
|
||||
WORD fRequest,
|
||||
LPCSTR lpszDriver,
|
||||
LPCSTR lpszAttributes)
|
||||
{
|
||||
const char* szDSN = "NDB";
|
||||
|
||||
switch(fRequest)
|
||||
{
|
||||
case ODBC_ADD_DSN:
|
||||
SQLWriteDSNToIni(szDSN, lpszDriver);
|
||||
break;
|
||||
|
||||
case ODBC_CONFIG_DSN:
|
||||
break;
|
||||
|
||||
case ODBC_REMOVE_DSN:
|
||||
SQLRemoveDSNFromIni(szDSN);
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
int FAR PASCAL
|
||||
DriverConnectProc(HWND hdlg, WORD wMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void __declspec( dllexport) FAR PASCAL LoadByOrdinal(void);
|
||||
/* Entry point to cause DM to load using ordinals */
|
||||
void __declspec( dllexport) FAR PASCAL LoadByOrdinal(void)
|
||||
{
|
||||
}
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
LIBRARY NdbOdbc.DLL
|
||||
VERSION 03.51.00
|
||||
EXPORTS
|
||||
SQLAllocConnect
|
||||
SQLAllocEnv
|
||||
SQLAllocHandle
|
||||
SQLAllocHandleStd
|
||||
SQLAllocStmt
|
||||
SQLBindCol
|
||||
SQLBindParam
|
||||
SQLBindParameter
|
||||
SQLBrowseConnect
|
||||
SQLBulkOperations
|
||||
SQLCancel
|
||||
SQLCloseCursor
|
||||
SQLColAttribute
|
||||
SQLColAttributes
|
||||
SQLColumnPrivileges
|
||||
SQLColumns
|
||||
SQLConnect
|
||||
SQLCopyDesc
|
||||
SQLDataSources
|
||||
SQLDescribeCol
|
||||
SQLDescribeParam
|
||||
SQLDisconnect
|
||||
SQLDriverConnect
|
||||
SQLDrivers
|
||||
SQLEndTran
|
||||
SQLError
|
||||
SQLExecDirect
|
||||
SQLExecute
|
||||
SQLExtendedFetch
|
||||
SQLFetch
|
||||
SQLFetchScroll
|
||||
SQLForeignKeys
|
||||
SQLFreeConnect
|
||||
SQLFreeEnv
|
||||
SQLFreeHandle
|
||||
SQLFreeStmt
|
||||
SQLGetConnectAttr
|
||||
SQLGetConnectOption
|
||||
SQLGetCursorName
|
||||
SQLGetData
|
||||
SQLGetDescField
|
||||
SQLGetDescRec
|
||||
SQLGetDiagField
|
||||
SQLGetDiagRec
|
||||
SQLGetEnvAttr
|
||||
SQLGetFunctions
|
||||
SQLGetInfo
|
||||
SQLGetStmtAttr
|
||||
SQLGetStmtOption
|
||||
SQLGetTypeInfo
|
||||
SQLMoreResults
|
||||
SQLNativeSql
|
||||
SQLNumParams
|
||||
SQLNumResultCols
|
||||
SQLParamData
|
||||
SQLParamOptions
|
||||
SQLPrepare
|
||||
SQLPrimaryKeys
|
||||
SQLProcedureColumns
|
||||
SQLProcedures
|
||||
SQLPutData
|
||||
SQLRowCount
|
||||
SQLSetConnectAttr
|
||||
SQLSetConnectOption
|
||||
SQLSetCursorName
|
||||
SQLSetDescField
|
||||
SQLSetDescRec
|
||||
SQLSetEnvAttr
|
||||
SQLSetParam
|
||||
SQLSetPos
|
||||
SQLSetScrollOptions
|
||||
SQLSetStmtAttr
|
||||
SQLSetStmtOption
|
||||
SQLSpecialColumns
|
||||
SQLStatistics
|
||||
SQLTablePrivileges
|
||||
SQLTables
|
||||
SQLTransact
|
||||
DllMain
|
||||
DriverConnectProc
|
||||
ConfigDSN
|
||||
LoadByOrdinal
|
|
@ -1,229 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include <common/StmtArea.hpp>
|
||||
#include <common/CodeTree.hpp>
|
||||
#include <executor/Executor.hpp>
|
||||
#include "CodeGen.hpp"
|
||||
#include "Code_root.hpp"
|
||||
|
||||
#include <FlexLexer.h>
|
||||
#include "SimpleParser.hpp"
|
||||
|
||||
void
|
||||
CodeGen::prepare(Ctx& ctx)
|
||||
{
|
||||
parse(ctx);
|
||||
if (! ctx.ok())
|
||||
return;
|
||||
analyze(ctx);
|
||||
if (! ctx.ok())
|
||||
return;
|
||||
describe(ctx);
|
||||
}
|
||||
|
||||
void
|
||||
CodeGen::execute(Ctx& ctx)
|
||||
{
|
||||
DescArea& ipd = m_stmtArea.descArea(Desc_usage_IPD);
|
||||
if (m_stmtArea.m_unbound) {
|
||||
analyze(ctx);
|
||||
if (! ctx.ok())
|
||||
return;
|
||||
describe(ctx);
|
||||
if (! ctx.ok())
|
||||
return;
|
||||
if (m_stmtArea.m_unbound) {
|
||||
ctx.pushStatus(Sqlstate::_HY010, Error::Gen, "%u input parameters have unbound SQL type", m_stmtArea.m_unbound);
|
||||
return;
|
||||
}
|
||||
ipd.setBound(true);
|
||||
}
|
||||
if (! ipd.isBound()) {
|
||||
ctx_log2(("IPD changed between executes - reanalyze"));
|
||||
// jdbc can change parameter length at each execute
|
||||
analyze(ctx);
|
||||
if (! ctx.ok())
|
||||
return;
|
||||
describe(ctx);
|
||||
if (! ctx.ok())
|
||||
return;
|
||||
freeExec(ctx);
|
||||
codegen(ctx);
|
||||
if (! ctx.ok())
|
||||
return;
|
||||
alloc(ctx);
|
||||
if (! ctx.ok())
|
||||
return;
|
||||
ipd.setBound(true);
|
||||
}
|
||||
if (m_stmtArea.m_execTree == 0) {
|
||||
codegen(ctx);
|
||||
if (! ctx.ok())
|
||||
return;
|
||||
alloc(ctx);
|
||||
if (! ctx.ok())
|
||||
return;
|
||||
}
|
||||
Executor executor(m_stmtArea);
|
||||
executor.execute(ctx);
|
||||
}
|
||||
|
||||
void
|
||||
CodeGen::fetch(Ctx& ctx)
|
||||
{
|
||||
// XXX parameter types are not checked any more
|
||||
ctx_assert(! m_stmtArea.m_unbound);
|
||||
Executor executor(m_stmtArea);
|
||||
executor.fetch(ctx);
|
||||
}
|
||||
|
||||
void
|
||||
CodeGen::parse(Ctx& ctx)
|
||||
{
|
||||
Plan_root* planRoot = new Plan_root(m_stmtArea);
|
||||
SimpleParser simpleParser(ctx, m_stmtArea, planRoot);
|
||||
simpleParser.yyparse();
|
||||
if (! ctx.ok())
|
||||
return;
|
||||
planRoot->m_paramList.resize(1 + simpleParser.paramNumber());
|
||||
ctx_log2(("CodeGen: parse done - plan tree follows"));
|
||||
if (ctx.logLevel() >= 2)
|
||||
planRoot->print(ctx);
|
||||
m_stmtArea.m_planTree = planRoot;
|
||||
}
|
||||
|
||||
void
|
||||
CodeGen::analyze(Ctx& ctx)
|
||||
{
|
||||
Plan_root* planRoot = static_cast<Plan_root*>(m_stmtArea.m_planTree);
|
||||
ctx_assert(planRoot != 0);
|
||||
Plan_base::Ctl ctl(0);
|
||||
planRoot->analyze(ctx, ctl); // returns itself
|
||||
if (! ctx.ok())
|
||||
return;
|
||||
ctx_log2(("CodeGen: analyze done - plan tree follows"));
|
||||
if (ctx.logLevel() >= 2)
|
||||
planRoot->print(ctx);
|
||||
}
|
||||
|
||||
void
|
||||
CodeGen::describe(Ctx& ctx)
|
||||
{
|
||||
Plan_root* planRoot = static_cast<Plan_root*>(m_stmtArea.m_planTree);
|
||||
ctx_assert(planRoot != 0);
|
||||
planRoot->describe(ctx);
|
||||
ctx_log2(("CodeGen: describe done"));
|
||||
}
|
||||
|
||||
void
|
||||
CodeGen::codegen(Ctx& ctx)
|
||||
{
|
||||
Plan_root* planRoot = static_cast<Plan_root*>(m_stmtArea.m_planTree);
|
||||
ctx_assert(planRoot != 0);
|
||||
Plan_base::Ctl ctl(0);
|
||||
Exec_root* execRoot = static_cast<Exec_root*>(planRoot->codegen(ctx, ctl));
|
||||
if (! ctx.ok())
|
||||
return;
|
||||
ctx_assert(execRoot != 0);
|
||||
ctx_log2(("CodeGen: codegen done - code tree follows"));
|
||||
if (ctx.logLevel() >= 2)
|
||||
execRoot->print(ctx);
|
||||
m_stmtArea.m_execTree = execRoot;
|
||||
}
|
||||
|
||||
void
|
||||
CodeGen::alloc(Ctx& ctx)
|
||||
{
|
||||
Exec_root* execRoot = static_cast<Exec_root*>(m_stmtArea.m_execTree);
|
||||
ctx_assert(execRoot != 0);
|
||||
Exec_base::Ctl ctl(0);
|
||||
execRoot->alloc(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return;
|
||||
ctx_log2(("CodeGen: alloc done"));
|
||||
}
|
||||
|
||||
void
|
||||
CodeGen::close(Ctx& ctx)
|
||||
{
|
||||
Exec_root* execRoot = static_cast<Exec_root*>(m_stmtArea.m_execTree);
|
||||
if (execRoot != 0) {
|
||||
execRoot->close(ctx);
|
||||
ctx_log2(("CodeGen: close done"));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CodeGen::free(Ctx& ctx)
|
||||
{
|
||||
freePlan(ctx);
|
||||
freeExec(ctx);
|
||||
}
|
||||
|
||||
void
|
||||
CodeGen::freePlan(Ctx & ctx)
|
||||
{
|
||||
if (m_stmtArea.m_planTree != 0) {
|
||||
Plan_root* planRoot = static_cast<Plan_root*>(m_stmtArea.m_planTree);
|
||||
ctx_assert(planRoot != 0);
|
||||
unsigned count = 1 + planRoot->m_nodeList.size();
|
||||
planRoot->freeNodeList();
|
||||
delete planRoot;
|
||||
m_stmtArea.m_planTree = 0;
|
||||
ctx_log3(("CodeGen: freed %u plan tree nodes", count));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CodeGen::freeExec(Ctx & ctx)
|
||||
{
|
||||
if (m_stmtArea.m_execTree != 0) {
|
||||
Exec_root* execRoot = static_cast<Exec_root*>(m_stmtArea.m_execTree);
|
||||
ctx_assert(execRoot != 0);
|
||||
unsigned count = 1 + execRoot->m_nodeList.size();
|
||||
execRoot->freeNodeList();
|
||||
delete execRoot;
|
||||
m_stmtArea.m_execTree = 0;
|
||||
ctx_log3(("CodeGen: freed %u exec tree nodes", count));
|
||||
}
|
||||
}
|
||||
|
||||
// odbc support
|
||||
|
||||
void
|
||||
CodeGen::sqlGetData(Ctx& ctx, SQLUSMALLINT columnNumber, SQLSMALLINT targetType, SQLPOINTER targetValue, SQLINTEGER bufferLength, SQLINTEGER* strlen_or_Ind)
|
||||
{
|
||||
Exec_root* execRoot = static_cast<Exec_root*>(m_stmtArea.m_execTree);
|
||||
ctx_assert(execRoot != 0);
|
||||
execRoot->sqlGetData(ctx, columnNumber, targetType, targetValue, bufferLength, strlen_or_Ind);
|
||||
}
|
||||
|
||||
void
|
||||
CodeGen::sqlParamData(Ctx& ctx, SQLPOINTER* value)
|
||||
{
|
||||
Exec_root* execRoot = static_cast<Exec_root*>(m_stmtArea.m_execTree);
|
||||
ctx_assert(execRoot != 0);
|
||||
execRoot->sqlParamData(ctx, value);
|
||||
}
|
||||
|
||||
void
|
||||
CodeGen::sqlPutData(Ctx& ctx, SQLPOINTER data, SQLINTEGER strlen_or_Ind)
|
||||
{
|
||||
Exec_root* execRoot = static_cast<Exec_root*>(m_stmtArea.m_execTree);
|
||||
ctx_assert(execRoot != 0);
|
||||
execRoot->sqlPutData(ctx, data, strlen_or_Ind);
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef ODBC_CODEGEN_CodeGen_hpp
|
||||
#define ODBC_CODEGEN_CodeGen_hpp
|
||||
|
||||
#include <common/common.hpp>
|
||||
|
||||
class StmtArea;
|
||||
class SqlField;
|
||||
class ExtField;
|
||||
|
||||
/**
|
||||
* @class CodeGen
|
||||
* @brief Compiles SQL text into ExecTree::Code
|
||||
*/
|
||||
class CodeGen {
|
||||
public:
|
||||
CodeGen(StmtArea& stmtArea);
|
||||
~CodeGen();
|
||||
// parse and analyze SQL statement
|
||||
void prepare(Ctx& ctx);
|
||||
// these are passed to Executor
|
||||
void execute(Ctx& ctx);
|
||||
void fetch(Ctx& ctx);
|
||||
// close statement (mainly scan)
|
||||
void close(Ctx& ctx);
|
||||
// free data structures
|
||||
void free(Ctx& ctx);
|
||||
// odbc support
|
||||
void sqlGetData(Ctx& ctx, SQLUSMALLINT columnNumber, SQLSMALLINT targetType, SQLPOINTER targetValue, SQLINTEGER bufferLength, SQLINTEGER* strlen_or_Ind);
|
||||
void sqlParamData(Ctx& ctx, SQLPOINTER* value);
|
||||
void sqlPutData(Ctx& ctx, SQLPOINTER data, SQLINTEGER strlen_or_Ind);
|
||||
private:
|
||||
void parse(Ctx& ctx);
|
||||
void analyze(Ctx& ctx);
|
||||
void describe(Ctx& ctx);
|
||||
void codegen(Ctx& ctx);
|
||||
void alloc(Ctx& ctx);
|
||||
void freePlan(Ctx& ctx);
|
||||
void freeExec(Ctx& ctx);
|
||||
StmtArea& m_stmtArea;
|
||||
};
|
||||
|
||||
inline
|
||||
CodeGen::CodeGen(StmtArea& stmtArea) :
|
||||
m_stmtArea(stmtArea)
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
CodeGen::~CodeGen()
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,167 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include <common/StmtArea.hpp>
|
||||
#include "Code_base.hpp"
|
||||
#include "Code_root.hpp"
|
||||
|
||||
// Plan_base
|
||||
|
||||
Plan_base::~Plan_base()
|
||||
{
|
||||
}
|
||||
|
||||
StmtArea&
|
||||
Plan_base::stmtArea() const
|
||||
{
|
||||
ctx_assert(m_root != 0);
|
||||
return m_root->m_stmtArea;
|
||||
}
|
||||
|
||||
DescArea&
|
||||
Plan_base::descArea(DescUsage u) const
|
||||
{
|
||||
return stmtArea().descArea(u);
|
||||
}
|
||||
|
||||
ConnArea&
|
||||
Plan_base::connArea() const
|
||||
{
|
||||
return stmtArea().connArea();
|
||||
}
|
||||
|
||||
DictCatalog&
|
||||
Plan_base::dictCatalog() const
|
||||
{
|
||||
return connArea().dictCatalog();
|
||||
}
|
||||
|
||||
DictSchema&
|
||||
Plan_base::dictSchema() const
|
||||
{
|
||||
return connArea().dictSchema();
|
||||
}
|
||||
|
||||
Ndb*
|
||||
Plan_base::ndbObject() const
|
||||
{
|
||||
Ndb* ndb = connArea().ndbObject();
|
||||
ctx_assert(ndb != 0);
|
||||
return ndb;
|
||||
}
|
||||
|
||||
NdbSchemaCon*
|
||||
Plan_base::ndbSchemaCon() const
|
||||
{
|
||||
NdbSchemaCon* ndbSchemaCon = connArea().ndbSchemaCon();
|
||||
ctx_assert(ndbSchemaCon != 0);
|
||||
return ndbSchemaCon;
|
||||
}
|
||||
|
||||
NdbConnection*
|
||||
Plan_base::ndbConnection() const
|
||||
{
|
||||
NdbConnection* ndbConnection = connArea().ndbConnection();
|
||||
ctx_assert(ndbConnection != 0);
|
||||
return ndbConnection;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_base::printList(Ctx& ctx, Plan_base* a[], unsigned n)
|
||||
{
|
||||
for (unsigned i = 0; i < n; i++) {
|
||||
if (a[i] == 0)
|
||||
ctx.print(" -");
|
||||
else
|
||||
a[i]->print(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
// Exec_base
|
||||
|
||||
Exec_base::Code::~Code()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_base::Data::~Data()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_base::~Exec_base()
|
||||
{
|
||||
delete m_code; // remove when code becomes shared
|
||||
m_code = 0;
|
||||
delete m_data;
|
||||
m_data = 0;
|
||||
}
|
||||
|
||||
StmtArea&
|
||||
Exec_base::stmtArea() const
|
||||
{
|
||||
ctx_assert(m_root != 0);
|
||||
return m_root->m_stmtArea;
|
||||
}
|
||||
|
||||
DescArea&
|
||||
Exec_base::descArea(DescUsage u) const
|
||||
{
|
||||
return stmtArea().descArea(u);
|
||||
}
|
||||
|
||||
ConnArea&
|
||||
Exec_base::connArea() const
|
||||
{
|
||||
return stmtArea().connArea();
|
||||
}
|
||||
|
||||
DictSchema&
|
||||
Exec_base::dictSchema() const
|
||||
{
|
||||
return connArea().dictSchema();
|
||||
}
|
||||
|
||||
Ndb*
|
||||
Exec_base::ndbObject() const
|
||||
{
|
||||
Ndb* ndb = connArea().ndbObject();
|
||||
ctx_assert(ndb != 0);
|
||||
return ndb;
|
||||
}
|
||||
|
||||
NdbSchemaCon*
|
||||
Exec_base::ndbSchemaCon() const
|
||||
{
|
||||
NdbSchemaCon* ndbSchemaCon = connArea().ndbSchemaCon();
|
||||
ctx_assert(ndbSchemaCon != 0);
|
||||
return ndbSchemaCon;
|
||||
}
|
||||
|
||||
NdbConnection*
|
||||
Exec_base::ndbConnection() const
|
||||
{
|
||||
NdbConnection* ndbConnection = connArea().ndbConnection();
|
||||
ctx_assert(ndbConnection != 0);
|
||||
return ndbConnection;
|
||||
}
|
||||
|
||||
void
|
||||
Exec_base::printList(Ctx& ctx, Exec_base* a[], unsigned n)
|
||||
{
|
||||
for (unsigned i = 0; i < n; i++) {
|
||||
ctx_assert(a[i] != 0);
|
||||
a[i]->print(ctx);
|
||||
}
|
||||
}
|
|
@ -1,237 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef ODBC_CODEGEN_Code_base_hpp
|
||||
#define ODBC_CODEGEN_Code_base_hpp
|
||||
|
||||
#include <set>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <common/common.hpp>
|
||||
#include <common/CodeTree.hpp>
|
||||
#include <common/DescArea.hpp>
|
||||
|
||||
class Ctx;
|
||||
class ConnArea;
|
||||
class StmtArea;
|
||||
class DescArea;
|
||||
class DictCatalog;
|
||||
class DictSchema;
|
||||
class ResultArea;
|
||||
class ResultSet;
|
||||
class SpecRow;
|
||||
class Ndb;
|
||||
class NdbSchemaCon;
|
||||
class NdbConnection;
|
||||
class NdbOperation;
|
||||
class NdbScanFilter;
|
||||
|
||||
class Plan_root;
|
||||
class Plan_table;
|
||||
class Plan_column;
|
||||
class Plan_expr;
|
||||
class Plan_expr_param;
|
||||
class Plan_pred;
|
||||
class Plan_dml_row;
|
||||
class Plan_dml_column;
|
||||
class Plan_ddl_column;
|
||||
class Plan_ddl_constr;
|
||||
class Plan_idx_column;
|
||||
class Exec_root;
|
||||
class Exec_base;
|
||||
class Exec_query;
|
||||
class Exec_expr;
|
||||
class Exec_expr_row;
|
||||
class Exec_expr_param;
|
||||
|
||||
/**
|
||||
* @class Plan_base
|
||||
* @brief Base class for plan trees
|
||||
*/
|
||||
class Plan_base : public PlanTree {
|
||||
public:
|
||||
Plan_base(Plan_root* root);
|
||||
virtual ~Plan_base() = 0;
|
||||
// get references to StmtArea via Plan_root
|
||||
StmtArea& stmtArea() const;
|
||||
DescArea& descArea(DescUsage u) const;
|
||||
ConnArea& connArea() const;
|
||||
// catalogs
|
||||
DictCatalog& dictCatalog() const;
|
||||
DictSchema& dictSchema() const;
|
||||
// ndb
|
||||
Ndb* ndbObject() const;
|
||||
NdbSchemaCon* ndbSchemaCon() const;
|
||||
NdbConnection* ndbConnection() const;
|
||||
// containers for Plan classes
|
||||
typedef std::vector<Plan_table*> TableVector;
|
||||
typedef std::vector<Plan_column*> ColumnVector;
|
||||
typedef std::vector<Plan_dml_column*> DmlColumnVector;
|
||||
typedef std::vector<Plan_ddl_column*> DdlColumnVector;
|
||||
typedef std::vector<Plan_ddl_constr*> DdlConstrVector;
|
||||
typedef std::vector<Plan_idx_column*> IdxColumnVector;
|
||||
typedef std::vector<Plan_expr*> ExprVector;
|
||||
typedef std::list<Plan_expr*> ExprList;
|
||||
typedef std::vector<ExprList> ExprListVector;
|
||||
typedef std::list<Plan_pred*> PredList;
|
||||
typedef std::set<Plan_table*> TableSet;
|
||||
typedef std::vector<Plan_expr_param*> ParamVector;
|
||||
// control area on the stack XXX needs to be designed
|
||||
struct Ctl {
|
||||
Ctl(Ctl* up);
|
||||
Ctl* m_up; // up the stack
|
||||
// analyze
|
||||
TableVector m_tableList; // resolve column names
|
||||
bool m_topand; // in top-level where clause
|
||||
bool m_extra; // anything but single pk=expr
|
||||
bool m_aggrok; // aggregate allowed
|
||||
bool m_aggrin; // within aggregate args
|
||||
bool m_const; // only constants in set clause
|
||||
PredList m_topcomp; // top level comparisons
|
||||
Plan_dml_row *m_dmlRow; // row type to convert to
|
||||
Plan_table* m_topTable; // top level table for interpreted progs
|
||||
bool m_having; // in having-predicate
|
||||
// codegen
|
||||
Exec_root* m_execRoot; // root of Exec tree
|
||||
const Exec_query* m_execQuery; // pass to column
|
||||
};
|
||||
// semantic analysis and optimization
|
||||
virtual Plan_base* analyze(Ctx& ctx, Ctl& ctl) = 0;
|
||||
// generate "executable" code
|
||||
virtual Exec_base* codegen(Ctx& ctx, Ctl& ctl) = 0;
|
||||
// misc
|
||||
virtual void print(Ctx& ctx) = 0;
|
||||
protected:
|
||||
Plan_root* m_root;
|
||||
void printList(Ctx& ctx, Plan_base* a[], unsigned n);
|
||||
};
|
||||
|
||||
inline
|
||||
Plan_base::Plan_base(Plan_root* root) :
|
||||
m_root(root)
|
||||
{
|
||||
ctx_assert(m_root != 0);
|
||||
}
|
||||
|
||||
inline
|
||||
Plan_base::Ctl::Ctl(Ctl* up) :
|
||||
m_up(up),
|
||||
m_tableList(1), // 1-based
|
||||
m_topand(false),
|
||||
m_extra(false),
|
||||
m_aggrok(false),
|
||||
m_aggrin(false),
|
||||
m_dmlRow(0),
|
||||
m_topTable(0),
|
||||
m_having(false),
|
||||
m_execRoot(0),
|
||||
m_execQuery(0)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @class Exec_base
|
||||
* @brief Base class for exec trees
|
||||
*/
|
||||
class Exec_base : public ExecTree {
|
||||
public:
|
||||
class Code : public ExecTree::Code {
|
||||
public:
|
||||
virtual ~Code() = 0;
|
||||
};
|
||||
class Data : public ExecTree::Data {
|
||||
public:
|
||||
virtual ~Data() = 0;
|
||||
};
|
||||
Exec_base(Exec_root* root);
|
||||
virtual ~Exec_base() = 0;
|
||||
// get references to StmtArea via Exec_root
|
||||
virtual StmtArea& stmtArea() const;
|
||||
DescArea& descArea(DescUsage u) const;
|
||||
ConnArea& connArea() const;
|
||||
// catalogs
|
||||
DictSchema& dictSchema() const;
|
||||
// ndb
|
||||
Ndb* ndbObject() const;
|
||||
NdbSchemaCon* ndbSchemaCon() const;
|
||||
NdbConnection* ndbConnection() const;
|
||||
// containers for Exec classes
|
||||
typedef std::vector<Exec_expr*> ExprVector;
|
||||
typedef std::vector<Exec_expr_param*> ParamVector;
|
||||
// control area on the stack
|
||||
struct Ctl {
|
||||
Ctl(Ctl* up);
|
||||
Ctl* m_up; // up the stack
|
||||
const Exec_query* m_query; // pass Data
|
||||
ExprVector m_exprList; // pass Data
|
||||
NdbOperation* m_scanOp; // scan operation
|
||||
bool m_postEval; // for rownum
|
||||
unsigned m_groupIndex; // for group by
|
||||
bool m_groupInit; // first in group
|
||||
Exec_expr_row* m_sortRow; // from sort to group by
|
||||
NdbScanFilter* m_scanFilter; // scan filter
|
||||
};
|
||||
// allocate and deallocate Data instances
|
||||
virtual void alloc(Ctx& ctx, Ctl& ctl) = 0;
|
||||
virtual void close(Ctx& ctx) = 0;
|
||||
// set Code and Data
|
||||
void setCode(const Code& code);
|
||||
void setData(Data& data);
|
||||
// misc
|
||||
virtual void print(Ctx& ctx) = 0;
|
||||
protected:
|
||||
const Code* m_code;
|
||||
Data* m_data;
|
||||
Exec_root* m_root;
|
||||
void printList(Ctx& ctx, Exec_base* a[], unsigned n);
|
||||
};
|
||||
|
||||
inline
|
||||
Exec_base::Exec_base(Exec_root* root) :
|
||||
m_code(0),
|
||||
m_data(0),
|
||||
m_root(root)
|
||||
{
|
||||
ctx_assert(m_root != 0);
|
||||
}
|
||||
|
||||
inline void
|
||||
Exec_base::setCode(const Code& code)
|
||||
{
|
||||
ctx_assert(m_code == 0);
|
||||
m_code = &code;
|
||||
}
|
||||
|
||||
inline void
|
||||
Exec_base::setData(Data& data)
|
||||
{
|
||||
ctx_assert(m_data == 0);
|
||||
m_data = &data;
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_base::Ctl::Ctl(Ctl* up) :
|
||||
m_up(up),
|
||||
m_scanOp(0),
|
||||
m_postEval(false),
|
||||
m_groupIndex(0),
|
||||
m_groupInit(false),
|
||||
m_sortRow(0),
|
||||
m_scanFilter(0)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,72 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include <NdbApi.hpp>
|
||||
#include <common/StmtArea.hpp>
|
||||
#include <dictionary/DictSchema.hpp>
|
||||
#include <dictionary/DictColumn.hpp>
|
||||
#include "Code_column.hpp"
|
||||
#include "Code_table_list.hpp"
|
||||
#include "Code_table.hpp"
|
||||
|
||||
// Plan_column
|
||||
|
||||
Plan_column::~Plan_column()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Plan_column::analyzeColumn(Ctx& ctx, Plan_base::Ctl& ctl)
|
||||
{
|
||||
if (m_resTable != 0) // done on previous pass
|
||||
return;
|
||||
if (! (ctl.m_tableList.size() > 1)) {
|
||||
ctx.pushStatus(Sqlstate::_42000, Error::Gen, "column %s not allowed here", getPrintName());
|
||||
return;
|
||||
}
|
||||
unsigned resCount = 0;
|
||||
for (unsigned i = 1; i < ctl.m_tableList.size(); i++) {
|
||||
Plan_table* table = ctl.m_tableList[i];
|
||||
ctx_assert(table != 0);
|
||||
int ret = table->resolveColumn(ctx, this);
|
||||
if (ret < 0)
|
||||
return;
|
||||
if (ret)
|
||||
resCount++;
|
||||
}
|
||||
if (resCount == 0) {
|
||||
// XXX try to strip "schema name" from table name
|
||||
for (unsigned i = 1; i < ctl.m_tableList.size(); i++) {
|
||||
Plan_table* table = ctl.m_tableList[i];
|
||||
ctx_assert(table != 0);
|
||||
int ret = table->resolveColumn(ctx, this, true);
|
||||
if (ret < 0)
|
||||
return;
|
||||
if (ret)
|
||||
resCount++;
|
||||
}
|
||||
}
|
||||
if (resCount == 0) {
|
||||
ctx.pushStatus(Sqlstate::_42S22, Error::Gen, "column %s not found", getPrintName());
|
||||
return;
|
||||
}
|
||||
if (resCount > 1) {
|
||||
ctx.pushStatus(Error::Gen, "column %s is ambiguous", getPrintName());
|
||||
return;
|
||||
}
|
||||
// copy SQL type
|
||||
m_sqlType = dictColumn().sqlType();
|
||||
}
|
|
@ -1,122 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef ODBC_CODEGEN_Code_column_hpp
|
||||
#define ODBC_CODEGEN_Code_column_hpp
|
||||
|
||||
#include <common/common.hpp>
|
||||
#include <common/DataType.hpp>
|
||||
#include "Code_base.hpp"
|
||||
|
||||
class DictColumn;
|
||||
class Plan_table;
|
||||
|
||||
/**
|
||||
* @class Plan_column
|
||||
* @brief Abstract base class for columns
|
||||
*/
|
||||
class Plan_column {
|
||||
public:
|
||||
enum Type {
|
||||
Type_expr = 1,
|
||||
Type_dml = 2,
|
||||
Type_ddl = 3, // new columns in create table
|
||||
Type_idx = 4 // old columns in create index
|
||||
};
|
||||
Plan_column(Type type, const BaseString& name);
|
||||
virtual ~Plan_column() = 0;
|
||||
void analyzeColumn(Ctx& ctx, Plan_base::Ctl& ctl);
|
||||
// attributes
|
||||
const BaseString& getName() const;
|
||||
const BaseString& getCname() const;
|
||||
const char* getPrintName() const;
|
||||
void setCname(const BaseString& cname);
|
||||
const DictColumn& dictColumn() const;
|
||||
const SqlType& sqlType() const;
|
||||
protected:
|
||||
friend class Plan_table;
|
||||
friend class Plan_comp_op;
|
||||
Type m_type;
|
||||
BaseString m_name;
|
||||
BaseString m_cname;
|
||||
BaseString m_printName;
|
||||
DictColumn* m_dictColumn;
|
||||
/**
|
||||
* Resolve to table and operational position (for example
|
||||
* column number in scan query).
|
||||
*/
|
||||
Plan_table* m_resTable;
|
||||
unsigned m_resPos;
|
||||
SqlType m_sqlType;
|
||||
};
|
||||
|
||||
inline
|
||||
Plan_column::Plan_column(Type type, const BaseString& name) :
|
||||
m_type(type),
|
||||
m_name(name),
|
||||
m_printName(name),
|
||||
m_dictColumn(0),
|
||||
m_resTable(0),
|
||||
m_resPos(0)
|
||||
{
|
||||
}
|
||||
|
||||
inline const BaseString&
|
||||
Plan_column::getName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
inline const BaseString&
|
||||
Plan_column::getCname() const
|
||||
{
|
||||
return m_cname;
|
||||
}
|
||||
|
||||
inline const char*
|
||||
Plan_column::getPrintName() const
|
||||
{
|
||||
return m_printName.c_str();
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_column::setCname(const BaseString& cname)
|
||||
{
|
||||
m_cname.assign(cname);
|
||||
if (m_cname.empty())
|
||||
m_printName.assign(m_name);
|
||||
else {
|
||||
m_printName.assign(m_cname);
|
||||
m_printName.append(".");
|
||||
m_printName.append(m_name);
|
||||
}
|
||||
}
|
||||
|
||||
inline const DictColumn&
|
||||
Plan_column::dictColumn() const
|
||||
{
|
||||
ctx_assert(m_dictColumn != 0);
|
||||
return *m_dictColumn;
|
||||
}
|
||||
|
||||
inline const SqlType&
|
||||
Plan_column::sqlType() const
|
||||
{
|
||||
ctx_assert(m_sqlType.type() != SqlType::Undef);
|
||||
return m_sqlType;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,485 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include <dictionary/DictColumn.hpp>
|
||||
#include "Code_pred.hpp"
|
||||
#include "Code_comp_op.hpp"
|
||||
#include "Code_expr_conv.hpp"
|
||||
#include "Code_expr_column.hpp"
|
||||
#include "Code_table.hpp"
|
||||
#include "Code_root.hpp"
|
||||
|
||||
// Comp_op
|
||||
|
||||
const char*
|
||||
Comp_op::name() const
|
||||
{
|
||||
switch (m_opcode) {
|
||||
case Eq:
|
||||
return "=";
|
||||
case Noteq:
|
||||
return "!=";
|
||||
case Lt:
|
||||
return "<";
|
||||
case Lteq:
|
||||
return "<=";
|
||||
case Gt:
|
||||
return ">";
|
||||
case Gteq:
|
||||
return ">=";
|
||||
case Like:
|
||||
return "like";
|
||||
case Notlike:
|
||||
return "not like";
|
||||
case Isnull:
|
||||
return "is null";
|
||||
case Isnotnull:
|
||||
return "is not null";
|
||||
}
|
||||
ctx_assert(false);
|
||||
return "";
|
||||
}
|
||||
|
||||
unsigned
|
||||
Comp_op::arity() const
|
||||
{
|
||||
switch (m_opcode) {
|
||||
case Eq:
|
||||
case Noteq:
|
||||
case Lt:
|
||||
case Lteq:
|
||||
case Gt:
|
||||
case Gteq:
|
||||
case Like:
|
||||
case Notlike:
|
||||
return 2;
|
||||
case Isnull:
|
||||
case Isnotnull:
|
||||
return 1;
|
||||
}
|
||||
ctx_assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Plan_comp_op
|
||||
|
||||
Plan_comp_op::~Plan_comp_op()
|
||||
{
|
||||
}
|
||||
|
||||
Plan_base*
|
||||
Plan_comp_op::analyze(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
m_exec = 0;
|
||||
const unsigned arity = m_op.arity();
|
||||
// analyze operands
|
||||
for (unsigned i = 1; i <= arity; i++) {
|
||||
ctx_assert(m_expr[i] != 0);
|
||||
m_expr[i]->analyze(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
}
|
||||
// for each operand, find type to convert to
|
||||
SqlType con[1 + 2];
|
||||
if (arity == 1) {
|
||||
const SqlType& t1 = m_expr[1]->sqlType();
|
||||
switch (t1.type()) {
|
||||
case SqlType::Char:
|
||||
case SqlType::Varchar:
|
||||
case SqlType::Smallint:
|
||||
case SqlType::Integer:
|
||||
case SqlType::Bigint:
|
||||
case SqlType::Real:
|
||||
case SqlType::Double:
|
||||
case SqlType::Datetime:
|
||||
case SqlType::Null:
|
||||
case SqlType::Unbound:
|
||||
con[1] = t1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (con[1].type() == SqlType::Undef) {
|
||||
char b1[40];
|
||||
t1.print(b1, sizeof(b1));
|
||||
ctx.pushStatus(Error::Gen, "type mismatch in comparison: %s %s", b1, m_op.name());
|
||||
return 0;
|
||||
}
|
||||
} else if (arity == 2) {
|
||||
const SqlType& t1 = m_expr[1]->sqlType();
|
||||
const SqlType& t2 = m_expr[2]->sqlType();
|
||||
switch (t1.type()) {
|
||||
case SqlType::Char:
|
||||
switch (t2.type()) {
|
||||
case SqlType::Char:
|
||||
case SqlType::Varchar:
|
||||
case SqlType::Null:
|
||||
con[1] = t1;
|
||||
con[2] = t2;
|
||||
break;
|
||||
case SqlType::Unbound:
|
||||
con[1] = con[2] = t2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SqlType::Varchar:
|
||||
switch (t2.type()) {
|
||||
case SqlType::Char:
|
||||
case SqlType::Varchar:
|
||||
case SqlType::Null:
|
||||
con[1] = t1;
|
||||
con[2] = t2;
|
||||
break;
|
||||
case SqlType::Unbound:
|
||||
con[1] = con[2] = t2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SqlType::Smallint:
|
||||
case SqlType::Integer:
|
||||
case SqlType::Bigint:
|
||||
switch (t2.type()) {
|
||||
case SqlType::Smallint:
|
||||
case SqlType::Integer:
|
||||
case SqlType::Bigint:
|
||||
// conversion would mask primary key optimization
|
||||
con[1] = t1;
|
||||
con[2] = t2;
|
||||
break;
|
||||
case SqlType::Real:
|
||||
case SqlType::Double:
|
||||
con[1].setType(ctx, SqlType::Double);
|
||||
con[2] = con[1];
|
||||
break;
|
||||
case SqlType::Null:
|
||||
con[1] = t1;
|
||||
con[2] = t2;
|
||||
break;
|
||||
case SqlType::Unbound:
|
||||
con[1] = con[2] = t2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SqlType::Real:
|
||||
case SqlType::Double:
|
||||
switch (t2.type()) {
|
||||
case SqlType::Smallint:
|
||||
case SqlType::Integer:
|
||||
case SqlType::Bigint:
|
||||
case SqlType::Real:
|
||||
case SqlType::Double:
|
||||
con[1].setType(ctx, SqlType::Double);
|
||||
con[2] = con[1];
|
||||
break;
|
||||
case SqlType::Null:
|
||||
con[1] = t1;
|
||||
con[2] = t2;
|
||||
break;
|
||||
case SqlType::Unbound:
|
||||
con[1] = con[2] = t2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SqlType::Datetime:
|
||||
switch (t2.type()) {
|
||||
case SqlType::Datetime:
|
||||
con[1] = t1;
|
||||
con[2] = t2;
|
||||
break;
|
||||
case SqlType::Unbound:
|
||||
con[1] = con[2] = t2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SqlType::Null:
|
||||
switch (t2.type()) {
|
||||
case SqlType::Char:
|
||||
case SqlType::Varchar:
|
||||
case SqlType::Smallint:
|
||||
case SqlType::Integer:
|
||||
case SqlType::Bigint:
|
||||
case SqlType::Real:
|
||||
case SqlType::Double:
|
||||
case SqlType::Datetime:
|
||||
con[1] = t1;
|
||||
con[2] = t2;
|
||||
break;
|
||||
case SqlType::Unbound:
|
||||
con[1] = con[2] = t2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SqlType::Unbound:
|
||||
con[1] = con[2] = t1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (con[1].type() == SqlType::Undef || con[2].type() == SqlType::Undef) {
|
||||
char b1[40], b2[40];
|
||||
t1.print(b1, sizeof(b1));
|
||||
t2.print(b2, sizeof(b2));
|
||||
ctx.pushStatus(Error::Gen, "type mismatch in comparison: %s %s %s", b1, m_op.name(), b2);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
ctx_assert(false);
|
||||
return 0;
|
||||
}
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
// insert required conversions
|
||||
for (unsigned i = 1; i <= arity; i++) {
|
||||
if (con[i].type() == SqlType::Unbound) {
|
||||
continue;
|
||||
}
|
||||
Plan_expr_conv* exprConv = new Plan_expr_conv(m_root, con[i]);
|
||||
m_root->saveNode(exprConv);
|
||||
exprConv->setExpr(m_expr[i]);
|
||||
m_expr[i] = static_cast<Plan_expr*>(exprConv->analyze(ctx, ctl));
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
ctx_assert(m_expr[i] != 0);
|
||||
}
|
||||
// look for column=expr
|
||||
if (ctl.m_topand && m_op.m_opcode == Comp_op::Eq) {
|
||||
ctx_assert(arity == 2);
|
||||
for (unsigned i = 1, j = 2; i <= 2; i++, j--) {
|
||||
if (m_expr[i]->type() != Plan_expr::TypeColumn)
|
||||
continue;
|
||||
Plan_expr_column* column = static_cast<Plan_expr_column*>(m_expr[i]);
|
||||
if (! column->resolveEq(ctx, m_expr[j]))
|
||||
ctl.m_extra = true;
|
||||
}
|
||||
} else {
|
||||
ctl.m_extra = true;
|
||||
}
|
||||
// save top level comparison on list
|
||||
if (ctl.m_topand) {
|
||||
ctl.m_topcomp.push_back(this);
|
||||
}
|
||||
// table dependencies are union from operands
|
||||
m_tableSet.clear();
|
||||
for (unsigned i = 1; i <= arity; i++) {
|
||||
const TableSet& ts = m_expr[i]->tableSet();
|
||||
m_tableSet.insert(ts.begin(), ts.end());
|
||||
}
|
||||
// set of tables for which interpreter cannot be used
|
||||
m_noInterp.clear();
|
||||
// convenient
|
||||
#undef ustype
|
||||
#define ustype(b, n) (((b) ? 1 : 0) * 100 + (n))
|
||||
if (arity == 1) {
|
||||
for (unsigned i = 1; i <= 1; i++) {
|
||||
const SqlType t1 = m_expr[i]->sqlType();
|
||||
switch (m_op.m_opcode) {
|
||||
case Comp_op::Isnull:
|
||||
case Comp_op::Isnotnull:
|
||||
if (m_expr[i]->type() == Plan_expr::TypeColumn) {
|
||||
switch (ustype(t1.unSigned(), t1.type())) {
|
||||
// all types accepted now
|
||||
default:
|
||||
{
|
||||
Plan_expr_column* column = static_cast<Plan_expr_column*>(m_expr[i]);
|
||||
ctx_assert(column->m_resTable != 0);
|
||||
m_interpColumn[i] = column;
|
||||
continue; // ok
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
const TableSet& ts = m_expr[i]->tableSet();
|
||||
m_noInterp.insert(ts.begin(), ts.end());
|
||||
}
|
||||
} else if (arity == 2) {
|
||||
for (unsigned i = 1, j = 2; i <= 2; i++, j--) {
|
||||
const SqlType t1 = m_expr[i]->sqlType();
|
||||
switch (m_op.m_opcode) {
|
||||
case Comp_op::Like:
|
||||
case Comp_op::Notlike:
|
||||
if (i == 2) // col like val but not val like col
|
||||
break;
|
||||
/*FALLTHRU*/
|
||||
case Comp_op::Eq:
|
||||
case Comp_op::Noteq:
|
||||
case Comp_op::Lt:
|
||||
case Comp_op::Lteq:
|
||||
case Comp_op::Gt:
|
||||
case Comp_op::Gteq:
|
||||
if (m_expr[i]->type() == Plan_expr::TypeColumn) {
|
||||
switch (ustype(t1.unSigned(), t1.type())) {
|
||||
case ustype(false, SqlType::Char):
|
||||
case ustype(false, SqlType::Varchar):
|
||||
case ustype(true, SqlType::Smallint):
|
||||
case ustype(true, SqlType::Integer):
|
||||
case ustype(true, SqlType::Bigint):
|
||||
{
|
||||
Plan_expr_column* column = static_cast<Plan_expr_column*>(m_expr[i]);
|
||||
ctx_assert(column->m_resTable != 0);
|
||||
const TableSet& ts = m_expr[j]->tableSet();
|
||||
if (ts.find(column->m_resTable) == ts.end()) {
|
||||
// candidate for column=const
|
||||
m_interpColumn[i] = column;
|
||||
continue; // ok
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
const TableSet& ts = m_expr[i]->tableSet();
|
||||
m_noInterp.insert(ts.begin(), ts.end());
|
||||
}
|
||||
} else {
|
||||
ctx_assert(false);
|
||||
return 0;
|
||||
}
|
||||
#undef ustype
|
||||
return this;
|
||||
}
|
||||
|
||||
Exec_base*
|
||||
Plan_comp_op::codegen(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
if (m_exec != 0)
|
||||
return m_exec;
|
||||
const unsigned arity = m_op.arity();
|
||||
Exec_comp_op* exec = new Exec_comp_op(ctl.m_execRoot);
|
||||
ctl.m_execRoot->saveNode(exec);
|
||||
// create code for operands
|
||||
for (unsigned i = 1; i <= arity; i++) {
|
||||
ctx_assert(m_expr[i] != 0);
|
||||
Exec_expr* execExpr = static_cast<Exec_expr*>(m_expr[i]->codegen(ctx, ctl));
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
ctx_assert(execExpr != 0);
|
||||
exec->setExpr(i, execExpr);
|
||||
}
|
||||
// create the code
|
||||
Exec_comp_op::Code& code = *new Exec_comp_op::Code(m_op);
|
||||
// interpreted column=const
|
||||
if (! ctl.m_having) {
|
||||
ctx_assert(ctl.m_topTable != 0);
|
||||
for (unsigned i = 1; i <= arity; i++) {
|
||||
Plan_expr_column* column = m_interpColumn[i];
|
||||
if (column == 0)
|
||||
continue;
|
||||
ctx_assert(column->m_resTable != 0);
|
||||
if (column->m_resTable != ctl.m_topTable)
|
||||
continue;
|
||||
ctx_assert(code.m_interpColumn == 0);
|
||||
code.m_interpColumn = i;
|
||||
code.m_interpAttrId = column->dictColumn().getAttrId();
|
||||
ctx_log2(("can use interpreter on %s", column->getPrintName()));
|
||||
}
|
||||
}
|
||||
exec->setCode(code);
|
||||
m_exec = exec;
|
||||
return exec;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_comp_op::print(Ctx& ctx)
|
||||
{
|
||||
ctx.print(" [%s", m_op.name());
|
||||
Plan_base* a[] = { m_expr[1], m_expr[2] };
|
||||
printList(ctx, a, m_op.arity());
|
||||
ctx.print("]");
|
||||
}
|
||||
|
||||
bool
|
||||
Plan_comp_op::isGroupBy(const Plan_expr_row* row) const
|
||||
{
|
||||
const unsigned arity = m_op.arity();
|
||||
for (unsigned i = 1; i <= arity; i++) {
|
||||
ctx_assert(m_expr[i] != 0);
|
||||
if (! m_expr[i]->isGroupBy(row))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Code_comp_op
|
||||
|
||||
Exec_comp_op::Code::~Code()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_comp_op::Data::~Data()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_comp_op::~Exec_comp_op()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Exec_comp_op::alloc(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
const Code& code = getCode();
|
||||
// allocate subexpressions
|
||||
unsigned arity = code.m_op.arity();
|
||||
for (unsigned i = 1; i <= arity; i++) {
|
||||
ctx_assert(m_expr[i] != 0);
|
||||
m_expr[i]->alloc(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return;
|
||||
}
|
||||
Data& data = *new Data;
|
||||
setData(data);
|
||||
}
|
||||
|
||||
void
|
||||
Exec_comp_op::close(Ctx& ctx)
|
||||
{
|
||||
const Code& code = getCode();
|
||||
unsigned arity = code.m_op.arity();
|
||||
for (unsigned i = 1; i <= arity; i++) {
|
||||
ctx_assert(m_expr[i] != 0);
|
||||
m_expr[i]->close(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Exec_comp_op::print(Ctx& ctx)
|
||||
{
|
||||
const Code& code = getCode();
|
||||
ctx.print(" [%s", code.m_op.name());
|
||||
Exec_base* a[] = { m_expr[1], m_expr[2] };
|
||||
printList(ctx, a, code.m_op.arity());
|
||||
ctx.print("]");
|
||||
}
|
|
@ -1,172 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef ODBC_CODEGEN_Code_comp_op_hpp
|
||||
#define ODBC_CODEGEN_Code_comp_op_hpp
|
||||
|
||||
#include <common/common.hpp>
|
||||
#include <common/DataField.hpp>
|
||||
#include "Code_pred.hpp"
|
||||
#include "Code_expr.hpp"
|
||||
#include "Code_expr_column.hpp"
|
||||
|
||||
/**
|
||||
* @class Comp_op
|
||||
* @brief Comparison operations
|
||||
*/
|
||||
struct Comp_op {
|
||||
enum Opcode {
|
||||
Eq = 1, // binary
|
||||
Noteq,
|
||||
Lt,
|
||||
Lteq,
|
||||
Gt,
|
||||
Gteq,
|
||||
Like,
|
||||
Notlike,
|
||||
Isnull, // unary
|
||||
Isnotnull
|
||||
};
|
||||
Comp_op(Opcode opcode);
|
||||
const char* name() const;
|
||||
unsigned arity() const;
|
||||
Opcode m_opcode;
|
||||
};
|
||||
|
||||
inline
|
||||
Comp_op::Comp_op(Opcode opcode) :
|
||||
m_opcode(opcode)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @class Plan_comp_op
|
||||
* @brief Comparison operator node in PlanTree
|
||||
*/
|
||||
class Plan_comp_op : public Plan_pred {
|
||||
public:
|
||||
Plan_comp_op(Plan_root* root, Comp_op op);
|
||||
virtual ~Plan_comp_op();
|
||||
void setExpr(unsigned i, Plan_expr* expr);
|
||||
Plan_base* analyze(Ctx& ctx, Ctl& ctl);
|
||||
Exec_base* codegen(Ctx& ctx, Ctl& ctl);
|
||||
void print(Ctx& ctx);
|
||||
virtual bool isGroupBy(const Plan_expr_row* row) const;
|
||||
protected:
|
||||
Comp_op m_op;
|
||||
Plan_expr* m_expr[1 + 2];
|
||||
Plan_expr_column* m_interpColumn[1 + 2]; // candidates
|
||||
};
|
||||
|
||||
inline
|
||||
Plan_comp_op::Plan_comp_op(Plan_root* root, Comp_op op) :
|
||||
Plan_pred(root, TypeComp),
|
||||
m_op(op)
|
||||
{
|
||||
m_expr[0] = m_expr[1] = m_expr[2] = 0;
|
||||
m_interpColumn[0] = m_interpColumn[1] = m_interpColumn[2] = 0;
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_comp_op::setExpr(unsigned i, Plan_expr* expr)
|
||||
{
|
||||
ctx_assert(1 <= i && i <= 2);
|
||||
m_expr[i] = expr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @class Exec_comp_op
|
||||
* @brief Comparison operator node in ExecTree
|
||||
*/
|
||||
class Exec_comp_op : public Exec_pred {
|
||||
public:
|
||||
class Code : public Exec_pred::Code {
|
||||
public:
|
||||
Code(Comp_op op);
|
||||
virtual ~Code();
|
||||
protected:
|
||||
friend class Plan_comp_op;
|
||||
friend class Exec_comp_op;
|
||||
Comp_op m_op;
|
||||
unsigned m_interpColumn; // 1 or 2 if interpreted column, 0 if both constant
|
||||
NdbAttrId m_interpAttrId;
|
||||
};
|
||||
class Data : public Exec_pred::Data {
|
||||
public:
|
||||
Data();
|
||||
virtual ~Data();
|
||||
protected:
|
||||
friend class Exec_comp_op;
|
||||
};
|
||||
Exec_comp_op(Exec_root* root);
|
||||
virtual ~Exec_comp_op();
|
||||
void alloc(Ctx& ctx, Ctl& ctl);
|
||||
void execInterp(Ctx& ctx, Ctl& ctl);
|
||||
void evaluate(Ctx& ctx, Ctl& ctl);
|
||||
void close(Ctx& ctx);
|
||||
void print(Ctx& ctx);
|
||||
// children
|
||||
const Code& getCode() const;
|
||||
Data& getData() const;
|
||||
void setExpr(unsigned i, Exec_expr* expr);
|
||||
protected:
|
||||
Exec_expr* m_expr[1 + 2];
|
||||
};
|
||||
|
||||
inline
|
||||
Exec_comp_op::Code::Code(Comp_op op) :
|
||||
m_op(op),
|
||||
m_interpColumn(0),
|
||||
m_interpAttrId((NdbAttrId)-1)
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_comp_op::Data::Data()
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_comp_op::Exec_comp_op(Exec_root* root) :
|
||||
Exec_pred(root)
|
||||
{
|
||||
m_expr[0] = m_expr[1] = m_expr[2] = 0;
|
||||
}
|
||||
|
||||
// children
|
||||
|
||||
inline const Exec_comp_op::Code&
|
||||
Exec_comp_op::getCode() const
|
||||
{
|
||||
const Code* code = static_cast<const Code*>(m_code);
|
||||
return *code;
|
||||
}
|
||||
|
||||
inline Exec_comp_op::Data&
|
||||
Exec_comp_op::getData() const
|
||||
{
|
||||
Data* data = static_cast<Data*>(m_data);
|
||||
return *data;
|
||||
}
|
||||
|
||||
inline void
|
||||
Exec_comp_op::setExpr(unsigned i, Exec_expr* expr)
|
||||
{
|
||||
ctx_assert(1 <= i && i <= 2 && m_expr[i] == 0);
|
||||
m_expr[i] = expr;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,124 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include <common/StmtArea.hpp>
|
||||
#include "Code_create_index.hpp"
|
||||
#include "Code_root.hpp"
|
||||
|
||||
// Plan_create_index
|
||||
|
||||
Plan_create_index::~Plan_create_index()
|
||||
{
|
||||
}
|
||||
|
||||
Plan_base*
|
||||
Plan_create_index::analyze(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
stmtArea().stmtInfo().setName(Stmt_name_create_index);
|
||||
// analyze the table
|
||||
ctx_assert(m_table != 0);
|
||||
m_table->analyze(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
// analyze the columns
|
||||
ctl.m_tableList.resize(1 + 1); // indexed from 1
|
||||
ctl.m_tableList[1] = m_table;
|
||||
for (unsigned i = 1, n = countColumn(); i <= n; i++) {
|
||||
Plan_idx_column* column = getColumn(i);
|
||||
column->analyze(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_create_index::describe(Ctx& ctx)
|
||||
{
|
||||
stmtArea().setFunction(ctx, "CREATE INDEX", SQL_DIAG_CREATE_INDEX);
|
||||
}
|
||||
|
||||
Exec_base*
|
||||
Plan_create_index::codegen(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
Exec_create_index* exec = new Exec_create_index(ctl.m_execRoot);
|
||||
ctl.m_execRoot->saveNode(exec);
|
||||
const unsigned count = countColumn();
|
||||
const char** attrList = new const char* [1 + count];
|
||||
attrList[0] = 0; // unused
|
||||
for (unsigned i = 1; i <= count; i++) {
|
||||
Plan_idx_column* column = getColumn(i);
|
||||
const char* cname = column->getName().c_str();
|
||||
attrList[i] = strcpy(new char[strlen(cname) + 1], cname);
|
||||
}
|
||||
Exec_create_index::Code& code = *new Exec_create_index::Code(m_name, m_table->getName(), m_type, count, attrList);
|
||||
exec->setCode(code);
|
||||
code.m_fragmentType = m_fragmentType;
|
||||
code.m_logging = m_logging;
|
||||
return exec;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_create_index::print(Ctx& ctx)
|
||||
{
|
||||
ctx.print(" [create_index name=%s table=%s type=%d", m_name.c_str(), m_table->getName().c_str(), (int)m_type);
|
||||
ctx.print(" [");
|
||||
for (unsigned i = 1; i <= countColumn(); i++) {
|
||||
Plan_idx_column* column = getColumn(i);
|
||||
if (i > 1)
|
||||
ctx.print(" ");
|
||||
column->print(ctx);
|
||||
}
|
||||
ctx.print("]");
|
||||
}
|
||||
|
||||
// Exec_create_index
|
||||
|
||||
Exec_create_index::Code::~Code()
|
||||
{
|
||||
for (unsigned i = 1; i <= m_attrCount; i++) {
|
||||
delete[] m_attrList[i];
|
||||
m_attrList[i] = 0;
|
||||
}
|
||||
delete[] m_attrList;
|
||||
}
|
||||
|
||||
Exec_create_index::Data::~Data()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_create_index::~Exec_create_index()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Exec_create_index::alloc(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
Data& data = *new Data;
|
||||
setData(data);
|
||||
}
|
||||
|
||||
void
|
||||
Exec_create_index::close(Ctx& ctx)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Exec_create_index::print(Ctx& ctx)
|
||||
{
|
||||
const Code& code = getCode();
|
||||
ctx.print(" [create_index %s]", code.m_tableName.c_str());
|
||||
}
|
|
@ -1,203 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef ODBC_CODEGEN_Code_create_index_hpp
|
||||
#define ODBC_CODEGEN_Code_create_index_hpp
|
||||
|
||||
#include <vector>
|
||||
#include <NdbApi.hpp>
|
||||
#include <common/common.hpp>
|
||||
#include "Code_ddl.hpp"
|
||||
#include "Code_table.hpp"
|
||||
#include "Code_idx_column.hpp"
|
||||
|
||||
class DictTable;
|
||||
class DictColumn;
|
||||
|
||||
/**
|
||||
* @class Plan_create_index
|
||||
* @brief Create table in PlanTree
|
||||
*/
|
||||
class Plan_create_index : public Plan_ddl {
|
||||
public:
|
||||
Plan_create_index(Plan_root* root, const BaseString& name);
|
||||
virtual ~Plan_create_index();
|
||||
Plan_base* analyze(Ctx& ctx, Ctl& ctl);
|
||||
Exec_base* codegen(Ctx& ctx, Ctl& ctl);
|
||||
void describe(Ctx & ctx);
|
||||
void print(Ctx& ctx);
|
||||
// attributes
|
||||
const BaseString& getName() const;
|
||||
// children
|
||||
void setType(NdbDictionary::Object::Type type);
|
||||
void setTable(Plan_table* table);
|
||||
unsigned countColumn() const;
|
||||
void addColumn(Plan_idx_column* column);
|
||||
Plan_idx_column* getColumn(unsigned i) const;
|
||||
void setFragmentType(NdbDictionary::Object::FragmentType fragmentType);
|
||||
void setLogging(bool logging);
|
||||
protected:
|
||||
BaseString m_name;
|
||||
NdbDictionary::Object::Type m_type;
|
||||
Plan_table* m_table;
|
||||
IdxColumnVector m_columnList;
|
||||
NdbDictionary::Object::FragmentType m_fragmentType;
|
||||
bool m_logging;
|
||||
};
|
||||
|
||||
inline
|
||||
Plan_create_index::Plan_create_index(Plan_root* root, const BaseString& name) :
|
||||
Plan_ddl(root),
|
||||
m_name(name),
|
||||
m_type(NdbDictionary::Object::TypeUndefined),
|
||||
m_columnList(1),
|
||||
m_fragmentType(NdbDictionary::Object::FragUndefined),
|
||||
m_logging(true)
|
||||
{
|
||||
}
|
||||
|
||||
inline const BaseString&
|
||||
Plan_create_index::getName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
// children
|
||||
|
||||
inline void
|
||||
Plan_create_index::setType(NdbDictionary::Object::Type type)
|
||||
{
|
||||
m_type = type;
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_create_index::setTable(Plan_table* table)
|
||||
{
|
||||
ctx_assert(table != 0);
|
||||
m_table = table;
|
||||
}
|
||||
|
||||
inline unsigned
|
||||
Plan_create_index::countColumn() const
|
||||
{
|
||||
return m_columnList.size() - 1;
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_create_index::addColumn(Plan_idx_column* column)
|
||||
{
|
||||
ctx_assert(column != 0);
|
||||
m_columnList.push_back(column);
|
||||
}
|
||||
|
||||
inline Plan_idx_column*
|
||||
Plan_create_index::getColumn(unsigned i) const
|
||||
{
|
||||
ctx_assert(1 <= i && i <= countColumn() && m_columnList[i] != 0);
|
||||
return m_columnList[i];
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_create_index::setFragmentType(NdbDictionary::Object::FragmentType fragmentType)
|
||||
{
|
||||
m_fragmentType = fragmentType;
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_create_index::setLogging(bool logging)
|
||||
{
|
||||
m_logging = logging;
|
||||
}
|
||||
|
||||
/**
|
||||
* @class Exec_create_index
|
||||
* @brief Create table in ExecTree
|
||||
*/
|
||||
class Exec_create_index : public Exec_ddl {
|
||||
public:
|
||||
class Code : public Exec_ddl::Code {
|
||||
public:
|
||||
Code(const BaseString& indexName, const BaseString& tableName, NdbDictionary::Object::Type type, unsigned attrCount, const char** attrList);
|
||||
virtual ~Code();
|
||||
protected:
|
||||
friend class Plan_create_index;
|
||||
friend class Exec_create_index;
|
||||
const BaseString m_indexName;
|
||||
const BaseString m_tableName;
|
||||
NdbDictionary::Object::Type m_type;
|
||||
const unsigned m_attrCount;
|
||||
const char** m_attrList;
|
||||
NdbDictionary::Object::FragmentType m_fragmentType;
|
||||
bool m_logging;
|
||||
};
|
||||
class Data : public Exec_ddl::Data {
|
||||
public:
|
||||
Data();
|
||||
virtual ~Data();
|
||||
protected:
|
||||
friend class Exec_create_index;
|
||||
};
|
||||
Exec_create_index(Exec_root* root);
|
||||
virtual ~Exec_create_index();
|
||||
void alloc(Ctx& ctx, Ctl& ctl);
|
||||
void execute(Ctx& ctx, Ctl& ctl);
|
||||
void close(Ctx& ctx);
|
||||
void print(Ctx& ctx);
|
||||
// children
|
||||
const Code& getCode() const;
|
||||
Data& getData() const;
|
||||
};
|
||||
|
||||
inline
|
||||
Exec_create_index::Code::Code(const BaseString& indexName, const BaseString& tableName, NdbDictionary::Object::Type type, unsigned attrCount, const char** attrList) :
|
||||
m_indexName(indexName),
|
||||
m_tableName(tableName),
|
||||
m_type(type),
|
||||
m_attrCount(attrCount),
|
||||
m_attrList(attrList),
|
||||
m_fragmentType(NdbDictionary::Object::FragUndefined),
|
||||
m_logging(true)
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_create_index::Data::Data()
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_create_index::Exec_create_index(Exec_root* root) :
|
||||
Exec_ddl(root)
|
||||
{
|
||||
}
|
||||
|
||||
// children
|
||||
|
||||
inline const Exec_create_index::Code&
|
||||
Exec_create_index::getCode() const
|
||||
{
|
||||
const Code* code = static_cast<const Code*>(m_code);
|
||||
return *code;
|
||||
}
|
||||
|
||||
inline Exec_create_index::Data&
|
||||
Exec_create_index::getData() const
|
||||
{
|
||||
Data* data = static_cast<Data*>(m_data);
|
||||
return *data;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,162 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include "Code_create_row.hpp"
|
||||
#include "Code_root.hpp"
|
||||
|
||||
Plan_create_row::~Plan_create_row()
|
||||
{
|
||||
}
|
||||
|
||||
Plan_base*
|
||||
Plan_create_row::analyze(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
// check for duplicate column name
|
||||
for (unsigned i = 1, n = countColumn(); i < n; i++) {
|
||||
const BaseString& a = getColumn(i)->getName();
|
||||
for (unsigned i2 = i + 1; i2 <= n; i2++) {
|
||||
const BaseString& a2 = getColumn(i2)->getName();
|
||||
if (strcmp(a.c_str(), a2.c_str()) == 0) {
|
||||
ctx.pushStatus(Error::Gen, "duplicate column %s", a.c_str());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// move single-column primary key constraint to constraint list
|
||||
for (unsigned i = 1, n = countColumn(); i <= n; i++) {
|
||||
Plan_ddl_column* column = getColumn(i);
|
||||
if (column->m_primaryKey) {
|
||||
Plan_ddl_row* ddlRow = new Plan_ddl_row(m_root);
|
||||
m_root->saveNode(ddlRow);
|
||||
ddlRow->addColumn(column);
|
||||
Plan_ddl_constr* constr = new Plan_ddl_constr(m_root);
|
||||
m_root->saveNode(constr);
|
||||
constr->setRow(ddlRow);
|
||||
addConstr(constr);
|
||||
column->m_primaryKey = false; // will be set again
|
||||
}
|
||||
}
|
||||
// check primary key constraints
|
||||
if (countConstr() < 1) {
|
||||
ctx.pushStatus(Error::Gen, "table must have a primary key");
|
||||
return 0;
|
||||
}
|
||||
if (countConstr() > 1) {
|
||||
ctx.pushStatus(Error::Gen, "table can have only one primary key");
|
||||
return 0;
|
||||
}
|
||||
Plan_ddl_row* ddlRow = getConstr(1)->getRow();
|
||||
for (unsigned i = 1, n = ddlRow->countColumn(); i <= n; i++) {
|
||||
Plan_ddl_column* column = ddlRow->getColumn(i);
|
||||
const BaseString& a = column->getName();
|
||||
bool found = false;
|
||||
for (unsigned i2 = 1, n2 = countColumn(); i2 <= n2; i2++) {
|
||||
Plan_ddl_column* column2 = getColumn(i2);
|
||||
const BaseString& a2 = column2->getName();
|
||||
if (strcmp(a.c_str(), a2.c_str()) != 0)
|
||||
continue;
|
||||
if (column2->getPrimaryKey()) {
|
||||
ctx.pushStatus(Error::Gen, "duplicate primary key constraint on %s", a.c_str());
|
||||
return 0;
|
||||
}
|
||||
column2->setPrimaryKey();
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if (! found) {
|
||||
ctx.pushStatus(Error::Gen, "undefined primary key column %s", a.c_str());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// analyze column types
|
||||
for (unsigned i = 1, n = countColumn(); i <= n; i++) {
|
||||
getColumn(i)->analyze(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
}
|
||||
// check TupleId
|
||||
unsigned tupleId = 0;
|
||||
for (unsigned i = 1, n = countColumn(); i <= n; i++) {
|
||||
Plan_ddl_column* column = getColumn(i);
|
||||
if (! column->getTupleId())
|
||||
continue;
|
||||
if (i != 1) {
|
||||
ctx.pushStatus(Error::Gen, "tuple id column %u is not first column", i);
|
||||
return 0;
|
||||
}
|
||||
if (tupleId != 0) { // cannot happen now since attr name is fixed
|
||||
ctx.pushStatus(Error::Gen, "duplicate tuple id column %u", i);
|
||||
return 0;
|
||||
}
|
||||
tupleId = i;
|
||||
}
|
||||
if (tupleId != 0) {
|
||||
for (unsigned i = 1, n = countColumn(); i <= n; i++) {
|
||||
Plan_ddl_column* column = getColumn(i);
|
||||
if (i == tupleId)
|
||||
continue;
|
||||
if (! column->getPrimaryKey())
|
||||
continue;
|
||||
ctx.pushStatus(Error::Gen, "cannot have both tuple id and other primary key column %u", i);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// check auto-increment
|
||||
unsigned autoIncrement = 0;
|
||||
for (unsigned i = 1, n = countColumn(); i <= n; i++) {
|
||||
Plan_ddl_column* column = getColumn(i);
|
||||
if (! column->getAutoIncrement())
|
||||
continue;
|
||||
if (autoIncrement != 0) {
|
||||
ctx.pushStatus(Error::Gen, "duplicate auto-increment column %u", i);
|
||||
return 0;
|
||||
}
|
||||
autoIncrement = i;
|
||||
}
|
||||
if (autoIncrement != 0) {
|
||||
for (unsigned i = 1, n = countColumn(); i <= n; i++) {
|
||||
Plan_ddl_column* column = getColumn(i);
|
||||
if (i == autoIncrement)
|
||||
continue;
|
||||
if (! column->getPrimaryKey())
|
||||
continue;
|
||||
ctx.pushStatus(Error::Gen, "cannot have both auto-increment column and other primary key column %u", i);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
Exec_base*
|
||||
Plan_create_row::codegen(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
ctx_assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_create_row::print(Ctx& ctx)
|
||||
{
|
||||
ctx.print(" [create_row");
|
||||
for (unsigned i = 1; i <= countColumn(); i++) {
|
||||
Plan_base* a = m_columnList[i];
|
||||
printList(ctx, &a, 1);
|
||||
}
|
||||
for (unsigned i = 1; i <= countConstr(); i++) {
|
||||
Plan_base* a = m_constrList[i];
|
||||
printList(ctx, &a, 1);
|
||||
}
|
||||
}
|
|
@ -1,99 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef ODBC_CODEGEN_Code_create_row_hpp
|
||||
#define ODBC_CODEGEN_Code_create_row_hpp
|
||||
|
||||
#include <vector>
|
||||
#include <common/common.hpp>
|
||||
#include "Code_base.hpp"
|
||||
#include "Code_ddl_column.hpp"
|
||||
#include "Code_ddl_constr.hpp"
|
||||
|
||||
/**
|
||||
* @class Plan_create_row
|
||||
* @brief Row of columns and constraints in create statement
|
||||
*/
|
||||
class Plan_create_row : public Plan_base {
|
||||
public:
|
||||
Plan_create_row(Plan_root* root);
|
||||
virtual ~Plan_create_row();
|
||||
Plan_base* analyze(Ctx& ctx, Ctl& ctl);
|
||||
Exec_base* codegen(Ctx& ctx, Ctl& ctl);
|
||||
void print(Ctx& ctx);
|
||||
// children
|
||||
unsigned countColumn() const;
|
||||
void addColumn(Plan_ddl_column* column);
|
||||
Plan_ddl_column* getColumn(unsigned i) const;
|
||||
unsigned countConstr() const;
|
||||
void addConstr(Plan_ddl_constr* constr);
|
||||
Plan_ddl_constr* getConstr(unsigned i) const;
|
||||
protected:
|
||||
DdlColumnVector m_columnList;
|
||||
DdlConstrVector m_constrList;
|
||||
};
|
||||
|
||||
inline
|
||||
Plan_create_row::Plan_create_row(Plan_root* root) :
|
||||
Plan_base(root),
|
||||
m_columnList(1),
|
||||
m_constrList(1)
|
||||
{
|
||||
}
|
||||
|
||||
// children
|
||||
|
||||
inline unsigned
|
||||
Plan_create_row::countColumn() const
|
||||
{
|
||||
return m_columnList.size() - 1;
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_create_row::addColumn(Plan_ddl_column* column)
|
||||
{
|
||||
ctx_assert(column != 0);
|
||||
m_columnList.push_back(column);
|
||||
}
|
||||
|
||||
inline Plan_ddl_column*
|
||||
Plan_create_row::getColumn(unsigned i) const
|
||||
{
|
||||
ctx_assert(1 <= i && i <= m_columnList.size() && m_columnList[i] != 0);
|
||||
return m_columnList[i];
|
||||
}
|
||||
|
||||
inline unsigned
|
||||
Plan_create_row::countConstr() const
|
||||
{
|
||||
return m_constrList.size() - 1;
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_create_row::addConstr(Plan_ddl_constr* constr)
|
||||
{
|
||||
ctx_assert(constr != 0);
|
||||
m_constrList.push_back(constr);
|
||||
}
|
||||
|
||||
inline Plan_ddl_constr*
|
||||
Plan_create_row::getConstr(unsigned i) const
|
||||
{
|
||||
ctx_assert(1 <= i && i <= m_constrList.size() && m_constrList[i] != 0);
|
||||
return m_constrList[i];
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,137 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include <common/StmtArea.hpp>
|
||||
#include "Code_create_table.hpp"
|
||||
#include "Code_root.hpp"
|
||||
|
||||
// Plan_create_table
|
||||
|
||||
Plan_create_table::~Plan_create_table()
|
||||
{
|
||||
}
|
||||
|
||||
Plan_base*
|
||||
Plan_create_table::analyze(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
stmtArea().stmtInfo().setName(Stmt_name_create_table);
|
||||
// analyze the create row
|
||||
ctx_assert(m_createRow != 0);
|
||||
m_createRow->analyze(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_create_table::describe(Ctx& ctx)
|
||||
{
|
||||
stmtArea().setFunction(ctx, "CREATE TABLE", SQL_DIAG_CREATE_TABLE);
|
||||
}
|
||||
|
||||
Exec_base*
|
||||
Plan_create_table::codegen(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
ctx_assert(m_createRow != 0);
|
||||
Exec_create_table* exec = new Exec_create_table(ctl.m_execRoot);
|
||||
ctl.m_execRoot->saveNode(exec);
|
||||
const unsigned count = m_createRow->countColumn();
|
||||
Exec_create_table::Code::Attr* attrList = new Exec_create_table::Code::Attr[1 + count];
|
||||
unsigned tupleId = 0;
|
||||
unsigned autoIncrement = 0;
|
||||
for (unsigned i = 1; i <= count; i++) {
|
||||
Plan_ddl_column* column = m_createRow->getColumn(i);
|
||||
Exec_create_table::Code::Attr& attr = attrList[i];
|
||||
attr.m_attrName.assign(column->getName());
|
||||
attr.m_sqlType = column->sqlType();
|
||||
attr.m_tupleKey = column->getPrimaryKey();
|
||||
attr.m_tupleId = column->getTupleId();
|
||||
attr.m_autoIncrement = column->getAutoIncrement();
|
||||
if (attr.m_tupleId)
|
||||
tupleId = i;
|
||||
if (attr.m_autoIncrement)
|
||||
autoIncrement = i;
|
||||
attr.m_defaultValue = 0;
|
||||
Plan_expr* expr;
|
||||
if ((expr = column->getDefaultValue()) != 0) {
|
||||
Exec_expr* execExpr = static_cast<Exec_expr*>(expr->codegen(ctx, ctl));
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
ctx_assert(execExpr != 0);
|
||||
attr.m_defaultValue = execExpr;
|
||||
}
|
||||
}
|
||||
Exec_create_table::Code& code = *new Exec_create_table::Code(m_name, count, attrList, tupleId, autoIncrement);
|
||||
exec->setCode(code);
|
||||
code.m_fragmentType = m_fragmentType;
|
||||
code.m_logging = m_logging;
|
||||
return exec;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_create_table::print(Ctx& ctx)
|
||||
{
|
||||
ctx.print(" [create_table '%s'", m_name.c_str());
|
||||
Plan_base* a[] = { m_createRow };
|
||||
printList(ctx, a, 1);
|
||||
ctx.print("]");
|
||||
}
|
||||
|
||||
// Exec_create_table
|
||||
|
||||
Exec_create_table::Code::~Code()
|
||||
{
|
||||
delete[] m_attrList;
|
||||
}
|
||||
|
||||
Exec_create_table::Data::~Data()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_create_table::~Exec_create_table()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Exec_create_table::alloc(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
const Code& code = getCode();
|
||||
for (unsigned i = 1; i <= code.m_attrCount; i++) {
|
||||
const Code::Attr& attr = code.m_attrList[i];
|
||||
if (attr.m_defaultValue != 0)
|
||||
attr.m_defaultValue->alloc(ctx, ctl);
|
||||
}
|
||||
Data& data = *new Data;
|
||||
setData(data);
|
||||
}
|
||||
|
||||
void
|
||||
Exec_create_table::close(Ctx& ctx)
|
||||
{
|
||||
const Code& code = getCode();
|
||||
for (unsigned i = 1; i <= code.m_attrCount; i++) {
|
||||
const Code::Attr& attr = code.m_attrList[i];
|
||||
if (attr.m_defaultValue != 0)
|
||||
attr.m_defaultValue->close(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Exec_create_table::print(Ctx& ctx)
|
||||
{
|
||||
const Code& code = getCode();
|
||||
ctx.print(" [create_table %s]", code.m_tableName.c_str());
|
||||
}
|
|
@ -1,178 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef ODBC_CODEGEN_Code_create_table_hpp
|
||||
#define ODBC_CODEGEN_Code_create_table_hpp
|
||||
|
||||
#include <vector>
|
||||
#include <common/common.hpp>
|
||||
#include "Code_ddl.hpp"
|
||||
#include "Code_ddl_row.hpp"
|
||||
#include "Code_create_row.hpp"
|
||||
|
||||
class DictTable;
|
||||
class DictColumn;
|
||||
|
||||
/**
|
||||
* @class Plan_create_table
|
||||
* @brief Create table in PlanTree
|
||||
*/
|
||||
class Plan_create_table : public Plan_ddl {
|
||||
public:
|
||||
Plan_create_table(Plan_root* root, const BaseString& name);
|
||||
virtual ~Plan_create_table();
|
||||
Plan_base* analyze(Ctx& ctx, Ctl& ctl);
|
||||
Exec_base* codegen(Ctx& ctx, Ctl& ctl);
|
||||
void describe(Ctx & ctx);
|
||||
void print(Ctx& ctx);
|
||||
// attributes
|
||||
const BaseString& getName() const;
|
||||
// children
|
||||
void setCreateRow(Plan_create_row* createRow);
|
||||
void setFragmentType(NdbDictionary::Object::FragmentType fragmentType);
|
||||
void setLogging(bool logging);
|
||||
protected:
|
||||
BaseString m_name;
|
||||
Plan_create_row* m_createRow;
|
||||
NdbDictionary::Object::FragmentType m_fragmentType;
|
||||
bool m_logging;
|
||||
};
|
||||
|
||||
inline
|
||||
Plan_create_table::Plan_create_table(Plan_root* root, const BaseString& name) :
|
||||
Plan_ddl(root),
|
||||
m_name(name),
|
||||
m_createRow(0),
|
||||
m_fragmentType(NdbDictionary::Object::FragUndefined),
|
||||
m_logging(true)
|
||||
{
|
||||
}
|
||||
|
||||
inline const BaseString&
|
||||
Plan_create_table::getName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
// children
|
||||
|
||||
inline void
|
||||
Plan_create_table::setCreateRow(Plan_create_row* createRow)
|
||||
{
|
||||
ctx_assert(createRow != 0);
|
||||
m_createRow = createRow;
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_create_table::setFragmentType(NdbDictionary::Object::FragmentType fragmentType)
|
||||
{
|
||||
m_fragmentType = fragmentType;
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_create_table::setLogging(bool logging)
|
||||
{
|
||||
m_logging = logging;
|
||||
}
|
||||
|
||||
/**
|
||||
* @class Exec_create_table
|
||||
* @brief Create table in ExecTree
|
||||
*/
|
||||
class Exec_create_table : public Exec_ddl {
|
||||
public:
|
||||
class Code : public Exec_ddl::Code {
|
||||
public:
|
||||
struct Attr {
|
||||
Attr() : m_defaultValue(0) {}
|
||||
BaseString m_attrName;
|
||||
SqlType m_sqlType;
|
||||
bool m_tupleKey;
|
||||
bool m_tupleId;
|
||||
bool m_autoIncrement;
|
||||
Exec_expr* m_defaultValue;
|
||||
};
|
||||
Code(const BaseString& tableName, unsigned attrCount, const Attr* attrList, unsigned tupleId, unsigned autoIncrement);
|
||||
virtual ~Code();
|
||||
protected:
|
||||
friend class Plan_create_table;
|
||||
friend class Exec_create_table;
|
||||
const BaseString m_tableName;
|
||||
const unsigned m_attrCount;
|
||||
const Attr* const m_attrList;
|
||||
unsigned m_tupleId;
|
||||
unsigned m_autoIncrement;
|
||||
NdbDictionary::Object::FragmentType m_fragmentType;
|
||||
bool m_logging;
|
||||
};
|
||||
class Data : public Exec_ddl::Data {
|
||||
public:
|
||||
Data();
|
||||
virtual ~Data();
|
||||
protected:
|
||||
friend class Exec_create_table;
|
||||
};
|
||||
Exec_create_table(Exec_root* root);
|
||||
virtual ~Exec_create_table();
|
||||
void alloc(Ctx& ctx, Ctl& ctl);
|
||||
void execute(Ctx& ctx, Ctl& ctl);
|
||||
void close(Ctx& ctx);
|
||||
void print(Ctx& ctx);
|
||||
// children
|
||||
const Code& getCode() const;
|
||||
Data& getData() const;
|
||||
};
|
||||
|
||||
inline
|
||||
Exec_create_table::Code::Code(const BaseString& tableName, unsigned attrCount, const Attr* attrList, unsigned tupleId, unsigned autoIncrement) :
|
||||
m_tableName(tableName),
|
||||
m_attrCount(attrCount),
|
||||
m_attrList(attrList),
|
||||
m_tupleId(tupleId),
|
||||
m_autoIncrement(autoIncrement),
|
||||
m_fragmentType(NdbDictionary::Object::FragUndefined),
|
||||
m_logging(true)
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_create_table::Data::Data()
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_create_table::Exec_create_table(Exec_root* root) :
|
||||
Exec_ddl(root)
|
||||
{
|
||||
}
|
||||
|
||||
// children
|
||||
|
||||
inline const Exec_create_table::Code&
|
||||
Exec_create_table::getCode() const
|
||||
{
|
||||
const Code* code = static_cast<const Code*>(m_code);
|
||||
return *code;
|
||||
}
|
||||
|
||||
inline Exec_create_table::Data&
|
||||
Exec_create_table::getData() const
|
||||
{
|
||||
Data* data = static_cast<Data*>(m_data);
|
||||
return *data;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,44 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include <NdbApi.hpp>
|
||||
#include <common/StmtArea.hpp>
|
||||
#include "Code_data_type.hpp"
|
||||
|
||||
// Plan_data_type
|
||||
|
||||
Plan_data_type::~Plan_data_type()
|
||||
{
|
||||
}
|
||||
|
||||
Plan_base*
|
||||
Plan_data_type::analyze(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
Exec_base*
|
||||
Plan_data_type::codegen(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
ctx_assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_data_type::print(Ctx& ctx)
|
||||
{
|
||||
ctx.print(" [data_type]");
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef ODBC_CODEGEN_Code_data_type_hpp
|
||||
#define ODBC_CODEGEN_Code_data_type_hpp
|
||||
|
||||
#include <common/common.hpp>
|
||||
#include <common/DataType.hpp>
|
||||
#include "Code_base.hpp"
|
||||
|
||||
/**
|
||||
* @class Plan_data_type
|
||||
* @brief Data type in DDL statement
|
||||
*
|
||||
* This is pure plan node.
|
||||
*/
|
||||
class Plan_data_type : public Plan_base {
|
||||
public:
|
||||
Plan_data_type(Plan_root* root, const SqlType& sqlType);
|
||||
virtual ~Plan_data_type();
|
||||
Plan_base* analyze(Ctx& ctx, Ctl& ctl);
|
||||
Exec_base* codegen(Ctx& ctx, Ctl& ctl);
|
||||
void print(Ctx& ctx);
|
||||
private:
|
||||
friend class Plan_ddl_column;
|
||||
SqlType m_sqlType;
|
||||
};
|
||||
|
||||
inline
|
||||
Plan_data_type::Plan_data_type(Plan_root* root, const SqlType& sqlType) :
|
||||
Plan_base(root),
|
||||
m_sqlType(sqlType)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,37 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include "Code_ddl.hpp"
|
||||
|
||||
// Plan_ddl
|
||||
|
||||
Plan_ddl::~Plan_ddl()
|
||||
{
|
||||
}
|
||||
|
||||
// Exec_ddl
|
||||
|
||||
Exec_ddl::Code::~Code()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_ddl::Data::~Data()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_ddl::~Exec_ddl()
|
||||
{
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef ODBC_CODEGEN_Code_ddl_hpp
|
||||
#define ODBC_CODEGEN_Code_ddl_hpp
|
||||
|
||||
#include <common/common.hpp>
|
||||
#include "Code_stmt.hpp"
|
||||
|
||||
/**
|
||||
* @class Plan_ddl
|
||||
* @brief Base class for DDL statements in PlanTree
|
||||
*/
|
||||
class Plan_ddl : public Plan_stmt {
|
||||
public:
|
||||
Plan_ddl(Plan_root* root);
|
||||
virtual ~Plan_ddl() = 0;
|
||||
};
|
||||
|
||||
inline
|
||||
Plan_ddl::Plan_ddl(Plan_root* root) :
|
||||
Plan_stmt(root)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @class Exec_ddl
|
||||
* @brief Base class for DDL statements in ExecTree
|
||||
*/
|
||||
class Exec_ddl : public Exec_stmt {
|
||||
public:
|
||||
class Code : public Exec_stmt::Code {
|
||||
public:
|
||||
virtual ~Code() = 0;
|
||||
};
|
||||
class Data : public Exec_stmt::Data {
|
||||
public:
|
||||
virtual ~Data() = 0;
|
||||
};
|
||||
Exec_ddl(Exec_root* root);
|
||||
virtual ~Exec_ddl() = 0;
|
||||
};
|
||||
|
||||
inline
|
||||
Exec_ddl::Exec_ddl(Exec_root* root) :
|
||||
Exec_stmt(root)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,104 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include <NdbApi.hpp>
|
||||
#include <common/StmtArea.hpp>
|
||||
#include "Code_ddl_column.hpp"
|
||||
#include "Code_expr_conv.hpp"
|
||||
#include "Code_root.hpp"
|
||||
|
||||
// Plan_ddl_column
|
||||
|
||||
Plan_ddl_column::~Plan_ddl_column()
|
||||
{
|
||||
}
|
||||
|
||||
Plan_base*
|
||||
Plan_ddl_column::analyze(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
ctx_assert(m_type != 0);
|
||||
if (! m_type->m_sqlType.nullable()) {
|
||||
m_nullable = false;
|
||||
}
|
||||
m_sqlType = m_type->m_sqlType;
|
||||
m_sqlType.nullable(m_nullable);
|
||||
const BaseString& name = getName();
|
||||
if (m_unSigned) {
|
||||
switch (m_sqlType.type()) {
|
||||
case SqlType::Smallint:
|
||||
case SqlType::Integer:
|
||||
case SqlType::Bigint:
|
||||
break;
|
||||
default:
|
||||
ctx.pushStatus(Error::Gen, "invalid unsigned qualifier on column %s", name.c_str());
|
||||
return 0;
|
||||
}
|
||||
m_sqlType.unSigned(true);
|
||||
}
|
||||
if (strcmp(name.c_str(), "NDB$TID") == 0) {
|
||||
if (! m_primaryKey) {
|
||||
ctx.pushStatus(Error::Gen, "column %s must be a primary key", name.c_str());
|
||||
return 0;
|
||||
}
|
||||
if (sqlType().type() != SqlType::Bigint || ! sqlType().unSigned()) {
|
||||
ctx.pushStatus(Error::Gen, "tuple id %s must have type BIGINT UNSIGNED", name.c_str());
|
||||
return 0;
|
||||
}
|
||||
setTupleId();
|
||||
}
|
||||
if (m_autoIncrement) {
|
||||
if (! m_primaryKey) {
|
||||
ctx.pushStatus(Error::Gen, "auto-increment column %s must be a primary key", name.c_str());
|
||||
return 0;
|
||||
}
|
||||
if (sqlType().type() != SqlType::Smallint && sqlType().type() != SqlType::Integer && sqlType().type() != SqlType::Bigint) {
|
||||
ctx.pushStatus(Error::Gen, "auto-increment column %s must have an integral type", name.c_str());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (m_defaultValue != 0) {
|
||||
if (m_primaryKey) {
|
||||
ctx.pushStatus(Sqlstate::_42000, Error::Gen, "default value not allowed on primary key column %s", name.c_str());
|
||||
return 0;
|
||||
}
|
||||
m_defaultValue->analyze(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
// insert conversion node
|
||||
Plan_expr_conv* exprConv = new Plan_expr_conv(m_root, sqlType());
|
||||
m_root->saveNode(exprConv);
|
||||
exprConv->setExpr(m_defaultValue);
|
||||
Plan_expr* expr = static_cast<Plan_expr*>(exprConv->analyze(ctx, ctl));
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
ctx_assert(expr != 0);
|
||||
m_defaultValue = expr;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
Exec_base*
|
||||
Plan_ddl_column::codegen(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
ctx_assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_ddl_column::print(Ctx& ctx)
|
||||
{
|
||||
ctx.print(" [ddl_column %s key=%d id=%d]", getPrintName(), m_primaryKey, m_tupleId);
|
||||
}
|
|
@ -1,150 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef ODBC_CODEGEN_Code_ddl_column_hpp
|
||||
#define ODBC_CODEGEN_Code_ddl_column_hpp
|
||||
|
||||
#include <common/common.hpp>
|
||||
#include "Code_column.hpp"
|
||||
#include "Code_data_type.hpp"
|
||||
#include "Code_expr.hpp"
|
||||
|
||||
class DictColumn;
|
||||
class Plan_table;
|
||||
|
||||
/**
|
||||
* @class Plan_ddl_column
|
||||
* @brief Column in DDL statement
|
||||
*/
|
||||
class Plan_ddl_column : public Plan_base, public Plan_column {
|
||||
public:
|
||||
Plan_ddl_column(Plan_root* root, const BaseString& name);
|
||||
virtual ~Plan_ddl_column();
|
||||
Plan_base* analyze(Ctx& ctx, Ctl& ctl);
|
||||
Exec_base* codegen(Ctx& ctx, Ctl& ctl);
|
||||
void print(Ctx& ctx);
|
||||
// attributes
|
||||
void setNotNull();
|
||||
void setUnSigned();
|
||||
void setPrimaryKey();
|
||||
bool getPrimaryKey() const;
|
||||
void setTupleId();
|
||||
bool getTupleId() const;
|
||||
void setAutoIncrement();
|
||||
bool getAutoIncrement() const;
|
||||
// children
|
||||
void setType(Plan_data_type* type);
|
||||
void setDefaultValue(Plan_expr* defaultValue);
|
||||
Plan_expr* getDefaultValue() const;
|
||||
protected:
|
||||
friend class Plan_create_row;
|
||||
Plan_data_type* m_type;
|
||||
Plan_expr* m_defaultValue;
|
||||
bool m_nullable;
|
||||
bool m_unSigned;
|
||||
bool m_primaryKey;
|
||||
bool m_tupleId;
|
||||
bool m_autoIncrement;
|
||||
};
|
||||
|
||||
inline
|
||||
Plan_ddl_column::Plan_ddl_column(Plan_root* root, const BaseString& name) :
|
||||
Plan_base(root),
|
||||
Plan_column(Type_ddl, name),
|
||||
m_type(0),
|
||||
m_defaultValue(0),
|
||||
m_nullable(true),
|
||||
m_unSigned(false),
|
||||
m_primaryKey(false),
|
||||
m_tupleId(false),
|
||||
m_autoIncrement(false)
|
||||
{
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_ddl_column::setNotNull()
|
||||
{
|
||||
m_nullable = false;
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_ddl_column::setUnSigned()
|
||||
{
|
||||
m_unSigned = true;
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_ddl_column::setPrimaryKey()
|
||||
{
|
||||
m_nullable = false;
|
||||
m_primaryKey = true;
|
||||
}
|
||||
|
||||
inline bool
|
||||
Plan_ddl_column::getPrimaryKey() const
|
||||
{
|
||||
return m_primaryKey;
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_ddl_column::setTupleId()
|
||||
{
|
||||
m_nullable = false;
|
||||
m_tupleId = true;
|
||||
}
|
||||
|
||||
inline bool
|
||||
Plan_ddl_column::getTupleId() const
|
||||
{
|
||||
return m_tupleId;
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_ddl_column::setAutoIncrement()
|
||||
{
|
||||
m_nullable = false;
|
||||
m_autoIncrement = true;
|
||||
}
|
||||
|
||||
inline bool
|
||||
Plan_ddl_column::getAutoIncrement() const
|
||||
{
|
||||
return m_autoIncrement;
|
||||
}
|
||||
|
||||
// children
|
||||
|
||||
inline void
|
||||
Plan_ddl_column::setType(Plan_data_type* type)
|
||||
{
|
||||
ctx_assert(type != 0);
|
||||
m_type = type;
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_ddl_column::setDefaultValue(Plan_expr* defaultValue)
|
||||
{
|
||||
ctx_assert(defaultValue != 0);
|
||||
m_defaultValue = defaultValue;
|
||||
}
|
||||
|
||||
inline Plan_expr*
|
||||
Plan_ddl_column::getDefaultValue() const
|
||||
{
|
||||
return m_defaultValue;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,51 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include <NdbApi.hpp>
|
||||
#include <common/StmtArea.hpp>
|
||||
#include "Code_ddl_constr.hpp"
|
||||
|
||||
// Plan_ddl_constr
|
||||
|
||||
Plan_ddl_constr::~Plan_ddl_constr()
|
||||
{
|
||||
}
|
||||
|
||||
Plan_base*
|
||||
Plan_ddl_constr::analyze(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
ctx_assert(m_ddlRow != 0);
|
||||
m_ddlRow->analyze(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
Exec_base*
|
||||
Plan_ddl_constr::codegen(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
ctx_assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_ddl_constr::print(Ctx& ctx)
|
||||
{
|
||||
ctx.print(" [ddl_constr");
|
||||
Plan_base* a[] = { m_ddlRow };
|
||||
printList(ctx, a, 1);
|
||||
ctx.print("]");
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef ODBC_CODEGEN_Code_ddl_constr_hpp
|
||||
#define ODBC_CODEGEN_Code_ddl_constr_hpp
|
||||
|
||||
#include <common/common.hpp>
|
||||
#include "Code_ddl_row.hpp"
|
||||
|
||||
/**
|
||||
* @class Plan_ddl_constr
|
||||
* @brief Constraint in DDL statement
|
||||
*
|
||||
* Only unnamed primary key constraint exists.
|
||||
*/
|
||||
class Plan_ddl_constr : public Plan_base {
|
||||
public:
|
||||
Plan_ddl_constr(Plan_root* root);
|
||||
virtual ~Plan_ddl_constr();
|
||||
Plan_base* analyze(Ctx& ctx, Ctl& ctl);
|
||||
Exec_base* codegen(Ctx& ctx, Ctl& ctl);
|
||||
void print(Ctx& ctx);
|
||||
// children
|
||||
void setRow(Plan_ddl_row* ddlRow);
|
||||
Plan_ddl_row* getRow() const;
|
||||
protected:
|
||||
Plan_ddl_row* m_ddlRow;
|
||||
};
|
||||
|
||||
inline
|
||||
Plan_ddl_constr::Plan_ddl_constr(Plan_root* root) :
|
||||
Plan_base(root)
|
||||
{
|
||||
}
|
||||
|
||||
// children
|
||||
|
||||
inline void
|
||||
Plan_ddl_constr::setRow(Plan_ddl_row* ddlRow)
|
||||
{
|
||||
ctx_assert(ddlRow != 0);
|
||||
m_ddlRow = ddlRow;
|
||||
}
|
||||
|
||||
inline Plan_ddl_row*
|
||||
Plan_ddl_constr::getRow() const
|
||||
{
|
||||
ctx_assert(m_ddlRow != 0);
|
||||
return m_ddlRow;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,54 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include "Code_ddl_row.hpp"
|
||||
#include "Code_ddl_column.hpp"
|
||||
#include "Code_ddl_constr.hpp"
|
||||
|
||||
Plan_ddl_row::~Plan_ddl_row()
|
||||
{
|
||||
}
|
||||
|
||||
Plan_base*
|
||||
Plan_ddl_row::analyze(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
// analyze the columns
|
||||
for (unsigned i = 1, n = countColumn(); i <= n; i++) {
|
||||
Plan_ddl_column* column = getColumn(i);
|
||||
column->analyze(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
}
|
||||
// node was not replaced
|
||||
return this;
|
||||
}
|
||||
|
||||
Exec_base*
|
||||
Plan_ddl_row::codegen(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
ctx_assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_ddl_row::print(Ctx& ctx)
|
||||
{
|
||||
ctx.print(" [ddl_row");
|
||||
for (unsigned i = 1, n = countColumn(); i <= n; i++) {
|
||||
Plan_base* a = m_columnList[i];
|
||||
printList(ctx, &a, 1);
|
||||
}
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef ODBC_CODEGEN_Code_ddl_row_hpp
|
||||
#define ODBC_CODEGEN_Code_ddl_row_hpp
|
||||
|
||||
#include <common/common.hpp>
|
||||
#include "Code_base.hpp"
|
||||
#include "Code_ddl_column.hpp"
|
||||
|
||||
/**
|
||||
* @class Plan_ddl_row
|
||||
* @brief Row of columns in create statement
|
||||
*/
|
||||
class Plan_ddl_row : public Plan_base {
|
||||
public:
|
||||
Plan_ddl_row(Plan_root* root);
|
||||
virtual ~Plan_ddl_row();
|
||||
Plan_base* analyze(Ctx& ctx, Ctl& ctl);
|
||||
Exec_base* codegen(Ctx& ctx, Ctl& ctl);
|
||||
void print(Ctx& ctx);
|
||||
// children
|
||||
unsigned countColumn() const;
|
||||
void addColumn(Plan_ddl_column* column);
|
||||
Plan_ddl_column* getColumn(unsigned i) const;
|
||||
protected:
|
||||
DdlColumnVector m_columnList;
|
||||
};
|
||||
|
||||
inline
|
||||
Plan_ddl_row::Plan_ddl_row(Plan_root* root) :
|
||||
Plan_base(root),
|
||||
m_columnList(1)
|
||||
{
|
||||
}
|
||||
|
||||
// children
|
||||
|
||||
inline unsigned
|
||||
Plan_ddl_row::countColumn() const
|
||||
{
|
||||
return m_columnList.size() - 1;
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_ddl_row::addColumn(Plan_ddl_column* column)
|
||||
{
|
||||
ctx_assert(column != 0);
|
||||
m_columnList.push_back(column);
|
||||
}
|
||||
|
||||
inline Plan_ddl_column*
|
||||
Plan_ddl_row::getColumn(unsigned i) const
|
||||
{
|
||||
ctx_assert(1 <= i && i <= countColumn() && m_columnList[i] != 0);
|
||||
return m_columnList[i];
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,205 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include <common/StmtArea.hpp>
|
||||
#include "Code_delete.hpp"
|
||||
#include "Code_delete_lookup.hpp"
|
||||
#include "Code_delete_index.hpp"
|
||||
#include "Code_delete_scan.hpp"
|
||||
#include "Code_query_filter.hpp"
|
||||
#include "Code_query_lookup.hpp"
|
||||
#include "Code_query_index.hpp"
|
||||
#include "Code_query_scan.hpp"
|
||||
#include "Code_query_range.hpp"
|
||||
#include "Code_query_repeat.hpp"
|
||||
#include "Code_table.hpp"
|
||||
#include "Code_root.hpp"
|
||||
|
||||
Plan_delete::~Plan_delete()
|
||||
{
|
||||
}
|
||||
|
||||
Plan_base*
|
||||
Plan_delete::analyze(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
stmtArea().stmtInfo().setName(Stmt_name_delete);
|
||||
// analyze the table
|
||||
ctx_assert(m_table != 0);
|
||||
m_table->analyze(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
// set name resolution scope
|
||||
ctl.m_tableList.resize(1 + 1); // indexed from 1
|
||||
ctl.m_tableList[1] = m_table;
|
||||
Plan_dml* stmt = 0;
|
||||
if (m_pred != 0) {
|
||||
// analyze the predicate
|
||||
ctl.m_topand = true;
|
||||
ctl.m_extra = false;
|
||||
m_pred = static_cast<Plan_pred*>(m_pred->analyze(ctx, ctl));
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
ctx_assert(m_pred != 0);
|
||||
// check for key match
|
||||
Plan_table::Index* indexBest = 0;
|
||||
for (unsigned i = 0; i <= m_table->indexCount(); i++) {
|
||||
Plan_table::Index& index = m_table->m_indexList[i];
|
||||
TableSet tsDone;
|
||||
m_table->resolveSet(ctx, index, tsDone);
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
if (! index.m_keyFound)
|
||||
continue;
|
||||
// prefer smaller rank, less unused keys
|
||||
int k;
|
||||
(k = (indexBest == 0)) ||
|
||||
(k = (indexBest->m_rank - index.m_rank)) ||
|
||||
(k = (indexBest->m_keyCountUnused - index.m_keyCountUnused));
|
||||
if (k > 0)
|
||||
indexBest = &index;
|
||||
}
|
||||
if (indexBest != 0) {
|
||||
const bool exactKey = indexBest->m_rank <= 1 ? m_table->exactKey(ctx, indexBest) : false;
|
||||
const bool direct = ! ctl.m_extra && exactKey;
|
||||
ctx_log3(("delete direct=%d: extra=%d exact=%d", direct, ctl.m_extra, exactKey));
|
||||
if (indexBest->m_rank == 0) {
|
||||
// primary key
|
||||
Plan_delete_lookup* deleteLookup = new Plan_delete_lookup(m_root);
|
||||
m_root->saveNode(deleteLookup);
|
||||
deleteLookup->setTable(m_table);
|
||||
if (direct) {
|
||||
// key match with no extra conditions
|
||||
Plan_query_repeat* queryRepeat = new Plan_query_repeat(m_root, 1);
|
||||
m_root->saveNode(queryRepeat);
|
||||
deleteLookup->setQuery(queryRepeat);
|
||||
} else {
|
||||
// key match with extra conditions
|
||||
Plan_query_lookup* queryLookup = new Plan_query_lookup(m_root);
|
||||
m_root->saveNode(queryLookup);
|
||||
Plan_query_filter* queryFilter = new Plan_query_filter(m_root);
|
||||
m_root->saveNode(queryFilter);
|
||||
queryLookup->setTable(m_table);
|
||||
queryFilter->setQuery(queryLookup);
|
||||
queryFilter->setPred(m_pred);
|
||||
queryFilter->m_topTable = m_table;
|
||||
deleteLookup->setQuery(queryFilter);
|
||||
}
|
||||
stmt = deleteLookup;
|
||||
} else if (indexBest->m_rank == 1) {
|
||||
// hash index
|
||||
Plan_delete_index* deleteIndex = new Plan_delete_index(m_root);
|
||||
m_root->saveNode(deleteIndex);
|
||||
deleteIndex->setTable(m_table, indexBest);
|
||||
if (direct) {
|
||||
// key match with no extra conditions
|
||||
Plan_query_repeat* queryRepeat = new Plan_query_repeat(m_root, 1);
|
||||
m_root->saveNode(queryRepeat);
|
||||
deleteIndex->setQuery(queryRepeat);
|
||||
} else {
|
||||
// key match with extra conditions
|
||||
Plan_query_index* queryIndex = new Plan_query_index(m_root);
|
||||
m_root->saveNode(queryIndex);
|
||||
Plan_query_filter* queryFilter = new Plan_query_filter(m_root);
|
||||
m_root->saveNode(queryFilter);
|
||||
queryIndex->setTable(m_table, indexBest);
|
||||
queryFilter->setQuery(queryIndex);
|
||||
queryFilter->setPred(m_pred);
|
||||
queryFilter->m_topTable = m_table;
|
||||
deleteIndex->setQuery(queryFilter);
|
||||
}
|
||||
stmt = deleteIndex;
|
||||
} else if (indexBest->m_rank == 2) {
|
||||
// ordered index
|
||||
Plan_delete_scan* deleteScan = new Plan_delete_scan(m_root);
|
||||
m_root->saveNode(deleteScan);
|
||||
Plan_query_filter* queryFilter = new Plan_query_filter(m_root);
|
||||
m_root->saveNode(queryFilter);
|
||||
Plan_query_range* queryRange = new Plan_query_range(m_root);
|
||||
m_root->saveNode(queryRange);
|
||||
queryRange->setTable(m_table, indexBest);
|
||||
queryRange->setExclusive();
|
||||
queryFilter->setQuery(queryRange);
|
||||
queryFilter->setPred(m_pred);
|
||||
queryFilter->m_topTable = m_table;
|
||||
const TableSet& ts2 = m_pred->noInterp();
|
||||
ctx_assert(ts2.size() <= 1);
|
||||
if (ts2.size() == 0) {
|
||||
queryRange->setInterp(m_pred);
|
||||
}
|
||||
deleteScan->setQuery(queryFilter);
|
||||
stmt = deleteScan;
|
||||
} else {
|
||||
ctx_assert(false);
|
||||
}
|
||||
} else {
|
||||
// scan delete with filter
|
||||
Plan_delete_scan* deleteScan = new Plan_delete_scan(m_root);
|
||||
m_root->saveNode(deleteScan);
|
||||
Plan_query_filter* queryFilter = new Plan_query_filter(m_root);
|
||||
m_root->saveNode(queryFilter);
|
||||
Plan_query_scan* queryScan = new Plan_query_scan(m_root);
|
||||
m_root->saveNode(queryScan);
|
||||
queryScan->setTable(m_table);
|
||||
queryScan->setExclusive();
|
||||
queryFilter->setQuery(queryScan);
|
||||
queryFilter->setPred(m_pred);
|
||||
queryFilter->m_topTable = m_table;
|
||||
// interpeter
|
||||
const TableSet& ts2 = m_pred->noInterp();
|
||||
ctx_assert(ts2.size() <= 1);
|
||||
if (ts2.size() == 0) {
|
||||
queryScan->setInterp(m_pred);
|
||||
}
|
||||
deleteScan->setQuery(queryFilter);
|
||||
stmt = deleteScan;
|
||||
}
|
||||
} else {
|
||||
// scan delete without filter
|
||||
Plan_delete_scan* deleteScan = new Plan_delete_scan(m_root);
|
||||
m_root->saveNode(deleteScan);
|
||||
Plan_query_scan* queryScan = new Plan_query_scan(m_root);
|
||||
m_root->saveNode(queryScan);
|
||||
queryScan->setTable(m_table);
|
||||
queryScan->setExclusive();
|
||||
deleteScan->setQuery(queryScan);
|
||||
stmt = deleteScan;
|
||||
}
|
||||
// set base for column position offsets
|
||||
m_table->m_resOff = 1;
|
||||
return stmt;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_delete::describe(Ctx& ctx)
|
||||
{
|
||||
stmtArea().setFunction(ctx, "DELETE WHERE", SQL_DIAG_DELETE_WHERE);
|
||||
}
|
||||
|
||||
Exec_base*
|
||||
Plan_delete::codegen(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
ctx_assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_delete::print(Ctx& ctx)
|
||||
{
|
||||
ctx.print(" [delete");
|
||||
Plan_base* a[] = { m_table, m_pred };
|
||||
printList(ctx, a, 1);
|
||||
ctx.print("]");
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef ODBC_CODEGEN_Code_delete_hpp
|
||||
#define ODBC_CODEGEN_Code_delete_hpp
|
||||
|
||||
#include <common/common.hpp>
|
||||
#include "Code_base.hpp"
|
||||
#include "Code_dml.hpp"
|
||||
#include "Code_table.hpp"
|
||||
#include "Code_query.hpp"
|
||||
#include "Code_pred.hpp"
|
||||
|
||||
/**
|
||||
* @class Plan_delete
|
||||
* @brief Delete in PlanTree
|
||||
*/
|
||||
class Plan_delete : public Plan_dml {
|
||||
public:
|
||||
Plan_delete(Plan_root* root);
|
||||
virtual ~Plan_delete();
|
||||
Plan_base* analyze(Ctx& ctx, Ctl& ctl);
|
||||
void describe(Ctx& ctx);
|
||||
Exec_base* codegen(Ctx& ctx, Ctl& ctl);
|
||||
void print(Ctx& ctx);
|
||||
// children
|
||||
void setTable(Plan_table* table);
|
||||
void setPred(Plan_pred* pred);
|
||||
protected:
|
||||
Plan_table* m_table;
|
||||
Plan_pred* m_pred;
|
||||
};
|
||||
|
||||
inline
|
||||
Plan_delete::Plan_delete(Plan_root* root) :
|
||||
Plan_dml(root),
|
||||
m_table(0),
|
||||
m_pred(0)
|
||||
{
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_delete::setTable(Plan_table* table)
|
||||
{
|
||||
ctx_assert(table != 0);
|
||||
m_table = table;
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_delete::setPred(Plan_pred* pred)
|
||||
{
|
||||
ctx_assert(pred != 0);
|
||||
m_pred = pred;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,164 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include <common/StmtArea.hpp>
|
||||
#include <dictionary/DictTable.hpp>
|
||||
#include "Code_expr.hpp"
|
||||
#include "Code_delete_index.hpp"
|
||||
#include "Code_table.hpp"
|
||||
#include "Code_root.hpp"
|
||||
|
||||
Plan_delete_index::~Plan_delete_index()
|
||||
{
|
||||
}
|
||||
|
||||
Plan_base*
|
||||
Plan_delete_index::analyze(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
ctx_assert(m_query != 0);
|
||||
m_query->analyze(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
ctx_assert(m_table != 0);
|
||||
m_table->analyze(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_delete_index::describe(Ctx& ctx)
|
||||
{
|
||||
stmtArea().setFunction(ctx, "DELETE WHERE", SQL_DIAG_DELETE_WHERE);
|
||||
}
|
||||
|
||||
Exec_base*
|
||||
Plan_delete_index::codegen(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
// create code for the query
|
||||
ctx_assert(m_query != 0);
|
||||
Exec_query* execQuery = static_cast<Exec_query*>(m_query->codegen(ctx, ctl));
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
ctx_assert(execQuery != 0);
|
||||
// set up
|
||||
ctx_assert(m_table != 0 && m_index != 0);
|
||||
const BaseString& tableName = m_table->getName();
|
||||
ctx_assert(m_index->m_dictIndex != 0);
|
||||
const DictIndex& dictIndex = *m_index->m_dictIndex;
|
||||
const BaseString& indexName = dictIndex.getName();
|
||||
const unsigned keyCount = m_index->m_keyCount;
|
||||
// create the code
|
||||
Exec_delete_index::Code& code = *new Exec_delete_index::Code(keyCount);
|
||||
code.m_tableName = strcpy(new char[tableName.length() + 1], tableName.c_str());
|
||||
code.m_indexName = strcpy(new char[indexName.length() + 1], indexName.c_str());
|
||||
// key attributes
|
||||
code.m_keyId = new NdbAttrId[1 + keyCount];
|
||||
code.m_keyId[0] = (NdbAttrId)-1;
|
||||
for (unsigned k = 1; k <= keyCount; k++) {
|
||||
const DictColumn* keyColumn = dictIndex.getColumn(k);
|
||||
const SqlType& sqlType = keyColumn->sqlType();
|
||||
SqlSpec sqlSpec(sqlType, SqlSpec::Physical);
|
||||
code.m_keySpecs.setEntry(k, sqlSpec);
|
||||
code.m_keyId[k] = k - 1; // index column order
|
||||
}
|
||||
// matching expressions
|
||||
ctx_assert(m_index->m_keyFound);
|
||||
const ExprVector& keyEq = m_index->m_keyEq;
|
||||
ctx_assert(keyEq.size() == 1 + keyCount);
|
||||
code.m_keyMatch = new Exec_expr* [1 + keyCount];
|
||||
code.m_keyMatch[0] = 0;
|
||||
for (unsigned k = 1; k <= keyCount; k++) {
|
||||
Plan_expr* expr = keyEq[k];
|
||||
Exec_expr* execExpr = static_cast<Exec_expr*>(expr->codegen(ctx, ctl));
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
ctx_assert(execExpr != 0);
|
||||
code.m_keyMatch[k] = execExpr;
|
||||
}
|
||||
// create the exec
|
||||
Exec_delete_index* exec = new Exec_delete_index(ctl.m_execRoot);
|
||||
ctl.m_execRoot->saveNode(exec);
|
||||
exec->setCode(code);
|
||||
exec->setQuery(execQuery);
|
||||
return exec;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_delete_index::print(Ctx& ctx)
|
||||
{
|
||||
ctx.print(" [delete_index");
|
||||
Plan_base* a[] = { m_query, m_table };
|
||||
printList(ctx, a, 2);
|
||||
ctx.print("]");
|
||||
}
|
||||
|
||||
// Exec_delete_index
|
||||
|
||||
Exec_delete_index::Code::~Code()
|
||||
{
|
||||
delete[] m_tableName;
|
||||
delete[] m_keyId;
|
||||
delete[] m_keyMatch;
|
||||
}
|
||||
|
||||
Exec_delete_index::Data::~Data()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_delete_index::~Exec_delete_index()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Exec_delete_index::alloc(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
const Code& code = getCode();
|
||||
// allocate the subquery
|
||||
ctx_assert(m_query != 0);
|
||||
m_query->alloc(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return;
|
||||
// allocate matching expressions
|
||||
for (unsigned k = 1; k <= code.m_keyCount; k++) {
|
||||
Exec_expr* expr = code.m_keyMatch[k];
|
||||
ctx_assert(expr != 0);
|
||||
expr->alloc(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return;
|
||||
}
|
||||
// create data
|
||||
Data& data = *new Data;
|
||||
setData(data);
|
||||
}
|
||||
|
||||
void
|
||||
Exec_delete_index::close(Ctx& ctx)
|
||||
{
|
||||
ctx_assert(m_query != 0);
|
||||
m_query->close(ctx);
|
||||
}
|
||||
|
||||
void
|
||||
Exec_delete_index::print(Ctx& ctx)
|
||||
{
|
||||
const Code& code = getCode();
|
||||
ctx.print(" [delete_index");
|
||||
Exec_base* a[] = { m_query };
|
||||
printList(ctx, a, 1);
|
||||
printList(ctx, (Exec_base**)&code.m_keyMatch[1], code.m_keyCount);
|
||||
ctx.print("]");
|
||||
}
|
|
@ -1,156 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef ODBC_CODEGEN_Code_delete_index_hpp
|
||||
#define ODBC_CODEGEN_Code_delete_index_hpp
|
||||
|
||||
#include <common/common.hpp>
|
||||
#include "Code_dml.hpp"
|
||||
#include "Code_query.hpp"
|
||||
#include "Code_table.hpp"
|
||||
|
||||
/**
|
||||
* @class Plan_delete_index
|
||||
* @brief Delete by primary key
|
||||
*/
|
||||
class Plan_delete_index : public Plan_dml {
|
||||
public:
|
||||
Plan_delete_index(Plan_root* root);
|
||||
virtual ~Plan_delete_index();
|
||||
Plan_base* analyze(Ctx& ctx, Ctl& ctl);
|
||||
void describe(Ctx& ctx);
|
||||
Exec_base* codegen(Ctx& ctx, Ctl& ctl);
|
||||
void print(Ctx& ctx);
|
||||
// children
|
||||
void setQuery(Plan_query* query);
|
||||
void setTable(Plan_table* table, Plan_table::Index* index);
|
||||
protected:
|
||||
Plan_query* m_query;
|
||||
Plan_table* m_table;
|
||||
Plan_table::Index* m_index;
|
||||
};
|
||||
|
||||
inline
|
||||
Plan_delete_index::Plan_delete_index(Plan_root* root) :
|
||||
Plan_dml(root),
|
||||
m_query(0),
|
||||
m_table(0)
|
||||
{
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_delete_index::setQuery(Plan_query* query)
|
||||
{
|
||||
ctx_assert(query != 0);
|
||||
m_query = query;
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_delete_index::setTable(Plan_table* table, Plan_table::Index* index)
|
||||
{
|
||||
ctx_assert(table != 0 && index != 0 && index == &table->m_indexList[index->m_pos] && index->m_pos != 0);
|
||||
m_table = table;
|
||||
m_index = index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @class Exec_delete_index
|
||||
* @brief Delete by primary key
|
||||
*/
|
||||
class Exec_delete_index : public Exec_dml {
|
||||
public:
|
||||
class Code : public Exec_dml::Code {
|
||||
public:
|
||||
Code(unsigned keyCount);
|
||||
virtual ~Code();
|
||||
protected:
|
||||
friend class Plan_delete_index;
|
||||
friend class Exec_delete_index;
|
||||
const char* m_tableName;
|
||||
const char* m_indexName;
|
||||
unsigned m_keyCount;
|
||||
SqlSpecs m_keySpecs; // key types
|
||||
NdbAttrId* m_keyId;
|
||||
Exec_expr** m_keyMatch; // XXX pointers for now
|
||||
};
|
||||
class Data : public Exec_dml::Data {
|
||||
public:
|
||||
Data();
|
||||
virtual ~Data();
|
||||
protected:
|
||||
friend class Exec_delete_index;
|
||||
};
|
||||
Exec_delete_index(Exec_root* root);
|
||||
virtual ~Exec_delete_index();
|
||||
void alloc(Ctx& ctx, Ctl& ctl);
|
||||
void execImpl(Ctx& ctx, Ctl& ctl);
|
||||
void close(Ctx& ctx);
|
||||
void print(Ctx& ctx);
|
||||
// children
|
||||
const Code& getCode() const;
|
||||
Data& getData() const;
|
||||
void setQuery(Exec_query* query);
|
||||
protected:
|
||||
Exec_query* m_query;
|
||||
};
|
||||
|
||||
inline
|
||||
Exec_delete_index::Code::Code(unsigned keyCount) :
|
||||
m_tableName(0),
|
||||
m_indexName(0),
|
||||
m_keyCount(keyCount),
|
||||
m_keySpecs(keyCount),
|
||||
m_keyId(0),
|
||||
m_keyMatch(0)
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_delete_index::Data::Data()
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_delete_index::Exec_delete_index(Exec_root* root) :
|
||||
Exec_dml(root),
|
||||
m_query(0)
|
||||
{
|
||||
}
|
||||
|
||||
// children
|
||||
|
||||
inline const Exec_delete_index::Code&
|
||||
Exec_delete_index::getCode() const
|
||||
{
|
||||
const Code* code = static_cast<const Code*>(m_code);
|
||||
return *code;
|
||||
}
|
||||
|
||||
inline Exec_delete_index::Data&
|
||||
Exec_delete_index::getData() const
|
||||
{
|
||||
Data* data = static_cast<Data*>(m_data);
|
||||
return *data;
|
||||
}
|
||||
|
||||
inline void
|
||||
Exec_delete_index::setQuery(Exec_query* query)
|
||||
{
|
||||
ctx_assert(query != 0 && m_query == 0);
|
||||
m_query = query;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,162 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include <common/StmtArea.hpp>
|
||||
#include <dictionary/DictTable.hpp>
|
||||
#include "Code_expr.hpp"
|
||||
#include "Code_delete_lookup.hpp"
|
||||
#include "Code_table.hpp"
|
||||
#include "Code_root.hpp"
|
||||
|
||||
Plan_delete_lookup::~Plan_delete_lookup()
|
||||
{
|
||||
}
|
||||
|
||||
Plan_base*
|
||||
Plan_delete_lookup::analyze(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
ctx_assert(m_query != 0);
|
||||
m_query->analyze(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
ctx_assert(m_table != 0);
|
||||
m_table->analyze(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_delete_lookup::describe(Ctx& ctx)
|
||||
{
|
||||
stmtArea().setFunction(ctx, "DELETE WHERE", SQL_DIAG_DELETE_WHERE);
|
||||
}
|
||||
|
||||
Exec_base*
|
||||
Plan_delete_lookup::codegen(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
// create code for the query
|
||||
ctx_assert(m_query != 0);
|
||||
Exec_query* execQuery = static_cast<Exec_query*>(m_query->codegen(ctx, ctl));
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
ctx_assert(execQuery != 0);
|
||||
// set up
|
||||
ctx_assert(m_table != 0);
|
||||
const BaseString& tableName = m_table->getName();
|
||||
const DictTable& dictTable = m_table->dictTable();
|
||||
const unsigned keyCount = dictTable.keyCount();
|
||||
// create the code
|
||||
Exec_delete_lookup::Code& code = *new Exec_delete_lookup::Code(keyCount);
|
||||
code.m_tableName = strcpy(new char[tableName.length() + 1], tableName.c_str());
|
||||
// key attributes
|
||||
code.m_keyId = new NdbAttrId[1 + keyCount];
|
||||
code.m_keyId[0] = (NdbAttrId)-1;
|
||||
for (unsigned k = 1; k <= keyCount; k++) {
|
||||
const DictColumn* keyColumn = dictTable.getKey(k);
|
||||
const SqlType& sqlType = keyColumn->sqlType();
|
||||
SqlSpec sqlSpec(sqlType, SqlSpec::Physical);
|
||||
code.m_keySpecs.setEntry(k, sqlSpec);
|
||||
code.m_keyId[k] = keyColumn->getAttrId();
|
||||
}
|
||||
// matching expressions
|
||||
const Plan_table::Index& index = m_table->m_indexList[0];
|
||||
ctx_assert(index.m_keyFound);
|
||||
const ExprVector& keyEq = index.m_keyEq;
|
||||
ctx_assert(keyEq.size() == 1 + keyCount);
|
||||
code.m_keyMatch = new Exec_expr* [1 + keyCount];
|
||||
code.m_keyMatch[0] = 0;
|
||||
for (unsigned k = 1; k <= keyCount; k++) {
|
||||
Plan_expr* expr = keyEq[k];
|
||||
Exec_expr* execExpr = static_cast<Exec_expr*>(expr->codegen(ctx, ctl));
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
ctx_assert(execExpr != 0);
|
||||
code.m_keyMatch[k] = execExpr;
|
||||
}
|
||||
// create the exec
|
||||
Exec_delete_lookup* exec = new Exec_delete_lookup(ctl.m_execRoot);
|
||||
ctl.m_execRoot->saveNode(exec);
|
||||
exec->setCode(code);
|
||||
exec->setQuery(execQuery);
|
||||
return exec;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_delete_lookup::print(Ctx& ctx)
|
||||
{
|
||||
ctx.print(" [delete_lookup");
|
||||
Plan_base* a[] = { m_query, m_table };
|
||||
printList(ctx, a, 2);
|
||||
ctx.print("]");
|
||||
}
|
||||
|
||||
// Exec_delete_lookup
|
||||
|
||||
Exec_delete_lookup::Code::~Code()
|
||||
{
|
||||
delete[] m_tableName;
|
||||
delete[] m_keyId;
|
||||
delete[] m_keyMatch;
|
||||
}
|
||||
|
||||
Exec_delete_lookup::Data::~Data()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_delete_lookup::~Exec_delete_lookup()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Exec_delete_lookup::alloc(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
const Code& code = getCode();
|
||||
// allocate the subquery
|
||||
ctx_assert(m_query != 0);
|
||||
m_query->alloc(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return;
|
||||
// allocate matching expressions
|
||||
for (unsigned k = 1; k <= code.m_keyCount; k++) {
|
||||
Exec_expr* expr = code.m_keyMatch[k];
|
||||
ctx_assert(expr != 0);
|
||||
expr->alloc(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return;
|
||||
}
|
||||
// create data
|
||||
Data& data = *new Data;
|
||||
setData(data);
|
||||
}
|
||||
|
||||
void
|
||||
Exec_delete_lookup::close(Ctx& ctx)
|
||||
{
|
||||
ctx_assert(m_query != 0);
|
||||
m_query->close(ctx);
|
||||
}
|
||||
|
||||
void
|
||||
Exec_delete_lookup::print(Ctx& ctx)
|
||||
{
|
||||
const Code& code = getCode();
|
||||
ctx.print(" [delete_lookup");
|
||||
Exec_base* a[] = { m_query };
|
||||
printList(ctx, a, 1);
|
||||
printList(ctx, (Exec_base**)&code.m_keyMatch[1], code.m_keyCount);
|
||||
ctx.print("]");
|
||||
}
|
|
@ -1,152 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef ODBC_CODEGEN_Code_delete_lookup_hpp
|
||||
#define ODBC_CODEGEN_Code_delete_lookup_hpp
|
||||
|
||||
#include <common/common.hpp>
|
||||
#include "Code_dml.hpp"
|
||||
#include "Code_query.hpp"
|
||||
#include "Code_table.hpp"
|
||||
|
||||
/**
|
||||
* @class Plan_delete_lookup
|
||||
* @brief Delete by primary key
|
||||
*/
|
||||
class Plan_delete_lookup : public Plan_dml {
|
||||
public:
|
||||
Plan_delete_lookup(Plan_root* root);
|
||||
virtual ~Plan_delete_lookup();
|
||||
Plan_base* analyze(Ctx& ctx, Ctl& ctl);
|
||||
void describe(Ctx& ctx);
|
||||
Exec_base* codegen(Ctx& ctx, Ctl& ctl);
|
||||
void print(Ctx& ctx);
|
||||
// children
|
||||
void setQuery(Plan_query* query);
|
||||
void setTable(Plan_table* table);
|
||||
protected:
|
||||
Plan_query* m_query;
|
||||
Plan_table* m_table;
|
||||
};
|
||||
|
||||
inline
|
||||
Plan_delete_lookup::Plan_delete_lookup(Plan_root* root) :
|
||||
Plan_dml(root),
|
||||
m_query(0),
|
||||
m_table(0)
|
||||
{
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_delete_lookup::setQuery(Plan_query* query)
|
||||
{
|
||||
ctx_assert(query != 0);
|
||||
m_query = query;
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_delete_lookup::setTable(Plan_table* table)
|
||||
{
|
||||
ctx_assert(table != 0);
|
||||
m_table = table;
|
||||
}
|
||||
|
||||
/**
|
||||
* @class Exec_delete_lookup
|
||||
* @brief Delete by primary key
|
||||
*/
|
||||
class Exec_delete_lookup : public Exec_dml {
|
||||
public:
|
||||
class Code : public Exec_dml::Code {
|
||||
public:
|
||||
Code(unsigned keyCount);
|
||||
virtual ~Code();
|
||||
protected:
|
||||
friend class Plan_delete_lookup;
|
||||
friend class Exec_delete_lookup;
|
||||
char* m_tableName;
|
||||
unsigned m_keyCount;
|
||||
SqlSpecs m_keySpecs; // key types
|
||||
NdbAttrId* m_keyId;
|
||||
Exec_expr** m_keyMatch; // XXX pointers for now
|
||||
};
|
||||
class Data : public Exec_dml::Data {
|
||||
public:
|
||||
Data();
|
||||
virtual ~Data();
|
||||
protected:
|
||||
friend class Exec_delete_lookup;
|
||||
};
|
||||
Exec_delete_lookup(Exec_root* root);
|
||||
virtual ~Exec_delete_lookup();
|
||||
void alloc(Ctx& ctx, Ctl& ctl);
|
||||
void execImpl(Ctx& ctx, Ctl& ctl);
|
||||
void close(Ctx& ctx);
|
||||
void print(Ctx& ctx);
|
||||
// children
|
||||
const Code& getCode() const;
|
||||
Data& getData() const;
|
||||
void setQuery(Exec_query* query);
|
||||
protected:
|
||||
Exec_query* m_query;
|
||||
};
|
||||
|
||||
inline
|
||||
Exec_delete_lookup::Code::Code(unsigned keyCount) :
|
||||
m_tableName(0),
|
||||
m_keyCount(keyCount),
|
||||
m_keySpecs(keyCount),
|
||||
m_keyId(0),
|
||||
m_keyMatch(0)
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_delete_lookup::Data::Data()
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_delete_lookup::Exec_delete_lookup(Exec_root* root) :
|
||||
Exec_dml(root),
|
||||
m_query(0)
|
||||
{
|
||||
}
|
||||
|
||||
// children
|
||||
|
||||
inline const Exec_delete_lookup::Code&
|
||||
Exec_delete_lookup::getCode() const
|
||||
{
|
||||
const Code* code = static_cast<const Code*>(m_code);
|
||||
return *code;
|
||||
}
|
||||
|
||||
inline Exec_delete_lookup::Data&
|
||||
Exec_delete_lookup::getData() const
|
||||
{
|
||||
Data* data = static_cast<Data*>(m_data);
|
||||
return *data;
|
||||
}
|
||||
|
||||
inline void
|
||||
Exec_delete_lookup::setQuery(Exec_query* query)
|
||||
{
|
||||
ctx_assert(query != 0 && m_query == 0);
|
||||
m_query = query;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,110 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include <common/StmtArea.hpp>
|
||||
#include "Code_delete_scan.hpp"
|
||||
#include "Code_root.hpp"
|
||||
|
||||
Plan_delete_scan::~Plan_delete_scan()
|
||||
{
|
||||
}
|
||||
|
||||
Plan_base*
|
||||
Plan_delete_scan::analyze(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
ctx_assert(m_query != 0);
|
||||
m_query->analyze(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_delete_scan::describe(Ctx& ctx)
|
||||
{
|
||||
stmtArea().setFunction(ctx, "DELETE WHERE", SQL_DIAG_DELETE_WHERE);
|
||||
}
|
||||
|
||||
Exec_base*
|
||||
Plan_delete_scan::codegen(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
// create code for the subquery
|
||||
ctx_assert(m_query != 0);
|
||||
Exec_query* execQuery = static_cast<Exec_query*>(m_query->codegen(ctx, ctl));
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
ctx_assert(execQuery != 0);
|
||||
// create the code
|
||||
Exec_delete_scan* exec = new Exec_delete_scan(ctl.m_execRoot);
|
||||
ctl.m_execRoot->saveNode(exec);
|
||||
Exec_delete_scan::Code& code = *new Exec_delete_scan::Code;
|
||||
exec->setCode(code);
|
||||
exec->setQuery(execQuery);
|
||||
return exec;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_delete_scan::print(Ctx& ctx)
|
||||
{
|
||||
ctx.print(" [delete_scan");
|
||||
Plan_base* a[] = { m_query };
|
||||
printList(ctx, a, 1);
|
||||
ctx.print("]");
|
||||
}
|
||||
|
||||
// Exec_delete_scan
|
||||
|
||||
Exec_delete_scan::Code::~Code()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_delete_scan::Data::~Data()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_delete_scan::~Exec_delete_scan()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Exec_delete_scan::alloc(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
// allocate the subquery
|
||||
ctx_assert(m_query != 0);
|
||||
m_query->alloc(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return;
|
||||
// create data
|
||||
Data& data = *new Data;
|
||||
setData(data);
|
||||
}
|
||||
|
||||
void
|
||||
Exec_delete_scan::close(Ctx& ctx)
|
||||
{
|
||||
ctx_assert(m_query != 0);
|
||||
m_query->close(ctx);
|
||||
}
|
||||
|
||||
void
|
||||
Exec_delete_scan::print(Ctx& ctx)
|
||||
{
|
||||
ctx.print(" [delete_scan");
|
||||
Exec_base* a[] = { m_query };
|
||||
printList(ctx, a, 1);
|
||||
ctx.print("]");
|
||||
}
|
||||
|
|
@ -1,130 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef ODBC_CODEGEN_Code_delete_scan_hpp
|
||||
#define ODBC_CODEGEN_Code_delete_scan_hpp
|
||||
|
||||
#include <common/common.hpp>
|
||||
#include "Code_dml.hpp"
|
||||
#include "Code_query.hpp"
|
||||
|
||||
/**
|
||||
* @class Plan_delete_scan
|
||||
* @brief Scan delete
|
||||
*/
|
||||
class Plan_delete_scan : public Plan_dml {
|
||||
public:
|
||||
Plan_delete_scan(Plan_root* root);
|
||||
virtual ~Plan_delete_scan();
|
||||
Plan_base* analyze(Ctx& ctx, Ctl& ctl);
|
||||
void describe(Ctx& ctx);
|
||||
Exec_base* codegen(Ctx& ctx, Ctl& ctl);
|
||||
void print(Ctx& ctx);
|
||||
// children
|
||||
void setQuery(Plan_query* query);
|
||||
protected:
|
||||
Plan_query* m_query;
|
||||
};
|
||||
|
||||
inline
|
||||
Plan_delete_scan::Plan_delete_scan(Plan_root* root) :
|
||||
Plan_dml(root),
|
||||
m_query(0)
|
||||
{
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_delete_scan::setQuery(Plan_query* query)
|
||||
{
|
||||
ctx_assert(query != 0);
|
||||
m_query = query;
|
||||
}
|
||||
|
||||
/**
|
||||
* @class Exec_delete_scan
|
||||
* @brief Scan delete
|
||||
*/
|
||||
class Exec_delete_scan : public Exec_dml {
|
||||
public:
|
||||
class Code : public Exec_dml::Code {
|
||||
public:
|
||||
Code();
|
||||
virtual ~Code();
|
||||
protected:
|
||||
friend class Exec_delete_scan;
|
||||
};
|
||||
class Data : public Exec_dml::Data {
|
||||
public:
|
||||
Data();
|
||||
virtual ~Data();
|
||||
protected:
|
||||
friend class Exec_delete_scan;
|
||||
};
|
||||
Exec_delete_scan(Exec_root* root);
|
||||
virtual ~Exec_delete_scan();
|
||||
void alloc(Ctx& ctx, Ctl& ctl);
|
||||
void execImpl(Ctx& ctx, Ctl& ctl);
|
||||
void close(Ctx& ctx);
|
||||
void print(Ctx& ctx);
|
||||
// children
|
||||
const Code& getCode() const;
|
||||
Data& getData() const;
|
||||
void setQuery(Exec_query* query);
|
||||
protected:
|
||||
Exec_query* m_query;
|
||||
};
|
||||
|
||||
inline
|
||||
Exec_delete_scan::Code::Code()
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_delete_scan::Data::Data()
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_delete_scan::Exec_delete_scan(Exec_root* root) :
|
||||
Exec_dml(root),
|
||||
m_query(0)
|
||||
{
|
||||
}
|
||||
|
||||
// children
|
||||
|
||||
inline const Exec_delete_scan::Code&
|
||||
Exec_delete_scan::getCode() const
|
||||
{
|
||||
const Code* code = static_cast<const Code*>(m_code);
|
||||
return *code;
|
||||
}
|
||||
|
||||
inline Exec_delete_scan::Data&
|
||||
Exec_delete_scan::getData() const
|
||||
{
|
||||
Data* data = static_cast<Data*>(m_data);
|
||||
return *data;
|
||||
}
|
||||
|
||||
inline void
|
||||
Exec_delete_scan::setQuery(Exec_query* query)
|
||||
{
|
||||
ctx_assert(query != 0 && m_query == 0);
|
||||
m_query = query;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,51 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include <common/StmtArea.hpp>
|
||||
#include "Code_dml.hpp"
|
||||
|
||||
// Plan_dml
|
||||
|
||||
Plan_dml::~Plan_dml()
|
||||
{
|
||||
}
|
||||
|
||||
// Exec_dml
|
||||
|
||||
Exec_dml::Code::~Code()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_dml::Data::~Data()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_dml::~Exec_dml()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Exec_dml::execute(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
execImpl(ctx, ctl);
|
||||
if (m_topLevel) {
|
||||
if (ctx.ok()) {
|
||||
if (stmtArea().getRowCount() == 0) {
|
||||
ctx.setCode(SQL_NO_DATA);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef ODBC_CODEGEN_Code_dml_hpp
|
||||
#define ODBC_CODEGEN_Code_dml_hpp
|
||||
|
||||
#include <common/common.hpp>
|
||||
#include <common/ResultArea.hpp>
|
||||
#include "Code_stmt.hpp"
|
||||
|
||||
/**
|
||||
* @class Plan_dml
|
||||
* @brief Base class for DML statements in PlanTree
|
||||
*/
|
||||
class Plan_dml : public Plan_stmt {
|
||||
public:
|
||||
Plan_dml(Plan_root* root);
|
||||
virtual ~Plan_dml() = 0;
|
||||
};
|
||||
|
||||
inline
|
||||
Plan_dml::Plan_dml(Plan_root* root) :
|
||||
Plan_stmt(root)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @class Exec_dml
|
||||
* @brief Base class for DML statements in ExecTree
|
||||
*/
|
||||
class Exec_dml : public Exec_stmt {
|
||||
public:
|
||||
class Code : public Exec_stmt::Code {
|
||||
public:
|
||||
virtual ~Code() = 0;
|
||||
};
|
||||
class Data : public Exec_stmt::Data, public ResultArea {
|
||||
public:
|
||||
virtual ~Data() = 0;
|
||||
};
|
||||
Exec_dml(Exec_root* root);
|
||||
virtual ~Exec_dml() = 0;
|
||||
void execute(Ctx& ctx, Ctl& ctl);
|
||||
protected:
|
||||
virtual void execImpl(Ctx& ctx, Ctl& ctl) = 0;
|
||||
};
|
||||
|
||||
inline
|
||||
Exec_dml::Exec_dml(Exec_root* root) :
|
||||
Exec_stmt(root)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,47 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include <NdbApi.hpp>
|
||||
#include <common/StmtArea.hpp>
|
||||
#include "Code_dml_column.hpp"
|
||||
|
||||
// Plan_dml_column
|
||||
|
||||
Plan_dml_column::~Plan_dml_column()
|
||||
{
|
||||
}
|
||||
|
||||
Plan_base*
|
||||
Plan_dml_column::analyze(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
analyzeColumn(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
Exec_base*
|
||||
Plan_dml_column::codegen(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
ctx_assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_dml_column::print(Ctx& ctx)
|
||||
{
|
||||
ctx.print(" [dml_column %s]", getPrintName());
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef ODBC_CODEGEN_Code_dml_column_hpp
|
||||
#define ODBC_CODEGEN_Code_dml_column_hpp
|
||||
|
||||
#include <common/common.hpp>
|
||||
#include "Code_column.hpp"
|
||||
|
||||
class DictColumn;
|
||||
class Plan_table;
|
||||
|
||||
/**
|
||||
* @class Plan_dml_column
|
||||
* @brief Column in query expression
|
||||
*/
|
||||
class Plan_dml_column : public Plan_base, public Plan_column {
|
||||
public:
|
||||
Plan_dml_column(Plan_root* root, const BaseString& name);
|
||||
virtual ~Plan_dml_column();
|
||||
Plan_base* analyze(Ctx& ctx, Ctl& ctl);
|
||||
Exec_base* codegen(Ctx& ctx, Ctl& ctl);
|
||||
void print(Ctx& ctx);
|
||||
};
|
||||
|
||||
inline
|
||||
Plan_dml_column::Plan_dml_column(Plan_root* root, const BaseString& name) :
|
||||
Plan_base(root),
|
||||
Plan_column(Type_dml, name)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,56 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include "Code_dml_row.hpp"
|
||||
#include "Code_dml_column.hpp"
|
||||
|
||||
Plan_dml_row::~Plan_dml_row()
|
||||
{
|
||||
}
|
||||
|
||||
Plan_base*
|
||||
Plan_dml_row::analyze(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
unsigned size = getSize();
|
||||
// analyze the columns
|
||||
for (unsigned i = 1; i <= size; i++) {
|
||||
Plan_dml_column* column = getColumn(i);
|
||||
column->analyze(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
}
|
||||
// node was not replaced
|
||||
return this;
|
||||
}
|
||||
|
||||
Exec_base*
|
||||
Plan_dml_row::codegen(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
ctx_assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_dml_row::print(Ctx& ctx)
|
||||
{
|
||||
unsigned size = getSize();
|
||||
ctx.print(" [dml_row");
|
||||
for (unsigned i = 1; i <= size; i++) {
|
||||
Plan_base* a = m_columnList[i];
|
||||
a == 0 ? ctx.print(" -") : a->print(ctx);
|
||||
}
|
||||
ctx.print("]");
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef ODBC_CODEGEN_Code_dml_row_hpp
|
||||
#define ODBC_CODEGEN_Code_dml_row_hpp
|
||||
|
||||
#include <vector>
|
||||
#include <common/common.hpp>
|
||||
#include <common/DataRow.hpp>
|
||||
#include "Code_base.hpp"
|
||||
#include "Code_dml_column.hpp"
|
||||
|
||||
class Plan_dml_column;
|
||||
|
||||
/**
|
||||
* @class Plan_dml_row
|
||||
* @brief Row of lvalue columns in insert or update
|
||||
*/
|
||||
class Plan_dml_row : public Plan_base {
|
||||
public:
|
||||
Plan_dml_row(Plan_root* root);
|
||||
virtual ~Plan_dml_row();
|
||||
Plan_base* analyze(Ctx& ctx, Ctl& ctl);
|
||||
Exec_base* codegen(Ctx& ctx, Ctl& ctl);
|
||||
void print(Ctx& ctx);
|
||||
// children
|
||||
unsigned getSize() const;
|
||||
void addColumn(Plan_dml_column* column);
|
||||
Plan_dml_column* getColumn(unsigned i) const;
|
||||
protected:
|
||||
DmlColumnVector m_columnList;
|
||||
};
|
||||
|
||||
inline
|
||||
Plan_dml_row::Plan_dml_row(Plan_root* root) :
|
||||
Plan_base(root),
|
||||
m_columnList(1)
|
||||
{
|
||||
}
|
||||
|
||||
// children
|
||||
|
||||
inline unsigned
|
||||
Plan_dml_row::getSize() const
|
||||
{
|
||||
return m_columnList.size() - 1;
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_dml_row::addColumn(Plan_dml_column* column)
|
||||
{
|
||||
ctx_assert(column != 0);
|
||||
m_columnList.push_back(column);
|
||||
}
|
||||
|
||||
inline Plan_dml_column*
|
||||
Plan_dml_row::getColumn(unsigned i) const
|
||||
{
|
||||
ctx_assert(1 <= i && i <= m_columnList.size() && m_columnList[i] != 0);
|
||||
return m_columnList[i];
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,87 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include <common/StmtArea.hpp>
|
||||
#include "Code_drop_index.hpp"
|
||||
#include "Code_root.hpp"
|
||||
|
||||
// Plan_drop_index
|
||||
|
||||
Plan_drop_index::~Plan_drop_index()
|
||||
{
|
||||
}
|
||||
|
||||
Plan_base*
|
||||
Plan_drop_index::analyze(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
stmtArea().stmtInfo().setName(Stmt_name_drop_index);
|
||||
return this;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_drop_index::describe(Ctx& ctx)
|
||||
{
|
||||
stmtArea().setFunction(ctx, "DROP INDEX", SQL_DIAG_DROP_INDEX);
|
||||
}
|
||||
|
||||
Exec_base*
|
||||
Plan_drop_index::codegen(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
Exec_drop_index* exec = new Exec_drop_index(ctl.m_execRoot);
|
||||
ctl.m_execRoot->saveNode(exec);
|
||||
Exec_drop_index::Code& code = *new Exec_drop_index::Code(m_name, m_tableName);
|
||||
exec->setCode(code);
|
||||
return exec;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_drop_index::print(Ctx& ctx)
|
||||
{
|
||||
ctx.print(" [drop_index %s]", m_name.c_str());
|
||||
}
|
||||
|
||||
// Exec_drop_index
|
||||
|
||||
Exec_drop_index::Code::~Code()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_drop_index::Data::~Data()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_drop_index::~Exec_drop_index()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Exec_drop_index::alloc(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
Data& data = *new Data;
|
||||
setData(data);
|
||||
}
|
||||
|
||||
void
|
||||
Exec_drop_index::close(Ctx& ctx)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Exec_drop_index::print(Ctx& ctx)
|
||||
{
|
||||
const Code& code = getCode();
|
||||
ctx.print(" [drop_index %s]", code.m_indexName.c_str());
|
||||
}
|
|
@ -1,136 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef ODBC_CODEGEN_Code_drop_index_hpp
|
||||
#define ODBC_CODEGEN_Code_drop_index_hpp
|
||||
|
||||
#include <vector>
|
||||
#include <NdbApi.hpp>
|
||||
#include <common/common.hpp>
|
||||
#include "Code_ddl.hpp"
|
||||
|
||||
class DictTable;
|
||||
class DictColumn;
|
||||
|
||||
/**
|
||||
* @class Plan_drop_index
|
||||
* @brief Drop index in PlanTree
|
||||
*/
|
||||
class Plan_drop_index : public Plan_ddl {
|
||||
public:
|
||||
Plan_drop_index(Plan_root* root, const BaseString& name);
|
||||
Plan_drop_index(Plan_root* root, const BaseString& name, const BaseString& tableName);
|
||||
virtual ~Plan_drop_index();
|
||||
Plan_base* analyze(Ctx& ctx, Ctl& ctl);
|
||||
Exec_base* codegen(Ctx& ctx, Ctl& ctl);
|
||||
void describe(Ctx & ctx);
|
||||
void print(Ctx& ctx);
|
||||
// attributes
|
||||
const BaseString& getName() const;
|
||||
protected:
|
||||
BaseString m_name;
|
||||
BaseString m_tableName;
|
||||
};
|
||||
|
||||
inline
|
||||
Plan_drop_index::Plan_drop_index(Plan_root* root, const BaseString& name) :
|
||||
Plan_ddl(root),
|
||||
m_name(name)
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Plan_drop_index::Plan_drop_index(Plan_root* root, const BaseString& name, const BaseString& tableName) :
|
||||
Plan_ddl(root),
|
||||
m_name(name),
|
||||
m_tableName(tableName)
|
||||
{
|
||||
}
|
||||
|
||||
inline const BaseString&
|
||||
Plan_drop_index::getName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @class Exec_drop_index
|
||||
* @brief Drop index in ExecTree
|
||||
*/
|
||||
class Exec_drop_index : public Exec_ddl {
|
||||
public:
|
||||
class Code : public Exec_ddl::Code {
|
||||
public:
|
||||
Code(const BaseString& indexName, const BaseString& tableName);
|
||||
virtual ~Code();
|
||||
protected:
|
||||
friend class Exec_drop_index;
|
||||
const BaseString m_indexName;
|
||||
const BaseString m_tableName;
|
||||
};
|
||||
class Data : public Exec_ddl::Data {
|
||||
public:
|
||||
Data();
|
||||
virtual ~Data();
|
||||
protected:
|
||||
friend class Exec_drop_index;
|
||||
};
|
||||
Exec_drop_index(Exec_root* root);
|
||||
virtual ~Exec_drop_index();
|
||||
void alloc(Ctx& ctx, Ctl& ctl);
|
||||
void execute(Ctx& ctx, Ctl& ctl);
|
||||
void close(Ctx& ctx);
|
||||
void print(Ctx& ctx);
|
||||
// children
|
||||
const Code& getCode() const;
|
||||
Data& getData() const;
|
||||
};
|
||||
|
||||
inline
|
||||
Exec_drop_index::Code::Code(const BaseString& indexName, const BaseString& tableName) :
|
||||
m_indexName(indexName),
|
||||
m_tableName(tableName)
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_drop_index::Data::Data()
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_drop_index::Exec_drop_index(Exec_root* root) :
|
||||
Exec_ddl(root)
|
||||
{
|
||||
}
|
||||
|
||||
// children
|
||||
|
||||
inline const Exec_drop_index::Code&
|
||||
Exec_drop_index::getCode() const
|
||||
{
|
||||
const Code* code = static_cast<const Code*>(m_code);
|
||||
return *code;
|
||||
}
|
||||
|
||||
inline Exec_drop_index::Data&
|
||||
Exec_drop_index::getData() const
|
||||
{
|
||||
Data* data = static_cast<Data*>(m_data);
|
||||
return *data;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,87 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include <common/StmtArea.hpp>
|
||||
#include "Code_drop_table.hpp"
|
||||
#include "Code_root.hpp"
|
||||
|
||||
// Plan_drop_table
|
||||
|
||||
Plan_drop_table::~Plan_drop_table()
|
||||
{
|
||||
}
|
||||
|
||||
Plan_base*
|
||||
Plan_drop_table::analyze(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
stmtArea().stmtInfo().setName(Stmt_name_drop_table);
|
||||
return this;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_drop_table::describe(Ctx& ctx)
|
||||
{
|
||||
stmtArea().setFunction(ctx, "DROP TABLE", SQL_DIAG_DROP_TABLE);
|
||||
}
|
||||
|
||||
Exec_base*
|
||||
Plan_drop_table::codegen(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
Exec_drop_table* exec = new Exec_drop_table(ctl.m_execRoot);
|
||||
ctl.m_execRoot->saveNode(exec);
|
||||
Exec_drop_table::Code& code = *new Exec_drop_table::Code(m_name);
|
||||
exec->setCode(code);
|
||||
return exec;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_drop_table::print(Ctx& ctx)
|
||||
{
|
||||
ctx.print(" [drop_table %s]", m_name.c_str());
|
||||
}
|
||||
|
||||
// Exec_drop_table
|
||||
|
||||
Exec_drop_table::Code::~Code()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_drop_table::Data::~Data()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_drop_table::~Exec_drop_table()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Exec_drop_table::alloc(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
Data& data = *new Data;
|
||||
setData(data);
|
||||
}
|
||||
|
||||
void
|
||||
Exec_drop_table::close(Ctx& ctx)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Exec_drop_table::print(Ctx& ctx)
|
||||
{
|
||||
const Code& code = getCode();
|
||||
ctx.print(" [drop_table %s]", code.m_tableName.c_str());
|
||||
}
|
|
@ -1,124 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef ODBC_CODEGEN_Code_drop_table_hpp
|
||||
#define ODBC_CODEGEN_Code_drop_table_hpp
|
||||
|
||||
#include <vector>
|
||||
#include <NdbApi.hpp>
|
||||
#include <common/common.hpp>
|
||||
#include "Code_ddl.hpp"
|
||||
|
||||
class DictTable;
|
||||
class DictColumn;
|
||||
|
||||
/**
|
||||
* @class Plan_drop_table
|
||||
* @brief Drop table in PlanTree
|
||||
*/
|
||||
class Plan_drop_table : public Plan_ddl {
|
||||
public:
|
||||
Plan_drop_table(Plan_root* root, const BaseString& name);
|
||||
virtual ~Plan_drop_table();
|
||||
Plan_base* analyze(Ctx& ctx, Ctl& ctl);
|
||||
Exec_base* codegen(Ctx& ctx, Ctl& ctl);
|
||||
void describe(Ctx & ctx);
|
||||
void print(Ctx& ctx);
|
||||
// attributes
|
||||
const BaseString& getName() const;
|
||||
protected:
|
||||
BaseString m_name;
|
||||
};
|
||||
|
||||
inline
|
||||
Plan_drop_table::Plan_drop_table(Plan_root* root, const BaseString& name) :
|
||||
Plan_ddl(root),
|
||||
m_name(name)
|
||||
{
|
||||
}
|
||||
|
||||
inline const BaseString&
|
||||
Plan_drop_table::getName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @class Exec_drop_table
|
||||
* @brief Drop table in ExecTree
|
||||
*/
|
||||
class Exec_drop_table : public Exec_ddl {
|
||||
public:
|
||||
class Code : public Exec_ddl::Code {
|
||||
public:
|
||||
Code(const BaseString& tableName);
|
||||
virtual ~Code();
|
||||
protected:
|
||||
friend class Exec_drop_table;
|
||||
const BaseString m_tableName;
|
||||
};
|
||||
class Data : public Exec_ddl::Data {
|
||||
public:
|
||||
Data();
|
||||
virtual ~Data();
|
||||
protected:
|
||||
friend class Exec_drop_table;
|
||||
};
|
||||
Exec_drop_table(Exec_root* root);
|
||||
virtual ~Exec_drop_table();
|
||||
void alloc(Ctx& ctx, Ctl& ctl);
|
||||
void execute(Ctx& ctx, Ctl& ctl);
|
||||
void close(Ctx& ctx);
|
||||
void print(Ctx& ctx);
|
||||
// children
|
||||
const Code& getCode() const;
|
||||
Data& getData() const;
|
||||
};
|
||||
|
||||
inline
|
||||
Exec_drop_table::Code::Code(const BaseString& tableName) :
|
||||
m_tableName(tableName)
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_drop_table::Data::Data()
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_drop_table::Exec_drop_table(Exec_root* root) :
|
||||
Exec_ddl(root)
|
||||
{
|
||||
}
|
||||
|
||||
// children
|
||||
|
||||
inline const Exec_drop_table::Code&
|
||||
Exec_drop_table::getCode() const
|
||||
{
|
||||
const Code* code = static_cast<const Code*>(m_code);
|
||||
return *code;
|
||||
}
|
||||
|
||||
inline Exec_drop_table::Data&
|
||||
Exec_drop_table::getData() const
|
||||
{
|
||||
Data* data = static_cast<Data*>(m_data);
|
||||
return *data;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,79 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include "Code_expr.hpp"
|
||||
#include "Code_expr_row.hpp"
|
||||
|
||||
// Plan_expr
|
||||
|
||||
Plan_expr::~Plan_expr()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
Plan_expr::isEqual(const Plan_expr* expr) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
Plan_expr::isAnyEqual(const Plan_expr_row* row) const
|
||||
{
|
||||
ctx_assert(row != 0);
|
||||
const unsigned size = row->getSize();
|
||||
for (unsigned i = 1; i <= size; i++) {
|
||||
if (isEqual(row->getExpr(i)))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
Plan_expr::isGroupBy(const Plan_expr_row* row) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Exec_expr
|
||||
|
||||
Exec_expr::Code::~Code()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_expr::Data::~Data()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_expr::~Exec_expr()
|
||||
{
|
||||
}
|
||||
|
||||
SqlField&
|
||||
Exec_expr::Data::groupField(const SqlType& sqlType, unsigned i, bool initFlag)
|
||||
{
|
||||
if (m_groupField.size() == 0) {
|
||||
m_groupField.resize(1);
|
||||
}
|
||||
if (initFlag) {
|
||||
//unsigned i2 = m_groupField.size();
|
||||
//ctx_assert(i == i2);
|
||||
const SqlSpec sqlSpec(sqlType, SqlSpec::Physical);
|
||||
const SqlField sqlField(sqlSpec);
|
||||
m_groupField.push_back(sqlField);
|
||||
}
|
||||
ctx_assert(i != 0 && i < m_groupField.size());
|
||||
return m_groupField[i];
|
||||
}
|
|
@ -1,219 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef ODBC_CODEGEN_Code_expr_hpp
|
||||
#define ODBC_CODEGEN_Code_expr_hpp
|
||||
|
||||
#include <common/common.hpp>
|
||||
#include <common/DataField.hpp>
|
||||
#include "Code_base.hpp"
|
||||
|
||||
class Ctx;
|
||||
class Plan_expr_row;
|
||||
class Exec_expr;
|
||||
|
||||
/**
|
||||
* @class Plan_expr
|
||||
* @brief Base class for expressions in PlanTree
|
||||
*/
|
||||
class Plan_expr : public Plan_base {
|
||||
public:
|
||||
// type is convenient since RTTI cannot be used
|
||||
enum Type {
|
||||
TypeUndefined = 0,
|
||||
TypeColumn,
|
||||
TypeConst,
|
||||
TypeConv,
|
||||
TypeFunc,
|
||||
TypeOp,
|
||||
TypeParam,
|
||||
TypeValue
|
||||
};
|
||||
Plan_expr(Plan_root* root, Type type);
|
||||
virtual ~Plan_expr() = 0;
|
||||
Type type() const;
|
||||
const SqlType& sqlType() const; // data type set by analyze
|
||||
const TableSet& tableSet() const;
|
||||
const BaseString& getAlias() const;
|
||||
bool isAggr() const;
|
||||
bool isBound() const;
|
||||
bool isAnyEqual(const Plan_expr_row* row) const;
|
||||
virtual bool isEqual(const Plan_expr* expr) const;
|
||||
virtual bool isGroupBy(const Plan_expr_row* row) const;
|
||||
protected:
|
||||
friend class Plan_expr_row;
|
||||
friend class Plan_expr_op;
|
||||
friend class Plan_expr_func;
|
||||
friend class Plan_comp_op;
|
||||
const Type m_type;
|
||||
SqlType m_sqlType; // subclass must set
|
||||
BaseString m_alias; // for row expression alias
|
||||
TableSet m_tableSet; // depends on these tables
|
||||
bool m_isAggr; // contains an aggregate expression
|
||||
bool m_isBound; // only constants and aggregates
|
||||
Exec_expr* m_exec; // XXX wrong move
|
||||
};
|
||||
|
||||
inline
|
||||
Plan_expr::Plan_expr(Plan_root* root, Type type) :
|
||||
Plan_base(root),
|
||||
m_type(type),
|
||||
m_isAggr(false),
|
||||
m_isBound(false),
|
||||
m_exec(0)
|
||||
{
|
||||
}
|
||||
|
||||
inline Plan_expr::Type
|
||||
Plan_expr::type() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
inline const SqlType&
|
||||
Plan_expr::sqlType() const
|
||||
{
|
||||
ctx_assert(m_sqlType.type() != SqlType::Undef);
|
||||
return m_sqlType;
|
||||
}
|
||||
|
||||
inline const Plan_base::TableSet&
|
||||
Plan_expr::tableSet() const
|
||||
{
|
||||
return m_tableSet;
|
||||
}
|
||||
|
||||
inline const BaseString&
|
||||
Plan_expr::getAlias() const
|
||||
{
|
||||
return m_alias;
|
||||
}
|
||||
|
||||
inline bool
|
||||
Plan_expr::isAggr() const
|
||||
{
|
||||
return m_isAggr;
|
||||
}
|
||||
|
||||
inline bool
|
||||
Plan_expr::isBound() const
|
||||
{
|
||||
return m_isBound;
|
||||
}
|
||||
|
||||
/**
|
||||
* @class Exec_expr
|
||||
* @brief Base class for expressions in ExecTree
|
||||
*/
|
||||
class Exec_expr : public Exec_base {
|
||||
public:
|
||||
/**
|
||||
* Exec_expr::Code includes reference to SqlSpec which
|
||||
* specifies data type and access method.
|
||||
*/
|
||||
class Code : public Exec_base::Code {
|
||||
public:
|
||||
Code(const SqlSpec& sqlSpec);
|
||||
virtual ~Code() = 0;
|
||||
const SqlSpec& sqlSpec() const;
|
||||
protected:
|
||||
friend class Exec_expr;
|
||||
const SqlSpec& m_sqlSpec; // subclass must contain
|
||||
};
|
||||
/**
|
||||
* Exec_expr::Data includes reference to SqlField which
|
||||
* contains specification and data address.
|
||||
*/
|
||||
class Data : public Exec_base::Data {
|
||||
public:
|
||||
Data(const SqlField& sqlField);
|
||||
virtual ~Data() = 0;
|
||||
const SqlField& sqlField() const;
|
||||
const SqlField& groupField(unsigned i) const;
|
||||
protected:
|
||||
friend class Exec_expr;
|
||||
const SqlField& m_sqlField; // subclass must contain
|
||||
// group-by data
|
||||
typedef std::vector<SqlField> GroupField;
|
||||
GroupField m_groupField;
|
||||
SqlField& groupField(const SqlType& sqlType, unsigned i, bool initFlag);
|
||||
};
|
||||
Exec_expr(Exec_root* root);
|
||||
virtual ~Exec_expr() = 0;
|
||||
/**
|
||||
* Evaluate the expression. Must be implemented by all
|
||||
* subclasses. Check ctx.ok() for errors.
|
||||
*/
|
||||
virtual void evaluate(Ctx& ctx, Ctl& ctl) = 0;
|
||||
// children
|
||||
const Code& getCode() const;
|
||||
Data& getData() const;
|
||||
};
|
||||
|
||||
inline
|
||||
Exec_expr::Code::Code(const SqlSpec& sqlSpec) :
|
||||
m_sqlSpec(sqlSpec)
|
||||
{
|
||||
}
|
||||
|
||||
inline const SqlSpec&
|
||||
Exec_expr::Code::sqlSpec() const {
|
||||
return m_sqlSpec;
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_expr::Data::Data(const SqlField& sqlField) :
|
||||
m_sqlField(sqlField)
|
||||
{
|
||||
}
|
||||
|
||||
inline const SqlField&
|
||||
Exec_expr::Data::sqlField() const
|
||||
{
|
||||
return m_sqlField;
|
||||
}
|
||||
|
||||
inline const SqlField&
|
||||
Exec_expr::Data::groupField(unsigned i) const
|
||||
{
|
||||
ctx_assert(i != 0 && i < m_groupField.size());
|
||||
return m_groupField[i];
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_expr::Exec_expr(Exec_root* root) :
|
||||
Exec_base(root)
|
||||
{
|
||||
}
|
||||
|
||||
// children
|
||||
|
||||
inline const Exec_expr::Code&
|
||||
Exec_expr::getCode() const
|
||||
{
|
||||
const Code* code = static_cast<const Code*>(m_code);
|
||||
return *code;
|
||||
}
|
||||
|
||||
inline Exec_expr::Data&
|
||||
Exec_expr::getData() const
|
||||
{
|
||||
Data* data = static_cast<Data*>(m_data);
|
||||
return *data;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -1,160 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include <NdbApi.hpp>
|
||||
#include <common/StmtArea.hpp>
|
||||
#include <dictionary/DictSchema.hpp>
|
||||
#include <dictionary/DictColumn.hpp>
|
||||
#include "Code_query.hpp"
|
||||
#include "Code_table.hpp"
|
||||
#include "Code_expr_column.hpp"
|
||||
#include "Code_root.hpp"
|
||||
|
||||
// Plan_expr_column
|
||||
|
||||
Plan_expr_column::~Plan_expr_column()
|
||||
{
|
||||
}
|
||||
|
||||
Plan_base*
|
||||
Plan_expr_column::analyze(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
m_exec = 0;
|
||||
analyzeColumn(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
Plan_expr::m_sqlType = Plan_column::m_sqlType;
|
||||
// depends on one table
|
||||
m_tableSet.insert(m_resTable);
|
||||
// not constant as set-value
|
||||
ctl.m_const = false;
|
||||
// set alias name
|
||||
m_alias = m_name;
|
||||
return this;
|
||||
}
|
||||
|
||||
Exec_base*
|
||||
Plan_expr_column::codegen(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
if (m_exec != 0)
|
||||
return m_exec;
|
||||
// connect column to query column
|
||||
const Exec_query* execQuery = ctl.m_execQuery;
|
||||
ctx_assert(execQuery != 0);
|
||||
const Exec_query::Code& codeQuery = execQuery->getCode();
|
||||
const SqlSpec sqlSpec(Plan_expr::m_sqlType, SqlSpec::Reference);
|
||||
// offset in final output row
|
||||
ctx_assert(m_resTable != 0 && m_resTable->m_resOff != 0 && m_resPos != 0);
|
||||
unsigned resOff = m_resTable->m_resOff + (m_resPos - 1);
|
||||
// create the code
|
||||
Exec_expr_column* exec = new Exec_expr_column(ctl.m_execRoot);
|
||||
ctl.m_execRoot->saveNode(exec);
|
||||
Exec_expr_column::Code& code = *new Exec_expr_column::Code(sqlSpec, resOff);
|
||||
exec->setCode(code);
|
||||
m_exec = exec;
|
||||
return exec;
|
||||
}
|
||||
|
||||
bool
|
||||
Plan_expr_column::resolveEq(Ctx& ctx, Plan_expr* expr)
|
||||
{
|
||||
ctx_assert(m_resTable != 0 && expr != 0);
|
||||
return m_resTable->resolveEq(ctx, this, expr);
|
||||
}
|
||||
|
||||
void
|
||||
Plan_expr_column::print(Ctx& ctx)
|
||||
{
|
||||
ctx.print(" [expr_column %s]", getPrintName());
|
||||
}
|
||||
|
||||
bool
|
||||
Plan_expr_column::isEqual(const Plan_expr* expr) const
|
||||
{
|
||||
ctx_assert(expr != 0);
|
||||
if (expr->type() != Plan_expr::TypeColumn)
|
||||
return false;
|
||||
const Plan_expr_column* expr2 = static_cast<const Plan_expr_column*>(expr);
|
||||
ctx_assert(m_resTable != 0 && expr2->m_resTable != 0);
|
||||
if (m_resTable != expr2->m_resTable)
|
||||
return false;
|
||||
ctx_assert(m_dictColumn != 0 && expr2->m_dictColumn != 0);
|
||||
if (m_dictColumn != expr2->m_dictColumn)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
Plan_expr_column::isGroupBy(const Plan_expr_row* row) const
|
||||
{
|
||||
if (isAnyEqual(row))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Exec_expr_column
|
||||
|
||||
Exec_expr_column::Code::~Code()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_expr_column::Data::~Data()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_expr_column::~Exec_expr_column()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Exec_expr_column::alloc(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
if (m_data != 0)
|
||||
return;
|
||||
const Code& code = getCode();
|
||||
// connect column to query column
|
||||
ctx_assert(ctl.m_query != 0);
|
||||
const SqlRow& sqlRow = ctl.m_query->getData().sqlRow();
|
||||
SqlField& sqlField = sqlRow.getEntry(code.m_resOff);
|
||||
// create the data
|
||||
Data& data = *new Data(sqlField);
|
||||
setData(data);
|
||||
}
|
||||
|
||||
void
|
||||
Exec_expr_column::evaluate(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
const Code& code = getCode();
|
||||
Data& data = getData();
|
||||
if (ctl.m_groupIndex != 0) {
|
||||
SqlField& out = data.groupField(code.sqlSpec().sqlType(), ctl.m_groupIndex, ctl.m_groupInit);
|
||||
data.sqlField().copy(ctx, out);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Exec_expr_column::close(Ctx& ctx)
|
||||
{
|
||||
Data& data = getData();
|
||||
data.m_groupField.clear();
|
||||
}
|
||||
|
||||
void
|
||||
Exec_expr_column::print(Ctx& ctx)
|
||||
{
|
||||
const Code& code = getCode();
|
||||
ctx.print(" [column %d]", code.m_resOff);
|
||||
}
|
|
@ -1,120 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef ODBC_CODEGEN_Code_expr_column_hpp
|
||||
#define ODBC_CODEGEN_Code_expr_column_hpp
|
||||
|
||||
#include <common/common.hpp>
|
||||
#include "Code_column.hpp"
|
||||
#include "Code_expr.hpp"
|
||||
|
||||
class DictColumn;
|
||||
class Plan_table;
|
||||
|
||||
/**
|
||||
* @class Plan_expr_column
|
||||
* @brief Column in query expression
|
||||
*/
|
||||
class Plan_expr_column : public Plan_expr, public Plan_column {
|
||||
public:
|
||||
Plan_expr_column(Plan_root* root, const BaseString& name);
|
||||
virtual ~Plan_expr_column();
|
||||
Plan_base* analyze(Ctx& ctx, Ctl& ctl);
|
||||
Exec_base* codegen(Ctx& ctx, Ctl& ctl);
|
||||
bool resolveEq(Ctx& ctx, Plan_expr* expr);
|
||||
void print(Ctx& ctx);
|
||||
bool isEqual(const Plan_expr* expr) const;
|
||||
bool isGroupBy(const Plan_expr_row* row) const;
|
||||
};
|
||||
|
||||
inline
|
||||
Plan_expr_column::Plan_expr_column(Plan_root* root, const BaseString& name) :
|
||||
Plan_expr(root, TypeColumn),
|
||||
Plan_column(Type_expr, name)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @class Exec_expr_column
|
||||
* @brief Column in query expression
|
||||
*/
|
||||
class Exec_expr_column : public Exec_expr {
|
||||
public:
|
||||
class Code : public Exec_expr::Code {
|
||||
public:
|
||||
Code(const SqlSpec& sqlSpec, unsigned resOff);
|
||||
virtual ~Code();
|
||||
protected:
|
||||
friend class Exec_expr_column;
|
||||
SqlSpec m_sqlSpec;
|
||||
unsigned m_resOff;
|
||||
};
|
||||
class Data : public Exec_expr::Data {
|
||||
public:
|
||||
Data(SqlField& sqlField);
|
||||
virtual ~Data();
|
||||
protected:
|
||||
friend class Exec_expr_column;
|
||||
// set reference to SqlField in query
|
||||
};
|
||||
Exec_expr_column(Exec_root* root);
|
||||
virtual ~Exec_expr_column();
|
||||
void alloc(Ctx& ctx, Ctl& ctl);
|
||||
void evaluate(Ctx& ctx, Ctl& ctl);
|
||||
void close(Ctx& ctx);
|
||||
void print(Ctx& ctx);
|
||||
// children
|
||||
const Code& getCode() const;
|
||||
Data& getData() const;
|
||||
};
|
||||
|
||||
inline
|
||||
Exec_expr_column::Code::Code(const SqlSpec& sqlSpec, unsigned resOff) :
|
||||
Exec_expr::Code(m_sqlSpec),
|
||||
m_sqlSpec(sqlSpec),
|
||||
m_resOff(resOff)
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_expr_column::Data::Data(SqlField& sqlField) :
|
||||
Exec_expr::Data(sqlField)
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_expr_column::Exec_expr_column(Exec_root* root) :
|
||||
Exec_expr(root)
|
||||
{
|
||||
}
|
||||
|
||||
// children
|
||||
|
||||
inline const Exec_expr_column::Code&
|
||||
Exec_expr_column::getCode() const
|
||||
{
|
||||
const Code* code = static_cast<const Code*>(m_code);
|
||||
return *code;
|
||||
}
|
||||
|
||||
inline Exec_expr_column::Data&
|
||||
Exec_expr_column::getData() const
|
||||
{
|
||||
Data* data = static_cast<Data*>(m_data);
|
||||
return *data;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,138 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include "Code_expr_const.hpp"
|
||||
#include "Code_root.hpp"
|
||||
|
||||
// Plan_expr_const
|
||||
|
||||
Plan_expr_const::~Plan_expr_const()
|
||||
{
|
||||
}
|
||||
|
||||
Plan_base*
|
||||
Plan_expr_const::analyze(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
m_exec = 0;
|
||||
// convert data type
|
||||
m_lexType.convert(ctx, m_sqlType, m_string.length());
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
// depends on no tables
|
||||
// set alias name
|
||||
m_alias = m_string;
|
||||
// node was not changed
|
||||
return this;
|
||||
}
|
||||
|
||||
Exec_base*
|
||||
Plan_expr_const::codegen(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
if (m_exec != 0)
|
||||
return m_exec;
|
||||
// convert data
|
||||
SqlSpec sqlSpec(m_sqlType, SqlSpec::Physical);
|
||||
SqlField sqlField(sqlSpec);
|
||||
LexSpec lexSpec(m_lexType);
|
||||
lexSpec.convert(ctx, m_string, sqlField);
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
// create code
|
||||
Exec_expr_const* exec = new Exec_expr_const(ctl.m_execRoot);
|
||||
ctl.m_execRoot->saveNode(exec);
|
||||
Exec_expr_const::Code& code = *new Exec_expr_const::Code(sqlField);
|
||||
exec->setCode(code);
|
||||
m_exec = exec;
|
||||
return exec;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_expr_const::print(Ctx& ctx)
|
||||
{
|
||||
ctx.print(" [const %s]", m_string.c_str());
|
||||
}
|
||||
|
||||
bool
|
||||
Plan_expr_const::isEqual(const Plan_expr* expr) const
|
||||
{
|
||||
ctx_assert(expr != 0);
|
||||
if (expr->type() != Plan_expr::TypeConst)
|
||||
return false;
|
||||
const Plan_expr_const* expr2 = static_cast<const Plan_expr_const*>(expr);
|
||||
if (strcmp(m_string.c_str(), expr2->m_string.c_str()) != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
Plan_expr_const::isGroupBy(const Plan_expr_row* row) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Exec_expr_const
|
||||
|
||||
Exec_expr_const::Code::~Code()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_expr_const::Data::~Data()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_expr_const::~Exec_expr_const()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Exec_expr_const::alloc(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
if (m_data != 0)
|
||||
return;
|
||||
// copy the value for const correctness reasons
|
||||
SqlField sqlField(getCode().m_sqlField);
|
||||
Data& data = *new Data(sqlField);
|
||||
setData(data);
|
||||
}
|
||||
|
||||
void
|
||||
Exec_expr_const::evaluate(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
const Code& code = getCode();
|
||||
Data& data = getData();
|
||||
if (ctl.m_groupIndex != 0) {
|
||||
SqlField& out = data.groupField(code.sqlSpec().sqlType(), ctl.m_groupIndex, ctl.m_groupInit);
|
||||
data.sqlField().copy(ctx, out);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Exec_expr_const::close(Ctx& ctx)
|
||||
{
|
||||
Data& data = getData();
|
||||
data.m_groupField.clear();
|
||||
}
|
||||
|
||||
void
|
||||
Exec_expr_const::print(Ctx& ctx)
|
||||
{
|
||||
const Code& code = getCode();
|
||||
ctx.print(" [");
|
||||
char buf[500];
|
||||
code.m_sqlField.print(buf, sizeof(buf));
|
||||
ctx.print("%s", buf);
|
||||
ctx.print("]");
|
||||
}
|
|
@ -1,120 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef ODBC_CODEGEN_Code_expr_const_hpp
|
||||
#define ODBC_CODEGEN_Code_expr_const_hpp
|
||||
|
||||
#include <common/common.hpp>
|
||||
#include <common/DataField.hpp>
|
||||
#include "Code_expr.hpp"
|
||||
|
||||
/**
|
||||
* @class Plan_expr_const
|
||||
* @brief Constant expression value in PlanTree
|
||||
*/
|
||||
class Plan_expr_const : public Plan_expr {
|
||||
public:
|
||||
Plan_expr_const(Plan_root* root, LexType lexType, const char* value);
|
||||
virtual ~Plan_expr_const();
|
||||
Plan_base* analyze(Ctx& ctx, Ctl& ctl);
|
||||
Exec_base* codegen(Ctx& ctx, Ctl& ctl);
|
||||
void print(Ctx& ctx);
|
||||
bool isEqual(const Plan_expr* expr) const;
|
||||
bool isGroupBy(const Plan_expr_row* row) const;
|
||||
protected:
|
||||
// lexical type and token set by the parser
|
||||
LexType m_lexType;
|
||||
BaseString m_string;
|
||||
};
|
||||
|
||||
inline
|
||||
Plan_expr_const::Plan_expr_const(Plan_root* root, LexType lexType, const char* value) :
|
||||
Plan_expr(root, TypeConst),
|
||||
m_lexType(lexType),
|
||||
m_string(value)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @class Exec_expr_const
|
||||
* @brief Constant expression value in ExecTree
|
||||
*/
|
||||
class Exec_expr_const : public Exec_expr {
|
||||
public:
|
||||
class Code : public Exec_expr::Code {
|
||||
public:
|
||||
Code(const SqlField& sqlField);
|
||||
virtual ~Code();
|
||||
protected:
|
||||
friend class Exec_expr_const;
|
||||
const SqlField m_sqlField;
|
||||
};
|
||||
class Data : public Exec_expr::Data {
|
||||
public:
|
||||
Data(SqlField& sqlField);
|
||||
virtual ~Data();
|
||||
protected:
|
||||
friend class Exec_expr_const;
|
||||
SqlField m_sqlField;
|
||||
};
|
||||
Exec_expr_const(Exec_root* root);
|
||||
virtual ~Exec_expr_const();
|
||||
void alloc(Ctx& ctx, Ctl& ctl);
|
||||
void evaluate(Ctx& ctx, Ctl& ctl);
|
||||
void close(Ctx& ctx);
|
||||
void print(Ctx& ctx);
|
||||
// children
|
||||
const Code& getCode() const;
|
||||
Data& getData() const;
|
||||
};
|
||||
|
||||
inline
|
||||
Exec_expr_const::Code::Code(const SqlField& sqlField) :
|
||||
Exec_expr::Code(m_sqlField.sqlSpec()),
|
||||
m_sqlField(sqlField)
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_expr_const::Data::Data(SqlField& sqlField) :
|
||||
Exec_expr::Data(m_sqlField),
|
||||
m_sqlField(sqlField)
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_expr_const::Exec_expr_const(Exec_root* root) :
|
||||
Exec_expr(root)
|
||||
{
|
||||
}
|
||||
|
||||
// children
|
||||
|
||||
inline const Exec_expr_const::Code&
|
||||
Exec_expr_const::getCode() const
|
||||
{
|
||||
const Code* code = static_cast<const Code*>(m_code);
|
||||
return *code;
|
||||
}
|
||||
|
||||
inline Exec_expr_const::Data&
|
||||
Exec_expr_const::getData() const
|
||||
{
|
||||
Data* data = static_cast<Data*>(m_data);
|
||||
return *data;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,273 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include "Code_expr.hpp"
|
||||
#include "Code_expr_conv.hpp"
|
||||
#include "Code_root.hpp"
|
||||
|
||||
// Plan_expr_conv
|
||||
|
||||
Plan_expr_conv::~Plan_expr_conv()
|
||||
{
|
||||
}
|
||||
|
||||
Plan_base*
|
||||
Plan_expr_conv::analyze(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
m_exec = 0;
|
||||
const SqlType& t1 = sqlType();
|
||||
ctx_assert(m_expr != 0);
|
||||
m_expr->analyze(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
const SqlType& t2 = m_expr->sqlType();
|
||||
if (t2.type() == SqlType::Unbound) {
|
||||
return m_expr;
|
||||
}
|
||||
if (t1.equal(t2)) {
|
||||
return m_expr;
|
||||
}
|
||||
// XXX move to runtime or make table-driven
|
||||
bool ok = false;
|
||||
if (t2.type() == SqlType::Null) {
|
||||
ok = true;
|
||||
} else if (t1.type() == SqlType::Char) {
|
||||
if (t2.type() == SqlType::Char) {
|
||||
ok = true;
|
||||
} else if (t2.type() == SqlType::Varchar) {
|
||||
ok = true;
|
||||
} else if (t2.type() == SqlType::Binary) {
|
||||
ok = true;
|
||||
} else if (t2.type() == SqlType::Varbinary) {
|
||||
ok = true;
|
||||
}
|
||||
} else if (t1.type() == SqlType::Varchar) {
|
||||
if (t2.type() == SqlType::Char) {
|
||||
ok = true;
|
||||
} else if (t2.type() == SqlType::Varchar) {
|
||||
ok = true;
|
||||
} else if (t2.type() == SqlType::Binary) {
|
||||
ok = true;
|
||||
} else if (t2.type() == SqlType::Varbinary) {
|
||||
ok = true;
|
||||
}
|
||||
} else if (t1.type() == SqlType::Binary) {
|
||||
if (t2.type() == SqlType::Char) {
|
||||
ok = true;
|
||||
} else if (t2.type() == SqlType::Varchar) {
|
||||
ok = true;
|
||||
} else if (t2.type() == SqlType::Binary) {
|
||||
ok = true;
|
||||
} else if (t2.type() == SqlType::Varbinary) {
|
||||
ok = true;
|
||||
}
|
||||
} else if (t1.type() == SqlType::Varbinary) {
|
||||
if (t2.type() == SqlType::Char) {
|
||||
ok = true;
|
||||
} else if (t2.type() == SqlType::Varchar) {
|
||||
ok = true;
|
||||
} else if (t2.type() == SqlType::Binary) {
|
||||
ok = true;
|
||||
} else if (t2.type() == SqlType::Varbinary) {
|
||||
ok = true;
|
||||
}
|
||||
} else if (t1.type() == SqlType::Smallint) {
|
||||
if (t2.type() == SqlType::Smallint) {
|
||||
ok = true;
|
||||
} else if (t2.type() == SqlType::Integer) {
|
||||
ok = true;
|
||||
} else if (t2.type() == SqlType::Bigint) {
|
||||
ok = true;
|
||||
} else if (t2.type() == SqlType::Real) {
|
||||
ok = true;
|
||||
} else if (t2.type() == SqlType::Double) {
|
||||
ok = true;
|
||||
}
|
||||
} else if (t1.type() == SqlType::Integer) {
|
||||
if (t2.type() == SqlType::Smallint) {
|
||||
ok = true;
|
||||
} else if (t2.type() == SqlType::Integer) {
|
||||
ok = true;
|
||||
} else if (t2.type() == SqlType::Bigint) {
|
||||
ok = true;
|
||||
} else if (t2.type() == SqlType::Real) {
|
||||
ok = true;
|
||||
} else if (t2.type() == SqlType::Double) {
|
||||
ok = true;
|
||||
}
|
||||
} else if (t1.type() == SqlType::Bigint) {
|
||||
if (t2.type() == SqlType::Smallint) {
|
||||
ok = true;
|
||||
} else if (t2.type() == SqlType::Integer) {
|
||||
ok = true;
|
||||
} else if (t2.type() == SqlType::Bigint) {
|
||||
ok = true;
|
||||
} else if (t2.type() == SqlType::Real) {
|
||||
ok = true;
|
||||
} else if (t2.type() == SqlType::Double) {
|
||||
ok = true;
|
||||
}
|
||||
} else if (t1.type() == SqlType::Real) {
|
||||
if (t2.type() == SqlType::Smallint) {
|
||||
ok = true;
|
||||
} else if (t2.type() == SqlType::Integer) {
|
||||
ok = true;
|
||||
} else if (t2.type() == SqlType::Bigint) {
|
||||
ok = true;
|
||||
} else if (t2.type() == SqlType::Real) {
|
||||
ok = true;
|
||||
} else if (t2.type() == SqlType::Double) {
|
||||
ok = true;
|
||||
}
|
||||
} else if (t1.type() == SqlType::Double) {
|
||||
if (t2.type() == SqlType::Smallint) {
|
||||
ok = true;
|
||||
} else if (t2.type() == SqlType::Integer) {
|
||||
ok = true;
|
||||
} else if (t2.type() == SqlType::Bigint) {
|
||||
ok = true;
|
||||
} else if (t2.type() == SqlType::Real) {
|
||||
ok = true;
|
||||
} else if (t2.type() == SqlType::Double) {
|
||||
ok = true;
|
||||
}
|
||||
} else if (t1.type() == SqlType::Datetime) {
|
||||
if (t2.type() == SqlType::Datetime) {
|
||||
ok = true;
|
||||
}
|
||||
}
|
||||
if (! ok) {
|
||||
char b1[40], b2[40];
|
||||
t1.print(b1, sizeof(b1));
|
||||
t2.print(b2, sizeof(b2));
|
||||
ctx.pushStatus(Error::Gen, "cannot convert %s to %s", b2, b1);
|
||||
return 0;
|
||||
}
|
||||
// depend on same tables
|
||||
const TableSet& ts = m_expr->tableSet();
|
||||
m_tableSet.insert(ts.begin(), ts.end());
|
||||
// set alias
|
||||
m_alias = m_expr->getAlias();
|
||||
return this;
|
||||
}
|
||||
|
||||
Exec_base*
|
||||
Plan_expr_conv::codegen(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
if (m_exec != 0)
|
||||
return m_exec;
|
||||
Exec_expr_conv* exec = new Exec_expr_conv(ctl.m_execRoot);
|
||||
ctl.m_execRoot->saveNode(exec);
|
||||
// create code for subexpression
|
||||
ctx_assert(m_expr != 0);
|
||||
Exec_expr* execExpr = static_cast<Exec_expr*>(m_expr->codegen(ctx, ctl));
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
exec->setExpr(execExpr);
|
||||
// create the code
|
||||
SqlSpec sqlSpec(sqlType(), SqlSpec::Physical);
|
||||
Exec_expr_conv::Code& code = *new Exec_expr_conv::Code(sqlSpec);
|
||||
exec->setCode(code);
|
||||
m_exec = exec;
|
||||
return exec;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_expr_conv::print(Ctx& ctx)
|
||||
{
|
||||
ctx.print(" [expr_conv ");
|
||||
char buf[100];
|
||||
m_sqlType.print(buf, sizeof(buf));
|
||||
ctx.print("%s", buf);
|
||||
Plan_base* a[] = { m_expr };
|
||||
printList(ctx, a, 1);
|
||||
ctx.print("]");
|
||||
}
|
||||
|
||||
bool
|
||||
Plan_expr_conv::isEqual(const Plan_expr* expr) const
|
||||
{
|
||||
ctx_assert(expr != 0);
|
||||
if (expr->type() != Plan_expr::TypeConv)
|
||||
return false;
|
||||
const Plan_expr_conv* expr2 = static_cast<const Plan_expr_conv*>(expr);
|
||||
if (! m_sqlType.equal(expr2->m_sqlType))
|
||||
return false;
|
||||
ctx_assert(m_expr != 0 && expr2->m_expr != 0);
|
||||
if (! m_expr->isEqual(expr2->m_expr))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
Plan_expr_conv::isGroupBy(const Plan_expr_row* row) const
|
||||
{
|
||||
if (isAnyEqual(row))
|
||||
return true;
|
||||
ctx_assert(m_expr != 0);
|
||||
if (m_expr->isGroupBy(row))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Code_expr_conv
|
||||
|
||||
Exec_expr_conv::Code::~Code()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_expr_conv::Data::~Data()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_expr_conv::~Exec_expr_conv()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Exec_expr_conv::alloc(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
if (m_data != 0)
|
||||
return;
|
||||
const Code& code = getCode();
|
||||
// allocate subexpression
|
||||
ctx_assert(m_expr != 0);
|
||||
m_expr->alloc(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return;
|
||||
SqlField sqlField(code.m_sqlSpec);
|
||||
Data& data = *new Data(sqlField);
|
||||
setData(data);
|
||||
}
|
||||
|
||||
void
|
||||
Exec_expr_conv::close(Ctx& ctx)
|
||||
{
|
||||
ctx_assert(m_expr != 0);
|
||||
m_expr->close(ctx);
|
||||
Data& data = getData();
|
||||
data.m_groupField.clear();
|
||||
}
|
||||
|
||||
void
|
||||
Exec_expr_conv::print(Ctx& ctx)
|
||||
{
|
||||
const Code& code = getCode();
|
||||
ctx.print(" [expr_conv");
|
||||
Exec_base* a[] = { m_expr };
|
||||
printList(ctx, a, sizeof(a)/sizeof(a[0]));
|
||||
ctx.print("]");
|
||||
}
|
|
@ -1,141 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef ODBC_CODEGEN_Code_expr_conv_hpp
|
||||
#define ODBC_CODEGEN_Code_expr_conv_hpp
|
||||
|
||||
#include <common/common.hpp>
|
||||
#include <common/DataField.hpp>
|
||||
#include "Code_expr.hpp"
|
||||
|
||||
/**
|
||||
* @class Plan_expr_conv
|
||||
* @brief Data type conversion in PlanTree
|
||||
*
|
||||
* Inserted to convert value to another compatible type.
|
||||
*/
|
||||
class Plan_expr_conv : public Plan_expr {
|
||||
public:
|
||||
Plan_expr_conv(Plan_root* root, const SqlType& sqlType);
|
||||
virtual ~Plan_expr_conv();
|
||||
Plan_base* analyze(Ctx& ctx, Ctl& ctl);
|
||||
Exec_base* codegen(Ctx& ctx, Ctl& ctl);
|
||||
void print(Ctx& ctx);
|
||||
bool isEqual(const Plan_expr* expr) const;
|
||||
bool isGroupBy(const Plan_expr_row* row) const;
|
||||
// children
|
||||
void setExpr(Plan_expr* expr);
|
||||
protected:
|
||||
Plan_expr* m_expr;
|
||||
};
|
||||
|
||||
inline
|
||||
Plan_expr_conv::Plan_expr_conv(Plan_root* root, const SqlType& sqlType) :
|
||||
Plan_expr(root, TypeConv),
|
||||
m_expr(0)
|
||||
{
|
||||
ctx_assert(sqlType.type() != SqlType::Undef);
|
||||
m_sqlType = sqlType;
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_expr_conv::setExpr(Plan_expr* expr)
|
||||
{
|
||||
ctx_assert(expr != 0);
|
||||
m_expr = expr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @class Exec_expr_conv
|
||||
* @brief Data type conversion in ExecTree
|
||||
*/
|
||||
class Exec_expr_conv : public Exec_expr {
|
||||
public:
|
||||
class Code : public Exec_expr::Code {
|
||||
public:
|
||||
Code(const SqlSpec& spec);
|
||||
virtual ~Code();
|
||||
protected:
|
||||
friend class Exec_expr_conv;
|
||||
const SqlSpec m_sqlSpec;
|
||||
};
|
||||
class Data : public Exec_expr::Data {
|
||||
public:
|
||||
Data(const SqlField& sqlField);
|
||||
virtual ~Data();
|
||||
protected:
|
||||
friend class Exec_expr_conv;
|
||||
SqlField m_sqlField;
|
||||
};
|
||||
Exec_expr_conv(Exec_root* root);
|
||||
virtual ~Exec_expr_conv();
|
||||
void alloc(Ctx& ctx, Ctl& ctl);
|
||||
void evaluate(Ctx& ctx, Ctl& ctl);
|
||||
void close(Ctx& ctx);
|
||||
void print(Ctx& ctx);
|
||||
// children
|
||||
const Code& getCode() const;
|
||||
Data& getData() const;
|
||||
void setExpr(Exec_expr* expr);
|
||||
protected:
|
||||
Exec_expr* m_expr;
|
||||
};
|
||||
|
||||
inline
|
||||
Exec_expr_conv::Code::Code(const SqlSpec& sqlSpec) :
|
||||
Exec_expr::Code(m_sqlSpec),
|
||||
m_sqlSpec(sqlSpec)
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_expr_conv::Data::Data(const SqlField& sqlField) :
|
||||
Exec_expr::Data(m_sqlField),
|
||||
m_sqlField(sqlField)
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_expr_conv::Exec_expr_conv(Exec_root* root) :
|
||||
Exec_expr(root),
|
||||
m_expr(0)
|
||||
{
|
||||
}
|
||||
|
||||
// children
|
||||
|
||||
inline const Exec_expr_conv::Code&
|
||||
Exec_expr_conv::getCode() const
|
||||
{
|
||||
const Code* code = static_cast<const Code*>(m_code);
|
||||
return *code;
|
||||
}
|
||||
|
||||
inline Exec_expr_conv::Data&
|
||||
Exec_expr_conv::getData() const
|
||||
{
|
||||
Data* data = static_cast<Data*>(m_data);
|
||||
return *data;
|
||||
}
|
||||
|
||||
inline void
|
||||
Exec_expr_conv::setExpr(Exec_expr* expr)
|
||||
{
|
||||
ctx_assert(m_expr == 0 && expr != 0);
|
||||
m_expr = expr;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,401 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include "Code_expr.hpp"
|
||||
#include "Code_expr_func.hpp"
|
||||
#include "Code_expr_conv.hpp"
|
||||
#include "Code_root.hpp"
|
||||
#include "PortDefs.h"
|
||||
|
||||
|
||||
// Expr_func
|
||||
|
||||
static const struct { const char* alias; const char* name; }
|
||||
expr_func_alias[] = {
|
||||
{ "SUBSTRING", "SUBSTR" },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static const Expr_func
|
||||
expr_func[] = {
|
||||
Expr_func(Expr_func::Substr, "SUBSTR", false ),
|
||||
Expr_func(Expr_func::Left, "LEFT", false ),
|
||||
Expr_func(Expr_func::Right, "RIGHT", false ),
|
||||
Expr_func(Expr_func::Count, "COUNT", true ),
|
||||
Expr_func(Expr_func::Max, "MAX", true ),
|
||||
Expr_func(Expr_func::Min, "MIN", true ),
|
||||
Expr_func(Expr_func::Sum, "SUM", true ),
|
||||
Expr_func(Expr_func::Avg, "AVG", true ),
|
||||
Expr_func(Expr_func::Rownum, "ROWNUM", false ),
|
||||
Expr_func(Expr_func::Sysdate, "SYSDATE", false ),
|
||||
Expr_func(Expr_func::Undef, 0, false )
|
||||
};
|
||||
|
||||
const Expr_func&
|
||||
Expr_func::find(const char* name)
|
||||
{
|
||||
for (unsigned i = 0; expr_func_alias[i].alias != 0; i++) {
|
||||
if (strcasecmp(expr_func_alias[i].alias, name) == 0) {
|
||||
name = expr_func_alias[i].name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
const Expr_func* p;
|
||||
for (p = expr_func; p->m_name != 0; p++) {
|
||||
if (strcasecmp(p->m_name, name) == 0)
|
||||
break;
|
||||
}
|
||||
return *p;
|
||||
}
|
||||
|
||||
// Plan_expr_func
|
||||
|
||||
Plan_expr_func::~Plan_expr_func()
|
||||
{
|
||||
delete[] m_conv;
|
||||
m_conv = 0;
|
||||
}
|
||||
|
||||
Plan_base*
|
||||
Plan_expr_func::analyze(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
m_exec = 0;
|
||||
ctx_assert(m_narg == 0 || m_args != 0);
|
||||
// aggregate check
|
||||
if (m_func.m_aggr) {
|
||||
if (! ctl.m_aggrok) {
|
||||
ctx.pushStatus(Error::Gen, "%s: invalid use of aggregate function", m_func.m_name);
|
||||
return 0;
|
||||
}
|
||||
if (ctl.m_aggrin) {
|
||||
// XXX actually possible with group-by but too hard
|
||||
ctx.pushStatus(Error::Gen, "%s: nested aggregate function", m_func.m_name);
|
||||
return 0;
|
||||
}
|
||||
ctl.m_aggrin = true;
|
||||
m_isAggr = true;
|
||||
m_isBound = true;
|
||||
}
|
||||
// analyze argument expressions
|
||||
if (m_func.m_code != Expr_func::Rownum)
|
||||
m_isBound = true;
|
||||
for (unsigned i = 1; i <= m_narg; i++) {
|
||||
Plan_expr* expr = m_args->getExpr(i);
|
||||
expr = static_cast<Plan_expr*>(expr->analyze(ctx, ctl));
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
ctx_assert(expr != 0);
|
||||
if (expr->m_isAggr)
|
||||
m_isAggr = true;
|
||||
if (! m_func.m_aggr && ! expr->m_isBound)
|
||||
m_isBound = false;
|
||||
}
|
||||
if (m_func.m_aggr)
|
||||
ctl.m_aggrin = false;
|
||||
// find result type and conversion types
|
||||
SqlType res;
|
||||
const Expr_func::Code fc = m_func.m_code;
|
||||
const char* const invalidArgCount = "%s: argument count %u is invalid";
|
||||
const char* const invalidArgType = "%s: argument %u has invalid type";
|
||||
if (fc == Expr_func::Substr || fc == Expr_func::Left || fc == Expr_func::Right) {
|
||||
if ((m_narg != (unsigned)2) && (m_narg != (unsigned)(fc == Expr_func::Substr ? 3 : 2))) {
|
||||
ctx.pushStatus(Error::Gen, invalidArgCount, m_func.m_name, m_narg);
|
||||
return 0;
|
||||
}
|
||||
const SqlType& t1 = m_args->getExpr(1)->sqlType();
|
||||
switch (t1.type()) {
|
||||
case SqlType::Char:
|
||||
{
|
||||
// XXX convert to varchar for now to get length right
|
||||
SqlType tx(SqlType::Varchar, t1.length());
|
||||
res = m_conv[1] = tx;
|
||||
}
|
||||
break;
|
||||
case SqlType::Varchar:
|
||||
case SqlType::Unbound:
|
||||
res = m_conv[1] = t1;
|
||||
break;
|
||||
default:
|
||||
ctx.pushStatus(Error::Gen, invalidArgType, m_func.m_name, 1);
|
||||
return 0;
|
||||
}
|
||||
for (unsigned i = 2; i <= m_narg; i++) {
|
||||
const SqlType& t2 = m_args->getExpr(i)->sqlType();
|
||||
switch (t2.type()) {
|
||||
case SqlType::Smallint:
|
||||
case SqlType::Integer:
|
||||
case SqlType::Bigint:
|
||||
case SqlType::Unbound:
|
||||
m_conv[i] = t2;
|
||||
break;
|
||||
default:
|
||||
ctx.pushStatus(Error::Gen, invalidArgType, m_func.m_name, i);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else if (fc == Expr_func::Count) {
|
||||
ctx_assert(m_args != 0);
|
||||
if (m_args->getAsterisk()) {
|
||||
ctx_assert(m_narg == 0);
|
||||
} else {
|
||||
if (m_narg != 1) {
|
||||
ctx.pushStatus(Error::Gen, invalidArgCount, m_func.m_name, m_narg);
|
||||
return 0;
|
||||
}
|
||||
m_conv[1] = m_args->getExpr(1)->sqlType();
|
||||
}
|
||||
res.setType(ctx, SqlType::Bigint);
|
||||
} else if (fc == Expr_func::Min || fc == Expr_func::Max) {
|
||||
if (m_narg != 1) {
|
||||
ctx.pushStatus(Error::Gen, invalidArgCount, m_func.m_name, m_narg);
|
||||
return 0;
|
||||
}
|
||||
const SqlType& t1 = m_args->getExpr(1)->sqlType();
|
||||
res = m_conv[1] = t1;
|
||||
} else if (fc == Expr_func::Sum) {
|
||||
if (m_narg != 1) {
|
||||
ctx.pushStatus(Error::Gen, invalidArgCount, m_func.m_name, m_narg);
|
||||
return 0;
|
||||
}
|
||||
const SqlType& t1 = m_args->getExpr(1)->sqlType();
|
||||
switch (t1.type()) {
|
||||
case SqlType::Smallint:
|
||||
case SqlType::Integer:
|
||||
case SqlType::Bigint:
|
||||
res.setType(ctx, SqlType::Bigint);
|
||||
m_conv[1] = res;
|
||||
break;
|
||||
case SqlType::Real:
|
||||
case SqlType::Double:
|
||||
res.setType(ctx, SqlType::Double);
|
||||
m_conv[1] = res;
|
||||
break;
|
||||
case SqlType::Unbound:
|
||||
res = m_conv[1] = t1;
|
||||
break;
|
||||
default:
|
||||
ctx.pushStatus(Error::Gen, invalidArgType, m_func.m_name, 1);
|
||||
return 0;
|
||||
}
|
||||
} else if (fc == Expr_func::Avg) {
|
||||
if (m_narg != 1) {
|
||||
ctx.pushStatus(Error::Gen, invalidArgCount, m_func.m_name, m_narg);
|
||||
return 0;
|
||||
}
|
||||
const SqlType& t1 = m_args->getExpr(1)->sqlType();
|
||||
switch (t1.type()) {
|
||||
case SqlType::Smallint:
|
||||
case SqlType::Integer:
|
||||
case SqlType::Bigint:
|
||||
case SqlType::Real:
|
||||
case SqlType::Double:
|
||||
res.setType(ctx, SqlType::Double);
|
||||
m_conv[1] = res;
|
||||
break;
|
||||
case SqlType::Unbound:
|
||||
res = m_conv[1] = t1;
|
||||
break;
|
||||
default:
|
||||
ctx.pushStatus(Error::Gen, invalidArgType, m_func.m_name, 1);
|
||||
return 0;
|
||||
}
|
||||
} else if (fc == Expr_func::Rownum) {
|
||||
ctx_assert(m_narg == 0 && m_args == 0);
|
||||
res.setType(ctx, SqlType::Bigint);
|
||||
} else if (fc == Expr_func::Sysdate) {
|
||||
ctx_assert(m_narg == 0 && m_args == 0);
|
||||
res.setType(ctx, SqlType::Datetime);
|
||||
} else {
|
||||
ctx_assert(false);
|
||||
}
|
||||
// insert required conversions
|
||||
for (unsigned i = 1; i <= m_narg; i++) {
|
||||
if (m_conv[i].type() == SqlType::Unbound) {
|
||||
// parameter type not yet bound
|
||||
continue;
|
||||
}
|
||||
Plan_expr_conv* exprConv = new Plan_expr_conv(m_root, m_conv[i]);
|
||||
m_root->saveNode(exprConv);
|
||||
exprConv->setExpr(m_args->getExpr(i));
|
||||
Plan_expr* expr = static_cast<Plan_expr*>(exprConv->analyze(ctx, ctl));
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
m_args->setExpr(i, expr);
|
||||
}
|
||||
// set result type
|
||||
m_sqlType = res;
|
||||
// set table dependencies
|
||||
for (unsigned i = 1; i <= m_narg; i++) {
|
||||
const TableSet& ts = m_args->getExpr(i)->tableSet();
|
||||
m_tableSet.insert(ts.begin(), ts.end());
|
||||
}
|
||||
// set alias name
|
||||
m_alias.assign(m_func.m_name);
|
||||
if (m_narg == 0) {
|
||||
if (fc == Expr_func::Count)
|
||||
m_alias.append("(*)");
|
||||
} else {
|
||||
m_alias.append("(");
|
||||
for (unsigned i = 1; i <= m_narg; i++) {
|
||||
if (i > 1)
|
||||
m_alias.append(",");
|
||||
m_alias.append(m_args->getExpr(i)->getAlias());
|
||||
}
|
||||
m_alias.append(")");
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
Exec_base*
|
||||
Plan_expr_func::codegen(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
if (m_exec != 0)
|
||||
return m_exec;
|
||||
Exec_expr_func* exec = new Exec_expr_func(ctl.m_execRoot);
|
||||
ctl.m_execRoot->saveNode(exec);
|
||||
SqlSpec sqlSpec(sqlType(), SqlSpec::Physical);
|
||||
Exec_expr_func::Code& code = *new Exec_expr_func::Code(m_func, sqlSpec);
|
||||
exec->setCode(code);
|
||||
code.m_narg = m_narg;
|
||||
code.m_args = new Exec_expr* [1 + m_narg];
|
||||
for (unsigned i = 0; i <= m_narg; i++)
|
||||
code.m_args[i] = 0;
|
||||
// create code for arguments
|
||||
for (unsigned i = 1; i <= m_narg; i++) {
|
||||
Plan_expr* expr = m_args->getExpr(i);
|
||||
ctx_assert(expr != 0);
|
||||
Exec_expr* execExpr = static_cast<Exec_expr*>(expr->codegen(ctx, ctl));
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
ctx_assert(execExpr != 0);
|
||||
code.m_args[i] = execExpr;
|
||||
}
|
||||
m_exec = exec;
|
||||
return exec;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_expr_func::print(Ctx& ctx)
|
||||
{
|
||||
ctx.print(" [%s", m_func.m_name);
|
||||
Plan_base* a[] = { m_args };
|
||||
printList(ctx, a, sizeof(a)/sizeof(a[1]));
|
||||
ctx.print("]");
|
||||
}
|
||||
|
||||
bool
|
||||
Plan_expr_func::isEqual(const Plan_expr* expr) const
|
||||
{
|
||||
ctx_assert(expr != 0);
|
||||
if (expr->type() != Plan_expr::TypeFunc)
|
||||
return false;
|
||||
const Plan_expr_func* expr2 = static_cast<const Plan_expr_func*>(expr);
|
||||
if (m_func.m_code != expr2->m_func.m_code)
|
||||
return false;
|
||||
if (m_narg != expr2->m_narg)
|
||||
return false;
|
||||
ctx_assert(m_args != 0 && expr2->m_args != 0);
|
||||
for (unsigned i = 1; i <= m_narg; i++) {
|
||||
if (! m_args->getExpr(i)->isEqual(expr2->m_args->getExpr(i)))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
Plan_expr_func::isGroupBy(const Plan_expr_row* row) const
|
||||
{
|
||||
if (m_func.m_aggr)
|
||||
return true;
|
||||
switch (m_func.m_code) {
|
||||
case Expr_func::Substr:
|
||||
case Expr_func::Left:
|
||||
case Expr_func::Right:
|
||||
ctx_assert(m_narg >= 1);
|
||||
if (m_args->getExpr(1)->isGroupBy(row))
|
||||
return true;
|
||||
break;
|
||||
case Expr_func::Sysdate:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (isAnyEqual(row))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Exec_expr_func
|
||||
|
||||
Exec_expr_func::Code::~Code()
|
||||
{
|
||||
delete[] m_args;
|
||||
m_args = 0;
|
||||
}
|
||||
|
||||
Exec_expr_func::Data::~Data()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_expr_func::~Exec_expr_func()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Exec_expr_func::alloc(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
if (m_data != 0)
|
||||
return;
|
||||
const Code& code = getCode();
|
||||
// allocate arguments
|
||||
for (unsigned i = 1; i <= code.m_narg; i++) {
|
||||
ctx_assert(code.m_args != 0 && code.m_args[i] != 0);
|
||||
code.m_args[i]->alloc(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return;
|
||||
}
|
||||
SqlField sqlField(code.m_sqlSpec);
|
||||
Data& data = *new Data(sqlField);
|
||||
setData(data);
|
||||
ctx_assert(ctl.m_groupIndex == 0);
|
||||
init(ctx, ctl);
|
||||
}
|
||||
|
||||
void
|
||||
Exec_expr_func::close(Ctx& ctx)
|
||||
{
|
||||
const Code& code = getCode();
|
||||
Data& data = getData();
|
||||
for (unsigned i = 1; i <= code.m_narg; i++) {
|
||||
ctx_assert(code.m_args != 0 && code.m_args[i] != 0);
|
||||
code.m_args[i]->close(ctx);
|
||||
}
|
||||
data.m_groupField.clear();
|
||||
Ctl ctl(0);
|
||||
init(ctx, ctl);
|
||||
}
|
||||
|
||||
void
|
||||
Exec_expr_func::print(Ctx& ctx)
|
||||
{
|
||||
const Code& code = getCode();
|
||||
ctx.print(" [%s", code.m_func.m_name);
|
||||
for (unsigned i = 1; i <= code.m_narg; i++) {
|
||||
Exec_base* a[] = { code.m_args[i] };
|
||||
printList(ctx, a, sizeof(a)/sizeof(a[0]));
|
||||
}
|
||||
ctx.print("]");
|
||||
}
|
|
@ -1,193 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef ODBC_CODEGEN_Code_expr_func_hpp
|
||||
#define ODBC_CODEGEN_Code_expr_func_hpp
|
||||
|
||||
#include <common/common.hpp>
|
||||
#include <common/DataField.hpp>
|
||||
#include "Code_expr.hpp"
|
||||
#include "Code_expr_row.hpp"
|
||||
|
||||
/**
|
||||
* @class Expr_func
|
||||
* @brief Specifies a function
|
||||
*/
|
||||
struct Expr_func {
|
||||
enum Code {
|
||||
Undef = 0,
|
||||
Substr,
|
||||
Left,
|
||||
Right,
|
||||
Count,
|
||||
Max,
|
||||
Min,
|
||||
Sum,
|
||||
Avg,
|
||||
Rownum,
|
||||
Sysdate
|
||||
};
|
||||
Expr_func(Code code, const char* name, bool aggr);
|
||||
Code m_code;
|
||||
const char* m_name;
|
||||
bool m_aggr;
|
||||
static const Expr_func& find(const char* name);
|
||||
};
|
||||
|
||||
inline
|
||||
Expr_func::Expr_func(Code code, const char* name, bool aggr) :
|
||||
m_code(code),
|
||||
m_name(name),
|
||||
m_aggr(aggr)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @class Plan_expr_func
|
||||
* @brief Function node in an expression in PlanTree
|
||||
*/
|
||||
class Plan_expr_func : public Plan_expr {
|
||||
public:
|
||||
Plan_expr_func(Plan_root* root, const Expr_func& func);
|
||||
virtual ~Plan_expr_func();
|
||||
Plan_base* analyze(Ctx& ctx, Ctl& ctl);
|
||||
Exec_base* codegen(Ctx& ctx, Ctl& ctl);
|
||||
void print(Ctx& ctx);
|
||||
bool isEqual(const Plan_expr* expr) const;
|
||||
bool isGroupBy(const Plan_expr_row* row) const;
|
||||
// children
|
||||
void setArgs(Plan_expr_row* args);
|
||||
protected:
|
||||
const Expr_func& m_func;
|
||||
Plan_expr_row* m_args;
|
||||
unsigned m_narg;
|
||||
SqlType* m_conv; // temp work area
|
||||
};
|
||||
|
||||
inline
|
||||
Plan_expr_func::Plan_expr_func(Plan_root* root, const Expr_func& func) :
|
||||
Plan_expr(root, TypeFunc),
|
||||
m_func(func),
|
||||
m_args(0),
|
||||
m_narg(0),
|
||||
m_conv(0)
|
||||
{
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_expr_func::setArgs(Plan_expr_row* args)
|
||||
{
|
||||
if (args == 0) {
|
||||
m_args = 0;
|
||||
m_narg = 0;
|
||||
} else {
|
||||
m_args = args;
|
||||
m_narg = m_args->getSize();
|
||||
delete[] m_conv;
|
||||
m_conv = new SqlType[1 + m_narg];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @class Exec_expr_func
|
||||
* @brief Function node in an expression in ExecTree
|
||||
*/
|
||||
class Exec_expr_func : public Exec_expr {
|
||||
public:
|
||||
class Code : public Exec_expr::Code {
|
||||
public:
|
||||
Code(const Expr_func& func, const SqlSpec& spec);
|
||||
virtual ~Code();
|
||||
protected:
|
||||
friend class Plan_expr_func;
|
||||
friend class Exec_expr_func;
|
||||
const Expr_func& m_func;
|
||||
const SqlSpec m_sqlSpec;
|
||||
unsigned m_narg;
|
||||
Exec_expr** m_args; // XXX pointers for now
|
||||
};
|
||||
class Data : public Exec_expr::Data {
|
||||
public:
|
||||
Data(const SqlField& sqlField);
|
||||
virtual ~Data();
|
||||
protected:
|
||||
friend class Exec_expr_func;
|
||||
SqlField m_sqlField;
|
||||
struct Acc { // accumulators etc
|
||||
SqlBigint m_count; // current row count
|
||||
union {
|
||||
SqlBigint m_bigint;
|
||||
SqlDouble m_double;
|
||||
SqlDatetime m_sysdate;
|
||||
};
|
||||
};
|
||||
// group-by extra accumulators (default in entry 0)
|
||||
typedef std::vector<Acc> GroupAcc;
|
||||
GroupAcc m_groupAcc;
|
||||
};
|
||||
Exec_expr_func(Exec_root* root);
|
||||
virtual ~Exec_expr_func();
|
||||
void alloc(Ctx& ctx, Ctl& ctl);
|
||||
void evaluate(Ctx& ctx, Ctl& ctl);
|
||||
void close(Ctx& ctx);
|
||||
void print(Ctx& ctx);
|
||||
// children
|
||||
const Code& getCode() const;
|
||||
Data& getData() const;
|
||||
protected:
|
||||
void init(Ctx &ctx, Ctl& ctl); // initialize values
|
||||
};
|
||||
|
||||
inline
|
||||
Exec_expr_func::Code::Code(const Expr_func& func, const SqlSpec& sqlSpec) :
|
||||
Exec_expr::Code(m_sqlSpec),
|
||||
m_func(func),
|
||||
m_sqlSpec(sqlSpec),
|
||||
m_args(0)
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_expr_func::Data::Data(const SqlField& sqlField) :
|
||||
Exec_expr::Data(m_sqlField),
|
||||
m_sqlField(sqlField),
|
||||
m_groupAcc(1)
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_expr_func::Exec_expr_func(Exec_root* root) :
|
||||
Exec_expr(root)
|
||||
{
|
||||
}
|
||||
|
||||
// children
|
||||
|
||||
inline const Exec_expr_func::Code&
|
||||
Exec_expr_func::getCode() const
|
||||
{
|
||||
const Code* code = static_cast<const Code*>(m_code);
|
||||
return *code;
|
||||
}
|
||||
|
||||
inline Exec_expr_func::Data&
|
||||
Exec_expr_func::getData() const
|
||||
{
|
||||
Data* data = static_cast<Data*>(m_data);
|
||||
return *data;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,424 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include "Code_expr.hpp"
|
||||
#include "Code_expr_op.hpp"
|
||||
#include "Code_expr_conv.hpp"
|
||||
#include "Code_root.hpp"
|
||||
|
||||
// Expr_op
|
||||
|
||||
const char*
|
||||
Expr_op::name() const
|
||||
{
|
||||
switch (m_opcode) {
|
||||
case Add:
|
||||
return "+";
|
||||
case Subtract:
|
||||
return "-";
|
||||
case Multiply:
|
||||
return "*";
|
||||
case Divide:
|
||||
return "/";
|
||||
case Plus:
|
||||
return "+";
|
||||
case Minus:
|
||||
return "-";
|
||||
}
|
||||
ctx_assert(false);
|
||||
return "";
|
||||
}
|
||||
|
||||
unsigned
|
||||
Expr_op::arity() const
|
||||
{
|
||||
switch (m_opcode) {
|
||||
case Add:
|
||||
case Subtract:
|
||||
case Multiply:
|
||||
case Divide:
|
||||
return 2;
|
||||
case Plus:
|
||||
case Minus:
|
||||
return 1;
|
||||
}
|
||||
ctx_assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Plan_expr_op
|
||||
|
||||
Plan_expr_op::~Plan_expr_op()
|
||||
{
|
||||
}
|
||||
|
||||
Plan_base*
|
||||
Plan_expr_op::analyze(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
m_exec = 0;
|
||||
unsigned arity = m_op.arity();
|
||||
// analyze operands
|
||||
m_isAggr = false;
|
||||
m_isBound = true;
|
||||
for (unsigned i = 1; i <= arity; i++) {
|
||||
ctx_assert(m_expr[i] != 0);
|
||||
m_expr[i]->analyze(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
if (m_expr[i]->m_isAggr)
|
||||
m_isAggr = true;
|
||||
if (! m_expr[i]->m_isBound)
|
||||
m_isBound = false;
|
||||
}
|
||||
// find result type and conversion types (currently same)
|
||||
SqlType res;
|
||||
SqlType con[1 + 2];
|
||||
if (arity == 1) {
|
||||
const SqlType& t1 = m_expr[1]->sqlType();
|
||||
switch (t1.type()) {
|
||||
case SqlType::Char:
|
||||
case SqlType::Varchar:
|
||||
break;
|
||||
case SqlType::Smallint:
|
||||
case SqlType::Integer:
|
||||
case SqlType::Bigint:
|
||||
res.setType(ctx, SqlType::Bigint);
|
||||
con[1] = res;
|
||||
break;
|
||||
case SqlType::Real:
|
||||
case SqlType::Double:
|
||||
res.setType(ctx, SqlType::Double);
|
||||
con[1] = res;
|
||||
break;
|
||||
case SqlType::Null:
|
||||
res.setType(ctx, SqlType::Null);
|
||||
con[1] = res;
|
||||
break;
|
||||
case SqlType::Unbound:
|
||||
res.setType(ctx, SqlType::Unbound);
|
||||
con[1] = res;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (con[1].type() == SqlType::Undef) {
|
||||
char b1[40];
|
||||
t1.print(b1, sizeof(b1));
|
||||
ctx.pushStatus(Error::Gen, "type mismatch in operation: %s %s", m_op.name(), b1);
|
||||
return 0;
|
||||
}
|
||||
} else if (arity == 2) {
|
||||
const SqlType& t1 = m_expr[1]->sqlType();
|
||||
const SqlType& t2 = m_expr[2]->sqlType();
|
||||
switch (t1.type()) {
|
||||
case SqlType::Char: // handle char types as in oracle
|
||||
switch (t2.type()) {
|
||||
case SqlType::Char:
|
||||
res.setType(ctx, SqlType::Char, t1.length() + t2.length());
|
||||
con[1] = t1;
|
||||
con[2] = t2;
|
||||
break;
|
||||
case SqlType::Varchar:
|
||||
res.setType(ctx, SqlType::Varchar, t1.length() + t2.length());
|
||||
con[1] = t1;
|
||||
con[2] = t2;
|
||||
break;
|
||||
case SqlType::Null:
|
||||
res.setType(ctx, SqlType::Varchar, t1.length());
|
||||
con[1] = t1;
|
||||
con[2] = t2;
|
||||
break;
|
||||
case SqlType::Unbound:
|
||||
res.setType(ctx, SqlType::Unbound);
|
||||
con[1] = con[2] = res;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SqlType::Varchar:
|
||||
switch (t2.type()) {
|
||||
case SqlType::Char:
|
||||
res.setType(ctx, SqlType::Varchar, t1.length() + t2.length());
|
||||
con[1] = t1;
|
||||
con[2] = t2;
|
||||
break;
|
||||
case SqlType::Varchar:
|
||||
res.setType(ctx, SqlType::Varchar, t1.length() + t2.length());
|
||||
con[1] = t1;
|
||||
con[2] = t2;
|
||||
break;
|
||||
case SqlType::Null:
|
||||
res.setType(ctx, SqlType::Varchar, t1.length());
|
||||
con[1] = t1;
|
||||
con[2] = t2;
|
||||
break;
|
||||
case SqlType::Unbound:
|
||||
res.setType(ctx, SqlType::Unbound);
|
||||
con[1] = con[2] = res;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SqlType::Smallint:
|
||||
case SqlType::Integer:
|
||||
case SqlType::Bigint:
|
||||
switch (t2.type()) {
|
||||
case SqlType::Smallint:
|
||||
case SqlType::Integer:
|
||||
case SqlType::Bigint:
|
||||
res.setType(ctx, SqlType::Bigint);
|
||||
con[1] = con[2] = res;
|
||||
if (t1.unSigned() || t2.unSigned()) {
|
||||
con[1].unSigned(true);
|
||||
con[2].unSigned(true);
|
||||
}
|
||||
break;
|
||||
case SqlType::Real:
|
||||
case SqlType::Double:
|
||||
res.setType(ctx, SqlType::Double);
|
||||
con[1] = con[2] = res;
|
||||
break;
|
||||
case SqlType::Null:
|
||||
res.setType(ctx, SqlType::Null);
|
||||
con[1] = con[2] = res;
|
||||
break;
|
||||
case SqlType::Unbound:
|
||||
res.setType(ctx, SqlType::Unbound);
|
||||
con[1] = con[2] = res;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SqlType::Real:
|
||||
case SqlType::Double:
|
||||
switch (t2.type()) {
|
||||
case SqlType::Smallint:
|
||||
case SqlType::Integer:
|
||||
case SqlType::Bigint:
|
||||
case SqlType::Real:
|
||||
case SqlType::Double:
|
||||
res.setType(ctx, SqlType::Double);
|
||||
con[1] = con[2] = res;
|
||||
break;
|
||||
case SqlType::Null:
|
||||
res.setType(ctx, SqlType::Null);
|
||||
con[1] = con[2] = res;
|
||||
break;
|
||||
case SqlType::Unbound:
|
||||
res.setType(ctx, SqlType::Unbound);
|
||||
con[1] = con[2] = res;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SqlType::Null:
|
||||
switch (t2.type()) {
|
||||
case SqlType::Char:
|
||||
case SqlType::Varchar:
|
||||
res.setType(ctx, SqlType::Varchar, t2.length());
|
||||
con[1] = con[2] = res;
|
||||
break;
|
||||
case SqlType::Unbound:
|
||||
res.setType(ctx, SqlType::Unbound);
|
||||
con[1] = con[2] = res;
|
||||
break;
|
||||
default:
|
||||
res.setType(ctx, SqlType::Null);
|
||||
con[1] = con[2] = res;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SqlType::Unbound:
|
||||
res.setType(ctx, SqlType::Unbound);
|
||||
con[1] = con[2] = res;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (con[1].type() == SqlType::Undef || con[2].type() == SqlType::Undef) {
|
||||
char b1[40], b2[40];
|
||||
t1.print(b1, sizeof(b1));
|
||||
t2.print(b2, sizeof(b2));
|
||||
ctx.pushStatus(Error::Gen, "type mismatch in operation: %s %s %s", b1, m_op.name(), b2);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
ctx_assert(false);
|
||||
return 0;
|
||||
}
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
// insert required conversions
|
||||
for (unsigned i = 1; i <= arity; i++) {
|
||||
if (con[i].type() == SqlType::Undef) {
|
||||
ctx.pushStatus(Error::Gen, "mismatched types in operation");
|
||||
return 0;
|
||||
}
|
||||
if (con[i].type() == SqlType::Unbound) {
|
||||
// parameter type not yet bound
|
||||
continue;
|
||||
}
|
||||
Plan_expr_conv* exprConv = new Plan_expr_conv(m_root, con[i]);
|
||||
m_root->saveNode(exprConv);
|
||||
exprConv->setExpr(m_expr[i]);
|
||||
m_expr[i] = static_cast<Plan_expr*>(exprConv->analyze(ctx, ctl));
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
ctx_assert(m_expr[i] != 0);
|
||||
}
|
||||
// set result type
|
||||
m_sqlType = res;
|
||||
// table dependencies are union from operands
|
||||
for (unsigned i = 1; i <= arity; i++) {
|
||||
const TableSet& ts = m_expr[i]->tableSet();
|
||||
m_tableSet.insert(ts.begin(), ts.end());
|
||||
}
|
||||
// set alias name XXX misses operator precedence
|
||||
if (arity == 1) {
|
||||
m_alias.assign(m_op.name());
|
||||
m_alias.append(m_expr[1]->m_alias);
|
||||
} else if (arity == 2) {
|
||||
m_alias.assign(m_expr[1]->m_alias);
|
||||
m_alias.append(m_op.name());
|
||||
m_alias.append(m_expr[2]->m_alias);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
Exec_base*
|
||||
Plan_expr_op::codegen(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
if (m_exec != 0)
|
||||
return m_exec;
|
||||
unsigned arity = m_op.arity();
|
||||
Exec_expr_op* exec = new Exec_expr_op(ctl.m_execRoot);
|
||||
ctl.m_execRoot->saveNode(exec);
|
||||
// create code for operands
|
||||
for (unsigned i = 1; i <= arity; i++) {
|
||||
ctx_assert(m_expr[i] != 0);
|
||||
Exec_expr* execExpr = static_cast<Exec_expr*>(m_expr[i]->codegen(ctx, ctl));
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
ctx_assert(execExpr != 0);
|
||||
exec->setExpr(i, execExpr);
|
||||
}
|
||||
// create the code
|
||||
SqlSpec sqlSpec(sqlType(), SqlSpec::Physical);
|
||||
Exec_expr_op::Code& code = *new Exec_expr_op::Code(m_op, sqlSpec);
|
||||
exec->setCode(code);
|
||||
m_exec = exec;
|
||||
return exec;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_expr_op::print(Ctx& ctx)
|
||||
{
|
||||
ctx.print(" [%s", m_op.name());
|
||||
Plan_base* a[] = { m_expr[1], m_expr[2] };
|
||||
printList(ctx, a, m_op.arity());
|
||||
ctx.print("]");
|
||||
}
|
||||
|
||||
bool
|
||||
Plan_expr_op::isEqual(const Plan_expr* expr) const
|
||||
{
|
||||
ctx_assert(expr != 0);
|
||||
if (expr->type() != Plan_expr::TypeOp)
|
||||
return false;
|
||||
const Plan_expr_op* expr2 = static_cast<const Plan_expr_op*>(expr);
|
||||
if (m_op.m_opcode != expr2->m_op.m_opcode)
|
||||
return false;
|
||||
const unsigned arity = m_op.arity();
|
||||
for (unsigned i = 1; i <= arity; i++) {
|
||||
ctx_assert(m_expr[i] != 0);
|
||||
if (! m_expr[i]->isEqual(expr2->m_expr[i]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
Plan_expr_op::isGroupBy(const Plan_expr_row* row) const
|
||||
{
|
||||
if (isAnyEqual(row))
|
||||
return true;
|
||||
const unsigned arity = m_op.arity();
|
||||
for (unsigned i = 1; i <= arity; i++) {
|
||||
ctx_assert(m_expr[i] != 0);
|
||||
if (! m_expr[i]->isGroupBy(row))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Code_expr_op
|
||||
|
||||
Exec_expr_op::Code::~Code()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_expr_op::Data::~Data()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_expr_op::~Exec_expr_op()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Exec_expr_op::alloc(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
if (m_data != 0)
|
||||
return;
|
||||
const Code& code = getCode();
|
||||
// allocate subexpressions
|
||||
unsigned arity = code.m_op.arity();
|
||||
for (unsigned i = 1; i <= arity; i++) {
|
||||
ctx_assert(m_expr[i] != 0);
|
||||
m_expr[i]->alloc(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return;
|
||||
}
|
||||
SqlField sqlField(code.m_sqlSpec);
|
||||
Data& data = *new Data(sqlField);
|
||||
setData(data);
|
||||
}
|
||||
|
||||
void
|
||||
Exec_expr_op::close(Ctx& ctx)
|
||||
{
|
||||
const Code& code = getCode();
|
||||
unsigned arity = code.m_op.arity();
|
||||
for (unsigned i = 1; i <= arity; i++) {
|
||||
ctx_assert(m_expr[i] != 0);
|
||||
m_expr[i]->close(ctx);
|
||||
}
|
||||
Data& data = getData();
|
||||
data.m_groupField.clear();
|
||||
}
|
||||
|
||||
void
|
||||
Exec_expr_op::print(Ctx& ctx)
|
||||
{
|
||||
const Code& code = getCode();
|
||||
ctx.print(" [%s", code.m_op.name());
|
||||
Exec_base* a[] = { m_expr[1], m_expr[2] };
|
||||
printList(ctx, a, code.m_op.arity());
|
||||
ctx.print("]");
|
||||
}
|
|
@ -1,166 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef ODBC_CODEGEN_Code_expr_op_hpp
|
||||
#define ODBC_CODEGEN_Code_expr_op_hpp
|
||||
|
||||
#include <common/common.hpp>
|
||||
#include <common/DataField.hpp>
|
||||
#include "Code_expr.hpp"
|
||||
|
||||
/**
|
||||
* @class Expr_op
|
||||
* @brief Arithmetic and string operators
|
||||
*/
|
||||
struct Expr_op {
|
||||
enum Opcode {
|
||||
Add = 1, // binary
|
||||
Subtract,
|
||||
Multiply,
|
||||
Divide,
|
||||
Plus, // unary
|
||||
Minus
|
||||
};
|
||||
Expr_op(Opcode opcode);
|
||||
const char* name() const;
|
||||
unsigned arity() const;
|
||||
Opcode m_opcode;
|
||||
};
|
||||
|
||||
inline
|
||||
Expr_op::Expr_op(Opcode opcode) :
|
||||
m_opcode(opcode)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @class Plan_expr_op
|
||||
* @brief Operator node in an expression in PlanTree
|
||||
*/
|
||||
class Plan_expr_op : public Plan_expr {
|
||||
public:
|
||||
Plan_expr_op(Plan_root* root, Expr_op op);
|
||||
virtual ~Plan_expr_op();
|
||||
Plan_base* analyze(Ctx& ctx, Ctl& ctl);
|
||||
Exec_base* codegen(Ctx& ctx, Ctl& ctl);
|
||||
void print(Ctx& ctx);
|
||||
bool isEqual(const Plan_expr* expr) const;
|
||||
bool isGroupBy(const Plan_expr_row* row) const;
|
||||
// children
|
||||
void setExpr(unsigned i, Plan_expr* expr);
|
||||
protected:
|
||||
Expr_op m_op;
|
||||
Plan_expr* m_expr[1 + 2];
|
||||
};
|
||||
|
||||
inline
|
||||
Plan_expr_op::Plan_expr_op(Plan_root* root, Expr_op op) :
|
||||
Plan_expr(root, TypeOp),
|
||||
m_op(op)
|
||||
{
|
||||
m_expr[0] = m_expr[1] = m_expr[2] = 0;
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_expr_op::setExpr(unsigned i, Plan_expr* expr)
|
||||
{
|
||||
ctx_assert(1 <= i && i <= 2 && expr != 0);
|
||||
m_expr[i] = expr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @class Exec_expr_op
|
||||
* @brief Operator node in an expression in ExecTree
|
||||
*/
|
||||
class Exec_expr_op : public Exec_expr {
|
||||
public:
|
||||
class Code : public Exec_expr::Code {
|
||||
public:
|
||||
Code(Expr_op op, const SqlSpec& spec);
|
||||
virtual ~Code();
|
||||
protected:
|
||||
friend class Exec_expr_op;
|
||||
Expr_op m_op;
|
||||
const SqlSpec m_sqlSpec;
|
||||
};
|
||||
class Data : public Exec_expr::Data {
|
||||
public:
|
||||
Data(const SqlField& sqlField);
|
||||
virtual ~Data();
|
||||
protected:
|
||||
friend class Exec_expr_op;
|
||||
SqlField m_sqlField;
|
||||
};
|
||||
Exec_expr_op(Exec_root* root);
|
||||
virtual ~Exec_expr_op();
|
||||
void alloc(Ctx& ctx, Ctl& ctl);
|
||||
void evaluate(Ctx& ctx, Ctl& ctl);
|
||||
void close(Ctx& ctx);
|
||||
void print(Ctx& ctx);
|
||||
// children
|
||||
const Code& getCode() const;
|
||||
Data& getData() const;
|
||||
void setExpr(unsigned i, Exec_expr* expr);
|
||||
protected:
|
||||
Exec_expr* m_expr[1 + 2];
|
||||
};
|
||||
|
||||
inline
|
||||
Exec_expr_op::Code::Code(Expr_op op, const SqlSpec& sqlSpec) :
|
||||
Exec_expr::Code(m_sqlSpec),
|
||||
m_op(op),
|
||||
m_sqlSpec(sqlSpec)
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_expr_op::Data::Data(const SqlField& sqlField) :
|
||||
Exec_expr::Data(m_sqlField),
|
||||
m_sqlField(sqlField)
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_expr_op::Exec_expr_op(Exec_root* root) :
|
||||
Exec_expr(root)
|
||||
{
|
||||
m_expr[0] = m_expr[1] = m_expr[2] = 0;
|
||||
}
|
||||
|
||||
// children
|
||||
|
||||
inline const Exec_expr_op::Code&
|
||||
Exec_expr_op::getCode() const
|
||||
{
|
||||
const Code* code = static_cast<const Code*>(m_code);
|
||||
return *code;
|
||||
}
|
||||
|
||||
inline Exec_expr_op::Data&
|
||||
Exec_expr_op::getData() const
|
||||
{
|
||||
Data* data = static_cast<Data*>(m_data);
|
||||
return *data;
|
||||
}
|
||||
|
||||
inline void
|
||||
Exec_expr_op::setExpr(unsigned i, Exec_expr* expr)
|
||||
{
|
||||
ctx_assert(1 <= i && i <= 2 && m_expr[i] == 0);
|
||||
m_expr[i] = expr;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,279 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include "Code_expr_param.hpp"
|
||||
#include "Code_root.hpp"
|
||||
|
||||
// Plan_expr_param
|
||||
|
||||
Plan_expr_param::~Plan_expr_param()
|
||||
{
|
||||
}
|
||||
|
||||
Plan_base*
|
||||
Plan_expr_param::analyze(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
m_exec = 0;
|
||||
ctx_assert(m_paramNumber != 0);
|
||||
ctx_assert(m_paramNumber < m_root->m_paramList.size());
|
||||
m_root->m_paramList[m_paramNumber] = this;
|
||||
m_sqlType.setType(ctx, SqlType::Unbound);
|
||||
// check if type is bound now
|
||||
DescArea& ipd = descArea(Desc_usage_IPD);
|
||||
if (m_paramNumber <= ipd.getCount()) {
|
||||
DescRec& rec = ipd.getRecord(m_paramNumber);
|
||||
OdbcData descData;
|
||||
rec.getField(ctx, SQL_DESC_TYPE, descData);
|
||||
if (descData.type() != OdbcData::Undef) {
|
||||
SQLSMALLINT desc_TYPE = descData.smallint();
|
||||
// XXX wrong but fixes sun.jdbc.odbc
|
||||
if (desc_TYPE == SQL_CHAR)
|
||||
desc_TYPE = SQL_VARCHAR;
|
||||
if (desc_TYPE == SQL_CHAR) {
|
||||
rec.getField(ctx, SQL_DESC_LENGTH, descData);
|
||||
if (descData.type() != OdbcData::Undef) {
|
||||
unsigned desc_LENGTH = descData.uinteger();
|
||||
m_sqlType.setType(ctx, SqlType::Char, desc_LENGTH);
|
||||
}
|
||||
} else if (desc_TYPE == SQL_VARCHAR) {
|
||||
rec.getField(ctx, SQL_DESC_LENGTH, descData);
|
||||
if (descData.type() != OdbcData::Undef) {
|
||||
unsigned desc_LENGTH = descData.uinteger();
|
||||
m_sqlType.setType(ctx, SqlType::Varchar, desc_LENGTH);
|
||||
}
|
||||
} else if (desc_TYPE == SQL_BINARY) {
|
||||
rec.getField(ctx, SQL_DESC_LENGTH, descData);
|
||||
if (descData.type() != OdbcData::Undef) {
|
||||
unsigned desc_LENGTH = descData.uinteger();
|
||||
m_sqlType.setType(ctx, SqlType::Binary, desc_LENGTH);
|
||||
}
|
||||
} else if (desc_TYPE == SQL_VARBINARY) {
|
||||
rec.getField(ctx, SQL_DESC_LENGTH, descData);
|
||||
if (descData.type() != OdbcData::Undef) {
|
||||
unsigned desc_LENGTH = descData.uinteger();
|
||||
m_sqlType.setType(ctx, SqlType::Varbinary, desc_LENGTH);
|
||||
} else {
|
||||
// XXX BLOB hack
|
||||
unsigned desc_LENGTH = FAKE_BLOB_SIZE;
|
||||
m_sqlType.setType(ctx, SqlType::Varbinary, desc_LENGTH);
|
||||
}
|
||||
} else if (desc_TYPE == SQL_SMALLINT) {
|
||||
m_sqlType.setType(ctx, SqlType::Smallint);
|
||||
} else if (desc_TYPE == SQL_INTEGER) {
|
||||
m_sqlType.setType(ctx, SqlType::Integer);
|
||||
} else if (desc_TYPE == SQL_BIGINT) {
|
||||
m_sqlType.setType(ctx, SqlType::Bigint);
|
||||
} else if (desc_TYPE == SQL_REAL) {
|
||||
m_sqlType.setType(ctx, SqlType::Real);
|
||||
} else if (desc_TYPE == SQL_DOUBLE) {
|
||||
m_sqlType.setType(ctx, SqlType::Double);
|
||||
} else if (desc_TYPE == SQL_TYPE_TIMESTAMP) {
|
||||
m_sqlType.setType(ctx, SqlType::Datetime);
|
||||
// XXX BLOB hack
|
||||
} else if (desc_TYPE == SQL_LONGVARBINARY) {
|
||||
m_sqlType.setType(ctx, SqlType::Varbinary, (unsigned)FAKE_BLOB_SIZE);
|
||||
} else {
|
||||
ctx.pushStatus(Error::Gen, "parameter %u unsupported SQL type %d", m_paramNumber, (int)desc_TYPE);
|
||||
return 0;
|
||||
}
|
||||
char buf[100];
|
||||
m_sqlType.print(buf, sizeof(buf));
|
||||
ctx_log2(("parameter %u SQL type bound to %s", m_paramNumber, buf));
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_expr_param::describe(Ctx& ctx)
|
||||
{
|
||||
DescArea& ipd = descArea(Desc_usage_IPD);
|
||||
if (ipd.getCount() < m_paramNumber)
|
||||
ipd.setCount(ctx, m_paramNumber);
|
||||
// XXX describe if possible
|
||||
DescRec& rec = ipd.getRecord(m_paramNumber);
|
||||
}
|
||||
|
||||
Exec_base*
|
||||
Plan_expr_param::codegen(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
if (m_exec != 0)
|
||||
return m_exec;
|
||||
SqlSpec sqlSpec(m_sqlType, SqlSpec::Physical);
|
||||
// create code
|
||||
Exec_expr_param* exec = new Exec_expr_param(ctl.m_execRoot);
|
||||
ctl.m_execRoot->saveNode(exec);
|
||||
ctx_assert(m_paramNumber != 0);
|
||||
Exec_expr_param::Code& code = *new Exec_expr_param::Code(sqlSpec, m_paramNumber);
|
||||
exec->setCode(code);
|
||||
m_exec = exec;
|
||||
return exec;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_expr_param::print(Ctx& ctx)
|
||||
{
|
||||
ctx.print(" [param %u]", m_paramNumber);
|
||||
}
|
||||
|
||||
bool
|
||||
Plan_expr_param::isEqual(const Plan_expr* expr) const
|
||||
{
|
||||
ctx_assert(expr != 0);
|
||||
if (expr->type() != Plan_expr::TypeParam)
|
||||
return false;
|
||||
const Plan_expr_param* expr2 = static_cast<const Plan_expr_param*>(expr);
|
||||
// params are not equal ever
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
Plan_expr_param::isGroupBy(const Plan_expr_row* row) const
|
||||
{
|
||||
// params are constants
|
||||
return true;
|
||||
}
|
||||
|
||||
// Exec_expr_param
|
||||
|
||||
Exec_expr_param::Code::~Code()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_expr_param::Data::~Data()
|
||||
{
|
||||
delete m_extField;
|
||||
m_extField = 0;
|
||||
}
|
||||
|
||||
Exec_expr_param::~Exec_expr_param()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Exec_expr_param::alloc(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
if (m_data != 0)
|
||||
return;
|
||||
const Code& code = getCode();
|
||||
SqlField sqlField(code.sqlSpec());
|
||||
Data& data = *new Data(sqlField);
|
||||
setData(data);
|
||||
}
|
||||
|
||||
void
|
||||
Exec_expr_param::bind(Ctx& ctx)
|
||||
{
|
||||
const Code& code = getCode();
|
||||
Data& data = getData();
|
||||
DescArea& apd = descArea(Desc_usage_APD);
|
||||
if (apd.getCount() < code.m_paramNumber) {
|
||||
ctx_log1(("parameter %u is not bound", code.m_paramNumber));
|
||||
return;
|
||||
}
|
||||
const unsigned paramNumber = code.m_paramNumber;
|
||||
DescRec& rec = apd.getRecord(paramNumber);
|
||||
OdbcData descData;
|
||||
// create type
|
||||
rec.getField(ctx, SQL_DESC_TYPE, descData);
|
||||
if (descData.type() == OdbcData::Undef) {
|
||||
ctx.pushStatus(Error::Gen, "parameter %u external type not defined", paramNumber);
|
||||
return;
|
||||
}
|
||||
ExtType extType;
|
||||
SQLSMALLINT desc_TYPE = descData.smallint();
|
||||
switch (desc_TYPE) {
|
||||
case SQL_C_CHAR:
|
||||
case SQL_C_SHORT: // for sun.jdbc.odbc
|
||||
case SQL_C_SSHORT:
|
||||
case SQL_C_USHORT:
|
||||
case SQL_C_LONG: // for sun.jdbc.odbc
|
||||
case SQL_C_SLONG:
|
||||
case SQL_C_ULONG:
|
||||
case SQL_C_SBIGINT:
|
||||
case SQL_C_UBIGINT:
|
||||
case SQL_C_FLOAT:
|
||||
case SQL_C_DOUBLE:
|
||||
case SQL_C_TYPE_TIMESTAMP:
|
||||
case SQL_C_BINARY: // XXX BLOB hack
|
||||
break;
|
||||
default:
|
||||
ctx.pushStatus(Error::Gen, "parameter %u unsupported external type %d", paramNumber, (int)desc_TYPE);
|
||||
return;
|
||||
}
|
||||
extType.setType(ctx, static_cast<ExtType::Type>(desc_TYPE));
|
||||
ExtSpec extSpec(extType);
|
||||
// create data field
|
||||
rec.getField(ctx, SQL_DESC_DATA_PTR, descData);
|
||||
if (descData.type() == OdbcData::Undef) {
|
||||
ctx.pushStatus(Error::Gen, "parameter %u data address not defined", paramNumber);
|
||||
return;
|
||||
}
|
||||
SQLPOINTER desc_DATA_PTR = descData.pointer();
|
||||
rec.getField(ctx, SQL_DESC_OCTET_LENGTH, descData);
|
||||
if (descData.type() == OdbcData::Undef) {
|
||||
ctx.pushStatus(Error::Gen, "parameter %u data length not defined", paramNumber);
|
||||
return;
|
||||
}
|
||||
SQLINTEGER desc_OCTET_LENGTH = descData.integer();
|
||||
rec.getField(ctx, SQL_DESC_INDICATOR_PTR, descData);
|
||||
if (descData.type() == OdbcData::Undef) {
|
||||
ctx.pushStatus(Error::Gen, "parameter %u indicator address not defined", paramNumber);
|
||||
return;
|
||||
}
|
||||
SQLINTEGER* desc_INDICATOR_PTR = descData.integerPtr();
|
||||
ctx_log4(("parameter %u bind to 0x%x %d 0x%x", paramNumber, (unsigned)desc_DATA_PTR, (int)desc_OCTET_LENGTH, (unsigned)desc_INDICATOR_PTR));
|
||||
ExtField& extField = *new ExtField(extSpec, desc_DATA_PTR, desc_OCTET_LENGTH, desc_INDICATOR_PTR, paramNumber);
|
||||
data.m_atExec = false;
|
||||
if (desc_INDICATOR_PTR != 0 && *desc_INDICATOR_PTR < 0) {
|
||||
if (*desc_INDICATOR_PTR == SQL_NULL_DATA) {
|
||||
;
|
||||
} else if (*desc_INDICATOR_PTR == SQL_DATA_AT_EXEC) {
|
||||
data.m_atExec = true;
|
||||
} else if (*desc_INDICATOR_PTR <= SQL_LEN_DATA_AT_EXEC(0)) {
|
||||
data.m_atExec = true;
|
||||
}
|
||||
}
|
||||
delete data.m_extField;
|
||||
data.m_extField = &extField;
|
||||
}
|
||||
|
||||
void
|
||||
Exec_expr_param::evaluate(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
if (ctl.m_postEval)
|
||||
return;
|
||||
const Code& code = getCode();
|
||||
Data& data = getData();
|
||||
if (data.m_atExec)
|
||||
return;
|
||||
ctx_assert(data.m_extField != 0);
|
||||
data.m_sqlField.copyin(ctx, *data.m_extField);
|
||||
}
|
||||
|
||||
void
|
||||
Exec_expr_param::close(Ctx& ctx)
|
||||
{
|
||||
Data& data = getData();
|
||||
data.m_extPos = -1;
|
||||
}
|
||||
|
||||
void
|
||||
Exec_expr_param::print(Ctx& ctx)
|
||||
{
|
||||
const Code& code = getCode();
|
||||
ctx.print(" [param %u]", code.m_paramNumber);
|
||||
}
|
|
@ -1,136 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef ODBC_CODEGEN_Code_expr_param_hpp
|
||||
#define ODBC_CODEGEN_Code_expr_param_hpp
|
||||
|
||||
#include <common/common.hpp>
|
||||
#include <common/DataField.hpp>
|
||||
#include "Code_expr.hpp"
|
||||
|
||||
/**
|
||||
* @class Plan_expr_param
|
||||
* @brief Constant expression value in PlanTree
|
||||
*/
|
||||
class Plan_expr_param : public Plan_expr {
|
||||
public:
|
||||
Plan_expr_param(Plan_root* root, unsigned paramNumber);
|
||||
virtual ~Plan_expr_param();
|
||||
Plan_base* analyze(Ctx& ctx, Ctl& ctl);
|
||||
void describe(Ctx& ctx);
|
||||
Exec_base* codegen(Ctx& ctx, Ctl& ctl);
|
||||
void print(Ctx& ctx);
|
||||
bool isEqual(const Plan_expr* expr) const;
|
||||
bool isGroupBy(const Plan_expr_row* row) const;
|
||||
protected:
|
||||
const unsigned m_paramNumber;
|
||||
};
|
||||
|
||||
inline
|
||||
Plan_expr_param::Plan_expr_param(Plan_root* root, unsigned paramNumber) :
|
||||
Plan_expr(root, TypeParam),
|
||||
m_paramNumber(paramNumber)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @class Exec_expr_param
|
||||
* @brief Constant expression value in ExecTree
|
||||
*/
|
||||
class Exec_expr_param : public Exec_expr {
|
||||
public:
|
||||
class Code : public Exec_expr::Code {
|
||||
public:
|
||||
Code(const SqlSpec& sqlSpec, unsigned paramNumber);
|
||||
virtual ~Code();
|
||||
protected:
|
||||
friend class Plan_expr_param;
|
||||
friend class Exec_expr_param;
|
||||
const SqlSpec m_sqlSpec;
|
||||
const unsigned m_paramNumber;
|
||||
};
|
||||
class Data : public Exec_expr::Data {
|
||||
public:
|
||||
Data(SqlField& sqlField);
|
||||
virtual ~Data();
|
||||
ExtField* extField() const;
|
||||
protected:
|
||||
friend class Exec_expr_param;
|
||||
friend class Exec_root;
|
||||
SqlField m_sqlField;
|
||||
ExtField* m_extField; // input binding
|
||||
bool m_atExec; // data at exec
|
||||
int m_extPos; // position for SQLPutData (-1 before first call)
|
||||
};
|
||||
Exec_expr_param(Exec_root* root);
|
||||
virtual ~Exec_expr_param();
|
||||
void alloc(Ctx& ctx, Ctl& ctl);
|
||||
void bind(Ctx& ctx);
|
||||
void evaluate(Ctx& ctx, Ctl& ctl);
|
||||
void close(Ctx& ctx);
|
||||
void print(Ctx& ctx);
|
||||
// children
|
||||
const Code& getCode() const;
|
||||
Data& getData() const;
|
||||
};
|
||||
|
||||
inline
|
||||
Exec_expr_param::Code::Code(const SqlSpec& sqlSpec, unsigned paramNumber) :
|
||||
Exec_expr::Code(m_sqlSpec),
|
||||
m_sqlSpec(sqlSpec),
|
||||
m_paramNumber(paramNumber)
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_expr_param::Data::Data(SqlField& sqlField) :
|
||||
Exec_expr::Data(m_sqlField),
|
||||
m_sqlField(sqlField),
|
||||
m_extField(0),
|
||||
m_atExec(false),
|
||||
m_extPos(-1)
|
||||
{
|
||||
}
|
||||
|
||||
inline ExtField*
|
||||
Exec_expr_param::Data::extField() const
|
||||
{
|
||||
return m_extField;
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_expr_param::Exec_expr_param(Exec_root* root) :
|
||||
Exec_expr(root)
|
||||
{
|
||||
}
|
||||
|
||||
// children
|
||||
|
||||
inline const Exec_expr_param::Code&
|
||||
Exec_expr_param::getCode() const
|
||||
{
|
||||
const Code* code = static_cast<const Code*>(m_code);
|
||||
return *code;
|
||||
}
|
||||
|
||||
inline Exec_expr_param::Data&
|
||||
Exec_expr_param::getData() const
|
||||
{
|
||||
Data* data = static_cast<Data*>(m_data);
|
||||
return *data;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,204 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include <common/DataType.hpp>
|
||||
#include "Code_expr_row.hpp"
|
||||
#include "Code_expr.hpp"
|
||||
#include "Code_expr_conv.hpp"
|
||||
#include "Code_dml_row.hpp"
|
||||
#include "Code_root.hpp"
|
||||
|
||||
// Plan_expr_row
|
||||
|
||||
Plan_expr_row::~Plan_expr_row()
|
||||
{
|
||||
}
|
||||
|
||||
Plan_base*
|
||||
Plan_expr_row::analyze(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
unsigned size = getSize();
|
||||
// analyze subexpressions
|
||||
m_anyAggr = false;
|
||||
m_allBound = true;
|
||||
for (unsigned i = 1; i <= size; i++) {
|
||||
Plan_expr* expr1 = getExpr(i);
|
||||
Plan_expr* expr2 = static_cast<Plan_expr*>(expr1->analyze(ctx, ctl));
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
setExpr(i, expr2);
|
||||
if (expr2->isAggr())
|
||||
m_anyAggr = true;
|
||||
if (! expr2->isBound())
|
||||
m_allBound = false;
|
||||
}
|
||||
// insert conversions if requested XXX ugly hack
|
||||
if (ctl.m_dmlRow != 0) {
|
||||
if (ctl.m_dmlRow->getSize() > getSize()) {
|
||||
ctx.pushStatus(Sqlstate::_21S01, Error::Gen, "not enough values (%u > %u)", ctl.m_dmlRow->getSize(), getSize());
|
||||
return 0;
|
||||
}
|
||||
if (ctl.m_dmlRow->getSize() < getSize()) {
|
||||
ctx.pushStatus(Sqlstate::_21S01, Error::Gen, "too many values (%u < %u)", ctl.m_dmlRow->getSize(), getSize());
|
||||
return 0;
|
||||
}
|
||||
for (unsigned i = 1; i <= size; i++) {
|
||||
const SqlType& sqlType = ctl.m_dmlRow->getColumn(i)->sqlType();
|
||||
Plan_expr_conv* exprConv = new Plan_expr_conv(m_root, sqlType);
|
||||
m_root->saveNode(exprConv);
|
||||
exprConv->setExpr(getExpr(i));
|
||||
Plan_expr* expr = static_cast<Plan_expr*>(exprConv->analyze(ctx, ctl));
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
ctx_assert(expr != 0);
|
||||
setExpr(i, expr);
|
||||
}
|
||||
}
|
||||
// set aliases
|
||||
m_aliasList.resize(1 + size);
|
||||
for (unsigned i = 1; i <= size; i++) {
|
||||
if (m_aliasList[i].empty()) {
|
||||
setAlias(i, getExpr(i)->getAlias());
|
||||
}
|
||||
}
|
||||
// node was not replaced
|
||||
return this;
|
||||
}
|
||||
|
||||
Exec_base*
|
||||
Plan_expr_row::codegen(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
unsigned size = getSize();
|
||||
Exec_expr_row* exec = new Exec_expr_row(ctl.m_execRoot, size);
|
||||
ctl.m_execRoot->saveNode(exec);
|
||||
SqlSpecs sqlSpecs(size);
|
||||
// create code for subexpressions
|
||||
for (unsigned i = 1; i <= size; i++) {
|
||||
Plan_expr* planExpr = getExpr(i);
|
||||
Exec_expr* execExpr = static_cast<Exec_expr*>(planExpr->codegen(ctx, ctl));
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
ctx_assert(execExpr != 0);
|
||||
exec->setExpr(i, execExpr);
|
||||
const SqlSpec sqlSpec(execExpr->getCode().sqlSpec(), SqlSpec::Reference);
|
||||
sqlSpecs.setEntry(i, sqlSpec);
|
||||
}
|
||||
// create alias list
|
||||
Exec_expr_row::Code::Alias* aliasList = new Exec_expr_row::Code::Alias[1 + size];
|
||||
strcpy(aliasList[0], "?");
|
||||
for (unsigned i = 1; i <= size; i++) {
|
||||
const char* s = m_aliasList[i].c_str();
|
||||
if (strlen(s) == 0)
|
||||
s = getExpr(i)->getAlias().c_str();
|
||||
unsigned n = strlen(s);
|
||||
if (n >= sizeof(Exec_expr_row::Code::Alias))
|
||||
n = sizeof(Exec_expr_row::Code::Alias) - 1;
|
||||
strncpy(aliasList[i], s, n);
|
||||
aliasList[i][n] = 0;
|
||||
}
|
||||
// create the code
|
||||
Exec_expr_row::Code& code = *new Exec_expr_row::Code(sqlSpecs, aliasList);
|
||||
exec->setCode(code);
|
||||
return exec;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_expr_row::print(Ctx& ctx)
|
||||
{
|
||||
const unsigned size = getSize();
|
||||
ctx.print(" [expr_row");
|
||||
for (unsigned i = 1; i <= size; i++) {
|
||||
Plan_base* a = m_exprList[i];
|
||||
a == 0 ? ctx.print(" -") : a->print(ctx);
|
||||
}
|
||||
ctx.print("]");
|
||||
}
|
||||
|
||||
bool
|
||||
Plan_expr_row::isAllGroupBy(const Plan_expr_row* row) const
|
||||
{
|
||||
const unsigned size = getSize();
|
||||
for (unsigned i = 1; i <= size; i++) {
|
||||
if (! getExpr(i)->isGroupBy(row))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Exec_expr_row
|
||||
|
||||
Exec_expr_row::Code::~Code()
|
||||
{
|
||||
delete[] m_aliasList;
|
||||
}
|
||||
|
||||
Exec_expr_row::Data::~Data()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_expr_row::~Exec_expr_row()
|
||||
{
|
||||
delete[] m_expr;
|
||||
}
|
||||
|
||||
void
|
||||
Exec_expr_row::alloc(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
// allocate subexpressions
|
||||
for (unsigned i = 1; i <= m_size; i++) {
|
||||
getExpr(i)->alloc(ctx, ctl);
|
||||
}
|
||||
// construct SqlRow of references
|
||||
const Code& code = getCode();
|
||||
SqlRow sqlRow(getCode().m_sqlSpecs);
|
||||
for (unsigned i = 1; i <= m_size; i++) {
|
||||
const Exec_expr::Data& dataExpr = getExpr(i)->getData();
|
||||
const SqlSpec& sqlSpec = code.m_sqlSpecs.getEntry(i);
|
||||
const SqlField sqlField(sqlSpec, &dataExpr.sqlField());
|
||||
sqlRow.setEntry(i, sqlField);
|
||||
}
|
||||
// create the data
|
||||
Data& data = *new Data(sqlRow);
|
||||
setData(data);
|
||||
}
|
||||
|
||||
void
|
||||
Exec_expr_row::evaluate(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
for (unsigned i = 1; i <= m_size; i++) {
|
||||
getExpr(i)->evaluate(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Exec_expr_row::close(Ctx& ctx)
|
||||
{
|
||||
for (unsigned i = 1; i <= m_size; i++) {
|
||||
getExpr(i)->close(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Exec_expr_row::print(Ctx& ctx)
|
||||
{
|
||||
ctx.print(" [expr_row");
|
||||
for (unsigned i = 1; i <= m_size; i++) {
|
||||
getExpr(i)->print(ctx);
|
||||
}
|
||||
ctx.print("]");
|
||||
}
|
|
@ -1,272 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef ODBC_CODEGEN_Code_expr_row_hpp
|
||||
#define ODBC_CODEGEN_Code_expr_row_hpp
|
||||
|
||||
#include <vector>
|
||||
#include <common/common.hpp>
|
||||
#include <common/DataRow.hpp>
|
||||
#include "Code_base.hpp"
|
||||
#include "Code_expr.hpp"
|
||||
|
||||
class Plan_expr;
|
||||
|
||||
/**
|
||||
* @class Plan_expr_row
|
||||
* @brief Row of expressions in PlanTree
|
||||
*
|
||||
* Used for select, value, and order by rows.
|
||||
*/
|
||||
class Plan_expr_row : public Plan_base {
|
||||
public:
|
||||
Plan_expr_row(Plan_root* root);
|
||||
virtual ~Plan_expr_row();
|
||||
Plan_base* analyze(Ctx& ctx, Ctl& ctl);
|
||||
Exec_base* codegen(Ctx& ctx, Ctl& ctl);
|
||||
void print(Ctx& ctx);
|
||||
// children
|
||||
void setAsterisk();
|
||||
bool getAsterisk() const;
|
||||
unsigned getSize() const;
|
||||
Plan_expr* getExpr(unsigned i) const;
|
||||
void setExpr(unsigned i, Plan_expr* expr);
|
||||
void addExpr(Plan_expr* expr);
|
||||
void addExpr(Plan_expr* expr, const BaseString& alias);
|
||||
void setAlias(unsigned i, const BaseString& alias);
|
||||
void addExpr(Plan_expr* expr, bool asc);
|
||||
bool anyAggr() const;
|
||||
bool allBound() const;
|
||||
bool isAllGroupBy(const Plan_expr_row* row) const;
|
||||
protected:
|
||||
friend class Plan_query;
|
||||
friend class Plan_query_sort;
|
||||
bool m_asterisk; // early plan node type
|
||||
ExprVector m_exprList;
|
||||
typedef std::vector<BaseString> AliasList;
|
||||
AliasList m_aliasList;
|
||||
typedef std::vector<bool> AscList;
|
||||
AscList m_ascList;
|
||||
bool m_anyAggr; // at least one aggreate
|
||||
bool m_allBound; // all bound
|
||||
};
|
||||
|
||||
inline
|
||||
Plan_expr_row::Plan_expr_row(Plan_root* root) :
|
||||
Plan_base(root),
|
||||
m_asterisk(false),
|
||||
m_exprList(1),
|
||||
m_aliasList(1),
|
||||
m_ascList(1),
|
||||
m_anyAggr(false),
|
||||
m_allBound(false)
|
||||
{
|
||||
}
|
||||
|
||||
// children
|
||||
|
||||
inline void
|
||||
Plan_expr_row::setAsterisk()
|
||||
{
|
||||
m_asterisk = true;
|
||||
}
|
||||
|
||||
inline bool
|
||||
Plan_expr_row::getAsterisk() const
|
||||
{
|
||||
return m_asterisk;
|
||||
}
|
||||
|
||||
inline unsigned
|
||||
Plan_expr_row::getSize() const
|
||||
{
|
||||
ctx_assert(m_exprList.size() >= 1);
|
||||
return m_exprList.size() - 1;
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_expr_row::addExpr(Plan_expr* expr)
|
||||
{
|
||||
ctx_assert(expr != 0);
|
||||
addExpr(expr, expr->m_alias);
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_expr_row::addExpr(Plan_expr* expr, const BaseString& alias)
|
||||
{
|
||||
ctx_assert(expr != 0);
|
||||
m_exprList.push_back(expr);
|
||||
m_aliasList.push_back(alias);
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_expr_row::addExpr(Plan_expr* expr, bool asc)
|
||||
{
|
||||
ctx_assert(expr != 0);
|
||||
m_exprList.push_back(expr);
|
||||
m_ascList.push_back(asc);
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_expr_row::setExpr(unsigned i, Plan_expr* expr)
|
||||
{
|
||||
ctx_assert(1 <= i && i < m_exprList.size() && expr != 0);
|
||||
m_exprList[i] = expr;
|
||||
}
|
||||
|
||||
inline Plan_expr*
|
||||
Plan_expr_row::getExpr(unsigned i) const
|
||||
{
|
||||
ctx_assert(1 <= i && i < m_exprList.size() && m_exprList[i] != 0);
|
||||
return m_exprList[i];
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_expr_row::setAlias(unsigned i, const BaseString& alias)
|
||||
{
|
||||
ctx_assert(1 <= i && i < m_aliasList.size());
|
||||
m_aliasList[i] = alias;
|
||||
}
|
||||
|
||||
inline bool
|
||||
Plan_expr_row::anyAggr() const
|
||||
{
|
||||
return m_anyAggr;
|
||||
}
|
||||
|
||||
inline bool
|
||||
Plan_expr_row::allBound() const
|
||||
{
|
||||
return m_allBound;
|
||||
}
|
||||
|
||||
/**
|
||||
* @class Expr_expr_row
|
||||
* @brief Row of expressions in ExecTree
|
||||
*/
|
||||
class Exec_expr_row : public Exec_base {
|
||||
public:
|
||||
class Code : public Exec_base::Code {
|
||||
public:
|
||||
typedef char Alias[40];
|
||||
Code(const SqlSpecs& sqlSpecs, const Alias* aliasList);
|
||||
virtual ~Code();
|
||||
const SqlSpecs& sqlSpecs() const;
|
||||
const char* getAlias(unsigned i) const;
|
||||
protected:
|
||||
friend class Exec_expr_row;
|
||||
const SqlSpecs m_sqlSpecs;
|
||||
const Alias* m_aliasList;
|
||||
};
|
||||
class Data : public Exec_base::Data {
|
||||
public:
|
||||
Data(const SqlRow& sqlRow);
|
||||
virtual ~Data();
|
||||
const SqlRow& sqlRow() const;
|
||||
protected:
|
||||
friend class Exec_expr_row;
|
||||
SqlRow m_sqlRow;
|
||||
};
|
||||
Exec_expr_row(Exec_root* root, unsigned size);
|
||||
virtual ~Exec_expr_row();
|
||||
void alloc(Ctx& ctx, Ctl& ctl);
|
||||
void evaluate(Ctx& ctx, Ctl& ctl);
|
||||
void close(Ctx& ctx);
|
||||
void print(Ctx& ctx);
|
||||
// children
|
||||
const Code& getCode() const;
|
||||
Data& getData() const;
|
||||
Exec_expr* getExpr(unsigned i) const;
|
||||
void setExpr(unsigned i, Exec_expr* expr);
|
||||
protected:
|
||||
Exec_expr** m_expr; // numbered from 1
|
||||
unsigned m_size;
|
||||
};
|
||||
|
||||
inline
|
||||
Exec_expr_row::Code::Code(const SqlSpecs& sqlSpecs, const Alias* aliasList) :
|
||||
m_sqlSpecs(sqlSpecs),
|
||||
m_aliasList(aliasList)
|
||||
{
|
||||
}
|
||||
|
||||
inline const SqlSpecs&
|
||||
Exec_expr_row::Code::sqlSpecs() const
|
||||
{
|
||||
return m_sqlSpecs;
|
||||
}
|
||||
|
||||
inline const char*
|
||||
Exec_expr_row::Code::getAlias(unsigned i) const
|
||||
{
|
||||
ctx_assert(1 <= i && i <= m_sqlSpecs.count() && m_aliasList != 0);
|
||||
return m_aliasList[i];
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_expr_row::Data::Data(const SqlRow& sqlRow) :
|
||||
m_sqlRow(sqlRow)
|
||||
{
|
||||
}
|
||||
|
||||
inline const SqlRow&
|
||||
Exec_expr_row::Data::sqlRow() const
|
||||
{
|
||||
return m_sqlRow;
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_expr_row::Exec_expr_row(Exec_root* root, unsigned size) :
|
||||
Exec_base(root),
|
||||
m_expr(new Exec_expr* [1 + size]),
|
||||
m_size(size)
|
||||
{
|
||||
m_expr[0] = (Exec_expr*)-1;
|
||||
for (unsigned i = 1; i <= m_size; i++)
|
||||
m_expr[i] = 0;
|
||||
}
|
||||
|
||||
// children
|
||||
|
||||
inline const Exec_expr_row::Code&
|
||||
Exec_expr_row::getCode() const
|
||||
{
|
||||
const Code* code = static_cast<const Code*>(m_code);
|
||||
return *code;
|
||||
}
|
||||
|
||||
inline Exec_expr_row::Data&
|
||||
Exec_expr_row::getData() const
|
||||
{
|
||||
Data* data = static_cast<Data*>(m_data);
|
||||
return *data;
|
||||
}
|
||||
|
||||
inline Exec_expr*
|
||||
Exec_expr_row::getExpr(unsigned i) const
|
||||
{
|
||||
ctx_assert(1 <= i && i <= m_size && m_expr != 0 && m_expr[i] != 0);
|
||||
return m_expr[i];
|
||||
}
|
||||
|
||||
inline void
|
||||
Exec_expr_row::setExpr(unsigned i, Exec_expr* expr)
|
||||
{
|
||||
ctx_assert(1 <= i && i <= m_size && m_expr != 0 && m_expr[i] == 0);
|
||||
m_expr[i] = expr;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,49 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include <NdbApi.hpp>
|
||||
#include <common/StmtArea.hpp>
|
||||
#include "Code_idx_column.hpp"
|
||||
#include "Code_expr_conv.hpp"
|
||||
#include "Code_root.hpp"
|
||||
|
||||
// Plan_idx_column
|
||||
|
||||
Plan_idx_column::~Plan_idx_column()
|
||||
{
|
||||
}
|
||||
|
||||
Plan_base*
|
||||
Plan_idx_column::analyze(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
analyzeColumn(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
Exec_base*
|
||||
Plan_idx_column::codegen(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
ctx_assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_idx_column::print(Ctx& ctx)
|
||||
{
|
||||
ctx.print(" [idx_column %s]", getPrintName());
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef ODBC_CODEGEN_Code_idx_column_hpp
|
||||
#define ODBC_CODEGEN_Code_idx_column_hpp
|
||||
|
||||
#include <common/common.hpp>
|
||||
#include "Code_column.hpp"
|
||||
#include "Code_data_type.hpp"
|
||||
#include "Code_expr.hpp"
|
||||
|
||||
class DictColumn;
|
||||
class Plan_table;
|
||||
|
||||
/**
|
||||
* @class Plan_idx_column
|
||||
* @brief Column in create index statement
|
||||
*/
|
||||
class Plan_idx_column : public Plan_base, public Plan_column {
|
||||
public:
|
||||
Plan_idx_column(Plan_root* root, const BaseString& name);
|
||||
virtual ~Plan_idx_column();
|
||||
Plan_base* analyze(Ctx& ctx, Ctl& ctl);
|
||||
Exec_base* codegen(Ctx& ctx, Ctl& ctl);
|
||||
void print(Ctx& ctx);
|
||||
protected:
|
||||
friend class Plan_create_row;
|
||||
};
|
||||
|
||||
inline
|
||||
Plan_idx_column::Plan_idx_column(Plan_root* root, const BaseString& name) :
|
||||
Plan_base(root),
|
||||
Plan_column(Type_idx, name)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,253 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include <common/StmtArea.hpp>
|
||||
#include <dictionary/DictTable.hpp>
|
||||
#include <dictionary/DictColumn.hpp>
|
||||
#include "Code_insert.hpp"
|
||||
#include "Code_query_repeat.hpp"
|
||||
#include "Code_query_project.hpp"
|
||||
#include "Code_table.hpp"
|
||||
#include "Code_root.hpp"
|
||||
|
||||
// Plan_insert
|
||||
|
||||
Plan_insert::~Plan_insert()
|
||||
{
|
||||
}
|
||||
|
||||
Plan_base*
|
||||
Plan_insert::analyze(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
stmtArea().stmtInfo().setName(Stmt_name_insert);
|
||||
ctx_assert(m_table != 0);
|
||||
m_table->analyze(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
// handle MySql syntax
|
||||
if (m_mysqlRow != 0) {
|
||||
setDmlRow(m_mysqlRow->m_dmlRow);
|
||||
setExprRow(m_mysqlRow->m_exprRow);
|
||||
m_mysqlRow = 0;
|
||||
}
|
||||
if (m_dmlRow == 0) {
|
||||
// construct column list
|
||||
setDmlRow(new Plan_dml_row(m_root));
|
||||
m_root->saveNode(m_dmlRow);
|
||||
const DictTable& dictTable = m_table->dictTable();
|
||||
unsigned n = dictTable.getSize();
|
||||
for (unsigned i = 1; i <= n; i++) {
|
||||
DictColumn* dictColumn = dictTable.getColumn(i);
|
||||
Plan_dml_column* column = new Plan_dml_column(m_root, dictColumn->getName());
|
||||
m_root->saveNode(column);
|
||||
m_dmlRow->addColumn(column);
|
||||
}
|
||||
}
|
||||
// set name resolution scope
|
||||
ctl.m_tableList.resize(1 + 1); // indexed from 1
|
||||
ctl.m_tableList[1] = m_table;
|
||||
// analyze the dml columns
|
||||
m_dmlRow->analyze(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
ctl.m_dmlRow = m_dmlRow; // row type to convert to
|
||||
if (m_query != 0) {
|
||||
m_query->analyze(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
} else if (m_select == 0) {
|
||||
// analyze the expression row
|
||||
m_exprRow->analyze(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
// transform the row into query
|
||||
Plan_query_repeat* queryRepeat = new Plan_query_repeat(m_root, 1);
|
||||
m_root->saveNode(queryRepeat);
|
||||
Plan_query_project* queryProject = new Plan_query_project(m_root);
|
||||
m_root->saveNode(queryProject);
|
||||
queryProject->setQuery(queryRepeat);
|
||||
queryProject->setRow(m_exprRow);
|
||||
setQuery(queryProject);
|
||||
} else {
|
||||
// analyze the select into query
|
||||
Plan_query* query = static_cast<Plan_query*>(m_select->analyze(ctx, ctl));
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
setQuery(query);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_insert::describe(Ctx& ctx)
|
||||
{
|
||||
stmtArea().setFunction(ctx, "INSERT", SQL_DIAG_INSERT);
|
||||
}
|
||||
|
||||
Exec_base*
|
||||
Plan_insert::codegen(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
// create code for the query
|
||||
ctx_assert(m_query != 0);
|
||||
Exec_query* execQuery = static_cast<Exec_query*>(m_query->codegen(ctx, ctl));
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
ctx_assert(execQuery != 0);
|
||||
// set up
|
||||
ctx_assert(m_table != 0);
|
||||
const BaseString& tableName = m_table->getName();
|
||||
const DictTable& dictTable = m_table->dictTable();
|
||||
const ColumnVector& columns = m_table->dmlColumns();
|
||||
ctx_assert(columns.size() > 0);
|
||||
const unsigned attrCount = columns.size() - 1;
|
||||
// create the code
|
||||
Exec_insert::Code& code = *new Exec_insert::Code();
|
||||
code.m_insertOp = m_insertOp;
|
||||
code.m_tableName = strcpy(new char[tableName.length() + 1], tableName.c_str());
|
||||
code.m_attrCount = attrCount;
|
||||
code.m_attrId = new NdbAttrId[1 + attrCount];
|
||||
code.m_isKey = new bool[1 + attrCount];
|
||||
code.m_attrId[0] = (NdbAttrId)-1;
|
||||
code.m_tupleId = dictTable.tupleId(); // maybe 0
|
||||
code.m_autoIncrement = dictTable.autoIncrement(); // maybe 0
|
||||
unsigned k;
|
||||
if ((k = code.m_tupleId) != 0 || (k = code.m_autoIncrement) != 0) {
|
||||
const DictColumn& dictColumn = *dictTable.getColumn(k);
|
||||
code.m_idType = dictColumn.sqlType();
|
||||
}
|
||||
for (unsigned i = 1; i <= attrCount; i++) {
|
||||
Plan_column* column = columns[i];
|
||||
ctx_assert(column != 0);
|
||||
const DictColumn& dictColumn = column->dictColumn();
|
||||
code.m_attrId[i] = dictColumn.getAttrId();
|
||||
code.m_isKey[i] = dictColumn.isKey();
|
||||
}
|
||||
// default values XXX a mess
|
||||
code.m_defaultCount = 0;
|
||||
for (unsigned j = 1; j <= dictTable.getSize(); j++) {
|
||||
const DictColumn& dictColumn = *dictTable.getColumn(j);
|
||||
if (dictColumn.getDefaultValue() != 0 && ! code.findAttrId(dictColumn.getAttrId()))
|
||||
code.m_defaultCount++;
|
||||
}
|
||||
if (code.m_defaultCount != 0) {
|
||||
code.m_defaultId = new NdbAttrId[1 + code.m_defaultCount];
|
||||
for (unsigned i = 0, j = 1; j <= dictTable.getSize(); j++) {
|
||||
const DictColumn& dictColumn = *dictTable.getColumn(j);
|
||||
if (dictColumn.getDefaultValue() != 0 && ! code.findAttrId(dictColumn.getAttrId()))
|
||||
code.m_defaultId[++i] = dictColumn.getAttrId();
|
||||
}
|
||||
SqlSpecs sqlSpecs(code.m_defaultCount);
|
||||
for (unsigned i = 0, j = 1; j <= dictTable.getSize(); j++) {
|
||||
const DictColumn& dictColumn = *dictTable.getColumn(j);
|
||||
if (dictColumn.getDefaultValue() != 0 && ! code.findAttrId(dictColumn.getAttrId())) {
|
||||
SqlSpec sqlSpec(dictColumn.sqlType(), SqlSpec::Physical);
|
||||
sqlSpecs.setEntry(++i, sqlSpec);
|
||||
}
|
||||
}
|
||||
code.m_defaultValue = new SqlRow(sqlSpecs);
|
||||
for (unsigned i = 0, j = 1; j <= dictTable.getSize(); j++) {
|
||||
const DictColumn& dictColumn = *dictTable.getColumn(j);
|
||||
if (dictColumn.getDefaultValue() != 0 && ! code.findAttrId(dictColumn.getAttrId())) {
|
||||
const char* defaultValue = dictColumn.getDefaultValue();
|
||||
ExtType extType(ExtType::Char);
|
||||
ExtSpec extSpec(extType);
|
||||
SQLINTEGER ind = SQL_NTS;
|
||||
ExtField extField(extSpec, (SQLPOINTER)defaultValue, 0, &ind);
|
||||
SqlField& f = code.m_defaultValue->getEntry(++i);
|
||||
f.copyin(ctx, extField);
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// create the exec
|
||||
Exec_insert* exec = new Exec_insert(ctl.m_execRoot);
|
||||
ctl.m_execRoot->saveNode(exec);
|
||||
exec->setCode(code);
|
||||
exec->setQuery(execQuery);
|
||||
return exec;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_insert::print(Ctx& ctx)
|
||||
{
|
||||
ctx.print(" [%s", m_insertOp == Insert_op_insert ? "insert" : "write");
|
||||
Plan_base* a[] = { m_table, m_dmlRow, m_exprRow, m_query };
|
||||
printList(ctx, a, 4);
|
||||
ctx.print("]");
|
||||
}
|
||||
|
||||
// Exec_insert
|
||||
|
||||
Exec_insert::Code::~Code()
|
||||
{
|
||||
delete[] m_tableName;
|
||||
delete[] m_attrId;
|
||||
delete[] m_isKey;
|
||||
delete[] m_defaultId;
|
||||
delete m_defaultValue;
|
||||
}
|
||||
|
||||
bool
|
||||
Exec_insert::Code::findAttrId(NdbAttrId attrId) const
|
||||
{
|
||||
for (unsigned i = 1; i <= m_attrCount; i++) {
|
||||
if (m_attrId[i] == attrId)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Exec_insert::Data::~Data()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_insert::~Exec_insert()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Exec_insert::alloc(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
// allocate the query
|
||||
ctx_assert(m_query != 0);
|
||||
m_query->alloc(ctx, ctl);
|
||||
// create data
|
||||
Data& data = *new Data();
|
||||
setData(data);
|
||||
}
|
||||
|
||||
void
|
||||
Exec_insert::close(Ctx& ctx)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Exec_insert::print(Ctx& ctx)
|
||||
{
|
||||
const Code& code = getCode();
|
||||
ctx_assert(m_query != 0);
|
||||
ctx.print(" [insert");
|
||||
ctx.print(" attrId=");
|
||||
for (unsigned i = 1; i <= code.m_attrCount; i++) {
|
||||
if (i > 1)
|
||||
ctx.print(",");
|
||||
ctx.print("%u", (unsigned)code.m_attrId[i]);
|
||||
}
|
||||
ctx.print(" table=%s", code.m_tableName);
|
||||
m_query->print(ctx);
|
||||
ctx.print("]");
|
||||
}
|
|
@ -1,229 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef ODBC_CODEGEN_Code_insert_hpp
|
||||
#define ODBC_CODEGEN_Code_insert_hpp
|
||||
|
||||
#include <common/common.hpp>
|
||||
#include "Code_base.hpp"
|
||||
#include "Code_dml.hpp"
|
||||
#include "Code_dml_row.hpp"
|
||||
#include "Code_expr_row.hpp"
|
||||
#include "Code_select.hpp"
|
||||
#include "Code_query.hpp"
|
||||
#include "Code_table.hpp"
|
||||
#include "Code_set_row.hpp"
|
||||
|
||||
enum Insert_op {
|
||||
Insert_op_undef = 0,
|
||||
Insert_op_insert = 1,
|
||||
Insert_op_write = 2
|
||||
};
|
||||
|
||||
/**
|
||||
* @class Plan_insert
|
||||
* @brief Insert in PlanTree
|
||||
*
|
||||
* Insert. Becomes directly executable.
|
||||
*/
|
||||
class Plan_insert : public Plan_dml {
|
||||
public:
|
||||
Plan_insert(Plan_root* root, Insert_op insertOp);
|
||||
virtual ~Plan_insert();
|
||||
Plan_base* analyze(Ctx& ctx, Ctl& ctl);
|
||||
void describe(Ctx& ctx);
|
||||
Exec_base* codegen(Ctx& ctx, Ctl& ctl);
|
||||
void print(Ctx& ctx);
|
||||
// children
|
||||
void setTable(Plan_table* table);
|
||||
Plan_dml_row* getDmlRow() const;
|
||||
void setDmlRow(Plan_dml_row* dmlRow);
|
||||
void setExprRow(Plan_expr_row* exprRow);
|
||||
void setSelect(Plan_select* select);
|
||||
void setQuery(Plan_query* query);
|
||||
void setMysqlRow(Plan_set_row* mysqlRow);
|
||||
protected:
|
||||
Insert_op m_insertOp;
|
||||
Plan_table* m_table;
|
||||
Plan_dml_row* m_dmlRow;
|
||||
Plan_expr_row* m_exprRow;
|
||||
Plan_select* m_select;
|
||||
Plan_query* m_query;
|
||||
Plan_set_row* m_mysqlRow;
|
||||
};
|
||||
|
||||
inline
|
||||
Plan_insert::Plan_insert(Plan_root* root, Insert_op insertOp) :
|
||||
Plan_dml(root),
|
||||
m_insertOp(insertOp),
|
||||
m_table(0),
|
||||
m_dmlRow(0),
|
||||
m_exprRow(0),
|
||||
m_select(0),
|
||||
m_query(0),
|
||||
m_mysqlRow(0)
|
||||
{
|
||||
}
|
||||
|
||||
// children
|
||||
|
||||
inline void
|
||||
Plan_insert::setTable(Plan_table* table)
|
||||
{
|
||||
ctx_assert(table != 0);
|
||||
m_table = table;
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_insert::setDmlRow(Plan_dml_row* dmlRow)
|
||||
{
|
||||
ctx_assert(dmlRow != 0);
|
||||
m_dmlRow = dmlRow;
|
||||
}
|
||||
|
||||
inline Plan_dml_row*
|
||||
Plan_insert::getDmlRow() const
|
||||
{
|
||||
ctx_assert(m_dmlRow != 0);
|
||||
return m_dmlRow;
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_insert::setExprRow(Plan_expr_row* exprRow)
|
||||
{
|
||||
ctx_assert(exprRow != 0);
|
||||
m_exprRow = exprRow;
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_insert::setSelect(Plan_select* select)
|
||||
{
|
||||
ctx_assert(select != 0);
|
||||
m_select = select;
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_insert::setQuery(Plan_query* query)
|
||||
{
|
||||
ctx_assert(query != 0);
|
||||
m_query = query;
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_insert::setMysqlRow(Plan_set_row* mysqlRow)
|
||||
{
|
||||
ctx_assert(mysqlRow != 0);
|
||||
m_mysqlRow = mysqlRow;
|
||||
}
|
||||
|
||||
/**
|
||||
* @class Exec_insert
|
||||
* @brief Executable insert
|
||||
*/
|
||||
class Exec_insert : public Exec_dml {
|
||||
public:
|
||||
class Code : public Exec_dml::Code {
|
||||
public:
|
||||
Code();
|
||||
virtual ~Code();
|
||||
protected:
|
||||
friend class Plan_insert;
|
||||
friend class Exec_insert;
|
||||
Insert_op m_insertOp;
|
||||
char* m_tableName;
|
||||
unsigned m_attrCount;
|
||||
NdbAttrId* m_attrId;
|
||||
bool* m_isKey;
|
||||
unsigned m_tupleId; // position of tuple id
|
||||
unsigned m_autoIncrement; // position of ai key
|
||||
SqlType m_idType; // type of tuple id or ai key
|
||||
unsigned m_defaultCount;
|
||||
NdbAttrId* m_defaultId;
|
||||
SqlRow* m_defaultValue;
|
||||
bool findAttrId(NdbAttrId attrId) const;
|
||||
};
|
||||
class Data : public Exec_dml::Data {
|
||||
public:
|
||||
Data();
|
||||
virtual ~Data();
|
||||
protected:
|
||||
friend class Exec_insert;
|
||||
};
|
||||
Exec_insert(Exec_root* root);
|
||||
virtual ~Exec_insert();
|
||||
void alloc(Ctx& ctx, Ctl& ctl);
|
||||
void execImpl(Ctx& ctx, Ctl& ctl);
|
||||
void close(Ctx& ctx);
|
||||
void print(Ctx& ctx);
|
||||
// children
|
||||
const Code& getCode() const;
|
||||
Data& getData() const;
|
||||
void setQuery(Exec_query* query);
|
||||
private:
|
||||
Exec_query* m_query;
|
||||
};
|
||||
|
||||
inline
|
||||
Exec_insert::Code::Code() :
|
||||
m_insertOp(Insert_op_undef),
|
||||
m_tableName(0),
|
||||
m_attrCount(0),
|
||||
m_attrId(0),
|
||||
m_isKey(0),
|
||||
m_tupleId(0),
|
||||
m_autoIncrement(0),
|
||||
m_defaultCount(0),
|
||||
m_defaultId(0),
|
||||
m_defaultValue(0)
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_insert::Data::Data()
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_insert::Exec_insert(Exec_root* root) :
|
||||
Exec_dml(root),
|
||||
m_query(0)
|
||||
{
|
||||
}
|
||||
|
||||
// children
|
||||
|
||||
inline const Exec_insert::Code&
|
||||
Exec_insert::getCode() const
|
||||
{
|
||||
const Code* code = static_cast<const Code*>(m_code);
|
||||
return *code;
|
||||
}
|
||||
|
||||
inline Exec_insert::Data&
|
||||
Exec_insert::getData() const
|
||||
{
|
||||
Data* data = static_cast<Data*>(m_data);
|
||||
return *data;
|
||||
}
|
||||
|
||||
inline void
|
||||
Exec_insert::setQuery(Exec_query* query)
|
||||
{
|
||||
ctx_assert(m_query == 0 && query != 0);
|
||||
m_query = query;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,70 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include "Code_pred.hpp"
|
||||
#include "Code_pred_op.hpp"
|
||||
#include "Code_root.hpp"
|
||||
|
||||
// Plan_pred
|
||||
|
||||
Plan_pred::~Plan_pred()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
Plan_pred::isGroupBy(const Plan_expr_row* row) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Plan_pred*
|
||||
Plan_pred::opAnd(Plan_pred* pred2)
|
||||
{
|
||||
Plan_pred_op* predAnd = new Plan_pred_op(m_root, Pred_op::And);
|
||||
m_root->saveNode(predAnd);
|
||||
predAnd->setPred(1, this);
|
||||
predAnd->setPred(2, pred2);
|
||||
return predAnd;
|
||||
}
|
||||
|
||||
// Exec_pred
|
||||
|
||||
Exec_pred::Code::~Code()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_pred::Data::~Data()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_pred::~Exec_pred()
|
||||
{
|
||||
}
|
||||
|
||||
Pred_value&
|
||||
Exec_pred::Data::groupValue(unsigned i, bool initFlag)
|
||||
{
|
||||
if (m_groupValue.size() == 0) {
|
||||
m_groupValue.resize(1);
|
||||
}
|
||||
if (initFlag) {
|
||||
//unsigned i2 = m_groupValue.size();
|
||||
//ctx_assert(i == i2);
|
||||
m_groupValue.push_back(Pred_value_unknown);
|
||||
}
|
||||
ctx_assert(i != 0 && i < m_groupValue.size());
|
||||
return m_groupValue[i];
|
||||
}
|
|
@ -1,172 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef ODBC_CODEGEN_Code_pred_hpp
|
||||
#define ODBC_CODEGEN_Code_pred_hpp
|
||||
|
||||
#include <common/common.hpp>
|
||||
#include <common/DataField.hpp>
|
||||
#include "Code_base.hpp"
|
||||
|
||||
enum Pred_value {
|
||||
Pred_value_unknown = -1,
|
||||
Pred_value_false = 0,
|
||||
Pred_value_true = 1
|
||||
};
|
||||
|
||||
class Ctx;
|
||||
class Plan_expr_row;
|
||||
class Exec_pred;
|
||||
|
||||
/**
|
||||
* @class Plan_pred
|
||||
* @brief Base class for predicates in PlanTree
|
||||
*
|
||||
* Predicate represents a boolean value.
|
||||
*/
|
||||
class Plan_pred : public Plan_base {
|
||||
public:
|
||||
// type is convenient since RTTI cannot be used
|
||||
enum Type {
|
||||
TypeUndefined = 0,
|
||||
TypeComp = 1,
|
||||
TypeOp = 2
|
||||
};
|
||||
Plan_pred(Plan_root* root, Type type);
|
||||
virtual ~Plan_pred() = 0;
|
||||
Type type() const;
|
||||
const TableSet& tableSet() const;
|
||||
const TableSet& noInterp() const;
|
||||
virtual bool isGroupBy(const Plan_expr_row* row) const;
|
||||
// helpers
|
||||
Plan_pred* opAnd(Plan_pred* pred2);
|
||||
protected:
|
||||
const Type m_type;
|
||||
TableSet m_tableSet; // depends on these tables
|
||||
TableSet m_noInterp; // cannot use interpreted TUP program on these tables
|
||||
Exec_pred* m_exec; // probably stupid
|
||||
};
|
||||
|
||||
inline
|
||||
Plan_pred::Plan_pred(Plan_root* root, Type type) :
|
||||
Plan_base(root),
|
||||
m_type(type),
|
||||
m_exec(0)
|
||||
{
|
||||
}
|
||||
|
||||
inline Plan_pred::Type
|
||||
Plan_pred::type() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
inline const Plan_pred::TableSet&
|
||||
Plan_pred::tableSet() const
|
||||
{
|
||||
return m_tableSet;
|
||||
}
|
||||
|
||||
inline const Plan_pred::TableSet&
|
||||
Plan_pred::noInterp() const
|
||||
{
|
||||
return m_noInterp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @class Exec_pred
|
||||
* @brief Base class for predicates in ExecTree
|
||||
*/
|
||||
class Exec_pred : public Exec_base {
|
||||
public:
|
||||
class Code : public Exec_base::Code {
|
||||
public:
|
||||
Code();
|
||||
virtual ~Code() = 0;
|
||||
protected:
|
||||
friend class Exec_pred;
|
||||
};
|
||||
class Data : public Exec_base::Data {
|
||||
public:
|
||||
Data();
|
||||
virtual ~Data() = 0;
|
||||
Pred_value getValue() const;
|
||||
Pred_value groupValue(unsigned i) const;
|
||||
protected:
|
||||
friend class Exec_pred;
|
||||
Pred_value m_value; // the value
|
||||
// group-by data
|
||||
typedef std::vector<Pred_value> GroupValue;
|
||||
GroupValue m_groupValue;
|
||||
Pred_value& groupValue(unsigned i, bool initFlag);
|
||||
};
|
||||
Exec_pred(Exec_root* root);
|
||||
virtual ~Exec_pred() = 0;
|
||||
virtual void execInterp(Ctx& ctx, Ctl& ctl) = 0;
|
||||
virtual void evaluate(Ctx& ctx, Ctl& ctl) = 0;
|
||||
// children
|
||||
const Code& getCode() const;
|
||||
Data& getData() const;
|
||||
};
|
||||
|
||||
inline
|
||||
Exec_pred::Code::Code()
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_pred::Data::Data() :
|
||||
m_value(Pred_value_unknown)
|
||||
{
|
||||
}
|
||||
|
||||
inline Pred_value
|
||||
Exec_pred::Data::getValue() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
inline Pred_value
|
||||
Exec_pred::Data::groupValue(unsigned i) const
|
||||
{
|
||||
ctx_assert(i != 0 && i < m_groupValue.size());
|
||||
return m_groupValue[i];
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_pred::Exec_pred(Exec_root* root) :
|
||||
Exec_base(root)
|
||||
{
|
||||
}
|
||||
|
||||
// children
|
||||
|
||||
inline const Exec_pred::Code&
|
||||
Exec_pred::getCode() const
|
||||
{
|
||||
const Code* code = static_cast<const Code*>(m_code);
|
||||
return *code;
|
||||
}
|
||||
|
||||
inline Exec_pred::Data&
|
||||
Exec_pred::getData() const
|
||||
{
|
||||
Data* data = static_cast<Data*>(m_data);
|
||||
return *data;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -1,188 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include "Code_pred.hpp"
|
||||
#include "Code_pred_op.hpp"
|
||||
#include "Code_root.hpp"
|
||||
|
||||
// Pred_op
|
||||
|
||||
const char*
|
||||
Pred_op::name() const
|
||||
{
|
||||
switch (m_opcode) {
|
||||
case And:
|
||||
return "and";
|
||||
case Or:
|
||||
return "or";
|
||||
case Not:
|
||||
return "not";
|
||||
}
|
||||
ctx_assert(false);
|
||||
return "";
|
||||
}
|
||||
|
||||
unsigned
|
||||
Pred_op::arity() const
|
||||
{
|
||||
switch (m_opcode) {
|
||||
case And:
|
||||
case Or:
|
||||
return 2;
|
||||
case Not:
|
||||
return 1;
|
||||
}
|
||||
ctx_assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Plan_pred_op
|
||||
|
||||
Plan_pred_op::~Plan_pred_op()
|
||||
{
|
||||
}
|
||||
|
||||
Plan_base*
|
||||
Plan_pred_op::analyze(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
m_exec = 0;
|
||||
unsigned arity = m_op.arity();
|
||||
// check if we remain in top-level AND-clause
|
||||
const bool topand = ctl.m_topand;
|
||||
if (m_op.m_opcode != Pred_op::And)
|
||||
ctl.m_topand = false;
|
||||
// analyze sub-predicates
|
||||
for (unsigned i = 1; i <= arity; i++) {
|
||||
ctx_assert(m_pred[i] != 0);
|
||||
m_pred[i]->analyze(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
}
|
||||
// save top level predicate on list
|
||||
if (topand && ! ctl.m_topand) {
|
||||
ctl.m_topcomp.push_back(this);
|
||||
}
|
||||
ctl.m_topand = topand;
|
||||
// table dependencies are union from operands
|
||||
m_tableSet.clear();
|
||||
for (unsigned i = 1; i <= arity; i++) {
|
||||
const TableSet& ts = m_pred[i]->tableSet();
|
||||
m_tableSet.insert(ts.begin(), ts.end());
|
||||
}
|
||||
// set of tables for which interpreter cannot be used
|
||||
m_noInterp.clear();
|
||||
for (unsigned i = 1; i <= arity; i++) {
|
||||
const TableSet& ts = m_pred[i]->noInterp();
|
||||
m_noInterp.insert(ts.begin(), ts.end());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
Exec_base*
|
||||
Plan_pred_op::codegen(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
if (m_exec != 0)
|
||||
return m_exec;
|
||||
unsigned arity = m_op.arity();
|
||||
Exec_pred_op* exec = new Exec_pred_op(ctl.m_execRoot);
|
||||
ctl.m_execRoot->saveNode(exec);
|
||||
// create code for operands
|
||||
for (unsigned i = 1; i <= arity; i++) {
|
||||
ctx_assert(m_pred[i] != 0);
|
||||
Exec_pred* execPred = static_cast<Exec_pred*>(m_pred[i]->codegen(ctx, ctl));
|
||||
if (! ctx.ok())
|
||||
return 0;
|
||||
ctx_assert(execPred != 0);
|
||||
exec->setPred(i, execPred);
|
||||
}
|
||||
// create the code
|
||||
Exec_pred_op::Code& code = *new Exec_pred_op::Code(m_op);
|
||||
exec->setCode(code);
|
||||
m_exec = exec;
|
||||
return exec;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_pred_op::print(Ctx& ctx)
|
||||
{
|
||||
ctx.print(" [%s", m_op.name());
|
||||
Plan_base* a[] = { m_pred[1], m_pred[2] };
|
||||
printList(ctx, a, m_op.arity());
|
||||
ctx.print("]");
|
||||
}
|
||||
|
||||
bool
|
||||
Plan_pred_op::isGroupBy(const Plan_expr_row* row) const
|
||||
{
|
||||
const unsigned arity = m_op.arity();
|
||||
for (unsigned i = 1; i <= arity; i++) {
|
||||
ctx_assert(m_pred[i] != 0);
|
||||
if (! m_pred[i]->isGroupBy(row))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Code_pred_op
|
||||
|
||||
Exec_pred_op::Code::~Code()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_pred_op::Data::~Data()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_pred_op::~Exec_pred_op()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Exec_pred_op::alloc(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
const Code& code = getCode();
|
||||
// allocate sub-predicates
|
||||
unsigned arity = code.m_op.arity();
|
||||
for (unsigned i = 1; i <= arity; i++) {
|
||||
ctx_assert(m_pred[i] != 0);
|
||||
m_pred[i]->alloc(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return;
|
||||
}
|
||||
Data& data = *new Data;
|
||||
setData(data);
|
||||
}
|
||||
|
||||
void
|
||||
Exec_pred_op::close(Ctx& ctx)
|
||||
{
|
||||
const Code& code = getCode();
|
||||
unsigned arity = code.m_op.arity();
|
||||
for (unsigned i = 1; i <= arity; i++) {
|
||||
ctx_assert(m_pred[i] != 0);
|
||||
m_pred[i]->close(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Exec_pred_op::print(Ctx& ctx)
|
||||
{
|
||||
const Code& code = getCode();
|
||||
ctx.print(" [%s", code.m_op.name());
|
||||
Exec_base* a[] = { m_pred[1], m_pred[2] };
|
||||
printList(ctx, a, code.m_op.arity());
|
||||
ctx.print("]");
|
||||
}
|
|
@ -1,158 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef ODBC_CODEGEN_Code_pred_op_hpp
|
||||
#define ODBC_CODEGEN_Code_pred_op_hpp
|
||||
|
||||
#include <common/common.hpp>
|
||||
#include <common/DataField.hpp>
|
||||
#include "Code_pred.hpp"
|
||||
|
||||
/**
|
||||
* @class Pred_op
|
||||
* @brief Boolean operators
|
||||
*/
|
||||
struct Pred_op {
|
||||
enum Opcode {
|
||||
And = 1, // binary
|
||||
Or,
|
||||
Not // unary
|
||||
};
|
||||
Pred_op(Opcode opcode);
|
||||
const char* name() const;
|
||||
unsigned arity() const;
|
||||
Opcode m_opcode;
|
||||
};
|
||||
|
||||
inline
|
||||
Pred_op::Pred_op(Opcode opcode) :
|
||||
m_opcode(opcode)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @class Plan_pred_op
|
||||
* @brief Operator node in a predicate in PlanTree
|
||||
*/
|
||||
class Plan_pred_op : public Plan_pred {
|
||||
public:
|
||||
Plan_pred_op(Plan_root* root, Pred_op op);
|
||||
virtual ~Plan_pred_op();
|
||||
Plan_base* analyze(Ctx& ctx, Ctl& ctl);
|
||||
Exec_base* codegen(Ctx& ctx, Ctl& ctl);
|
||||
void print(Ctx& ctx);
|
||||
bool isGroupBy(const Plan_expr_row* row) const;
|
||||
// children
|
||||
void setPred(unsigned i, Plan_pred* pred);
|
||||
protected:
|
||||
friend class Plan_pred;
|
||||
Pred_op m_op;
|
||||
Plan_pred* m_pred[1 + 2];
|
||||
};
|
||||
|
||||
inline
|
||||
Plan_pred_op::Plan_pred_op(Plan_root* root, Pred_op op) :
|
||||
Plan_pred(root, TypeOp),
|
||||
m_op(op)
|
||||
{
|
||||
m_pred[0] = m_pred[1] = m_pred[2] = 0;
|
||||
}
|
||||
|
||||
inline void
|
||||
Plan_pred_op::setPred(unsigned i, Plan_pred* pred)
|
||||
{
|
||||
ctx_assert(1 <= i && i <= m_op.arity() && pred != 0);
|
||||
m_pred[i] = pred;
|
||||
}
|
||||
|
||||
/**
|
||||
* @class Exec_pred_op
|
||||
* @brief Operator node in a predicate in ExecTree
|
||||
*/
|
||||
class Exec_pred_op : public Exec_pred {
|
||||
public:
|
||||
class Code : public Exec_pred::Code {
|
||||
public:
|
||||
Code(Pred_op op);
|
||||
virtual ~Code();
|
||||
protected:
|
||||
friend class Exec_pred_op;
|
||||
Pred_op m_op;
|
||||
};
|
||||
class Data : public Exec_pred::Data {
|
||||
public:
|
||||
Data();
|
||||
virtual ~Data();
|
||||
protected:
|
||||
friend class Exec_pred_op;
|
||||
};
|
||||
Exec_pred_op(Exec_root* root);
|
||||
virtual ~Exec_pred_op();
|
||||
void alloc(Ctx& ctx, Ctl& ctl);
|
||||
void execInterp(Ctx& ctx, Ctl& ctl);
|
||||
void evaluate(Ctx& ctx, Ctl& ctl);
|
||||
void close(Ctx& ctx);
|
||||
void print(Ctx& ctx);
|
||||
// children
|
||||
const Code& getCode() const;
|
||||
Data& getData() const;
|
||||
void setPred(unsigned i, Exec_pred* pred);
|
||||
protected:
|
||||
Exec_pred* m_pred[1 + 2];
|
||||
};
|
||||
|
||||
inline
|
||||
Exec_pred_op::Code::Code(Pred_op op) :
|
||||
m_op(op)
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_pred_op::Data::Data()
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Exec_pred_op::Exec_pred_op(Exec_root* root) :
|
||||
Exec_pred(root)
|
||||
{
|
||||
m_pred[0] = m_pred[1] = m_pred[2] = 0;
|
||||
}
|
||||
|
||||
// children
|
||||
|
||||
inline const Exec_pred_op::Code&
|
||||
Exec_pred_op::getCode() const
|
||||
{
|
||||
const Code* code = static_cast<const Code*>(m_code);
|
||||
return *code;
|
||||
}
|
||||
|
||||
inline Exec_pred_op::Data&
|
||||
Exec_pred_op::getData() const
|
||||
{
|
||||
Data* data = static_cast<Data*>(m_data);
|
||||
return *data;
|
||||
}
|
||||
|
||||
inline void
|
||||
Exec_pred_op::setPred(unsigned i, Exec_pred* pred)
|
||||
{
|
||||
ctx_assert(1 <= i && i <= 2 && m_pred[i] == 0);
|
||||
m_pred[i] = pred;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,299 +0,0 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include <common/StmtArea.hpp>
|
||||
#include "Code_query.hpp"
|
||||
#include "Code_query_project.hpp"
|
||||
#include "Code_query_count.hpp"
|
||||
|
||||
// Plan_query
|
||||
|
||||
Plan_query::~Plan_query()
|
||||
{
|
||||
}
|
||||
|
||||
Plan_expr_row*
|
||||
Plan_query::getRow()
|
||||
{
|
||||
ctx_assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
Plan_query::describe(Ctx& ctx)
|
||||
{
|
||||
const Plan_expr_row* exprRow = getRow();
|
||||
const unsigned count = exprRow->getSize();
|
||||
// create IRD
|
||||
DescArea& ird = descArea(Desc_usage_IRD);
|
||||
ird.setCount(ctx, count);
|
||||
for (unsigned i = 1; i <= count; i++) {
|
||||
DescRec& rec = ird.getRecord(i);
|
||||
const Plan_expr* expr = exprRow->m_exprList[i];
|
||||
const SqlType& sqlType = expr->sqlType();
|
||||
// data type
|
||||
SQLSMALLINT desc_TYPE = sqlType.type();
|
||||
rec.setField(SQL_DESC_TYPE, desc_TYPE);
|
||||
SQLSMALLINT desc_CONCISE_TYPE = desc_TYPE;
|
||||
rec.setField(SQL_DESC_CONCISE_TYPE, desc_CONCISE_TYPE);
|
||||
SQLSMALLINT desc_DESC_DATETIME_INTERVAL_CODE = 0;
|
||||
rec.setField(SQL_DESC_DATETIME_INTERVAL_CODE, desc_DESC_DATETIME_INTERVAL_CODE);
|
||||
// nullable
|
||||
SQLSMALLINT desc_NULLABLE = sqlType.nullable() ? SQL_NULLABLE : SQL_NO_NULLS;
|
||||
rec.setField(SQL_DESC_NULLABLE, desc_NULLABLE);
|
||||
// unsigned
|
||||
SQLSMALLINT desc_UNSIGNED;
|
||||
switch (sqlType.type()) {
|
||||
case SQL_SMALLINT:
|
||||
case SQL_INTEGER:
|
||||
case SQL_BIGINT:
|
||||
desc_UNSIGNED = sqlType.unSigned() ? SQL_TRUE : SQL_FALSE;
|
||||
break;
|
||||
default:
|
||||
desc_UNSIGNED = SQL_TRUE; // thus spake microsoft
|
||||
break;
|
||||
}
|
||||
rec.setField(SQL_DESC_UNSIGNED, desc_UNSIGNED);
|
||||
// sizes
|
||||
SQLUINTEGER desc_LENGTH = sqlType.length();
|
||||
rec.setField(SQL_DESC_LENGTH, desc_LENGTH);
|
||||
SQLINTEGER desc_OCTET_LENGTH = sqlType.size();
|
||||
rec.setField(SQL_DESC_OCTET_LENGTH, desc_OCTET_LENGTH);
|
||||
SQLINTEGER desc_DISPLAY_SIZE = sqlType.displaySize();
|
||||
rec.setField(SQL_DESC_DISPLAY_SIZE, desc_DISPLAY_SIZE);
|
||||
// name
|
||||
ctx_assert(i < exprRow->m_aliasList.size());
|
||||
const char* desc_NAME = exprRow->m_aliasList[i].c_str();
|
||||
rec.setField(SQL_DESC_NAME, desc_NAME);
|
||||
}
|
||||
ctx_log3(("describe %u columns done", count));
|
||||
stmtArea().setFunction(ctx, "SELECT CURSOR", SQL_DIAG_SELECT_CURSOR);
|
||||
}
|
||||
|
||||
// Exec_query
|
||||
|
||||
Exec_query::Code::~Code()
|
||||
{
|
||||
}
|
||||
|
||||
Exec_query::Data::~Data()
|
||||
{
|
||||
delete m_extRow;
|
||||
m_extRow = 0;
|
||||
delete[] m_extPos;
|
||||
m_extPos = 0;
|
||||
}
|
||||
|
||||
Exec_query::~Exec_query()
|
||||
{
|
||||
}
|
||||
|
||||
const Exec_query*
|
||||
Exec_query::getRawQuery() const
|
||||
{
|
||||
ctx_assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
Exec_query::bind(Ctx& ctx)
|
||||
{
|
||||
const Code& code = getCode();
|
||||
const SqlSpecs& sqlSpecs = code.sqlSpecs();
|
||||
const unsigned count = sqlSpecs.count();
|
||||
// read ARD
|
||||
DescArea& ard = descArea(Desc_usage_ARD);
|
||||
const unsigned ardCount = ard.getCount();
|
||||
// create specification row
|
||||
ExtSpecs extSpecs(count);
|
||||
for (unsigned i = 1; i <= count; i++) {
|
||||
ExtType extType;
|
||||
if (i <= ardCount) {
|
||||
OdbcData descData;
|
||||
DescRec& rec = ard.getRecord(i);
|
||||
// check for unbound column
|
||||
rec.getField(ctx, SQL_DESC_DATA_PTR, descData);
|
||||
SQLPOINTER desc_DATA_PTR = descData.type() != OdbcData::Undef ? descData.pointer() : 0;
|
||||
if (desc_DATA_PTR == 0) {
|
||||
extType.setType(ctx, ExtType::Unbound);
|
||||
} else {
|
||||
rec.getField(ctx, SQL_DESC_TYPE, descData);
|
||||
if (descData.type() == OdbcData::Undef) {
|
||||
ctx.pushStatus(Error::Gen, "query column %u: external type not defined", i);
|
||||
return;
|
||||
}
|
||||
SQLSMALLINT desc_TYPE = descData.smallint();
|
||||
if (desc_TYPE == SQL_C_DEFAULT) {
|
||||
if (i <= code.m_sqlSpecs.count())
|
||||
desc_TYPE = code.m_sqlSpecs.getEntry(i).sqlType().sqlcdefault(ctx);
|
||||
}
|
||||
switch (desc_TYPE) {
|
||||
case SQL_C_CHAR:
|
||||
case SQL_C_BINARY:
|
||||
case SQL_C_SHORT: // for sun.jdbc.odbc
|
||||
case SQL_C_SSHORT:
|
||||
case SQL_C_USHORT:
|
||||
case SQL_C_LONG: // for sun.jdbc.odbc
|
||||
case SQL_C_SLONG:
|
||||
case SQL_C_ULONG:
|
||||
case SQL_C_SBIGINT:
|
||||
case SQL_C_UBIGINT:
|
||||
case SQL_C_FLOAT:
|
||||
case SQL_C_DOUBLE:
|
||||
case SQL_C_TYPE_TIMESTAMP:
|
||||
break;
|
||||
default:
|
||||
ctx.pushStatus(Error::Gen, "query column %u: unsupported external type %d", i, (int)desc_TYPE);
|
||||
return;
|
||||
}
|
||||
extType.setType(ctx, static_cast<ExtType::Type>(desc_TYPE));
|
||||
}
|
||||
} else {
|
||||
extType.setType(ctx, ExtType::Unbound);
|
||||
}
|
||||
const ExtSpec extSpec(extType);
|
||||
extSpecs.setEntry(i, extSpec);
|
||||
}
|
||||
// create data row
|
||||
ExtRow& extRow = *new ExtRow(extSpecs);
|
||||
unsigned boundCount = 0;
|
||||
for (unsigned i = 1; i <= count; i++) {
|
||||
const ExtSpec& extSpec = extSpecs.getEntry(i);
|
||||
if (extSpec.extType().type() != ExtType::Unbound) {
|
||||
OdbcData descData;
|
||||
DescRec& rec = ard.getRecord(i);
|
||||
rec.getField(ctx, SQL_DESC_DATA_PTR, descData);
|
||||
SQLPOINTER desc_DATA_PTR = descData.type() != OdbcData::Undef ? descData.pointer() : 0;
|
||||
rec.getField(ctx, SQL_DESC_OCTET_LENGTH, descData);
|
||||
SQLINTEGER desc_OCTET_LENGTH = descData.type() != OdbcData::Undef ? descData.integer() : 0;
|
||||
rec.getField(ctx, SQL_DESC_INDICATOR_PTR, descData);
|
||||
SQLINTEGER* desc_INDICATOR_PTR = descData.type() != OdbcData::Undef ? descData.integerPtr() : 0;
|
||||
ctx_log4(("column %u: bind to 0x%x %d 0x%x", i, (unsigned)desc_DATA_PTR, (int)desc_OCTET_LENGTH, (unsigned)desc_INDICATOR_PTR));
|
||||
ExtField extField(extSpec, desc_DATA_PTR, desc_OCTET_LENGTH, desc_INDICATOR_PTR, i);
|
||||
extRow.setEntry(i, extField);
|
||||
boundCount++;
|
||||
} else {
|
||||
ExtField extField(extSpec, i);
|
||||
extRow.setEntry(i, extField);
|
||||
}
|
||||
}
|
||||
Data& data = getData();
|
||||
delete data.m_extRow;
|
||||
data.m_extRow = &extRow;
|
||||
ctx_log3(("bound %u out of %u columns", boundCount, count));
|
||||
}
|
||||
|
||||
// execute and fetch
|
||||
|
||||
void
|
||||
Exec_query::execute(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
Data& data = getData();
|
||||
execImpl(ctx, ctl);
|
||||
if (! ctx.ok())
|
||||
return;
|
||||
data.initState();
|
||||
if (m_topLevel) {
|
||||
stmtArea().setRowCount(ctx, data.getCount());
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Exec_query::fetch(Ctx& ctx, Ctl& ctl)
|
||||
{
|
||||
const Code& code = getCode();
|
||||
Data& data = getData();
|
||||
if (data.fetch(ctx, ctl)) {
|
||||
if (m_topLevel) {
|
||||
stmtArea().setRowCount(ctx, data.getCount());
|
||||
}
|
||||
if (data.m_extRow != 0) {
|
||||
data.sqlRow().copyout(ctx, *data.m_extRow);
|
||||
if (! ctx.ok())
|
||||
return false;
|
||||
}
|
||||
if (data.m_extPos != 0) {
|
||||
const unsigned count = code.sqlSpecs().count();
|
||||
for (unsigned i = 0; i <= count; i++) {
|
||||
data.m_extPos[i] = 0;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (m_topLevel) {
|
||||
stmtArea().setRowCount(ctx, data.getCount());
|
||||
if (ctx.ok()) {
|
||||
ctx.setCode(SQL_NO_DATA);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// odbc support
|
||||
|
||||
void
|
||||
Exec_query::sqlGetData(Ctx& ctx, SQLUSMALLINT columnNumber, SQLSMALLINT targetType, SQLPOINTER targetValue, SQLINTEGER bufferLength, SQLINTEGER* strlen_or_Ind)
|
||||
{
|
||||
const Code& code = getCode();
|
||||
Data& data = getData();
|
||||
const SqlSpecs& sqlSpecs = code.m_sqlSpecs;
|
||||
const unsigned count = sqlSpecs.count();
|
||||
if (columnNumber == 0 || columnNumber > count) {
|
||||
ctx.pushStatus(Sqlstate::_07009, Error::Gen, "column index %u is not within 1 to %u", (unsigned)columnNumber, count);
|
||||
return;
|
||||
}
|
||||
// create positions array on first use
|
||||
if (data.m_extPos == 0) {
|
||||
data.m_extPos = new int[1 + count];
|
||||
for (unsigned i = 0; i <= count; i++) {
|
||||
data.m_extPos[i] = 0;
|
||||
}
|
||||
}
|
||||
if (targetType == SQL_ARD_TYPE) {
|
||||
// get type from ARD
|
||||
DescArea& ard = descArea(Desc_usage_ARD);
|
||||
const unsigned ardCount = ard.getCount();
|
||||
if (columnNumber <= ardCount) {
|
||||
OdbcData descData;
|
||||
DescRec& rec = ard.getRecord(columnNumber);
|
||||
rec.getField(ctx, SQL_DESC_CONCISE_TYPE, descData);
|
||||
if (descData.type() != OdbcData::Undef) {
|
||||
targetType = descData.smallint();
|
||||
}
|
||||
}
|
||||
if (targetType == SQL_ARD_TYPE) {
|
||||
ctx.pushStatus(Sqlstate::_07009, Error::Gen, "output column %u type not bound - cannot use SQL_ARD_TYPE", (unsigned)columnNumber);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ExtType extType;
|
||||
if (targetValue != 0) {
|
||||
extType.setType(ctx, static_cast<ExtType::Type>(targetType));
|
||||
// check if supported
|
||||
if (! ctx.ok())
|
||||
return;
|
||||
} else {
|
||||
extType.setType(ctx, ExtType::Unbound);
|
||||
}
|
||||
ExtSpec extSpec(extType);
|
||||
ExtField extField(extSpec, targetValue, bufferLength, strlen_or_Ind, columnNumber);
|
||||
// copy out and update position
|
||||
extField.setPos(data.m_extPos[columnNumber]);
|
||||
const SqlRow& sqlRow = data.sqlRow();
|
||||
const SqlField& sqlField = sqlRow.getEntry(columnNumber);
|
||||
sqlField.copyout(ctx, extField);
|
||||
data.m_extPos[columnNumber] = extField.getPos();
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue