parse.c

来自「postgresql-odbc,跨平台应用」· C语言 代码 · 共 1,872 行 · 第 1/3 页

C
1,872
字号
			} /* (in_expr || in_func) && in_select */			if (in_distinct)			{				mylog("in distinct\n");				if (unquoted && !stricmp(token, "on"))				{					in_on = TRUE;					mylog("got on\n");					continue;				}				if (in_on)				{					in_distinct = FALSE;					in_on = FALSE;					continue;	/* just skip the unique on field */				}				mylog("done distinct\n");				in_distinct = FALSE;			} /* in_distinct */			if (!in_field)			{				BOOL	fi_reuse = FALSE;				if (!token[0])					continue;				/* if (!(irdflds->nfields % FLD_INCR)) */				if (irdflds->nfields >= allocated_size)				{					mylog("reallocing at nfld=%d\n", irdflds->nfields);					new_size = irdflds->nfields + 1;					if (!allocateFields(irdflds, new_size))					{						SC_set_parse_status(stmt, STMT_PARSE_FATAL);						SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "PGAPI_AllocStmt failed in parse_statement for FIELD_INFO.", func);						goto cleanup;					}					fi = irdflds->fi;					allocated_size = irdflds->allocated;				}				wfi = fi[irdflds->nfields];				if (wfi)					fi_reuse = TRUE;				else					wfi = fi[irdflds->nfields] = (FIELD_INFO *) malloc(sizeof(FIELD_INFO));				if (wfi == NULL)				{					SC_set_parse_status(stmt, STMT_PARSE_FATAL);					SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "PGAPI_AllocStmt failed in parse_statement for FIELD_INFO(2).", func);					goto cleanup;				}				/* Initialize the field info */				FI_Constructor(wfi, fi_reuse);				wfi->flag = FIELD_PARSING;				/* double quotes are for qualifiers */				if (dquote)					wfi->dquote = TRUE;				if (quote)				{					wfi->quote = TRUE;					wfi->column_size = (int) strlen(token);				}				else if (numeric)				{					mylog("**** got numeric: nfld = %d\n", irdflds->nfields);					wfi->numeric = TRUE;				}				else if (0 == old_blevel && blevel > 0)				{				/* expression */					mylog("got EXPRESSION\n");					wfi->expr = TRUE;					in_expr = TRUE;					/* continue; */				}				else				{					STR_TO_NAME(wfi->column_name, token);					NULL_THE_NAME(wfi->before_dot);				}				mylog("got field='%s', dot='%s'\n", PRINT_NAME(wfi->column_name), PRINT_NAME(wfi->before_dot));				if (delim == ',')					mylog("comma (1)\n");				else					in_field = TRUE;				irdflds->nfields++;				continue;			} /* !in_field */			/*			 * We are in a field now			 */			wfi = fi[irdflds->nfields - 1];			if (in_dot)			{				if (NAME_IS_VALID(wfi->before_dot))				{					MOVE_NAME(wfi->schema_name, wfi->before_dot);				}				MOVE_NAME(wfi->before_dot, wfi->column_name);				STR_TO_NAME(wfi->column_name, token);				if (delim == ',')				{					mylog("in_dot: got comma\n");					in_field = FALSE;				}				in_dot = FALSE;				continue;			}			if (in_as)			{				STR_TO_NAME(wfi->column_alias, token);				mylog("alias for field '%s' is '%s'\n", PRINT_NAME(wfi->column_name), PRINT_NAME(wfi->column_alias));				in_as = FALSE;				in_field = FALSE;				if (delim == ',')					mylog("comma(2)\n");				continue;			}			/* Function */			if (0 == old_blevel && blevel > 0)			{				in_dot = FALSE;				in_func = TRUE;				wfi->func = TRUE;				/*				 * name will have the function name -- maybe useful some				 * day				 */				mylog("**** got function = '%s'\n", PRINT_NAME(wfi->column_name));				continue;			}			if (token[0] == '.')			{				in_dot = TRUE;				mylog("got dot\n");				continue;			}			in_dot = FALSE;			if (!stricmp(token, "as"))			{				in_as = TRUE;				mylog("got AS\n");				continue;			}			/* otherwise, it's probably an expression */			in_expr = TRUE;			wfi->expr = TRUE;			NULL_THE_NAME(wfi->column_name);			wfi->column_size = 0;			mylog("*** setting expression\n");		} /* in_select end */		if (in_from || in_where)		{			if (token[0] == ';') /* end of the first command */			{				in_select = in_from = in_where = in_table = FALSE;				break;			}		}		if (in_from)		{			switch (token[0])			{				case '\0':					continue;				case ',':					out_table = TRUE; 					continue;			}			if (out_table && !in_table) /* new table */			{				in_dot = FALSE;				maybe_join = 0;				if (!dquote)				{					if (token[0] == '(' ||					    token[0] == ')')						continue;				}				if (!increaseNtab(stmt, func))				{					SC_set_parse_status(stmt, STMT_PARSE_FATAL);					goto cleanup;				}				ti = stmt->ti;				wti = ti[stmt->ntab - 1];				if (dquote || stricmp(token, "select"))				{					STR_TO_NAME(wti->table_name, token);					lower_the_name(GET_NAME(wti->table_name), conn, dquote);				}				else				{					NULL_THE_NAME(wti->table_name);					TI_no_updatable(wti);				}				mylog("got table = '%s'\n", PRINT_NAME(wti->table_name));				if (0 == blevel && delim == ',')				{					out_table = TRUE;					mylog("more than 1 tables\n");				}				else				{					out_table = FALSE;					in_table = TRUE;				}				continue;			}			if (0 != blevel)				continue;			/* out_table is FALSE here */			if (!dquote && !in_dot)			{				if (')' == token[0])					continue;				if (stricmp(token, "LEFT") == 0 ||			    	    stricmp(token, "RIGHT") == 0 ||			    	    stricmp(token, "OUTER") == 0 ||			    	    stricmp(token, "FULL") == 0)				{					maybe_join = 1;					in_table = FALSE;					continue;				}				else if (stricmp(token, "INNER") == 0 ||					 stricmp(token, "CROSS") == 0)				{					maybe_join = 2;					in_table = FALSE;					continue;				}				else if (stricmp(token, "JOIN") == 0)				{					in_table = FALSE;					out_table = TRUE;					switch (maybe_join)					{						case 1:							SC_set_outer_join(stmt);							break;						case 2:							SC_set_inner_join(stmt);							break;					}					maybe_join = 0;					continue;				}			}			maybe_join = 0;			if (in_table)			{				wti = ti[stmt->ntab - 1];				if (in_dot)				{					MOVE_NAME(wti->schema_name, wti->table_name);					STR_TO_NAME(wti->table_name, token);					lower_the_name(GET_NAME(wti->table_name), conn, dquote);					in_dot = FALSE;					continue;				}				if (strcmp(token, ".") == 0)				{					in_dot = TRUE;					continue;				}				if (dquote || stricmp(token, "as"))				{					if (!dquote)					{						if (stricmp(token, "ON") == 0)						{							in_table = FALSE;							continue;						}					}					STR_TO_NAME(wti->table_alias, token);					mylog("alias for table '%s' is '%s'\n", PRINT_NAME(wti->table_name), PRINT_NAME(wti->table_alias));					in_table = FALSE;					if (delim == ',')					{						out_table = TRUE;						mylog("more than 1 tables\n");					}				}			}		} /* in_from */	}	/*	 * Resolve any possible field names with tables	 */	parse = TRUE;	/* Resolve field names with tables */	for (i = 0; i < (int) irdflds->nfields; i++)	{		wfi = fi[i];		if (wfi->func || wfi->expr || wfi->numeric)		{			wfi->ti = NULL;			wfi->columntype = wfi->basetype = (OID) 0;			parse = FALSE;			continue;		}		else if (wfi->quote)		{						/* handle as text */			wfi->ti = NULL;			/*			 * wfi->type = PG_TYPE_TEXT; wfi->column_size = 0; the			 * following may be better			 */			wfi->basetype = PG_TYPE_UNKNOWN;			if (wfi->column_size == 0)			{				wfi->basetype = PG_TYPE_VARCHAR;				wfi->column_size = 254;			}			wfi->length = wfi->column_size;			continue;		}		/* field name contains the schema name */		else if (NAME_IS_VALID(wfi->schema_name))		{			int	matchidx = -1;			for (k = 0; k < stmt->ntab; k++)			{				wti = ti[k];				if (!NAMEICMP(wti->table_name, wfi->before_dot))				{					if (!NAMEICMP(wti->schema_name, wfi->schema_name))					{						wfi->ti = wti;						break;					}					else if (NAME_IS_NULL(wti->schema_name))					{						if (matchidx < 0)							matchidx = k;						else						{							SC_set_parse_status(stmt, STMT_PARSE_FATAL);							SC_set_error(stmt, STMT_EXEC_ERROR, "duplicated Table name", func);							stmt->updatable = FALSE;							goto cleanup;						}					}				}			}			if (matchidx >= 0)				wfi->ti = ti[matchidx];		}		/* it's a dot, resolve to table or alias */		else if (NAME_IS_VALID(wfi->before_dot))		{			for (k = 0; k < stmt->ntab; k++)			{				wti = ti[k];				if (!NAMEICMP(wti->table_alias, wfi->before_dot))				{					wfi->ti = wti;					break;				}				else if (!NAMEICMP(wti->table_name, wfi->before_dot))				{					wfi->ti = wti;					break;				}			}		}		else if (stmt->ntab == 1)			wfi->ti = ti[0];	}	mylog("--------------------------------------------\n");	mylog("nfld=%d, ntab=%d\n", irdflds->nfields, stmt->ntab);	if (0 == stmt->ntab)	{		SC_set_parse_status(stmt, STMT_PARSE_FATAL);		goto cleanup;	}	for (i = 0; i < (int) irdflds->nfields; i++)	{		wfi = fi[i];		mylog("Field %d:  expr=%d, func=%d, quote=%d, dquote=%d, numeric=%d, name='%s', alias='%s', dot='%s'\n", i, wfi->expr, wfi->func, wfi->quote, wfi->dquote, wfi->numeric, PRINT_NAME(wfi->column_name), PRINT_NAME(wfi->column_alias), PRINT_NAME(wfi->before_dot));		if (wfi->ti)			mylog("     ----> table_name='%s', table_alias='%s'\n", PRINT_NAME(wfi->ti->table_name), PRINT_NAME(wfi->ti->table_alias));	}	for (i = 0; i < stmt->ntab; i++)	{		wti = ti[i];		mylog("Table %d: name='%s', alias='%s'\n", i, PRINT_NAME(wti->table_name), PRINT_NAME(wti->table_alias));	}	/*	 * Now save the SQLColumns Info for the parse tables	 */	/* Call SQLColumns for each table and store the result */	if (stmt->ntab > 1)		updatable = FALSE;	else if (stmt->from_pos < 0)		updatable = FALSE;	for (i = 0; i < stmt->ntab; i++)	{		/* See if already got it */		wti = ti[i];		if (!getCOLIfromTI(func, NULL, stmt, 0, &wti))			break;	}	if (STMT_PARSE_FATAL == SC_parsed_status(stmt))	{		goto cleanup;	}	mylog("Done PG_Columns\n");	/*	 * Now resolve the fields to point to column info	 */	if (updatable && 1 == stmt->ntab)		updatable = TI_is_updatable(stmt->ti[0]);	for (i = 0; i < (int) irdflds->nfields;)	{		wfi = fi[i];		wfi->updatable = updatable;		/* Dont worry about functions or quotes */		if (wfi->func || wfi->quote || wfi->numeric)		{			wfi->updatable = FALSE;			i++;			continue;		}		/* Stars get expanded to all fields in the table */		else if (SAFE_NAME(wfi->column_name)[0] == '*')		{			char		do_all_tables;			Int2			total_cols,						cols,						increased_cols;			mylog("expanding field %d\n", i);			total_cols = 0;			if (wfi->ti)		/* The star represents only the qualified								 * table */				total_cols = (Int2) QR_get_num_cached_tuples(wfi->ti->col_info->result);			else			{	/* The star represents all tables */				/* Calculate the total number of columns after expansion */				for (k = 0; k < stmt->ntab; k++)					total_cols += (Int2) QR_get_num_cached_tuples(ti[k]->col_info->result);			}			increased_cols = total_cols - 1;			/* Allocate some more field pointers if necessary */			new_size = irdflds->nfields + increased_cols;			mylog("k=%d, increased_cols=%d, allocated_size=%d, new_size=%d\n", k, increased_cols, allocated_size, new_size);			if (new_size > allocated_size)			{				int	new_alloc = new_size;				mylog("need more cols: new_alloc = %d\n", new_alloc);				if (!allocateFields(irdflds, new_alloc))				{					SC_set_parse_status(stmt, STMT_PARSE_FATAL);					goto cleanup;				}				fi = irdflds->fi;				allocated_size = irdflds->allocated;			}			/*			 * copy any other fields (if there are any) up past the			 * expansion			 */			for (j = irdflds->nfields - 1; j > i; j--)			{				mylog("copying field %d to %d\n", j, increased_cols + j);				fi[increased_cols + j] = fi[j];			}			mylog("done copying fields\n");			/* Set the new number of fields */			irdflds->nfields += increased_cols;			mylog("irdflds->nfields now at %d\n", irdflds->nfields);			/* copy the new field info */			do_all_tables = (wfi->ti ? FALSE : TRUE);			wfi = NULL;			for (k = 0; k < (do_all_tables ? stmt->ntab : 1); k++)			{				TABLE_INFO *the_ti = do_all_tables ? ti[k] : fi[i]->ti;				cols = (Int2) QR_get_num_cached_tuples(the_ti->col_info->result);				for (n = 0; n < cols; n++)				{					FIELD_INFO	*afi;					BOOL		reuse = TRUE;					mylog("creating field info: n=%d\n", n);					/* skip malloc (already did it for the Star) */					if (k > 0 || n > 0)					{						mylog("allocating field info at %d\n", n + i);						fi[n + i] = (FIELD_INFO *) malloc(sizeof(FIELD_INFO));						if (fi[n + i] == NULL)						{							SC_set_parse_status(stmt, STMT_PARSE_FATAL);							goto cleanup;						}						reuse = FALSE;					}					afi = fi[n + i];					/* Initialize the new space (or the * field) */					FI_Constructor(afi, reuse);					afi->ti = the_ti;					mylog("about to copy at %d\n", n + i);					getColInfo(the_ti->col_info, afi, n);					afi->updatable = updatable;					mylog("done copying\n");				}				i += cols;				mylog("i now at %d\n", i);			}		}		/*		 * We either know which table the field was in because it was		 * qualified with a table name or alias -OR- there was only 1		 * table.		 */		else if (wfi->ti)		{			if (!searchColInfo(fi[i]->ti->col_info, wfi))			{				parse = FALSE;				wfi->updatable = FALSE;			}			i++;		}		/* Don't know the table -- search all tables in "from" list */		else		{			for (k = 0; k < stmt->ntab; k++)			{				if (searchColInfo(ti[k]->col_info, wfi))				{					wfi->ti = ti[k];	/* now know the table */					break;				}			}			if (k >= stmt->ntab)			{				parse = FALSE;				wfi->updatable = FALSE;			}			i++;		}	}	if (check_hasoids && updatable)		CheckHasOids(stmt);	SC_set_parse_status(stmt, parse ? STMT_PARSE_COMPLETE : STMT_PARSE_INCOMPLETE);	for (i = 0; i < (int) irdflds->nfields; i++)	{		wfi = fi[i];		wfi->flag &= ~FIELD_PARSING;		if (0 != wfi->columntype || 0 != wfi->basetype)			wfi->flag |= FIELD_PARSED_OK;	}	stmt->updatable = updatable;cleanup:#undef	return	if (STMT_PARSE_FATAL == SC_parsed_status(stmt))	{		SC_initialize_cols_info(stmt, FALSE, FALSE);		parse = FALSE;	}	mylog("done parse_statement: parse=%d, parse_status=%d\n", parse, SC_parsed_status(stmt));	return parse;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?