Си диез / Говнокод #3628 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37
  38. 38
  39. 39
  40. 40
  41. 41
  42. 42
  43. 43
  44. 44
  45. 45
  46. 46
  47. 47
  48. 48
  49. 49
  50. 50
  51. 51
  52. 52
  53. 53
  54. 54
  55. 55
  56. 56
  57. 57
  58. 58
  59. 59
  60. 60
  61. 61
  62. 62
  63. 63
  64. 64
  65. 65
  66. 66
public void Parse(string sqlScript)
{
	batches = new List<string>();
	State state = State.WaitingGO;
	StartNewBatch();
	for(position = 0; position < sqlScript.Length; position++)
	{
		char c = sqlScript[position];
		if(state == State.WaitingGO)
		{
			PutToBuffer(c);
			if(IsWhiteSpace(c) || IsEndOfLineCharacter(c)) continue;
			else if(c == 'g' || c == 'G') state = State.ReadingGO;
			else
			{
				state = State.ReadingBatch;
				FlushBuffer();
			}
		}
		else if(state == State.ReadingGO)
		{
			PutToBuffer(c);
			if(c == 'o' || c == 'O') state = State.ReadedGO;
			else if(IsEndOfLineCharacter(c))
			{
				state = State.WaitingGO;
				FlushBuffer();
			}
			else
			{
				state = State.ReadingBatch;
				FlushBuffer();
			}
		}
		else if(state == State.ReadedGO)
		{
			if(IsWhiteSpace(c) || IsEndOfLineCharacter(c))
			{
				state = State.WaitingGO;
				FinishBatch();
				StartNewBatch();
			}
			else
			{
				state = State.ReadingBatch;
				PutToBuffer(c);
				FlushBuffer();
			}
		}
		else if(state == State.ReadingBatch)
		{
			PutToBatch(c);
			if(IsEndOfLineCharacter(c)) state = State.WaitingGO;
		}
	}
	if(state != State.ReadedGO) FlushBuffer();
	FinishBatch();
}

private enum State
{
	WaitingGO,
	ReadingGO,
	ReadedGO,
	ReadingBatch
}

Требовалось распарсить string с sql-текстом на отдельные транзакции (т.е. просто разбить текст по go).
Функции для работы с Batch-ем не привожу и так уйма говнокода

Запостил: FedorFo FedorFo, (Updated )

Комментарии (23) RSS

  • если нужно выполнить сразу весть batch - есть специальный тип из сборок Microsoft.SqlServer.*
    Ответить
  • неужели в С# нет красивых методов неиспользования конструкции
    if(state == State.WaitingGO)
    else if(state == State.ReadingGO)
    ...
    ???
    Ответить
    • switch(state)
      {
               case State.WaitingGO: /* ... */ break;
               case State.ReadingGO: /* ... */ break;
               default: /* ... */ break;
      }
      Ответить
        • А как надо? И причём тут сишарп? "Очень много стейтов" можно накуралесить на любом языке.
          Ответить
    • Вообще есть отличный рефакторинг "замена условной логики состоянием/стратегией".
      Но тут этого явно не надо
      Ответить
      • типа да... я ждал этого на уровне языка... В С++ приходится пользоваться фабрикой, для которой создавать таблицу соответствия...
        Ответить
    • >неужели в С# нет красивых методов неиспользования конструкции
      >if(state == State.WaitingGO)
      >else if(state == State.ReadingGO)

      тебе не понравилась конструкция State.WaitingGO? Уж это лучше, чем приходится в С++ писать State_WaitingGO, что-бы имена констант из различных энумов не совпали.
      Ответить
      • в новом стандарте будет State::WaitingGo

        а вообще можно так выкрутиться
        struct State
        {
          enum value_type
          {
            Waiting_Go,
            SomeOther,
          };
        }
        
        State::value_type var = State::Waiting_Go;
        Ответить
    • >неужели в С# нет красивых методов неиспользования конструкции
      >if(state == State.WaitingGO)
      >else if(state == State.ReadingGO)

      Какие проблемы?
      Заводи Dictionary для (типа Map) возвращающий функции и радуйся жизни. Можно даже просто массив завести для увеличения быстродействия.
      Итого будет типа:
      funcMap[state]();
      Ответить
      • Да, причём если создать сразу внутри метода и задействовать замыкания - тогда лямбды внутри словаря смогут получать доступ к локальным данным метода. Это то, чего нет в С++. Не этого ли хотел Пушкофф?
        Ответить
        • >Это то, чего нет в С++.
          Чего? Лямбды в стандарте С++0х есть и могут получать доступ к локальным данным метода.
          Ответить
          • Смешно читать "в стандарте С++0х есть", где суффикс -0x означает "to be released somewhere in 2000's". А на дворе 2010-ый год...

            Есть в стандарте, которого нет - это мощно!)
            Ответить
              • Да, но теоретически всё могут поменять, компиляторы что-то могут не поддерживать, расходиться в чём-то, коль стандарта реального нет. Не ынтырпрайз это всё!
                Ответить
        • я фабрику написал, составил таблицу соответствия, вызов нужной функции одна (правда длинная) строка...
          всеравно это не то и не удобно (хотя удобнее чем 100 else if)...
          Ответить
  • это вместо sqlScript.Split(new[]{"GO","Go","go","gO"},StringSplitOptions .RemoveEmptyEntries) столько ифов колотить...
    Ответить
    • особенно если у вас будет таблица, содержащая сочетание букв go - от шикарные будут у вас кастрированные запросы
      Ответить
      • сделать тогда без StringSplitOptions .RemoveEmptyEntries, и 1 раз проверять на первый и последний пробел/энтер/таб
        Ответить

Добавить комментарий

Из-за тебя ушел bormand, guest!

    А не использовать ли нам bbcode?


    8