Nuke all of the old_* directories in the ndb tree.

This commit is contained in:
jimw@mysql.com 2006-04-18 12:12:46 -07:00
parent 1d1040e1ea
commit 0302bb4fdd
581 changed files with 0 additions and 90603 deletions

View file

@ -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 \

View file

@ -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*

View file

@ -1,14 +0,0 @@
include .defs.mk
TYPE := ndbapitest
BIN_TARGET := munmaptest
SOURCES = munmaptest.cpp
include $(NDB_TOP)/Epilogue.mk

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}

View file

@ -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();
}

View file

@ -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

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}

View file

@ -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();
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -1,9 +0,0 @@
include .defs.mk
DIRS =
ifneq ($(NDB_ODBC),N)
DIRS += odbc
endif
include $(NDB_TOP)/Epilogue.mk

View file

@ -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

View file

@ -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

View file

@ -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)
{
}

View file

@ -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

View file

@ -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);
}

View file

@ -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

View file

@ -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);
}
}

View file

@ -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

View file

@ -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();
}

View file

@ -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

View file

@ -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("]");
}

View file

@ -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

View file

@ -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());
}

View file

@ -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

View file

@ -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);
}
}

View file

@ -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

View file

@ -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());
}

View file

@ -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

View file

@ -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]");
}

View file

@ -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

View file

@ -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()
{
}

View file

@ -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

View file

@ -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);
}

View file

@ -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

View file

@ -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("]");
}

View file

@ -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

View file

@ -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);
}
}

View file

@ -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

View file

@ -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("]");
}

View file

@ -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

View file

@ -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("]");
}

View file

@ -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

View file

@ -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("]");
}

View file

@ -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

View file

@ -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("]");
}

View file

@ -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

View file

@ -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);
}
}
}
}

View file

@ -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

View file

@ -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());
}

View file

@ -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

View file

@ -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("]");
}

View file

@ -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

View file

@ -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());
}

View file

@ -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

View file

@ -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());
}

View file

@ -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

View file

@ -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];
}

View file

@ -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

View file

@ -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);
}

View file

@ -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

View file

@ -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("]");
}

View file

@ -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

View file

@ -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("]");
}

View file

@ -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

View file

@ -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("]");
}

View file

@ -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

View file

@ -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("]");
}

View file

@ -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

View file

@ -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);
}

View file

@ -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

View file

@ -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("]");
}

View file

@ -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

View file

@ -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());
}

View file

@ -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

View file

@ -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("]");
}

View file

@ -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

View file

@ -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];
}

View file

@ -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

View file

@ -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("]");
}

View file

@ -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

View file

@ -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